diff --git a/android/filament-android/src/main/cpp/LightManager.cpp b/android/filament-android/src/main/cpp/LightManager.cpp index 84df8ecd7f..4e1cd23d4a 100644 --- a/android/filament-android/src/main/cpp/LightManager.cpp +++ b/android/filament-android/src/main/cpp/LightManager.cpp @@ -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, diff --git a/android/filament-android/src/main/java/com/google/android/filament/LightManager.java b/android/filament-android/src/main/java/com/google/android/filament/LightManager.java index f3c4c5cb4a..0d969237ef 100644 --- a/android/filament-android/src/main/java/com/google/android/filament/LightManager.java +++ b/android/filament-android/src/main/java/com/google/android/filament/LightManager.java @@ -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); diff --git a/filament/include/filament/LightManager.h b/filament/include/filament/LightManager.h index 71a7355f3b..46e5de4d0e 100644 --- a/filament/include/filament/LightManager.h +++ b/filament/include/filament/LightManager.h @@ -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; diff --git a/filament/src/ShadowMap.h b/filament/src/ShadowMap.h index 43af1cfb47..5e44673c74 100644 --- a/filament/src/ShadowMap.h +++ b/filament/src/ShadowMap.h @@ -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; }; diff --git a/filament/src/ShadowMapManager.cpp b/filament/src/ShadowMapManager.cpp index 25e945271f..d443eb746c 100644 --- a/filament/src/ShadowMapManager.cpp +++ b/filament/src/ShadowMapManager.cpp @@ -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 } };