2024-10-08 16:47:56 +08:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
// float/rgba8 encoding/decoding so that we can use an RGBA8
|
|
|
|
|
// shadow map instead of floating point render targets which might
|
|
|
|
|
// not be supported everywhere
|
|
|
|
|
//
|
|
|
|
|
// http://aras-p.info/blog/2009/07/30/encoding-floats-to-rgba-the-final/
|
|
|
|
|
//
|
|
|
|
|
@ctype mat4 hmm_mat4
|
|
|
|
|
@ctype vec3 hmm_vec3
|
|
|
|
|
@ctype vec2 hmm_vec2
|
|
|
|
|
|
|
|
|
|
@block util
|
|
|
|
|
|
|
|
|
|
vec4 encode_depth(float v) {
|
|
|
|
|
vec4 enc = vec4(1.0, 255.0, 65025.0, 16581375.0) * v;
|
|
|
|
|
enc = fract(enc);
|
|
|
|
|
enc -= enc.yzww * vec4(1.0/255.0,1.0/255.0,1.0/255.0,0.0);
|
|
|
|
|
return enc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float decodeDepth(vec4 rgba) {
|
|
|
|
|
return dot(rgba, vec4(1.0, 1.0/255.0, 1.0/65025.0, 1.0/16581375.0));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float sample_shadow(texture2D tex, sampler smp, vec2 uv, float compare) {
|
|
|
|
|
float depth = decodeDepth(texture(sampler2D(tex, smp), vec2(uv.x, uv.y)));
|
|
|
|
|
return step(compare, depth);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float sample_shadow_pcf(texture2D tex, sampler smp, vec3 uv_depth, vec2 sm_size) {
|
|
|
|
|
float result = 0.0;
|
|
|
|
|
for (int x = -2; x <= 2; x++) {
|
|
|
|
|
for (int y =- 2; y <= 2; y++) {
|
|
|
|
|
vec2 offset = vec2(x, y) / sm_size;
|
|
|
|
|
result += sample_shadow(tex, smp, uv_depth.xy + offset, uv_depth.z);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result / 25.0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
//=== shadow pass
|
|
|
|
|
@vs vs_shadow
|
|
|
|
|
|
2025-01-29 17:48:20 +08:00
|
|
|
layout(binding=0) uniform vs_shadow_params {
|
2024-10-08 16:47:56 +08:00
|
|
|
mat4 mvp;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
in vec4 pos;
|
|
|
|
|
out vec2 proj_zw;
|
|
|
|
|
|
|
|
|
|
void main() {
|
|
|
|
|
gl_Position = mvp * pos;
|
|
|
|
|
proj_zw = gl_Position.zw;
|
|
|
|
|
}
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
@fs fs_shadow
|
|
|
|
|
@include_block util
|
|
|
|
|
|
|
|
|
|
in vec2 proj_zw;
|
|
|
|
|
out vec4 frag_color;
|
|
|
|
|
|
|
|
|
|
void main() {
|
|
|
|
|
float depth = proj_zw.x / proj_zw.y;
|
|
|
|
|
frag_color = encode_depth(depth);
|
|
|
|
|
}
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
@program shadow vs_shadow fs_shadow
|
|
|
|
|
|
|
|
|
|
//=== display pass
|
|
|
|
|
@vs vs_display
|
|
|
|
|
|
2025-01-29 17:48:20 +08:00
|
|
|
layout(binding=0) uniform vs_display_params {
|
2024-10-08 16:47:56 +08:00
|
|
|
mat4 mvp;
|
|
|
|
|
mat4 model;
|
|
|
|
|
mat4 light_mvp;
|
|
|
|
|
vec3 diff_color;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
in vec4 pos;
|
|
|
|
|
in vec3 norm;
|
|
|
|
|
out vec3 color;
|
|
|
|
|
out vec4 light_proj_pos;
|
|
|
|
|
out vec4 world_pos;
|
|
|
|
|
out vec3 world_norm;
|
|
|
|
|
|
|
|
|
|
void main() {
|
|
|
|
|
gl_Position = mvp * pos;
|
|
|
|
|
light_proj_pos = light_mvp * pos;
|
|
|
|
|
#if !SOKOL_GLSL
|
|
|
|
|
light_proj_pos.y = -light_proj_pos.y;
|
|
|
|
|
#endif
|
|
|
|
|
world_pos = model * pos;
|
|
|
|
|
world_norm = normalize((model * vec4(norm, 0.0)).xyz);
|
|
|
|
|
color = diff_color;
|
|
|
|
|
}
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
@fs fs_display
|
|
|
|
|
@include_block util
|
|
|
|
|
|
2025-01-29 17:48:20 +08:00
|
|
|
layout(binding=1) uniform fs_display_params {
|
2024-10-08 16:47:56 +08:00
|
|
|
vec3 light_dir;
|
|
|
|
|
vec3 eye_pos;
|
|
|
|
|
};
|
|
|
|
|
|
2025-01-29 17:48:20 +08:00
|
|
|
layout(binding=0) uniform texture2D shadow_map;
|
|
|
|
|
layout(binding=0) uniform sampler shadow_sampler;
|
2024-10-08 16:47:56 +08:00
|
|
|
|
|
|
|
|
in vec3 color;
|
|
|
|
|
in vec4 light_proj_pos;
|
|
|
|
|
in vec4 world_pos;
|
|
|
|
|
in vec3 world_norm;
|
|
|
|
|
|
|
|
|
|
out vec4 frag_color;
|
|
|
|
|
|
|
|
|
|
vec4 gamma(vec4 c) {
|
|
|
|
|
float p = 1.0 / 2.2;
|
|
|
|
|
return vec4(pow(c.xyz, vec3(p)), c.w);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void main() {
|
|
|
|
|
vec2 sm_size = textureSize(sampler2D(shadow_map, shadow_sampler), 0);
|
|
|
|
|
float spec_power = 2.2;
|
|
|
|
|
float ambient_intensity = 0.25;
|
|
|
|
|
vec3 l = normalize(light_dir);
|
|
|
|
|
vec3 n = normalize(world_norm);
|
|
|
|
|
float n_dot_l = dot(n, l);
|
|
|
|
|
if (n_dot_l > 0.0) {
|
|
|
|
|
|
|
|
|
|
vec3 light_pos = light_proj_pos.xyz / light_proj_pos.w;
|
|
|
|
|
vec3 sm_pos = vec3((light_pos.xy + 1.0) * 0.5, light_pos.z);
|
|
|
|
|
float s = sample_shadow_pcf(shadow_map, shadow_sampler, sm_pos, sm_size);
|
|
|
|
|
float diff_intensity = max(n_dot_l * s, 0.0);
|
|
|
|
|
|
|
|
|
|
vec3 v = normalize(eye_pos - world_pos.xyz);
|
|
|
|
|
vec3 r = reflect(-l, n);
|
|
|
|
|
float r_dot_v = max(dot(r, v), 0.0);
|
|
|
|
|
float spec_intensity = pow(r_dot_v, spec_power) * n_dot_l * s;
|
|
|
|
|
|
|
|
|
|
frag_color = vec4(vec3(spec_intensity) + (diff_intensity + ambient_intensity) * color, 1.0);
|
|
|
|
|
} else {
|
|
|
|
|
frag_color = vec4(color * ambient_intensity, 1.0);
|
|
|
|
|
}
|
|
|
|
|
frag_color = gamma(frag_color);
|
|
|
|
|
}
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
@program display vs_display fs_display
|
|
|
|
|
|
|
|
|
|
//=== debug visualization sampler to render shadow map as regular texture
|
|
|
|
|
@vs vs_dbg
|
|
|
|
|
@glsl_options flip_vert_y
|
|
|
|
|
|
|
|
|
|
in vec2 pos;
|
|
|
|
|
out vec2 uv;
|
|
|
|
|
|
|
|
|
|
void main() {
|
|
|
|
|
gl_Position = vec4(pos*2.0 - 1.0, 0.5, 1.0);
|
|
|
|
|
uv = pos;
|
|
|
|
|
}
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
@fs fs_dbg
|
|
|
|
|
@include_block util
|
|
|
|
|
|
2025-01-29 17:48:20 +08:00
|
|
|
layout(binding=0) uniform texture2D dbg_tex;
|
|
|
|
|
layout(binding=0) uniform sampler dbg_smp;
|
2024-10-08 16:47:56 +08:00
|
|
|
|
|
|
|
|
in vec2 uv;
|
|
|
|
|
out vec4 frag_color;
|
|
|
|
|
|
|
|
|
|
void main() {
|
|
|
|
|
float depth = decodeDepth(texture(sampler2D(dbg_tex, dbg_smp), uv));
|
|
|
|
|
frag_color = vec4(depth, depth, depth, 1.0);
|
|
|
|
|
}
|
|
|
|
|
@end
|
|
|
|
|
|
2025-01-29 17:48:20 +08:00
|
|
|
@program dbg vs_dbg fs_dbg
|