Fix java shadow biases + minor cleanups

- constant bias and normal bias default values in java didn't match
  C++ or the documentation

- stable shadows were enabled by default in java

- polygon offset biases were missing from the java API

- document and don't apply polygon offset to VSM

- remove unused code
This commit is contained in:
Mathias Agopian
2021-11-02 17:10:34 -07:00
committed by Mathias Agopian
parent c382c0a9cc
commit e172f3a67f
5 changed files with 48 additions and 45 deletions

View File

@@ -76,7 +76,9 @@ extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nBuilderShadowOptions(JNIEnv* env, jclass,
jlong nativeBuilder, jint mapSize, jint cascades, jfloatArray splitPositions,
jfloat constantBias, jfloat normalBias, jfloat shadowFar, jfloat shadowNearHint,
jfloat shadowFarHint, jboolean stable, jboolean screenSpaceContactShadows, jint stepCount,
jfloat shadowFarHint, jboolean stable,
jfloat polygonOffsetConstant, jfloat polygonOffsetSlope,
jboolean screenSpaceContactShadows, jint stepCount,
jfloat maxShadowDistance, jint vsmMsaaSamples, jfloat blurWidth) {
LightManager::Builder *builder = (LightManager::Builder *) nativeBuilder;
LightManager::ShadowOptions shadowOptions {
@@ -88,6 +90,8 @@ Java_com_google_android_filament_LightManager_nBuilderShadowOptions(JNIEnv* env,
.shadowNearHint = shadowNearHint,
.shadowFarHint = shadowFarHint,
.stable = (bool)stable,
.polygonOffsetConstant = polygonOffsetConstant,
.polygonOffsetSlope = polygonOffsetConstant,
.screenSpaceContactShadows = (bool)screenSpaceContactShadows,
.stepCount = uint8_t(stepCount),
.maxShadowDistance = maxShadowDistance,

View File

@@ -244,13 +244,13 @@ public class LightManager {
* light. 1mm by default.
* This is ignored when the View's ShadowType is set to VSM.
*/
public float constantBias = 0.05f;
public float constantBias = 0.001f;
/** Amount by which the maximum sampling error is scaled. The resulting value is used
* to move the shadow away from the fragment normal. Should be 1.0.
* This is ignored when the View's ShadowType is set to VSM.
*/
public float normalBias = 0.4f;
public float normalBias = 1.0f;
/** Distance from the camera after which shadows are clipped. This is used to clip
* shadows that are too far and wouldn't contribute to the scene much, improving
@@ -279,7 +279,24 @@ public class LightManager {
* When set to true, all resolution enhancing features that can affect stability are
* disabling, resulting in significantly lower resolution shadows, albeit stable ones.
*/
public boolean stable = true;
public boolean stable = false;
/**
* Constant bias in depth-resolution units by which shadows are moved away from the
* light. The default value of 0.5 is used to round depth values up.
* Generally this value shouldn't be changed or at least be small and positive.
* This is ignored when the View's ShadowType is set to VSM.
*/
float polygonOffsetConstant = 0.5f;
/**
* Bias based on the change in depth in depth-resolution units by which shadows are moved
* away from the light. The default value of 2.0 works well with SHADOW_SAMPLING_PCF_LOW.
* Generally this value is between 0.5 and the size in texel of the PCF filter.
* Setting this value correctly is essential for LISPSM shadow-maps.
* This is ignored when the View's ShadowType is set to VSM.
*/
float polygonOffsetSlope = 2.0f;
/**
* Whether screen-space contact shadows are used. This applies regardless of whether a
@@ -471,7 +488,9 @@ public class LightManager {
nBuilderShadowOptions(mNativeBuilder,
options.mapSize, options.shadowCascades, options.cascadeSplitPositions,
options.constantBias, options.normalBias, options.shadowFar, options.shadowNearHint,
options.shadowFarHint, options.stable, options.screenSpaceContactShadows,
options.shadowFarHint, options.stable,
options.polygonOffsetConstant, options.polygonOffsetSlope,
options.screenSpaceContactShadows,
options.stepCount, options.maxShadowDistance, options.vsmMsaaSamples,
options.blurWidth);
return this;
@@ -1131,7 +1150,7 @@ public class LightManager {
private static native void nDestroyBuilder(long nativeBuilder);
private static native boolean nBuilderBuild(long nativeBuilder, long nativeEngine, int entity);
private static native void nBuilderCastShadows(long nativeBuilder, boolean enable);
private static native void nBuilderShadowOptions(long nativeBuilder, int mapSize, int cascades, float[] splitPositions, float constantBias, float normalBias, float shadowFar, float shadowNearHint, float shadowFarhint, boolean stable, boolean screenSpaceContactShadows, int stepCount, float maxShadowDistance, int vsmMsaaSamples, float blurWidth);
private static native void nBuilderShadowOptions(long nativeBuilder, int mapSize, int cascades, float[] splitPositions, float constantBias, float normalBias, float shadowFar, float shadowNearHint, float shadowFarhint, boolean stable, float polygonOffsetConstant, float polygonOffsetSlope, boolean screenSpaceContactShadows, int stepCount, float maxShadowDistance, int vsmMsaaSamples, float blurWidth);
private static native void nBuilderCastLight(long nativeBuilder, boolean enabled);
private static native void nBuilderPosition(long nativeBuilder, float x, float y, float z);
private static native void nBuilderDirection(long nativeBuilder, float x, float y, float z);

View File

@@ -273,6 +273,7 @@ public:
* Constant bias in depth-resolution units by which shadows are moved away from the
* light. The default value of 0.5 is used to round depth values up.
* Generally this value shouldn't be changed or at least be small and positive.
* This is ignored when the View's ShadowType is set to VSM.
*/
float polygonOffsetConstant = 0.5f;
@@ -281,6 +282,7 @@ public:
* away from the light. The default value of 2.0 works well with SHADOW_SAMPLING_PCF_LOW.
* Generally this value is between 0.5 and the size in texel of the PCF filter.
* Setting this value correctly is essential for LISPSM shadow-maps.
* This is ignored when the View's ShadowType is set to VSM.
*/
float polygonOffsetSlope = 2.0f;

View File

@@ -139,19 +139,6 @@ public:
ShadowMap::SceneInfo& sceneInfo, uint16_t index);
private:
struct ShadowCameraInfo {
math::mat4f projection;
math::mat4f model;
math::mat4f view;
math::mat4f worldOrigin;
float zn = 0;
float zf = 0;
math::float3 const& getPosition() const noexcept { return model[3].xyz; }
math::float3 getForwardVector() const noexcept {
return -normalize(model[2].xyz); // the camera looks towards -z
}
};
struct Segment {
uint8_t v0, v1;
};

View File

@@ -345,32 +345,33 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateCascadeShadowMaps(FEng
FLightManager::ShadowOptions const& options = lcm.getShadowOptions(directionalLight);
FLightManager::ShadowParams const& params = lcm.getShadowParams(directionalLight);
const ShadowMap::ShadowMapInfo shadowMapInfo{
.atlasDimension = mTextureAtlasRequirements.size,
.textureDimension = uint16_t(options.mapSize),
.shadowDimension = uint16_t(options.mapSize - 2u),
.vsm = view.hasVsm(),
.polygonOffset = { // handle reversed Z
.slope = view.hasVsm() ? 0.0f : -params.options.polygonOffsetSlope,
.constant = view.hasVsm() ? 0.0f : -params.options.polygonOffsetConstant
}
};
if (!mCascadeShadowMaps.empty()) {
// Even if we have more than one cascade, we cull directional shadow casters against the
// entire camera frustum, as if we only had a single cascade.
ShadowMapEntry& entry = mCascadeShadowMaps[0];
ShadowMap& map = entry.getShadowMap();
const ShadowMap::ShadowMapInfo shadowMapInfo{
.atlasDimension = mTextureAtlasRequirements.size,
.textureDimension = uint16_t(options.mapSize),
.shadowDimension = uint16_t(options.mapSize - 2u),
.vsm = view.hasVsm(),
.polygonOffset = { // handle reversed Z
.slope = -params.options.polygonOffsetSlope,
.constant = -params.options.polygonOffsetConstant
}
};
ShadowMap& shadowMap = entry.getShadowMap();
map.updateDirectional(lightData, 0, viewingCameraInfo, shadowMapInfo, *scene, sceneInfo);
shadowMap.updateDirectional(lightData, 0, viewingCameraInfo, shadowMapInfo, *scene, sceneInfo);
Frustum const& frustum = map.getCamera().getCullingFrustum();
Frustum const& frustum = shadowMap.getCamera().getCullingFrustum();
FView::cullRenderables(engine.getJobSystem(), renderableData, frustum,
VISIBLE_DIR_SHADOW_RENDERABLE_BIT);
// note: normalBias is set to zero for VSM
const float normalBias = shadowMapInfo.vsm ? 0.0f : lcm.getShadowNormalBias(0);
// Set shadowBias, using the first directional cascade.
const float texelSizeWorldSpace = map.getTexelSizeWorldSpace();
const float texelSizeWorldSpace = shadowMap.getTexelSizeWorldSpace();
mShadowMappingUniforms.shadowBias = float3{ 0, normalBias * texelSizeWorldSpace, 0 };
}
@@ -428,16 +429,6 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateCascadeShadowMaps(FEng
ShadowMap& shadowMap = entry.getShadowMap();
assert_invariant(entry.getLightIndex() == 0);
const ShadowMap::ShadowMapInfo shadowMapInfo{
.atlasDimension = mTextureAtlasRequirements.size,
.textureDimension = uint16_t(options.mapSize),
.shadowDimension = uint16_t(options.mapSize - 2u),
.vsm = view.hasVsm(),
.polygonOffset = { // handle reversed Z
.slope = -params.options.polygonOffsetSlope,
.constant = -params.options.polygonOffsetConstant
}
};
sceneInfo.csNearFar = { csSplitPosition[i], csSplitPosition[i + 1] };
shadowMap.updateDirectional(lightData, 0,
@@ -506,8 +497,8 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateSpotShadowMaps(FEngine
.spotIndex = uint16_t(i),
.vsm = view.hasVsm(),
.polygonOffset = { // handle reversed Z
.slope = -params.options.polygonOffsetSlope,
.constant = -params.options.polygonOffsetConstant
.slope = view.hasVsm() ? 0.0f : -params.options.polygonOffsetSlope,
.constant = view.hasVsm() ? 0.0f : -params.options.polygonOffsetConstant
}
};