mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-06-18 00:27:02 +08:00
feat(renderer): add shadow mapping with PCF soft shadows
Introduce shadow mapping using a dedicated depth framebuffer and shader. The block fragment shader now performs percentage-closer filtering (PCF) with Poisson disk sampling and random rotation for soft shadows. The vertex shader outputs light-space coordinates. A new depth shader pair handles rendering from the light's perspective, discarding transparent fragments. The renderer sets up the light projection based on the camera position and sun direction, and applies the shadow factor to diffuse lighting. Day/night cycle can now be toggled off in the world server thread.
This commit is contained in:
@@ -3,15 +3,62 @@
|
||||
in vec2 tc;
|
||||
in vec3 normal;
|
||||
in vec3 vert_pos;
|
||||
in vec4 FragPosLightSpace;
|
||||
flat in int tex_layer;
|
||||
out vec4 color;
|
||||
|
||||
layout (binding = 0) uniform sampler2DArray samp;
|
||||
layout (binding = 0) uniform sampler2D shadowMap;
|
||||
layout (binding = 1) uniform sampler2DArray samp;
|
||||
|
||||
uniform float ambientStrength;
|
||||
uniform vec3 sunlightColor;
|
||||
uniform vec3 sunlightDir;
|
||||
|
||||
const vec2 poissonDisk[8] = vec2[](
|
||||
vec2( 0.1440, 0.7659), vec2(-0.5761, 0.4479),
|
||||
vec2(-0.3220, -0.6058), vec2( 0.5693, -0.4048),
|
||||
vec2(-0.1276, 0.1657), vec2(-0.0649, -0.0165),
|
||||
vec2( 0.2773, -0.0305), vec2(-0.1134, -0.2122)
|
||||
);
|
||||
|
||||
float random(vec3 seed) {
|
||||
return fract(sin(dot(seed, vec3(12.9898,78.233,45.5432))) * 43758.5453);
|
||||
}
|
||||
|
||||
float ShadowCalculation(vec4 fragPosLightSpace, vec3 norm, vec3 lightDir)
|
||||
{
|
||||
|
||||
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
||||
|
||||
projCoords = projCoords * 0.5 + 0.5;
|
||||
if (projCoords.x < 0.0 || projCoords.x > 1.0 ||
|
||||
projCoords.y < 0.0 || projCoords.y > 1.0 ||
|
||||
projCoords.z < 0.0 || projCoords.z > 1.0) {
|
||||
return 0.0;
|
||||
}
|
||||
float currentDepth = projCoords.z;
|
||||
vec2 texelSize = 1.0 / vec2(textureSize(shadowMap, 0));
|
||||
float bias = 0.0002;
|
||||
bias += max(0.005 * texelSize.x * (1.0 - dot(norm, lightDir)), 0.0);
|
||||
|
||||
float angle = random(gl_FragCoord.xyy) * 6.2831853; // 2*PI
|
||||
float s = sin(angle), c = cos(angle);
|
||||
mat2 rot = mat2(c, -s, s, c);
|
||||
|
||||
float radius = 1.5;
|
||||
|
||||
float shadow = 0.0;
|
||||
const int samples = 8;
|
||||
for (int i = 0; i < samples; ++i) {
|
||||
vec2 offset = rot * poissonDisk[i] * radius * texelSize;
|
||||
float pcfDepth = texture(shadowMap, projCoords.xy + offset).r;
|
||||
shadow += (currentDepth - bias > pcfDepth ? 1.0 : 0.0);
|
||||
}
|
||||
shadow /= float(samples);
|
||||
|
||||
return shadow;
|
||||
}
|
||||
|
||||
|
||||
void main(void) {
|
||||
vec4 objectColor = texture(samp, vec3(tc, tex_layer));
|
||||
|
||||
@@ -28,8 +75,10 @@ void main(void) {
|
||||
float diff = max(dot(norm, lightDir), 0.0);
|
||||
|
||||
vec3 diffuse = diff * sunlightColor;
|
||||
|
||||
color = vec4((ambient + diffuse) * objectColor.rgb, objectColor.a);
|
||||
|
||||
float shadow = ShadowCalculation(FragPosLightSpace, norm, lightDir);
|
||||
|
||||
color = vec4((ambient + (1.0 - shadow) * (diffuse)) * objectColor.rgb, objectColor.a);
|
||||
|
||||
//color = varyingColor;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ out vec2 tc;
|
||||
out vec3 normal;
|
||||
out vec3 vert_pos;
|
||||
flat out int tex_layer;
|
||||
out vec4 FragPosLightSpace;
|
||||
|
||||
mat4 buildRotateX(float rad);
|
||||
mat4 buildRotateY(float rad);
|
||||
@@ -17,19 +18,19 @@ mat4 buildTranslate(float x, float y, float z);
|
||||
uniform mat4 mv_matrix;
|
||||
uniform mat4 proj_matrix;
|
||||
uniform mat4 norm_matrix;
|
||||
|
||||
uniform mat4 lightSpaceMatrix;
|
||||
|
||||
void main(void) {
|
||||
vec4 viewPos = mv_matrix * vec4(pos, 1.0);
|
||||
|
||||
vert_pos = viewPos.xyz;
|
||||
vert_pos = pos;
|
||||
|
||||
tc = texCoord;
|
||||
|
||||
tex_layer = int(layer);
|
||||
|
||||
normal = mat3(norm_matrix) * aNormal;
|
||||
|
||||
FragPosLightSpace = lightSpaceMatrix * vec4(pos, 1.0);
|
||||
gl_Position = proj_matrix * viewPos;
|
||||
}
|
||||
|
||||
|
||||
12
assets/shaders/depth_fragment_shader.glsl
Normal file
12
assets/shaders/depth_fragment_shader.glsl
Normal file
@@ -0,0 +1,12 @@
|
||||
#version 460
|
||||
|
||||
in vec2 tc;
|
||||
flat in int tex_layer;
|
||||
layout (binding = 1) uniform sampler2DArray samp;
|
||||
|
||||
void main() {
|
||||
vec4 texColor = texture(samp, vec3(tc, tex_layer));
|
||||
if (texColor.a < 0.8)
|
||||
discard;
|
||||
//gl_FragDepth = gl_FragCoord.z;
|
||||
}
|
||||
12
assets/shaders/depth_shader.glsl
Normal file
12
assets/shaders/depth_shader.glsl
Normal file
@@ -0,0 +1,12 @@
|
||||
#version 460
|
||||
layout (location = 0) in vec3 pos;
|
||||
layout (location = 1) in vec2 texCoord;
|
||||
layout (location = 2) in float layer;
|
||||
uniform mat4 lightSpaceMatrix;
|
||||
out vec2 tc;
|
||||
flat out int tex_layer;
|
||||
void main() {
|
||||
tc = texCoord;
|
||||
tex_layer = int(layer);
|
||||
gl_Position = lightSpaceMatrix * vec4(pos, 1.0);
|
||||
}
|
||||
Reference in New Issue
Block a user