From b71861114926dd161a76202559e03ae7b12ac34e Mon Sep 17 00:00:00 2001 From: bloeys Date: Sun, 14 Apr 2024 03:45:48 +0400 Subject: [PATCH] Improving shadows --- main.go | 36 ++++++++++++++++++++++++++---------- res/shaders/simple.glsl | 10 +++++++--- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/main.go b/main.go index aba6b96..e36177e 100755 --- a/main.go +++ b/main.go @@ -51,7 +51,7 @@ type DirLight struct { } var ( - dSize float32 = 50 + dSize float32 = 30 dNear float32 = 1 dFar float32 = 50 dPos = gglm.NewVec3(0, 10, 0) @@ -163,7 +163,7 @@ var ( // Lights dirLight = DirLight{ - Dir: *gglm.NewVec3(0.57735, -0.57735, 0.57735).Normalize(), + Dir: *gglm.NewVec3(0, -0.5, -0.8).Normalize(), DiffuseColor: *gglm.NewVec3(1, 1, 1), SpecularColor: *gglm.NewVec3(1, 1, 1), } @@ -848,10 +848,19 @@ func (g *Game) Render() { depthMapMat.SetUnifMat4("projViewMat", &dirLightProjViewMat) + // // Render depth map for shadows + // depthMapFbo.BindWithViewport() depthMapFbo.Clear() + + // Culling front faces helps 'peter panning' when + // drawing shadow maps, but works only for solids with a back face (i.e. quads won't cast shadows). + // Check more here: https://learnopengl.com/Advanced-Lighting/Shadows/Shadow-Mapping + gl.CullFace(gl.FRONT) g.RenderScene(depthMapMat) + gl.CullFace(gl.BACK) + depthMapFbo.UnBindWithViewport(uint32(g.WinWidth), uint32(g.WinHeight)) if renderToDepthMapFbo { @@ -932,14 +941,21 @@ func (g *Game) RenderScene(overrideMat *materials.Material) { window.Rend.DrawMesh(cubeMesh, gglm.NewTrMatId().Translate(gglm.NewVec3(0, -3, 0)).Scale(gglm.NewVec3(20, 1, 20)), cubeMat) // Cubes - rowSize := 1 - for y := 0; y < rowSize; y++ { - for x := 0; x < rowSize; x++ { - tempModelMatrix.Translate(gglm.NewVec3(-6, 0, 0)) - window.Rend.DrawMesh(cubeMesh, tempModelMatrix, cubeMat) - } - tempModelMatrix.Translate(gglm.NewVec3(float32(rowSize), -1, 0)) - } + tempModelMatrix.Translate(gglm.NewVec3(-6, 0, 0)) + window.Rend.DrawMesh(cubeMesh, tempModelMatrix, cubeMat) + + tempModelMatrix.Translate(gglm.NewVec3(0, -1, -4)) + window.Rend.DrawMesh(cubeMesh, tempModelMatrix, cubeMat) + + // Cubes generator + // rowSize := 1 + // for y := 0; y < rowSize; y++ { + // for x := 0; x < rowSize; x++ { + // tempModelMatrix.Translate(gglm.NewVec3(-6, 0, 0)) + // window.Rend.DrawMesh(cubeMesh, tempModelMatrix, cubeMat) + // } + // tempModelMatrix.Translate(gglm.NewVec3(float32(rowSize), -1, 0)) + // } } func (g *Game) DrawSkybox() { diff --git a/res/shaders/simple.glsl b/res/shaders/simple.glsl index b98ad79..085adf5 100755 --- a/res/shaders/simple.glsl +++ b/res/shaders/simple.glsl @@ -99,7 +99,7 @@ vec4 emissionTexColor; vec3 normalizedVertNorm; vec3 viewDir; -float CalcShadow(sampler2D shadowMap) +float CalcShadow(sampler2D shadowMap, vec3 lightDir) { // Move from clip space to NDC vec3 projCoords = fragPosDirLight.xyz / fragPosDirLight.w; @@ -113,9 +113,13 @@ float CalcShadow(sampler2D shadowMap) // Closest depth is the closest depth value from the light's perspective float closestDepth = texture(shadowMap, projCoords.xy).r; + // Bias in the range [0.005, 0.05] depending on the angle, where a higher + // angle gives a higher bias, as shadow acne gets worse with angle + float bias = max(0.05 * (1.0 - dot(normalizedVertNorm, lightDir)), 0.005); + // If our depth is larger than the lights closest depth, // then there is something closer to the light than us, and so we are in shadow - float shadow = currentDepth > closestDepth ? 1.0 : 0.0; + float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0; return shadow; } @@ -134,7 +138,7 @@ vec3 CalcDirLight() vec3 finalSpecular = specularAmount * dirLight.specularColor * specularTexColor.rgb; // Shadow - float shadow = CalcShadow(dirLight.shadowMap); + float shadow = CalcShadow(dirLight.shadowMap, lightDir); return (finalDiffuse + finalSpecular) * (1.0 - shadow); }