Basic directional shadows

This commit is contained in:
bloeys
2024-04-14 02:50:40 +04:00
parent 040228319e
commit be85e20024
4 changed files with 239 additions and 90 deletions

255
main.go
View File

@ -50,6 +50,29 @@ type DirLight struct {
SpecularColor gglm.Vec3 SpecularColor gglm.Vec3
} }
var (
dSize float32 = 50
dNear float32 = 1
dFar float32 = 50
dPos = gglm.NewVec3(0, 10, 0)
)
func (d *DirLight) GetProjViewMat() gglm.Mat4 {
// Some arbitrary position for the directional light
pos := dPos //gglm.NewVec3(0, 10, 0)
size := dSize //float32(50)
nearClip := dNear //float32(1)
farClip := dFar //float32(50)
projMat := gglm.Ortho(-size, size, -size, size, nearClip, farClip).Mat4
// viewMat := gglm.LookAtRH(pos, gglm.NewVec3(0, 0, 0), gglm.NewVec3(0, 1, 0)).Mat4
viewMat := gglm.LookAtRH(pos, pos.Clone().Add(d.Dir.Clone().Scale(10)), gglm.NewVec3(0, 1, 0)).Mat4
return *projMat.Mul(&viewMat)
}
// Check https://wiki.ogre3d.org/tiki-index.php?page=-Point+Light+Attenuation for values // Check https://wiki.ogre3d.org/tiki-index.php?page=-Point+Light+Attenuation for values
type PointLight struct { type PointLight struct {
Pos gglm.Vec3 Pos gglm.Vec3
@ -99,13 +122,16 @@ var (
yaw float32 = -1.5 yaw float32 = -1.5
cam *camera.Camera cam *camera.Camera
renderToFbo = true renderToDemoFbo = true
fboRenderDirectly = true renderToBackBuffer = true
fboScale = gglm.NewVec2(0.25, 0.25) demoFboScale = gglm.NewVec2(0.25, 0.25)
fboOffset = gglm.NewVec2(0.75, -0.75) demoFboOffset = gglm.NewVec2(0.75, -0.75)
demoFbo buffers.Framebuffer demoFbo buffers.Framebuffer
depthMapFbo buffers.Framebuffer renderToDepthMapFbo = true
depthMapFboScale = gglm.NewVec2(0.25, 0.25)
depthMapFboOffset = gglm.NewVec2(0.75, -0.2)
depthMapFbo buffers.Framebuffer
screenQuadVao buffers.VertexArray screenQuadVao buffers.VertexArray
screenQuadMat *materials.Material screenQuadMat *materials.Material
@ -115,6 +141,7 @@ var (
containerMat *materials.Material containerMat *materials.Material
palleteMat *materials.Material palleteMat *materials.Material
skyboxMat *materials.Material skyboxMat *materials.Material
depthMapMat *materials.Material
debugDepthMat *materials.Material debugDepthMat *materials.Material
cubeMesh *meshes.Mesh cubeMesh *meshes.Mesh
@ -124,8 +151,8 @@ var (
cubeModelMat = gglm.NewTrMatId() cubeModelMat = gglm.NewTrMatId()
drawSkybox = true renderSkybox = true
debugDrawDepthBuffer bool renderDepthBuffer bool
skyboxCmap assets.Cubemap skyboxCmap assets.Cubemap
@ -136,9 +163,9 @@ var (
// Lights // Lights
dirLight = DirLight{ dirLight = DirLight{
Dir: *gglm.NewVec3(0, -0.8, 0.2).Normalize(), Dir: *gglm.NewVec3(0.57735, -0.57735, 0.57735).Normalize(),
DiffuseColor: *gglm.NewVec3(0, 0, 0), DiffuseColor: *gglm.NewVec3(1, 1, 1),
SpecularColor: *gglm.NewVec3(0, 0, 0), SpecularColor: *gglm.NewVec3(1, 1, 1),
} }
pointLights = [...]PointLight{ pointLights = [...]PointLight{
{ {
@ -236,7 +263,8 @@ func (g *Game) handleWindowEvents(e sdl.Event) {
g.WinHeight = e.Data2 g.WinHeight = e.Data2
cam.AspectRatio = float32(g.WinWidth) / float32(g.WinHeight) cam.AspectRatio = float32(g.WinWidth) / float32(g.WinHeight)
updateProjViewMat() cam.Update()
updateAllProjViewMats(cam.ProjMat, cam.ViewMat)
} }
} }
} }
@ -351,8 +379,8 @@ func (g *Game) Init() {
// Create materials and assign any unused texture slots to black // Create materials and assign any unused texture slots to black
// //
screenQuadMat = materials.NewMaterial("Screen Quad Mat", "./res/shaders/screen-quad.glsl") screenQuadMat = materials.NewMaterial("Screen Quad Mat", "./res/shaders/screen-quad.glsl")
screenQuadMat.SetUnifVec2("scale", fboScale) screenQuadMat.SetUnifVec2("scale", demoFboScale)
screenQuadMat.SetUnifVec2("offset", fboOffset) screenQuadMat.SetUnifVec2("offset", demoFboOffset)
screenQuadMat.SetUnifInt32("material.diffuse", int32(materials.TextureSlot_Diffuse)) screenQuadMat.SetUnifInt32("material.diffuse", int32(materials.TextureSlot_Diffuse))
unlitMat = materials.NewMaterial("Unlit mat", "./res/shaders/simple-unlit.glsl") unlitMat = materials.NewMaterial("Unlit mat", "./res/shaders/simple-unlit.glsl")
@ -373,6 +401,7 @@ func (g *Game) Init() {
whiteMat.SetUnifVec3("dirLight.dir", &dirLight.Dir) whiteMat.SetUnifVec3("dirLight.dir", &dirLight.Dir)
whiteMat.SetUnifVec3("dirLight.diffuseColor", &dirLight.DiffuseColor) whiteMat.SetUnifVec3("dirLight.diffuseColor", &dirLight.DiffuseColor)
whiteMat.SetUnifVec3("dirLight.specularColor", &dirLight.SpecularColor) whiteMat.SetUnifVec3("dirLight.specularColor", &dirLight.SpecularColor)
whiteMat.SetUnifInt32("dirLight.shadowMap", int32(materials.TextureSlot_ShadowMap))
containerMat = materials.NewMaterial("Container mat", "./res/shaders/simple.glsl") containerMat = materials.NewMaterial("Container mat", "./res/shaders/simple.glsl")
containerMat.Shininess = 64 containerMat.Shininess = 64
@ -389,6 +418,7 @@ func (g *Game) Init() {
containerMat.SetUnifVec3("dirLight.dir", &dirLight.Dir) containerMat.SetUnifVec3("dirLight.dir", &dirLight.Dir)
containerMat.SetUnifVec3("dirLight.diffuseColor", &dirLight.DiffuseColor) containerMat.SetUnifVec3("dirLight.diffuseColor", &dirLight.DiffuseColor)
containerMat.SetUnifVec3("dirLight.specularColor", &dirLight.SpecularColor) containerMat.SetUnifVec3("dirLight.specularColor", &dirLight.SpecularColor)
containerMat.SetUnifInt32("dirLight.shadowMap", int32(materials.TextureSlot_ShadowMap))
palleteMat = materials.NewMaterial("Pallete mat", "./res/shaders/simple.glsl") palleteMat = materials.NewMaterial("Pallete mat", "./res/shaders/simple.glsl")
palleteMat.Shininess = 64 palleteMat.Shininess = 64
@ -404,9 +434,12 @@ func (g *Game) Init() {
palleteMat.SetUnifFloat32("material.shininess", palleteMat.Shininess) palleteMat.SetUnifFloat32("material.shininess", palleteMat.Shininess)
palleteMat.SetUnifVec3("dirLight.diffuseColor", &dirLight.DiffuseColor) palleteMat.SetUnifVec3("dirLight.diffuseColor", &dirLight.DiffuseColor)
palleteMat.SetUnifVec3("dirLight.specularColor", &dirLight.SpecularColor) palleteMat.SetUnifVec3("dirLight.specularColor", &dirLight.SpecularColor)
palleteMat.SetUnifInt32("dirLight.shadowMap", int32(materials.TextureSlot_ShadowMap))
debugDepthMat = materials.NewMaterial("Debug depth mat", "./res/shaders/debug-depth.glsl") debugDepthMat = materials.NewMaterial("Debug depth mat", "./res/shaders/debug-depth.glsl")
depthMapMat = materials.NewMaterial("Depth Map mat", "./res/shaders/depth-map.glsl")
skyboxMat = materials.NewMaterial("Skybox mat", "./res/shaders/skybox.glsl") skyboxMat = materials.NewMaterial("Skybox mat", "./res/shaders/skybox.glsl")
skyboxMat.CubemapTex = skyboxCmap.TexID skyboxMat.CubemapTex = skyboxCmap.TexID
skyboxMat.SetUnifInt32("skybox", int32(materials.TextureSlot_Cubemap)) skyboxMat.SetUnifInt32("skybox", int32(materials.TextureSlot_Cubemap))
@ -425,9 +458,13 @@ func (g *Game) Init() {
screenQuadVao = buffers.NewVertexArray() screenQuadVao = buffers.NewVertexArray()
screenQuadVao.AddVertexBuffer(screenQuadVbo) screenQuadVao.AddVertexBuffer(screenQuadVbo)
// Fbos and lights
g.initFbos() g.initFbos()
g.updateLights() g.updateLights()
updateProjViewMat()
// Initial camera update
cam.Update()
updateAllProjViewMats(cam.ProjMat, cam.ViewMat)
} }
func (g *Game) initFbos() { func (g *Game) initFbos() {
@ -460,6 +497,12 @@ func (g *Game) initFbos() {
func (g *Game) updateLights() { func (g *Game) updateLights() {
// Directional light
whiteMat.ShadowMap = depthMapFbo.Attachments[0].Id
containerMat.ShadowMap = depthMapFbo.Attachments[0].Id
palleteMat.ShadowMap = depthMapFbo.Attachments[0].Id
// Point lights
for i := 0; i < len(pointLights); i++ { for i := 0; i < len(pointLights); i++ {
pl := &pointLights[i] pl := &pointLights[i]
@ -490,6 +533,7 @@ func (g *Game) updateLights() {
palleteMat.SetUnifFloat32(indexString+".quadratic", pl.Quadratic) palleteMat.SetUnifFloat32(indexString+".quadratic", pl.Quadratic)
} }
// Spotlights
for i := 0; i < len(spotLights); i++ { for i := 0; i < len(spotLights); i++ {
l := &spotLights[i] l := &spotLights[i]
@ -553,10 +597,12 @@ func (g *Game) showDebugWindow() {
// Camera // Camera
imgui.Text("Camera") imgui.Text("Camera")
if imgui.DragFloat3("Cam Pos", &cam.Pos.Data) { if imgui.DragFloat3("Cam Pos", &cam.Pos.Data) {
updateProjViewMat() cam.Update()
updateAllProjViewMats(cam.ProjMat, cam.ViewMat)
} }
if imgui.DragFloat3("Cam Forward", &cam.Forward.Data) { if imgui.DragFloat3("Cam Forward", &cam.Forward.Data) {
updateProjViewMat() cam.Update()
updateAllProjViewMats(cam.ProjMat, cam.ViewMat)
} }
imgui.Spacing() imgui.Spacing()
@ -572,17 +618,6 @@ func (g *Game) showDebugWindow() {
imgui.Spacing() imgui.Spacing()
// Specular
imgui.Text("Specular Settings")
if imgui.DragFloat("Specular Shininess", &whiteMat.Shininess) {
whiteMat.SetUnifFloat32("material.shininess", whiteMat.Shininess)
containerMat.SetUnifFloat32("material.shininess", whiteMat.Shininess)
palleteMat.SetUnifFloat32("material.shininess", whiteMat.Shininess)
}
imgui.Spacing()
// Directional light // Directional light
imgui.Text("Directional Light") imgui.Text("Directional Light")
@ -604,6 +639,22 @@ func (g *Game) showDebugWindow() {
palleteMat.SetUnifVec3("dirLight.specularColor", &dirLight.SpecularColor) palleteMat.SetUnifVec3("dirLight.specularColor", &dirLight.SpecularColor)
} }
imgui.DragFloat("dSize", &dSize)
imgui.DragFloat("dNear", &dNear)
imgui.DragFloat("dFar", &dFar)
imgui.DragFloat3("dPos", &dPos.Data)
imgui.Spacing()
// Specular
imgui.Text("Specular Settings")
if imgui.DragFloat("Specular Shininess", &whiteMat.Shininess) {
whiteMat.SetUnifFloat32("material.shininess", whiteMat.Shininess)
containerMat.SetUnifFloat32("material.shininess", whiteMat.Shininess)
palleteMat.SetUnifFloat32("material.shininess", whiteMat.Shininess)
}
imgui.Spacing() imgui.Spacing()
// Point lights // Point lights
@ -700,25 +751,24 @@ func (g *Game) showDebugWindow() {
imgui.EndListBox() imgui.EndListBox()
} }
// Fbo // Demo fbo
imgui.Text("Framebuffer") imgui.Text("Demo Framebuffer")
imgui.Checkbox("Render to demo FBO", &renderToDemoFbo)
imgui.DragFloat2("Scale##0", &demoFboScale.Data)
imgui.DragFloat2("Offset##0", &demoFboOffset.Data)
imgui.Checkbox("Render to FBO", &renderToFbo) // Depth map fbo
imgui.Checkbox("Render Directly", &fboRenderDirectly) imgui.Text("Depth Map Framebuffer")
imgui.Checkbox("Render to depth map FBO", &renderToDepthMapFbo)
if imgui.DragFloat2("Scale", &fboScale.Data) { imgui.DragFloat2("Scale##1", &depthMapFboScale.Data)
screenQuadMat.SetUnifVec2("scale", fboScale) imgui.DragFloat2("Offset##1", &depthMapFboOffset.Data)
}
if imgui.DragFloat2("Offset", &fboOffset.Data) {
screenQuadMat.SetUnifVec2("offset", fboOffset)
}
// Other // Other
imgui.Text("Other Settings") imgui.Text("Other Settings")
imgui.Checkbox("Draw Skybox", &drawSkybox) imgui.Checkbox("Render skybox", &renderSkybox)
imgui.Checkbox("Debug depth buffer", &debugDrawDepthBuffer) imgui.Checkbox("Render to back buffer", &renderToBackBuffer)
imgui.Checkbox("Render depth buffer", &renderDepthBuffer)
imgui.End() imgui.End()
} }
@ -746,7 +796,7 @@ func (g *Game) updateCameraLookAround() {
// Update cam forward // Update cam forward
cam.UpdateRotation(pitch, yaw) cam.UpdateRotation(pitch, yaw)
updateProjViewMat() updateAllProjViewMats(cam.ProjMat, cam.ViewMat)
} }
func (g *Game) updateCameraPos() { func (g *Game) updateCameraPos() {
@ -777,45 +827,92 @@ func (g *Game) updateCameraPos() {
} }
if update { if update {
updateProjViewMat() cam.Update()
updateAllProjViewMats(cam.ProjMat, cam.ViewMat)
} }
} }
func (g *Game) Render() { func (g *Game) Render() {
if !renderToFbo { dirLightProjViewMat := dirLight.GetProjViewMat()
g.RenderScene()
return // Set some uniforms
whiteMat.SetUnifVec3("camPos", &cam.Pos)
whiteMat.SetUnifMat4("dirLightProjViewMat", &dirLightProjViewMat)
containerMat.SetUnifVec3("camPos", &cam.Pos)
containerMat.SetUnifMat4("dirLightProjViewMat", &dirLightProjViewMat)
palleteMat.SetUnifVec3("camPos", &cam.Pos)
palleteMat.SetUnifMat4("dirLightProjViewMat", &dirLightProjViewMat)
depthMapMat.SetUnifMat4("projViewMat", &dirLightProjViewMat)
// Render depth map for shadows
depthMapFbo.BindWithViewport()
depthMapFbo.Clear()
g.RenderScene(depthMapMat)
depthMapFbo.UnBindWithViewport(uint32(g.WinWidth), uint32(g.WinHeight))
if renderToDepthMapFbo {
screenQuadMat.DiffuseTex = depthMapFbo.Attachments[0].Id
screenQuadMat.SetUnifVec2("offset", depthMapFboOffset)
screenQuadMat.SetUnifVec2("scale", depthMapFboScale)
screenQuadMat.Bind()
window.Rend.DrawVertexArray(screenQuadMat, &screenQuadVao, 0, 6)
} }
demoFbo.Bind() if renderToBackBuffer {
demoFbo.Clear()
g.RenderScene()
demoFbo.UnBind()
if fboRenderDirectly { if renderDepthBuffer {
g.RenderScene() g.RenderScene(debugDepthMat)
} else {
g.RenderScene(nil)
}
} }
screenQuadMat.DiffuseTex = demoFbo.Attachments[0].Id if renderSkybox {
window.Rend.DrawVertexArray(screenQuadMat, &screenQuadVao, 0, 6) g.DrawSkybox()
}
if renderToDemoFbo {
demoFbo.Bind()
demoFbo.Clear()
if renderDepthBuffer {
g.RenderScene(debugDepthMat)
} else {
g.RenderScene(nil)
}
if renderSkybox {
g.DrawSkybox()
}
demoFbo.UnBind()
screenQuadMat.DiffuseTex = demoFbo.Attachments[0].Id
screenQuadMat.SetUnifVec2("offset", demoFboOffset)
screenQuadMat.SetUnifVec2("scale", demoFboScale)
window.Rend.DrawVertexArray(screenQuadMat, &screenQuadVao, 0, 6)
}
} }
func (g *Game) RenderScene() { func (g *Game) RenderScene(overrideMat *materials.Material) {
tempModelMatrix := cubeModelMat.Clone() tempModelMatrix := cubeModelMat.Clone()
whiteMat.SetUnifVec3("camPos", &cam.Pos) // See if we need overrides
containerMat.SetUnifVec3("camPos", &cam.Pos)
palleteMat.SetUnifVec3("camPos", &cam.Pos)
sunMat := palleteMat sunMat := palleteMat
chairMat := palleteMat chairMat := palleteMat
cubeMat := containerMat cubeMat := containerMat
if debugDrawDepthBuffer {
sunMat = debugDepthMat if overrideMat != nil {
chairMat = debugDepthMat sunMat = overrideMat
cubeMat = debugDepthMat chairMat = overrideMat
cubeMat = overrideMat
} }
// Draw dir light // Draw dir light
@ -843,10 +940,6 @@ func (g *Game) RenderScene() {
} }
tempModelMatrix.Translate(gglm.NewVec3(float32(rowSize), -1, 0)) tempModelMatrix.Translate(gglm.NewVec3(float32(rowSize), -1, 0))
} }
if drawSkybox {
g.DrawSkybox()
}
} }
func (g *Game) DrawSkybox() { func (g *Game) DrawSkybox() {
@ -867,12 +960,9 @@ func (g *Game) DeInit() {
g.Win.Destroy() g.Win.Destroy()
} }
func updateProjViewMat() { func updateAllProjViewMats(projMat, viewMat gglm.Mat4) {
cam.Update() projViewMat := projMat.Clone().Mul(&viewMat)
projViewMat := cam.ProjMat.Clone()
projViewMat.Mul(&cam.ViewMat)
unlitMat.SetUnifMat4("projViewMat", projViewMat) unlitMat.SetUnifMat4("projViewMat", projViewMat)
whiteMat.SetUnifMat4("projViewMat", projViewMat) whiteMat.SetUnifMat4("projViewMat", projViewMat)
@ -881,14 +971,13 @@ func updateProjViewMat() {
debugDepthMat.SetUnifMat4("projViewMat", projViewMat) debugDepthMat.SetUnifMat4("projViewMat", projViewMat)
// Update skybox projViewMat // Update skybox projViewMat
viewMat := cam.ViewMat.Clone() skyboxViewMat := viewMat.Clone()
viewMat.Set(0, 3, 0) skyboxViewMat.Set(0, 3, 0)
viewMat.Set(1, 3, 0) skyboxViewMat.Set(1, 3, 0)
viewMat.Set(2, 3, 0) skyboxViewMat.Set(2, 3, 0)
viewMat.Set(3, 0, 0) skyboxViewMat.Set(3, 0, 0)
viewMat.Set(3, 1, 0) skyboxViewMat.Set(3, 1, 0)
viewMat.Set(3, 2, 0) skyboxViewMat.Set(3, 2, 0)
viewMat.Set(3, 3, 0) skyboxViewMat.Set(3, 3, 0)
skyboxMat.SetUnifMat4("projViewMat", cam.ProjMat.Clone().Mul(viewMat)) skyboxMat.SetUnifMat4("projViewMat", projMat.Clone().Mul(skyboxViewMat))
} }

View File

@ -11,11 +11,12 @@ import (
type TextureSlot uint32 type TextureSlot uint32
const ( const (
TextureSlot_Diffuse TextureSlot = 0 TextureSlot_Diffuse TextureSlot = 0
TextureSlot_Specular TextureSlot = 1 TextureSlot_Specular TextureSlot = 1
TextureSlot_Normal TextureSlot = 2 TextureSlot_Normal TextureSlot = 2
TextureSlot_Emission TextureSlot = 3 TextureSlot_Emission TextureSlot = 3
TextureSlot_Cubemap TextureSlot = 10 TextureSlot_Cubemap TextureSlot = 10
TextureSlot_ShadowMap TextureSlot = 11
) )
type Material struct { type Material struct {
@ -36,6 +37,9 @@ type Material struct {
// Cubemap // Cubemap
CubemapTex uint32 CubemapTex uint32
// Shadowmaps
ShadowMap uint32
} }
func (m *Material) Bind() { func (m *Material) Bind() {
@ -66,6 +70,11 @@ func (m *Material) Bind() {
gl.ActiveTexture(uint32(gl.TEXTURE0 + TextureSlot_Cubemap)) gl.ActiveTexture(uint32(gl.TEXTURE0 + TextureSlot_Cubemap))
gl.BindTexture(gl.TEXTURE_CUBE_MAP, m.CubemapTex) gl.BindTexture(gl.TEXTURE_CUBE_MAP, m.CubemapTex)
} }
if m.ShadowMap != 0 {
gl.ActiveTexture(uint32(gl.TEXTURE0 + TextureSlot_ShadowMap))
gl.BindTexture(gl.TEXTURE_2D, m.ShadowMap)
}
} }
func (m *Material) UnBind() { func (m *Material) UnBind() {

21
res/shaders/depth-map.glsl Executable file
View File

@ -0,0 +1,21 @@
//shader:vertex
#version 410
layout(location=0) in vec3 vertPosIn;
uniform mat4 modelMat;
uniform mat4 projViewMat;
void main()
{
gl_Position = projViewMat * modelMat * vec4(vertPosIn, 1);
}
//shader:fragment
#version 410
void main()
{
// This implicitly writes to the depth buffer with no color operations
// Equivalent: gl_FragDepth = gl_FragCoord.z;
}

View File

@ -10,10 +10,11 @@ out vec3 vertNormal;
out vec2 vertUV0; out vec2 vertUV0;
out vec3 vertColor; out vec3 vertColor;
out vec3 fragPos; out vec3 fragPos;
out vec4 fragPosDirLight;
//MVP = Model View Projection
uniform mat4 modelMat; uniform mat4 modelMat;
uniform mat4 projViewMat; uniform mat4 projViewMat;
uniform mat4 dirLightProjViewMat;
void main() void main()
{ {
@ -22,12 +23,15 @@ void main()
// This produces the normal matrix that multiplies with the model normal to produce the // This produces the normal matrix that multiplies with the model normal to produce the
// world space normal. Based on 'One last thing' section from: https://learnopengl.com/Lighting/Basic-Lighting // world space normal. Based on 'One last thing' section from: https://learnopengl.com/Lighting/Basic-Lighting
vertNormal = mat3(transpose(inverse(modelMat))) * vertNormalIn; vertNormal = mat3(transpose(inverse(modelMat))) * vertNormalIn;
vertNormal = mat3(transpose(inverse(modelMat))) * vertNormalIn;
vertUV0 = vertUV0In; vertUV0 = vertUV0In;
vertColor = vertColorIn; vertColor = vertColorIn;
vec4 modelVert = modelMat * vec4(vertPosIn, 1); vec4 modelVert = modelMat * vec4(vertPosIn, 1);
fragPos = modelVert.xyz; fragPos = modelVert.xyz;
fragPosDirLight = dirLightProjViewMat * vec4(fragPos, 1);
gl_Position = projViewMat * modelVert; gl_Position = projViewMat * modelVert;
} }
@ -48,6 +52,7 @@ struct DirLight {
vec3 dir; vec3 dir;
vec3 diffuseColor; vec3 diffuseColor;
vec3 specularColor; vec3 specularColor;
sampler2D shadowMap;
}; };
uniform DirLight dirLight; uniform DirLight dirLight;
@ -83,6 +88,7 @@ in vec3 vertColor;
in vec3 vertNormal; in vec3 vertNormal;
in vec2 vertUV0; in vec2 vertUV0;
in vec3 fragPos; in vec3 fragPos;
in vec4 fragPosDirLight;
out vec4 fragColor; out vec4 fragColor;
@ -93,6 +99,27 @@ vec4 emissionTexColor;
vec3 normalizedVertNorm; vec3 normalizedVertNorm;
vec3 viewDir; vec3 viewDir;
float CalcShadow(sampler2D shadowMap)
{
// Move from clip space to NDC
vec3 projCoords = fragPosDirLight.xyz / fragPosDirLight.w;
// Move from [-1,1] to [0, 1]
projCoords = projCoords * 0.5 + 0.5;
// currentDepth is the fragment depth from the light's perspective
float currentDepth = projCoords.z;
// Closest depth is the closest depth value from the light's perspective
float closestDepth = texture(shadowMap, projCoords.xy).r;
// 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;
return shadow;
}
vec3 CalcDirLight() vec3 CalcDirLight()
{ {
vec3 lightDir = normalize(-dirLight.dir); vec3 lightDir = normalize(-dirLight.dir);
@ -106,7 +133,10 @@ vec3 CalcDirLight()
float specularAmount = pow(max(dot(normalizedVertNorm, halfwayDir), 0.0), material.shininess); float specularAmount = pow(max(dot(normalizedVertNorm, halfwayDir), 0.0), material.shininess);
vec3 finalSpecular = specularAmount * dirLight.specularColor * specularTexColor.rgb; vec3 finalSpecular = specularAmount * dirLight.specularColor * specularTexColor.rgb;
return finalDiffuse + finalSpecular; // Shadow
float shadow = CalcShadow(dirLight.shadowMap);
return (finalDiffuse + finalSpecular) * (1.0 - shadow);
} }
vec3 CalcPointLight(PointLight pointLight) vec3 CalcPointLight(PointLight pointLight)