From f45ad72056401823052c6d01f2ba509486b9f9f2 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Sat, 31 Oct 2026 01:10:21 -0700 Subject: [PATCH] Scaled slope bias and transparent shadows fixes --- .../deferred_light/deferred_light.frag.glsl | 2 +- .../deferred_light/deferred_light.json | 5 ++ .../deferred_light.frag.glsl | 2 +- .../deferred_light_mobile.json | 5 ++ leenkx/Shaders/std/light.glsl | 1 + leenkx/Shaders/std/shadows.glsl | 53 +++++++++++++------ leenkx/Sources/iron/object/LightObject.hx | 35 ++++++------ leenkx/Sources/iron/object/Uniforms.hx | 39 ++++++++++++++ leenkx/Sources/leenkx/renderpath/Inc.hx | 4 +- .../leenkx/renderpath/RenderPathDeferred.hx | 2 +- leenkx/blender/lnx/material/make_depth.py | 9 +++- leenkx/blender/lnx/material/make_mesh.py | 11 ++-- leenkx/blender/lnx/material/make_voxel.py | 2 +- leenkx/blender/lnx/material/mat_utils.py | 2 +- leenkx/blender/lnx/props.py | 2 +- 15 files changed, 126 insertions(+), 48 deletions(-) diff --git a/leenkx/Shaders/deferred_light/deferred_light.frag.glsl b/leenkx/Shaders/deferred_light/deferred_light.frag.glsl index 61f39501..98d45dd3 100644 --- a/leenkx/Shaders/deferred_light/deferred_light.frag.glsl +++ b/leenkx/Shaders/deferred_light/deferred_light.frag.glsl @@ -636,7 +636,7 @@ void main() { shadowMap #endif #endif - , eye, p + n * shadowsBias * 2, shadowsBias + , eye, p, n, shadowsBias #ifdef _ShadowMapTransparent , false #endif diff --git a/leenkx/Shaders/deferred_light/deferred_light.json b/leenkx/Shaders/deferred_light/deferred_light.json index f2df396b..ed63c3ca 100644 --- a/leenkx/Shaders/deferred_light/deferred_light.json +++ b/leenkx/Shaders/deferred_light/deferred_light.json @@ -259,6 +259,11 @@ "link": "_biasLightWorldViewProjectionMatrixSpotArray", "ifdef": ["_Clusters", "_ShadowMap", "_Spot"] }, + { + "name": "LWVPSpotArray", + "link": "_biasLightViewProjectionMatrixSpotArray", + "ifdef": ["_SinglePoint", "_ShadowMap", "_Spot"] + }, { "name": "pointLightDataArray", "link": "_pointLightsAtlasArray", diff --git a/leenkx/Shaders/deferred_light_mobile/deferred_light.frag.glsl b/leenkx/Shaders/deferred_light_mobile/deferred_light.frag.glsl index aa86595f..5cf1c7a7 100644 --- a/leenkx/Shaders/deferred_light_mobile/deferred_light.frag.glsl +++ b/leenkx/Shaders/deferred_light_mobile/deferred_light.frag.glsl @@ -448,7 +448,7 @@ void main() { shadowMap #endif #endif - , eye, p + n * shadowsBias * 2, shadowsBias + , eye, p, n, shadowsBias #ifdef _ShadowMapTransparent , false #endif diff --git a/leenkx/Shaders/deferred_light_mobile/deferred_light_mobile.json b/leenkx/Shaders/deferred_light_mobile/deferred_light_mobile.json index 1c02511a..f2a21b72 100644 --- a/leenkx/Shaders/deferred_light_mobile/deferred_light_mobile.json +++ b/leenkx/Shaders/deferred_light_mobile/deferred_light_mobile.json @@ -183,6 +183,11 @@ "link": "_biasLightWorldViewProjectionMatrixSpotArray", "ifdef": ["_Clusters", "_ShadowMap", "_Spot"] }, + { + "name": "LWVPSpotArray", + "link": "_biasLightViewProjectionMatrixSpotArray", + "ifdef": ["_SinglePoint", "_ShadowMap", "_Spot"] + }, { "name": "pointLightDataArray", "link": "_pointLightsAtlasArray", diff --git a/leenkx/Shaders/std/light.glsl b/leenkx/Shaders/std/light.glsl index 51d872d2..33527b3f 100644 --- a/leenkx/Shaders/std/light.glsl +++ b/leenkx/Shaders/std/light.glsl @@ -595,3 +595,4 @@ vec3 sampleLightVoxels(const vec3 p, const vec3 n, const vec3 v, const float dot #endif #endif + diff --git a/leenkx/Shaders/std/shadows.glsl b/leenkx/Shaders/std/shadows.glsl index 5573fd9c..5dae5fea 100644 --- a/leenkx/Shaders/std/shadows.glsl +++ b/leenkx/Shaders/std/shadows.glsl @@ -24,7 +24,7 @@ uniform vec2 smSizeUniform; #ifdef _ShadowMapAtlas uniform vec4 tileBoundsSunArray[maxLights * shadowmapCascades]; -#if defined(_Clusters) && defined(_Spot) && defined(_ShadowMap) +#if defined(_Clusters) && (defined(_Spot) || defined(_LTC)) && defined(_ShadowMap) uniform vec4 tileBoundsSpotArray[maxLightsCluster]; #endif vec4 tileBounds = vec4(0.0, 0.0, 1.0, 1.0); @@ -180,7 +180,7 @@ vec3 PCFCube(samplerCubeShadow shadowMapCube, #endif ) { const float s = shadowmapCubePcfSize; // TODO: incorrect... - float compare = lpToDepth(lp, lightProj) - bias * 1.5; + float compare = lpToDepth(lp, lightProj) - bias * 1.5 - 0.0001; ml = ml + n * bias * 20; #ifdef _InvY ml.y = -ml.y; @@ -321,7 +321,7 @@ vec3 PCFFakeCube(sampler2DShadow shadowMap, , const bool transparent #endif ) { - const float compare = lpToDepth(lp, lightProj) - bias * 1.5; + const float compare = lpToDepth(lp, lightProj) - bias * 1.5 - 0.0001; ml = ml + n * bias * 20; int faceIndex = 0; const int lightIndex = index * 6; @@ -408,10 +408,16 @@ vec3 PCFFakeCube(sampler2DShadow shadowMap, #ifdef _ShadowMapTransparent if (transparent == false) { vec3 transResult = vec3(0.0); + vec2 tileMin = pointLightTile.xy; + vec2 tileMax = pointLightTile.xy + pointLightTile.z; + #ifdef _FlipY + tileMin.y = 1.0 - tileMax.y; + tileMax.y = 1.0 - pointLightTile.y; + #endif for (int x = -1; x <= 1; x++) { for (int y = -1; y <= 1; y++) { vec4 smt = texture(shadowMapTransparent, - clamp(uvtiled + vec2(x, y) / smSize, 0.0, 1.0)); + clamp(uvtiled + vec2(x, y) / smSize, tileMin, tileMax)); transResult += (smt.a < compare) ? smt.rgb : vec3(1.0); } } @@ -437,15 +443,15 @@ vec3 shadowTest(sampler2DShadow shadowMap, #ifdef _ShadowMapAtlas // use tile PCF #ifdef _SMSizeUniform - vec2 smSizeAtlas = smSizeUniform * (tileBounds.zw - tileBounds.xy); + vec2 smSizeAtlas = smSizeUniform; #else - vec2 smSizeAtlas = shadowmapSize * (tileBounds.zw - tileBounds.xy); + vec2 smSizeAtlas = shadowmapSize; #endif return PCFTileAware(shadowMap, #ifdef _ShadowMapTransparent shadowMapTransparent, #endif - lPos.xy, lPos.z - shadowsBias, smSizeAtlas, + lPos.xy, lPos.z - shadowsBias - 0.0001, smSizeAtlas, tileBounds.xy, tileBounds.zw #ifdef _ShadowMapTransparent , transparent @@ -462,7 +468,7 @@ vec3 shadowTest(sampler2DShadow shadowMap, #ifdef _ShadowMapTransparent shadowMapTransparent, #endif - lPos.xy, lPos.z - shadowsBias, smSize + lPos.xy, lPos.z - shadowsBias - 0.0001, smSize #ifdef _ShadowMapTransparent , transparent #endif @@ -499,11 +505,22 @@ mat4 getCascadeMat(const float d, out int casi, out int casIndex) { // .. } +float worldPerTexel(const mat4 LWVP, const vec2 smSize) { + return max(1.0 / abs(LWVP[0][0]), 1.0 / abs(LWVP[1][1])) / smSize.x; +} + +float nlSlopeBias(const vec3 n, const mat4 LWVP, const float wpt) { + vec3 ldir = normalize(vec3(LWVP[0][2], LWVP[1][2], LWVP[2][2])); + float ndotl = max(abs(dot(n, ldir)), 0.05); + float tanTheta = min(sqrt(1.0 - ndotl * ndotl) / ndotl, 1.5); + return wpt * tanTheta * abs(LWVP[2][2]); +} + vec3 shadowTestCascade(sampler2DShadow shadowMap, #ifdef _ShadowMapTransparent sampler2D shadowMapTransparent, #endif - const vec3 eye, const vec3 p, const float shadowsBias + const vec3 eye, const vec3 p, const vec3 n, const float shadowsBias #ifdef _ShadowMapTransparent , const bool transparent #endif @@ -522,8 +539,10 @@ vec3 shadowTestCascade(sampler2DShadow shadowMap, int casi; int casIndex; mat4 LWVP = getCascadeMat(d, casi, casIndex); - vec4 lPos = LWVP * vec4(p, 1.0); + float wpt = worldPerTexel(LWVP, smSize); + vec4 lPos = LWVP * vec4(p + n * 0.5 * wpt, 1.0); lPos.xyz /= lPos.w; + float scaledBias = shadowsBias + nlSlopeBias(n, LWVP, wpt); #ifdef _ShadowMapAtlas tileBounds = tileBoundsSunArray[casi]; @@ -536,7 +555,7 @@ vec3 shadowTestCascade(sampler2DShadow shadowMap, #ifdef _ShadowMapTransparent shadowMapTransparent, #endif - lPos.xy, lPos.z - shadowsBias, smSize, + lPos.xy, lPos.z - scaledBias, smSize, tileBounds.xy, tileBounds.zw #ifdef _ShadowMapTransparent , transparent @@ -547,7 +566,7 @@ vec3 shadowTestCascade(sampler2DShadow shadowMap, #ifdef _ShadowMapTransparent shadowMapTransparent, #endif - lPos.xy, lPos.z - shadowsBias, smSize + lPos.xy, lPos.z - scaledBias, smSize #ifdef _ShadowMapTransparent , transparent #endif @@ -569,8 +588,10 @@ vec3 shadowTestCascade(sampler2DShadow shadowMap, casData[casIndex2 + 2], casData[casIndex2 + 3]); - vec4 lPos2 = LWVP2 * vec4(p, 1.0); + float wpt2 = worldPerTexel(LWVP2, smSize); + vec4 lPos2 = LWVP2 * vec4(p + n * 0.5 * wpt2, 1.0); lPos2.xyz /= lPos2.w; + float scaledBias2 = shadowsBias + nlSlopeBias(n, LWVP2, wpt2); vec3 visibility2 = vec3(1.0); // use lPos2 coordinates for second cascade, not lPos #ifdef _ShadowMapAtlas @@ -582,7 +603,7 @@ vec3 shadowTestCascade(sampler2DShadow shadowMap, #ifdef _ShadowMapTransparent shadowMapTransparent, #endif - lPos2.xy, lPos2.z - shadowsBias, smSize, + lPos2.xy, lPos2.z - scaledBias2, smSize, tileBounds.xy, tileBounds.zw #ifdef _ShadowMapTransparent , transparent @@ -593,7 +614,7 @@ vec3 shadowTestCascade(sampler2DShadow shadowMap, #ifdef _ShadowMapTransparent shadowMapTransparent, #endif - lPos2.xy, lPos2.z - shadowsBias, smSize + lPos2.xy, lPos2.z - scaledBias2, smSize #ifdef _ShadowMapTransparent , transparent #endif @@ -612,4 +633,4 @@ vec3 shadowTestCascade(sampler2DShadow shadowMap, // if (ci == 12) albedo.rgb = vec3(1.0, 1.0, 0.0); } #endif -#endif \ No newline at end of file +#endif diff --git a/leenkx/Sources/iron/object/LightObject.hx b/leenkx/Sources/iron/object/LightObject.hx index a55d2682..a4f6e52b 100644 --- a/leenkx/Sources/iron/object/LightObject.hx +++ b/leenkx/Sources/iron/object/LightObject.hx @@ -674,7 +674,7 @@ class LightObject extends Object { break; } if (discardLightCulled(light)) continue; - if (light.data.raw.type == type) { + if (light.data.raw.type == type || (type == "spot" && light.data.raw.type == "area")) { m.setFrom(light.VP); m.multmat(Uniforms.biasMat); #if lnx_shadowmap_atlas @@ -711,8 +711,8 @@ class LightObject extends Object { LWVPMatrixArray[i * 16 + 13] = m._31; LWVPMatrixArray[i * 16 + 14] = m._32; LWVPMatrixArray[i * 16 + 15] = m._33; - i++; // only increment in light type - } + } + i++; } return LWVPMatrixArray; } @@ -791,7 +791,7 @@ class LightObject extends Object { public static var spotTileBoundsArray: Float32Array = null; public static function updateSpotTileBoundsArray(): Float32Array { - var maxLights = getMaxLights(); + var maxLights = maxLightsCluster; if (spotTileBoundsArray == null) { spotTileBoundsArray = new Float32Array(maxLights * 4); } @@ -799,19 +799,20 @@ class LightObject extends Object { var i = 0; for (light in Scene.active.lights) { if (i >= maxLights) break; - if (!light.visible || light.data.raw.type != "spot") continue; - if (!light.data.raw.cast_shadow || light.data.raw.strength == 0.0) continue; - var idx = i * 4; - spotTileBoundsArray[idx ] = light.tileOffsetX[0]; - spotTileBoundsArray[idx + 2] = light.tileOffsetX[0] + light.tileScale[0]; - #if (!kha_opengl) - // flip bounds - spotTileBoundsArray[idx + 1] = 1.0 - (light.tileOffsetY[0] + light.tileScale[0]); - spotTileBoundsArray[idx + 3] = 1.0 - light.tileOffsetY[0]; - #else - spotTileBoundsArray[idx + 1] = light.tileOffsetY[0]; - spotTileBoundsArray[idx + 3] = light.tileOffsetY[0] + light.tileScale[0]; - #end + if (discardLightCulled(light)) continue; + if ((light.data.raw.type == "spot" || light.data.raw.type == "area") && light.data.raw.cast_shadow) { + var idx = i * 4; + spotTileBoundsArray[idx ] = light.tileOffsetX[0]; + spotTileBoundsArray[idx + 2] = light.tileOffsetX[0] + light.tileScale[0]; + #if (!kha_opengl) + // flip bounds + spotTileBoundsArray[idx + 1] = 1.0 - (light.tileOffsetY[0] + light.tileScale[0]); + spotTileBoundsArray[idx + 3] = 1.0 - light.tileOffsetY[0]; + #else + spotTileBoundsArray[idx + 1] = light.tileOffsetY[0]; + spotTileBoundsArray[idx + 3] = light.tileOffsetY[0] + light.tileScale[0]; + #end + } i++; } return spotTileBoundsArray; diff --git a/leenkx/Sources/iron/object/Uniforms.hx b/leenkx/Sources/iron/object/Uniforms.hx index b404bb1b..8b263a3d 100644 --- a/leenkx/Sources/iron/object/Uniforms.hx +++ b/leenkx/Sources/iron/object/Uniforms.hx @@ -928,6 +928,14 @@ class Uniforms { case "_tileBoundsSunArray": { fa = LightObject.updateSunTileBoundsArray(); } + case "_tileBoundsSpotArray": { + fa = LightObject.updateSpotTileBoundsArray(); + } + #end + #if (!lnx_clusters && lnx_spot) + case "_biasLightWorldViewProjectionMatrixSpotArray": { + fa = updateSpotMatrixFloats(); + } #end } @@ -1387,6 +1395,11 @@ class Uniforms { fa = LightObject.updateLWVPMatrixArray(object, "spot"); } #end // lnx_clusters + #if (!lnx_clusters && lnx_spot) + case "_biasLightWorldViewProjectionMatrixSpotArray": { + fa = updateSpotMatrixFloats(); + } + #end #if lnx_morph_target case "_morphWeights": { fa = cast(object, MeshObject).morphTarget.morphWeights; @@ -1473,6 +1486,32 @@ class Uniforms { } return null; } + + static var spotMatrixFloats: Float32Array = null; + static function updateSpotMatrixFloats(): Float32Array { + var light = getSpot(0); + if (light == null) return null; + if (spotMatrixFloats == null) spotMatrixFloats = new Float32Array(16); + helpMat.setFrom(light.VP); + helpMat.multmat(biasMat); + spotMatrixFloats[0 ] = helpMat._00; + spotMatrixFloats[1 ] = helpMat._01; + spotMatrixFloats[2 ] = helpMat._02; + spotMatrixFloats[3 ] = helpMat._03; + spotMatrixFloats[4 ] = helpMat._10; + spotMatrixFloats[5 ] = helpMat._11; + spotMatrixFloats[6 ] = helpMat._12; + spotMatrixFloats[7 ] = helpMat._13; + spotMatrixFloats[8 ] = helpMat._20; + spotMatrixFloats[9 ] = helpMat._21; + spotMatrixFloats[10] = helpMat._22; + spotMatrixFloats[11] = helpMat._23; + spotMatrixFloats[12] = helpMat._30; + spotMatrixFloats[13] = helpMat._31; + spotMatrixFloats[14] = helpMat._32; + spotMatrixFloats[15] = helpMat._33; + return spotMatrixFloats; + } #end static function currentMat(object: Object): MaterialData { diff --git a/leenkx/Sources/leenkx/renderpath/Inc.hx b/leenkx/Sources/leenkx/renderpath/Inc.hx index de585e18..6be010cb 100644 --- a/leenkx/Sources/leenkx/renderpath/Inc.hx +++ b/leenkx/Sources/leenkx/renderpath/Inc.hx @@ -171,7 +171,7 @@ class Inc { var t = new RenderTargetRaw(); t.name = name; t.width = t.height = size; - t.format = transparent ? "RGBA64" : "DEPTH16"; + t.format = transparent ? "RGBA128" : "DEPTH16"; return path.createRenderTarget(t); } @@ -498,7 +498,7 @@ class Inc { t.name = target; t.width = sizew; t.height = sizeh; - t.format = transparent ? "RGBA64" : "DEPTH16"; + t.format = transparent ? "RGBA128" : "DEPTH16"; rt = path.createRenderTarget(t); } } diff --git a/leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx b/leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx index 546214b8..69c93259 100644 --- a/leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx +++ b/leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx @@ -540,7 +540,7 @@ class RenderPathDeferred { t2.name = "empty_shadowmap_transparent"; t2.width = 1; t2.height = 1; - t2.format = "RGBA64"; + t2.format = "RGBA128"; path.createRenderTarget(t2); path.setTarget("empty_shadowmap_transparent"); path.currentG.clear(0xffffffff, null); diff --git a/leenkx/blender/lnx/material/make_depth.py b/leenkx/blender/lnx/material/make_depth.py index 2d2ae08e..6cf902b7 100644 --- a/leenkx/blender/lnx/material/make_depth.py +++ b/leenkx/blender/lnx/material/make_depth.py @@ -43,7 +43,7 @@ def make(context_id, rpasses, shadowmap=False, shadowmap_transparent=False): 'name': context_id, 'vertex_elements': vs, 'depth_write': False, - 'depth_read': True, + 'depth_read': False, 'compare_mode': 'less', 'cull_mode': 'clockwise', 'blend_source': 'blend_zero', @@ -241,6 +241,7 @@ def make(context_id, rpasses, shadowmap=False, shadowmap_transparent=False): vert.add_out('vec4 wvpposition') vert.write('wvpposition = gl_Position;') frag.write('float depth = (wvpposition.z / wvpposition.w) * 0.5 + 0.5;') + frag.write('depth += 0.00002 + min(max(abs(dFdx(gl_FragCoord.z)), abs(dFdy(gl_FragCoord.z))), 0.0005);') frag.write('vec3 color = mix(vec3(1.0), basecol, opacity);') frag.write('fragColor = vec4(color, depth);') @@ -248,12 +249,16 @@ def make(context_id, rpasses, shadowmap=False, shadowmap_transparent=False): if mat_state.material.lnx_discard: opac = mat_state.material.lnx_discard_opacity_shadows frag.write('if (opacity < {0}) discard;'.format(opac)) - elif rpdat.rp_renderer == 'Deferred' and 'translucent' in rpasses and not shadowmap: + elif shadowmap or (rpdat.rp_renderer == 'Deferred' and 'translucent' in rpasses): pass else: opac = '1.0' frag.write('if (opacity < {0}) discard;'.format(opac)) + if shadowmap and not shadowmap_transparent: + frag.write('vec2 sdz = vec2(dFdx(gl_FragCoord.z), dFdy(gl_FragCoord.z));') + frag.write('gl_FragDepth = gl_FragCoord.z + (0.00002 + min(max(abs(sdz.x), abs(sdz.y)), 0.0005)) * float(gl_FragCoord.w == 1.0);') + make_finalize.make(con_depth) assets.vs_equal(con_depth, assets.shader_cons['depth_vert']) diff --git a/leenkx/blender/lnx/material/make_mesh.py b/leenkx/blender/lnx/material/make_mesh.py index 61098b65..51122dff 100644 --- a/leenkx/blender/lnx/material/make_mesh.py +++ b/leenkx/blender/lnx/material/make_mesh.py @@ -415,9 +415,10 @@ def make_forward_mobile(con_mesh): frag.write('vec3 svisibility = vec3(1.0);') frag.write('float sdotNL = max(dot(n, sunDir), 0.0);') if is_shadows: - vert.add_out('vec4 lightPosition') - vert.add_uniform('mat4 LWVP', '_biasLightWorldViewProjectionMatrixSun') - vert.write('lightPosition = LWVP * spos;') + if not '_CSM' in wrd.world_defs: + vert.add_out('vec4 lightPosition') + vert.add_uniform('mat4 LWVP', '_biasLightWorldViewProjectionMatrixSun') + vert.write('lightPosition = LWVP * spos;') frag.add_uniform('bool receiveShadow') frag.add_uniform(f'sampler2DShadow {shadowmap_sun}') if is_transparent_shadows: @@ -435,7 +436,7 @@ def make_forward_mobile(con_mesh): frag.write(f'svisibility = shadowTestCascade({shadowmap_sun},') if is_transparent_shadows: frag.write(f'{shadowmap_sun_tr},') - frag.write('eye, wposition + n * shadowsBias * 10, shadowsBias') + frag.write('eye, wposition, n, shadowsBias') if is_transparent_shadows: frag.write(', opacity != 1.0') frag.write(');') @@ -826,7 +827,7 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): frag.write(f'svisibility = shadowTestCascade({shadowmap_sun},') if is_transparent_shadows: frag.write(f'{shadowmap_sun_tr},') - frag.write('eye, wposition + n * shadowsBias * 10, shadowsBias') + frag.write('eye, wposition, n, shadowsBias') if is_transparent_shadows: frag.write(', false') frag.write(');') diff --git a/leenkx/blender/lnx/material/make_voxel.py b/leenkx/blender/lnx/material/make_voxel.py index 9a975b43..6212906a 100644 --- a/leenkx/blender/lnx/material/make_voxel.py +++ b/leenkx/blender/lnx/material/make_voxel.py @@ -328,7 +328,7 @@ def make_gi(context_id): frag.write(f'svisibility = shadowTestCascade({shadowmap_sun},') if is_transparent_shadows: frag.write(f'{shadowmap_sun_tr},') - frag.write('eye, P + N * shadowsBias * 10, shadowsBias') + frag.write('eye, P, N, shadowsBias') if is_transparent_shadows: frag.write(', false') frag.write(');') diff --git a/leenkx/blender/lnx/material/mat_utils.py b/leenkx/blender/lnx/material/mat_utils.py index acba54f5..838462c0 100644 --- a/leenkx/blender/lnx/material/mat_utils.py +++ b/leenkx/blender/lnx/material/mat_utils.py @@ -58,7 +58,7 @@ def get_rpasses(material): ar.append('depth') if material.lnx_cast_shadow and rpdat.rp_shadows and ('mesh' in ar): - if 'translucent' in ar or 'refraction' in ar: + if ('translucent' in ar or 'refraction' in ar) and rpdat.rp_shadowmap_transparent: ar.append('shadowmap_transparent') else: ar.append('shadowmap') diff --git a/leenkx/blender/lnx/props.py b/leenkx/blender/lnx/props.py index ce237445..0dce587e 100644 --- a/leenkx/blender/lnx/props.py +++ b/leenkx/blender/lnx/props.py @@ -661,7 +661,7 @@ def init_properties(): bpy.types.Light.lnx_clip_start = FloatProperty(name="Clip Start", default=0.1) bpy.types.Light.lnx_clip_end = FloatProperty(name="Clip End", default=50.0) bpy.types.Light.lnx_fov = FloatProperty(name="Field of View", default=0.84) - bpy.types.Light.lnx_shadows_bias = FloatProperty(name="Bias", description="Depth offset to fight shadow acne", default=1.0) + bpy.types.Light.lnx_shadows_bias = FloatProperty(name="Bias", description="Depth offset to fight shadow acne", default=0.0) # For world bpy.types.World.lnx_light_ies_texture = BoolProperty(name="IES Texture (iestexture.png)", default=False, update=assets.invalidate_compiler_cache) bpy.types.World.lnx_light_clouds_texture = BoolProperty(name="Clouds Texture (cloudstexture.png)", default=False, update=assets.invalidate_compiler_cache)