Proper (but unoptimized) PCF

This commit is contained in:
sergeypdev 2024-03-02 17:32:36 +04:00
parent 73501f7991
commit daf85fc614
3 changed files with 52 additions and 25 deletions

View File

@ -56,6 +56,11 @@ VERTEX_EXPORT VertexData {
vec3 wPos;
} VertexOut;
float random(vec4 seed4) {
float dot_product = dot(seed4, vec4(12.9898,78.233,45.164,94.673));
return fract(sin(dot_product) * 43758.5453);
}
#if VERTEX_SHADER
layout(location = 0) in vec3 aPos;
@ -133,6 +138,12 @@ float lightAttenuation(float point, float dist, float radius) {
return att;
}
vec2 poissonDisk[4] = vec2[](
vec2( -0.94201624, -0.39906216 ),
vec2( 0.94558609, -0.76890725 ),
vec2( -0.094184101, -0.92938870 ),
vec2( 0.34495938, 0.29387760 )
);
vec3 microfacetModel(Material mat, Light light, vec3 P, vec3 N) {
vec3 diffuseBrdf = vec3(0); // metallic
@ -166,9 +177,41 @@ vec3 microfacetModel(Material mat, Light light, vec3 P, vec3 N) {
float NDotL = max(dot(N, L), 0);
float NDotV = dot(N, V);
float shadow_mult = 1;
//// TODO: Shadows for directional light only for now
if (point == 0) {
vec4 shadow_pos = shadow_map_vp * vec4(VertexOut.wPos, 1.0);
shadow_pos /= shadow_pos.w;
shadow_pos.xyz = shadow_pos.xyz * 0.5 + 0.5; // [-1, 1] to [0, 1]
float bias = 0.005 * tan(acos(NDotL));
shadow_pos.z -= bias;
vec4 texcoord;
texcoord.xyw = shadow_pos.xyz; // sampler2DArrayShadow strange texcoord mapping
texcoord.z = 0; // First shadow map
float sum = 0;
vec2 tex_scale = 1.0 / vec2(textureSize(shadow_maps, 0));
for (float y = -1.5; y <= 1.5; y += 1) {
for (float x = -1.5; x <= 1.5; x += 1) {
sum += texture(shadow_maps, vec4(texcoord.xy + vec2(x, y) * tex_scale, texcoord.zw));
}
}
shadow_mult = sum / 16.0;
// for (int i=0; i<4; i++){
// int index = int(16.0 * random(vec4(VertexOut.wPos.xyz * 1000.0, i))) % 4;
// float depth_test = texture(shadow_maps, vec4(texcoord.xy + poissonDisk[index]/700.0, texcoord.zw));
// shadow_mult -= 0.25 * (1 - depth_test);
// }
//shadow_mult = texture(shadow_maps, texcoord);
}
vec3 specBrdf = 0.25 * ggxDistribution(mat, NDotH) * schlickFresnel(mat, LDotH) * geomSmith(mat, NDotL) * geomSmith(mat, NDotV);
return (diffuseBrdf + PI * specBrdf) * lightI * NDotL;
return (diffuseBrdf + PI * specBrdf) * lightI * NDotL * shadow_mult;
}
void main() {
@ -183,23 +226,7 @@ void main() {
vec3 finalColor = vec3(0);
for (int i = 0; i < lights_count; i++) {
float shadow_mult = 1;
//// TODO: Shadows for directional light only for now
if (lights[i].vPos.w == 0) {
vec4 shadow_pos = shadow_map_vp * vec4(VertexOut.wPos, 1.0);
shadow_pos /= shadow_pos.w;
shadow_pos.xyz = shadow_pos.xyz * 0.5 + 0.5; // [-1, 1] to [0, 1]
float bias = 0.005;
shadow_pos.z -= bias;
vec4 texcoord;
texcoord.xyw = shadow_pos.xyz; // sampler2DArrayShadow strange texcoord mapping
texcoord.z = 0; // First shadow map
shadow_mult = texture(shadow_maps, texcoord).r;
}
finalColor += microfacetModel(material, lights[i], VertexOut.vPos, N) * shadow_mult;
finalColor += microfacetModel(material, lights[i], VertexOut.vPos, N);
}
FragColor = vec4(finalColor, 1.0f);

View File

@ -141,15 +141,16 @@ pub fn init(allocator: std.mem.Allocator, frame_arena: std.mem.Allocator, assetm
checkGLError();
std.debug.assert(render.shadow_texture_arrray != 0);
gl.textureStorage3D(render.shadow_texture_arrray, 1, gl.DEPTH_COMPONENT16, 1024, 1024, 1);
gl.textureStorage3D(render.shadow_texture_arrray, 1, gl.DEPTH_COMPONENT16, 2048, 2048, 1);
checkGLError();
gl.textureParameteri(render.shadow_texture_arrray, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
//gl.textureParameteri(render.shadow_texture_arrray, gl.TEXTURE_COMPARE_FUNC, gl.LEQUAL);
gl.textureParameteri(render.shadow_texture_arrray, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.textureParameteri(render.shadow_texture_arrray, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.textureParameteri(render.shadow_texture_arrray, gl.TEXTURE_COMPARE_FUNC, gl.LESS);
gl.textureParameteri(render.shadow_texture_arrray, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_BORDER);
gl.textureParameteri(render.shadow_texture_arrray, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_BORDER);
gl.textureParameteri(render.shadow_texture_arrray, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.textureParameteri(render.shadow_texture_arrray, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.textureParameterfv(render.shadow_texture_arrray, gl.TEXTURE_BORDER_COLOR, @ptrCast(&Vec4.one().data));
// First shadow texture handle
render.shadow_texture_handle = gl.GL_ARB_bindless_texture.getTextureHandleARB(render.shadow_texture_arrray);
@ -270,7 +271,7 @@ pub fn finish(self: *Render) void {
// Directional Light shadow map
if (dir_light) |light| {
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, self.shadow_framebuffer);
gl.viewport(0, 0, 1024, 1024);
gl.viewport(0, 0, 2048, 2048);
gl.clear(gl.DEPTH_BUFFER_BIT);
gl.useProgram(self.assetman.resolveShaderProgram(a.ShaderPrograms.shaders.shadow).program);
@ -278,7 +279,7 @@ pub fn finish(self: *Render) void {
const camera_matrix = &self.shadow_matrices;
camera_matrix.* = .{
.projection = Mat4.orthographic(-5, 5, -5, 5, -10, 10),
.projection = Mat4.orthographic(-2, 2, -2, 2, -5, 5),
.view = Mat4.lookAt(
Vec3.new(light.pos.x(), light.pos.y(), light.pos.z()).scale(-1),
Vec3.zero(),

View File

@ -189,7 +189,6 @@ export fn game_init(global_allocator: *std.mem.Allocator) void {
.flags = .{ .dir_light = true, .rotate = true },
.transform = .{ .rot = Quat.fromEulerAngles(Vec3.new(60, 15, 0)) },
.light = .{ .color_intensity = Vec4.new(1, 1, 0.83, 1) },
.rotate = .{ .rate = 45, .axis = Vec3.up() },
});
const light_root = globals.g_mem.world.addEntity(.{