Implement receive shadow setting for mobile path + all light types

This commit is contained in:
Moritz Brückner 2020-07-13 23:20:58 +02:00
parent c765561ca6
commit 9a47d77594
3 changed files with 80 additions and 64 deletions

View file

@ -70,7 +70,7 @@ uniform sampler2D sltcMag;
vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol, vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol,
const vec3 albedo, const float rough, const float spec, const vec3 f0 const vec3 albedo, const float rough, const float spec, const vec3 f0
#ifdef _ShadowMap #ifdef _ShadowMap
, int index, float bias , int index, float bias, bool receiveShadow
#endif #endif
#ifdef _Spot #ifdef _Spot
, bool isSpot, float spotA, float spotB, vec3 spotDir , bool isSpot, float spotA, float spotB, vec3 spotDir
@ -130,28 +130,30 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
#ifdef _LTC #ifdef _LTC
#ifdef _ShadowMap #ifdef _ShadowMap
#ifdef _SinglePoint if (receiveShadow) {
vec4 lPos = LWVPSpot0 * vec4(p + n * bias * 10, 1.0); #ifdef _SinglePoint
direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias); vec4 lPos = LWVPSpot0 * vec4(p + n * bias * 10, 1.0);
#endif direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias);
#ifdef _Clusters #endif
if (index == 0) { #ifdef _Clusters
vec4 lPos = LWVPSpot0 * vec4(p + n * bias * 10, 1.0); if (index == 0) {
direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias); vec4 lPos = LWVPSpot0 * vec4(p + n * bias * 10, 1.0);
} direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias);
else if (index == 1) { }
vec4 lPos = LWVPSpot1 * vec4(p + n * bias * 10, 1.0); else if (index == 1) {
direct *= shadowTest(shadowMapSpot[1], lPos.xyz / lPos.w, bias); vec4 lPos = LWVPSpot1 * vec4(p + n * bias * 10, 1.0);
} direct *= shadowTest(shadowMapSpot[1], lPos.xyz / lPos.w, bias);
else if (index == 2) { }
vec4 lPos = LWVPSpot2 * vec4(p + n * bias * 10, 1.0); else if (index == 2) {
direct *= shadowTest(shadowMapSpot[2], lPos.xyz / lPos.w, bias); vec4 lPos = LWVPSpot2 * vec4(p + n * bias * 10, 1.0);
} direct *= shadowTest(shadowMapSpot[2], lPos.xyz / lPos.w, bias);
else if (index == 3) { }
vec4 lPos = LWVPSpot3 * vec4(p + n * bias * 10, 1.0); else if (index == 3) {
direct *= shadowTest(shadowMapSpot[3], lPos.xyz / lPos.w, bias); vec4 lPos = LWVPSpot3 * vec4(p + n * bias * 10, 1.0);
} direct *= shadowTest(shadowMapSpot[3], lPos.xyz / lPos.w, bias);
#endif }
#endif
}
#endif #endif
return direct; return direct;
#endif #endif
@ -164,28 +166,30 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
direct *= smoothstep(spotB, spotA, spotEffect); direct *= smoothstep(spotB, spotA, spotEffect);
} }
#ifdef _ShadowMap #ifdef _ShadowMap
#ifdef _SinglePoint if (receiveShadow) {
vec4 lPos = LWVPSpot0 * vec4(p + n * bias * 10, 1.0); #ifdef _SinglePoint
direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias); vec4 lPos = LWVPSpot0 * vec4(p + n * bias * 10, 1.0);
#endif direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias);
#ifdef _Clusters #endif
if (index == 0) { #ifdef _Clusters
vec4 lPos = LWVPSpot0 * vec4(p + n * bias * 10, 1.0); if (index == 0) {
direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias); vec4 lPos = LWVPSpot0 * vec4(p + n * bias * 10, 1.0);
} direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias);
else if (index == 1) { }
vec4 lPos = LWVPSpot1 * vec4(p + n * bias * 10, 1.0); else if (index == 1) {
direct *= shadowTest(shadowMapSpot[1], lPos.xyz / lPos.w, bias); vec4 lPos = LWVPSpot1 * vec4(p + n * bias * 10, 1.0);
} direct *= shadowTest(shadowMapSpot[1], lPos.xyz / lPos.w, bias);
else if (index == 2) { }
vec4 lPos = LWVPSpot2 * vec4(p + n * bias * 10, 1.0); else if (index == 2) {
direct *= shadowTest(shadowMapSpot[2], lPos.xyz / lPos.w, bias); vec4 lPos = LWVPSpot2 * vec4(p + n * bias * 10, 1.0);
} direct *= shadowTest(shadowMapSpot[2], lPos.xyz / lPos.w, bias);
else if (index == 3) { }
vec4 lPos = LWVPSpot3 * vec4(p + n * bias * 10, 1.0); else if (index == 3) {
direct *= shadowTest(shadowMapSpot[3], lPos.xyz / lPos.w, bias); vec4 lPos = LWVPSpot3 * vec4(p + n * bias * 10, 1.0);
} direct *= shadowTest(shadowMapSpot[3], lPos.xyz / lPos.w, bias);
#endif }
#endif
}
#endif #endif
return direct; return direct;
} }
@ -196,17 +200,19 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
#endif #endif
#ifdef _ShadowMap #ifdef _ShadowMap
#ifdef _SinglePoint if (receiveShadow) {
#ifndef _Spot #ifdef _SinglePoint
direct *= PCFCube(shadowMapPoint[0], ld, -l, bias, lightProj, n); #ifndef _Spot
#endif direct *= PCFCube(shadowMapPoint[0], ld, -l, bias, lightProj, n);
#endif #endif
#ifdef _Clusters #endif
if (index == 0) direct *= PCFCube(shadowMapPoint[0], ld, -l, bias, lightProj, n); #ifdef _Clusters
else if (index == 1) direct *= PCFCube(shadowMapPoint[1], ld, -l, bias, lightProj, n); if (index == 0) direct *= PCFCube(shadowMapPoint[0], ld, -l, bias, lightProj, n);
else if (index == 2) direct *= PCFCube(shadowMapPoint[2], ld, -l, bias, lightProj, n); else if (index == 1) direct *= PCFCube(shadowMapPoint[1], ld, -l, bias, lightProj, n);
else if (index == 3) direct *= PCFCube(shadowMapPoint[3], ld, -l, bias, lightProj, n); else if (index == 2) direct *= PCFCube(shadowMapPoint[2], ld, -l, bias, lightProj, n);
#endif else if (index == 3) direct *= PCFCube(shadowMapPoint[3], ld, -l, bias, lightProj, n);
#endif
}
#endif #endif
return direct; return direct;

View file

@ -3,13 +3,14 @@ import bpy
def write(vert, frag): def write(vert, frag):
wrd = bpy.data.worlds['Arm'] wrd = bpy.data.worlds['Arm']
is_shadows = '_ShadowMap' in wrd.world_defs is_shadows = '_ShadowMap' in wrd.world_defs
frag.add_include('std/clusters.glsl') frag.add_include('std/clusters.glsl')
frag.add_uniform('vec2 cameraProj', link='_cameraPlaneProj') frag.add_uniform('vec2 cameraProj', link='_cameraPlaneProj')
frag.add_uniform('vec2 cameraPlane', link='_cameraPlane') frag.add_uniform('vec2 cameraPlane', link='_cameraPlane')
frag.add_uniform('vec4 lightsArray[maxLights * 2]', link='_lightsArray') frag.add_uniform('vec4 lightsArray[maxLights * 2]', link='_lightsArray')
frag.add_uniform('sampler2D clustersData', link='_clustersData') frag.add_uniform('sampler2D clustersData', link='_clustersData')
if is_shadows: if is_shadows:
frag.add_uniform('bool receiveShadow')
frag.add_uniform('vec2 lightProj', link='_lightPlaneProj', included=True) frag.add_uniform('vec2 lightProj', link='_lightPlaneProj', included=True)
frag.add_uniform('samplerCubeShadow shadowMapPoint[4]', included=True) frag.add_uniform('samplerCubeShadow shadowMapPoint[4]', included=True)
vert.add_out('vec4 wvpposition') vert.add_out('vec4 wvpposition')
@ -36,7 +37,7 @@ def write(vert, frag):
frag.write('for (int i = 0; i < min(numLights, maxLightsCluster); i++) {') frag.write('for (int i = 0; i < min(numLights, maxLightsCluster); i++) {')
frag.write('int li = int(texelFetch(clustersData, ivec2(clusterI, i + 1), 0).r * 255);') frag.write('int li = int(texelFetch(clustersData, ivec2(clusterI, i + 1), 0).r * 255);')
frag.write('direct += sampleLight(') frag.write('direct += sampleLight(')
frag.write(' wposition,') frag.write(' wposition,')
frag.write(' n,') frag.write(' n,')
@ -49,7 +50,7 @@ def write(vert, frag):
frag.write(' specular,') frag.write(' specular,')
frag.write(' f0') frag.write(' f0')
if is_shadows: if is_shadows:
frag.write(' , li, lightsArray[li * 2].w') # bias frag.write(' , li, lightsArray[li * 2].w, receiveShadow') # bias
if '_Spot' in wrd.world_defs: if '_Spot' in wrd.world_defs:
frag.write(' , li > numPoints - 1') frag.write(' , li > numPoints - 1')
frag.write(' , lightsArray[li * 2 + 1].w') # cutoff frag.write(' , lightsArray[li * 2 + 1].w') # cutoff
@ -59,4 +60,4 @@ def write(vert, frag):
frag.write(' , voxels, voxpos') frag.write(' , voxels, voxpos')
frag.write(');') frag.write(');')
frag.write('}') # for numLights frag.write('}') # for numLights

View file

@ -366,8 +366,11 @@ def make_forward_mobile(con_mesh):
vert.add_out('vec4 lightPosition') vert.add_out('vec4 lightPosition')
vert.add_uniform('mat4 LWVP', '_biasLightWorldViewProjectionMatrix') vert.add_uniform('mat4 LWVP', '_biasLightWorldViewProjectionMatrix')
vert.write('lightPosition = LWVP * spos;') vert.write('lightPosition = LWVP * spos;')
frag.add_uniform('bool receiveShadow')
frag.add_uniform('sampler2DShadow shadowMap') frag.add_uniform('sampler2DShadow shadowMap')
frag.add_uniform('float shadowsBias', '_sunShadowsBias') frag.add_uniform('float shadowsBias', '_sunShadowsBias')
frag.write('if (receiveShadow) {')
if '_CSM' in wrd.world_defs: if '_CSM' in wrd.world_defs:
frag.add_include('std/shadows.glsl') frag.add_include('std/shadows.glsl')
frag.add_uniform('vec4 casData[shadowmapCascades * 4 + 4]', '_cascadeData', included=True) frag.add_uniform('vec4 casData[shadowmapCascades * 4 + 4]', '_cascadeData', included=True)
@ -381,6 +384,7 @@ def make_forward_mobile(con_mesh):
else: else:
frag.write(' svisibility = texture(shadowMap, vec3(lPos.xy, lPos.z - shadowsBias)).r;') frag.write(' svisibility = texture(shadowMap, vec3(lPos.xy, lPos.z - shadowsBias)).r;')
frag.write('}') frag.write('}')
frag.write('}') # receiveShadow
frag.write('direct += basecol * sdotNL * sunCol * svisibility;') frag.write('direct += basecol * sdotNL * sunCol * svisibility;')
if '_SinglePoint' in wrd.world_defs: if '_SinglePoint' in wrd.world_defs:
@ -394,8 +398,11 @@ def make_forward_mobile(con_mesh):
frag.write('vec3 l = normalize(ld);') frag.write('vec3 l = normalize(ld);')
frag.write('float dotNL = max(dot(n, l), 0.0);') frag.write('float dotNL = max(dot(n, l), 0.0);')
if is_shadows: if is_shadows:
frag.add_uniform('bool receiveShadow')
frag.add_uniform('float pointBias', link='_pointShadowsBias') frag.add_uniform('float pointBias', link='_pointShadowsBias')
frag.add_include('std/shadows.glsl') frag.add_include('std/shadows.glsl')
frag.write('if (receiveShadow) {')
if '_Spot' in wrd.world_defs: if '_Spot' in wrd.world_defs:
vert.add_out('vec4 spotPosition') vert.add_out('vec4 spotPosition')
vert.add_uniform('mat4 LWVPSpot0', link='_biasLightWorldViewProjectionMatrixSpot0') vert.add_uniform('mat4 LWVPSpot0', link='_biasLightWorldViewProjectionMatrixSpot0')
@ -420,6 +427,7 @@ def make_forward_mobile(con_mesh):
frag.write('visibility = float(texture(shadowMapPoint[0], vec3(-l + n * pointBias * 20)).r > compare);') frag.write('visibility = float(texture(shadowMapPoint[0], vec3(-l + n * pointBias * 20)).r > compare);')
else: else:
frag.write('visibility = texture(shadowMapPoint[0], vec4(-l + n * pointBias * 20, compare)).r;') frag.write('visibility = texture(shadowMapPoint[0], vec4(-l + n * pointBias * 20, compare)).r;')
frag.write('}') # receiveShadow
frag.write('direct += basecol * dotNL * pointCol * attenuate(distance(wposition, pointPos)) * visibility;') frag.write('direct += basecol * dotNL * pointCol * attenuate(distance(wposition, pointPos)) * visibility;')
@ -593,7 +601,7 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False):
float dotNV = max(dot(n, vVec), 0.0); float dotNV = max(dot(n, vVec), 0.0);
""") """)
sh = tese if tese != None else vert sh = tese if tese is not None else vert
sh.add_out('vec3 eyeDir') sh.add_out('vec3 eyeDir')
sh.add_uniform('vec3 eye', '_cameraPosition') sh.add_uniform('vec3 eye', '_cameraPosition')
sh.write('eyeDir = eye - wposition;') sh.write('eyeDir = eye - wposition;')
@ -645,7 +653,6 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False):
frag.write('indirect *= vec3(1.0 - traceAO(voxpos, n, voxels));') frag.write('indirect *= vec3(1.0 - traceAO(voxpos, n, voxels));')
frag.write('vec3 direct = vec3(0.0);') frag.write('vec3 direct = vec3(0.0);')
frag.add_uniform('bool receiveShadow')
if '_Sun' in wrd.world_defs: if '_Sun' in wrd.world_defs:
frag.add_uniform('vec3 sunCol', '_sunColor') frag.add_uniform('vec3 sunCol', '_sunColor')
@ -656,6 +663,7 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False):
frag.write('float sdotNH = dot(n, sh);') frag.write('float sdotNH = dot(n, sh);')
frag.write('float sdotVH = dot(vVec, sh);') frag.write('float sdotVH = dot(vVec, sh);')
if is_shadows: if is_shadows:
frag.add_uniform('bool receiveShadow')
frag.add_uniform('sampler2DShadow shadowMap') frag.add_uniform('sampler2DShadow shadowMap')
frag.add_uniform('float shadowsBias', '_sunShadowsBias') frag.add_uniform('float shadowsBias', '_sunShadowsBias')
frag.write('if (receiveShadow) {') frag.write('if (receiveShadow) {')
@ -665,7 +673,7 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False):
frag.add_uniform('vec3 eye', '_cameraPosition') frag.add_uniform('vec3 eye', '_cameraPosition')
frag.write('svisibility = shadowTestCascade(shadowMap, eye, wposition + n * shadowsBias * 10, shadowsBias);') frag.write('svisibility = shadowTestCascade(shadowMap, eye, wposition + n * shadowsBias * 10, shadowsBias);')
else: else:
if tese != None: if tese is not None:
tese.add_out('vec4 lightPosition') tese.add_out('vec4 lightPosition')
tese.add_uniform('mat4 LVP', '_biasLightViewProjectionMatrix') tese.add_uniform('mat4 LVP', '_biasLightViewProjectionMatrix')
tese.write('lightPosition = LVP * vec4(wposition, 1.0);') tese.write('lightPosition = LVP * vec4(wposition, 1.0);')
@ -694,6 +702,7 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False):
frag.add_uniform('vec3 spotDir', link='_spotDirection') frag.add_uniform('vec3 spotDir', link='_spotDirection')
frag.add_uniform('vec2 spotData', link='_spotData') frag.add_uniform('vec2 spotData', link='_spotData')
if is_shadows: if is_shadows:
frag.add_uniform('bool receiveShadow')
frag.add_uniform('float pointBias', link='_pointShadowsBias') frag.add_uniform('float pointBias', link='_pointShadowsBias')
if '_Spot' in wrd.world_defs: if '_Spot' in wrd.world_defs:
# Skip world matrix, already in world-space # Skip world matrix, already in world-space
@ -705,7 +714,7 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False):
frag.write('direct += sampleLight(') frag.write('direct += sampleLight(')
frag.write(' wposition, n, vVec, dotNV, pointPos, pointCol, albedo, roughness, specular, f0') frag.write(' wposition, n, vVec, dotNV, pointPos, pointCol, albedo, roughness, specular, f0')
if is_shadows: if is_shadows:
frag.write(' , 0, pointBias') frag.write(' , 0, pointBias, receiveShadow')
if '_Spot' in wrd.world_defs: if '_Spot' in wrd.world_defs:
frag.write(' , true, spotData.x, spotData.y, spotDir') frag.write(' , true, spotData.x, spotData.y, spotDir')
if '_VoxelShadow' in wrd.world_defs and '_VoxelAOvar' in wrd.world_defs: if '_VoxelShadow' in wrd.world_defs and '_VoxelAOvar' in wrd.world_defs: