forked from LeenkxTeam/LNXSDK
Update leenkx/Shaders/std/shadows.glsl
This commit is contained in:
@ -58,7 +58,15 @@ vec2 sampleCube(vec3 dir, out int faceIndex) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
vec3 PCF(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, const vec2 uv, const float compare, const vec2 smSize, const bool transparent) {
|
vec3 PCF(sampler2DShadow shadowMap,
|
||||||
|
#ifdef _ShadowMapTransparent
|
||||||
|
sampler2D shadowMapTransparent,
|
||||||
|
#endif
|
||||||
|
const vec2 uv, const float compare, const vec2 smSize
|
||||||
|
#ifdef _ShadowMapTransparent
|
||||||
|
, const bool transparent
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
vec3 result = vec3(0.0);
|
vec3 result = vec3(0.0);
|
||||||
result.x = texture(shadowMap, vec3(uv + (vec2(-1.0, -1.0) / smSize), compare));
|
result.x = texture(shadowMap, vec3(uv + (vec2(-1.0, -1.0) / smSize), compare));
|
||||||
result.x += texture(shadowMap, vec3(uv + (vec2(-1.0, 0.0) / smSize), compare));
|
result.x += texture(shadowMap, vec3(uv + (vec2(-1.0, 0.0) / smSize), compare));
|
||||||
@ -71,11 +79,13 @@ vec3 PCF(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, const vec2 u
|
|||||||
result.x += texture(shadowMap, vec3(uv + (vec2(1.0, 1.0) / smSize), compare));
|
result.x += texture(shadowMap, vec3(uv + (vec2(1.0, 1.0) / smSize), compare));
|
||||||
result = result.xxx / 9.0;
|
result = result.xxx / 9.0;
|
||||||
|
|
||||||
|
#ifdef _ShadowMapTransparent
|
||||||
if (transparent == false) {
|
if (transparent == false) {
|
||||||
vec4 shadowmap_transparent = texture(shadowMapTransparent, uv);
|
vec4 shadowmap_transparent = texture(shadowMapTransparent, uv);
|
||||||
if (shadowmap_transparent.a < compare)
|
if (shadowmap_transparent.a < compare)
|
||||||
result *= shadowmap_transparent.rgb;
|
result *= shadowmap_transparent.rgb;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -87,7 +97,15 @@ float lpToDepth(vec3 lp, const vec2 lightProj) {
|
|||||||
return zcomp * 0.5 + 0.5;
|
return zcomp * 0.5 + 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 PCFCube(samplerCubeShadow shadowMapCube, samplerCube shadowMapCubeTransparent, const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n, const bool transparent) {
|
vec3 PCFCube(samplerCubeShadow shadowMapCube,
|
||||||
|
#ifdef _ShadowMapTransparent
|
||||||
|
samplerCube shadowMapCubeTransparent,
|
||||||
|
#endif
|
||||||
|
const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n
|
||||||
|
#ifdef _ShadowMapTransparent
|
||||||
|
, const bool transparent
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
const float s = shadowmapCubePcfSize; // TODO: incorrect...
|
const float s = shadowmapCubePcfSize; // TODO: incorrect...
|
||||||
float compare = lpToDepth(lp, lightProj) - bias * 1.5;
|
float compare = lpToDepth(lp, lightProj) - bias * 1.5;
|
||||||
ml = ml + n * bias * 20;
|
ml = ml + n * bias * 20;
|
||||||
@ -106,11 +124,13 @@ vec3 PCFCube(samplerCubeShadow shadowMapCube, samplerCube shadowMapCubeTranspare
|
|||||||
result.x += texture(shadowMapCube, vec4(ml + vec3(-s, -s, -s), compare));
|
result.x += texture(shadowMapCube, vec4(ml + vec3(-s, -s, -s), compare));
|
||||||
result = result.xxx / 9.0;
|
result = result.xxx / 9.0;
|
||||||
|
|
||||||
|
#ifdef _ShadowMapTransparent
|
||||||
if (transparent == false) {
|
if (transparent == false) {
|
||||||
vec4 shadowmap_transparent = texture(shadowMapCubeTransparent, ml);
|
vec4 shadowmap_transparent = texture(shadowMapCubeTransparent, ml);
|
||||||
if (shadowmap_transparent.a < compare)
|
if (shadowmap_transparent.a < compare)
|
||||||
result *= shadowmap_transparent.rgb;
|
result *= shadowmap_transparent.rgb;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -209,32 +229,57 @@ vec2 transformOffsetedUV(const int faceIndex, out int newFaceIndex, vec2 uv) {
|
|||||||
return uv;
|
return uv;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 PCFFakeCube(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n, const int index, const bool transparent) {
|
vec3 PCFFakeCube(sampler2DShadow shadowMap,
|
||||||
|
#ifdef _ShadowMapTransparent
|
||||||
|
sampler2D shadowMapTransparent,
|
||||||
|
#endif
|
||||||
|
const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n, const int index
|
||||||
|
#ifdef _ShadowMapTransparent
|
||||||
|
, const bool transparent
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
const vec2 smSize = smSizeUniform; // TODO: incorrect...
|
const vec2 smSize = smSizeUniform; // TODO: incorrect...
|
||||||
const float compare = lpToDepth(lp, lightProj) - bias * 1.5;
|
const float compare = lpToDepth(lp, lightProj) - bias * 1.5;
|
||||||
ml = ml + n * bias * 20;
|
ml = ml + n * bias * 20;
|
||||||
|
|
||||||
int faceIndex = 0;
|
int faceIndex = 0;
|
||||||
const int lightIndex = index * 6;
|
const int lightIndex = index * 6;
|
||||||
const vec2 uv = sampleCube(ml, faceIndex);
|
const vec2 uv = sampleCube(ml, faceIndex);
|
||||||
|
|
||||||
vec4 pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas
|
vec4 pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas
|
||||||
vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy;
|
vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy;
|
||||||
#ifdef _FlipY
|
#ifdef _FlipY
|
||||||
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
|
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (any(lessThan(uvtiled, vec2(0.0))) || any(greaterThan(uvtiled, vec2(1.0)))) {
|
||||||
|
return vec3(1.0); // Or handle edge cases differently
|
||||||
|
}
|
||||||
|
|
||||||
vec3 result = vec3(0.0);
|
vec3 result = vec3(0.0);
|
||||||
result.x += texture(shadowMap, vec3(uvtiled, compare));
|
// In PCFFakeCube(), modify the sampling pattern to be more robust:
|
||||||
// soft shadowing
|
const vec2 offsets[9] = vec2[](
|
||||||
int newFaceIndex = 0;
|
vec2(0, 0),
|
||||||
uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(-1.0, 0.0) / smSize)));
|
vec2(1, 0), vec2(-1, 0), vec2(0, 1), vec2(0, -1),
|
||||||
|
vec2(1, 1), vec2(-1, 1), vec2(1, -1), vec2(-1, -1)
|
||||||
|
);
|
||||||
|
|
||||||
|
for (int i = 0; i < 9; i++) {
|
||||||
|
vec2 sampleUV = uv + offsets[i] / smSize;
|
||||||
|
int newFaceIndex;
|
||||||
|
vec2 transformedUV = transformOffsetedUV(faceIndex, newFaceIndex, sampleUV);
|
||||||
pointLightTile = pointLightDataArray[lightIndex + newFaceIndex];
|
pointLightTile = pointLightDataArray[lightIndex + newFaceIndex];
|
||||||
uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy;
|
uvtiled = pointLightTile.z * transformedUV + pointLightTile.xy;
|
||||||
|
#ifdef _FlipY
|
||||||
|
uvtiled.y = 1.0 - uvtiled.y;
|
||||||
|
#endif
|
||||||
|
result.x += texture(shadowMap, vec3(uvtiled, compare));
|
||||||
|
}
|
||||||
|
result = result.xxx / 9.0;
|
||||||
|
|
||||||
|
pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas
|
||||||
|
uvtiled = pointLightTile.z * uv + pointLightTile.xy;
|
||||||
#ifdef _FlipY
|
#ifdef _FlipY
|
||||||
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
|
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
|
||||||
#endif
|
#endif
|
||||||
result.x += texture(shadowMap, vec3(uvtiled, compare));
|
|
||||||
|
|
||||||
#ifdef _ShadowMapTransparent
|
#ifdef _ShadowMapTransparent
|
||||||
if (transparent == false) {
|
if (transparent == false) {
|
||||||
@ -244,88 +289,39 @@ vec3 PCFFakeCube(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, cons
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
result.x += texture(shadowMap, vec3(uvtiled, compare));
|
|
||||||
|
|
||||||
uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(0.0, -1.0) / smSize)));
|
|
||||||
pointLightTile = pointLightDataArray[lightIndex + newFaceIndex];
|
|
||||||
uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy;
|
|
||||||
#ifdef _FlipY
|
|
||||||
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
|
|
||||||
#endif
|
|
||||||
result.x += texture(shadowMap, vec3(uvtiled, compare));
|
|
||||||
|
|
||||||
uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(-1.0, -1.0) / smSize)));
|
|
||||||
pointLightTile = pointLightDataArray[lightIndex + newFaceIndex];
|
|
||||||
uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy;
|
|
||||||
#ifdef _FlipY
|
|
||||||
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
|
|
||||||
#endif
|
|
||||||
result.x += texture(shadowMap, vec3(uvtiled, compare));
|
|
||||||
|
|
||||||
uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(0.0, 1.0) / smSize)));
|
|
||||||
pointLightTile = pointLightDataArray[lightIndex + newFaceIndex];
|
|
||||||
uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy;
|
|
||||||
#ifdef _FlipY
|
|
||||||
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
|
|
||||||
#endif
|
|
||||||
result.x += texture(shadowMap, vec3(uvtiled, compare));
|
|
||||||
|
|
||||||
uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(1.0, -1.0) / smSize)));
|
|
||||||
pointLightTile = pointLightDataArray[lightIndex + newFaceIndex];
|
|
||||||
uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy;
|
|
||||||
#ifdef _FlipY
|
|
||||||
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
|
|
||||||
#endif
|
|
||||||
result.x += texture(shadowMap, vec3(uvtiled, compare));
|
|
||||||
|
|
||||||
uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(1.0, 0.0) / smSize)));
|
|
||||||
pointLightTile = pointLightDataArray[lightIndex + newFaceIndex];
|
|
||||||
uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy;
|
|
||||||
#ifdef _FlipY
|
|
||||||
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
|
|
||||||
#endif
|
|
||||||
result.x += texture(shadowMap, vec3(uvtiled, compare));
|
|
||||||
|
|
||||||
uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(1.0, 1.0) / smSize)));
|
|
||||||
pointLightTile = pointLightDataArray[lightIndex + newFaceIndex];
|
|
||||||
uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy;
|
|
||||||
#ifdef _FlipY
|
|
||||||
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
|
|
||||||
#endif
|
|
||||||
result.x += texture(shadowMap, vec3(uvtiled, compare));
|
|
||||||
|
|
||||||
result = result.xxx / 9.0;
|
|
||||||
|
|
||||||
pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas
|
|
||||||
uvtiled = pointLightTile.z * uv + pointLightTile.xy;
|
|
||||||
#ifdef _FlipY
|
|
||||||
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (transparent == false) {
|
|
||||||
vec4 shadowmap_transparent = texture(shadowMapTransparent, uvtiled);
|
|
||||||
if (shadowmap_transparent.a < compare)
|
|
||||||
result *= shadowmap_transparent.rgb;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
vec3 shadowTest(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, const vec3 lPos, const float shadowsBias, const bool transparent) {
|
vec3 shadowTest(sampler2DShadow shadowMap,
|
||||||
|
#ifdef _ShadowMapTransparent
|
||||||
|
sampler2D shadowMapTransparent,
|
||||||
|
#endif
|
||||||
|
const vec3 lPos, const float shadowsBias
|
||||||
|
#ifdef _ShadowMapTransparent
|
||||||
|
, const bool transparent
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
#ifdef _SMSizeUniform
|
#ifdef _SMSizeUniform
|
||||||
vec2 smSize = smSizeUniform;
|
vec2 smSize = smSizeUniform;
|
||||||
#else
|
#else
|
||||||
const vec2 smSize = shadowmapSize;
|
const vec2 smSize = shadowmapSize;
|
||||||
#endif
|
#endif
|
||||||
if (lPos.x < 0.0 || lPos.y < 0.0 || lPos.x > 1.0 || lPos.y > 1.0) return vec3(1.0);
|
if (lPos.x < 0.0 || lPos.y < 0.0 || lPos.x > 1.0 || lPos.y > 1.0) return vec3(1.0);
|
||||||
return PCF(shadowMap, shadowMapTransparent, lPos.xy, lPos.z - shadowsBias, smSize, transparent);
|
return PCF(shadowMap,
|
||||||
|
#ifdef _ShadowMapTransparent
|
||||||
|
shadowMapTransparent,
|
||||||
|
#endif
|
||||||
|
lPos.xy, lPos.z - shadowsBias, smSize
|
||||||
|
#ifdef _ShadowMapTransparent
|
||||||
|
, transparent
|
||||||
|
#endif
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _CSM
|
#ifdef _CSM
|
||||||
mat4 getCascadeMat(const float d, out int casi, out int casIndex) {
|
mat4 getCascadeMat(const float d, out int casi, out int casIndex) {
|
||||||
const int c = shadowmapCascades;
|
const int c = shadowmapCascades;
|
||||||
|
|
||||||
// Get cascade index
|
// Get cascade index
|
||||||
// TODO: use bounding box slice selection instead of sphere
|
// TODO: use bounding box slice selection instead of sphere
|
||||||
const vec4 ci = vec4(float(c > 0), float(c > 1), float(c > 2), float(c > 3));
|
const vec4 ci = vec4(float(c > 0), float(c > 1), float(c > 2), float(c > 3));
|
||||||
@ -341,21 +337,26 @@ mat4 getCascadeMat(const float d, out int casi, out int casIndex) {
|
|||||||
float(d > casData[c * 4].z),
|
float(d > casData[c * 4].z),
|
||||||
float(d > casData[c * 4].w));
|
float(d > casData[c * 4].w));
|
||||||
casi = int(min(dot(ci, comp), c));
|
casi = int(min(dot(ci, comp), c));
|
||||||
|
|
||||||
// Get cascade mat
|
// Get cascade mat
|
||||||
casIndex = casi * 4;
|
casIndex = casi * 4;
|
||||||
|
|
||||||
return mat4(
|
return mat4(
|
||||||
casData[casIndex ],
|
casData[casIndex ],
|
||||||
casData[casIndex + 1],
|
casData[casIndex + 1],
|
||||||
casData[casIndex + 2],
|
casData[casIndex + 2],
|
||||||
casData[casIndex + 3]);
|
casData[casIndex + 3]);
|
||||||
|
|
||||||
// if (casIndex == 0) return mat4(casData[0], casData[1], casData[2], casData[3]);
|
// if (casIndex == 0) return mat4(casData[0], casData[1], casData[2], casData[3]);
|
||||||
// ..
|
// ..
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 shadowTestCascade(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, const vec3 eye, const vec3 p, const float shadowsBias, const bool transparent) {
|
vec3 shadowTestCascade(sampler2DShadow shadowMap,
|
||||||
|
#ifdef _ShadowMapTransparent
|
||||||
|
sampler2D shadowMapTransparent,
|
||||||
|
#endif
|
||||||
|
const vec3 eye, const vec3 p, const float shadowsBias
|
||||||
|
#ifdef _ShadowMapTransparent
|
||||||
|
, const bool transparent
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
#ifdef _SMSizeUniform
|
#ifdef _SMSizeUniform
|
||||||
vec2 smSize = smSizeUniform;
|
vec2 smSize = smSizeUniform;
|
||||||
#else
|
#else
|
||||||
@ -363,16 +364,22 @@ vec3 shadowTestCascade(sampler2DShadow shadowMap, sampler2D shadowMapTransparent
|
|||||||
#endif
|
#endif
|
||||||
const int c = shadowmapCascades;
|
const int c = shadowmapCascades;
|
||||||
float d = distance(eye, p);
|
float d = distance(eye, p);
|
||||||
|
|
||||||
int casi;
|
int casi;
|
||||||
int casIndex;
|
int casIndex;
|
||||||
mat4 LWVP = getCascadeMat(d, casi, casIndex);
|
mat4 LWVP = getCascadeMat(d, casi, casIndex);
|
||||||
|
|
||||||
vec4 lPos = LWVP * vec4(p, 1.0);
|
vec4 lPos = LWVP * vec4(p, 1.0);
|
||||||
lPos.xyz /= lPos.w;
|
lPos.xyz /= lPos.w;
|
||||||
|
|
||||||
vec3 visibility = vec3(1.0);
|
vec3 visibility = vec3(1.0);
|
||||||
if (lPos.w > 0.0) visibility = PCF(shadowMap, shadowMapTransparent, lPos.xy, lPos.z - shadowsBias, smSize, transparent);
|
if (lPos.w > 0.0) visibility = PCF(shadowMap,
|
||||||
|
#ifdef _ShadowMapTransparent
|
||||||
|
shadowMapTransparent,
|
||||||
|
#endif
|
||||||
|
lPos.xy, lPos.z - shadowsBias, smSize
|
||||||
|
#ifdef _ShadowMapTransparent
|
||||||
|
, transparent
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
|
||||||
// Blend cascade
|
// Blend cascade
|
||||||
// https://github.com/TheRealMJP/Shadows
|
// https://github.com/TheRealMJP/Shadows
|
||||||
@ -391,13 +398,20 @@ vec3 shadowTestCascade(sampler2DShadow shadowMap, sampler2D shadowMapTransparent
|
|||||||
vec4 lPos2 = LWVP2 * vec4(p, 1.0);
|
vec4 lPos2 = LWVP2 * vec4(p, 1.0);
|
||||||
lPos2.xyz /= lPos2.w;
|
lPos2.xyz /= lPos2.w;
|
||||||
vec3 visibility2 = vec3(1.0);
|
vec3 visibility2 = vec3(1.0);
|
||||||
if (lPos2.w > 0.0) visibility2 = PCF(shadowMap, shadowMapTransparent, lPos2.xy, lPos2.z - shadowsBias, smSize, transparent);
|
if (lPos2.w > 0.0) visibility2 = PCF(shadowMap,
|
||||||
|
#ifdef _ShadowMapTransparent
|
||||||
|
shadowMapTransparent,
|
||||||
|
#endif
|
||||||
|
lPos.xy, lPos.z - shadowsBias, smSize
|
||||||
|
#ifdef _ShadowMapTransparent
|
||||||
|
, transparent
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
|
||||||
float lerpAmt = smoothstep(0.0, blendThres, splitDist);
|
float lerpAmt = smoothstep(0.0, blendThres, splitDist);
|
||||||
return mix(visibility2, visibility, lerpAmt);
|
return mix(visibility2, visibility, lerpAmt);
|
||||||
}
|
}
|
||||||
return visibility;
|
return visibility;
|
||||||
|
|
||||||
// Visualize cascades
|
// Visualize cascades
|
||||||
// if (ci == 0) albedo.rgb = vec3(1.0, 0.0, 0.0);
|
// if (ci == 0) albedo.rgb = vec3(1.0, 0.0, 0.0);
|
||||||
// if (ci == 4) albedo.rgb = vec3(0.0, 1.0, 0.0);
|
// if (ci == 4) albedo.rgb = vec3(0.0, 1.0, 0.0);
|
||||||
|
Reference in New Issue
Block a user