前言
我们模拟了光照,发现真的很厉害,加上天空盒子,再加上反射感觉很逼真,但是看着看着你会发现。。不对,没影子。是的,光和影分不开的,有光的地方就会有影子,这才是真实的道理。怎么模拟影子呢?这就要用到前面学到的,帧缓冲-写入纹理。
阴影产生的原因如图,就是因为同一条射线上里的光近的物体挡住了离的远的物体。
我们如何判断一个物体是否在阴影中呢?就是按照图上的,Z Distance也就是在光源方向上的空间来看的。这些Z表示深度,也就是距离光源的距离,如果我们从光源的透视图来渲染场景,并把深度值的结果储存到纹理中会怎样?通过这种方式,我们就能对光源的透视图所见的最近的深度值进行采样。最终,深度值就会显示从光源的透视图下见到的第一个片元了。我们管储存在纹理中的所有这些深度值,叫做深度贴图(depth map)或阴影贴图。
定向光产生的阴影
// 1. Render depth of scene to texture (from light's perspective)
// - Get light projection/view matrix.
glCullFace(GL_FRONT);
glm::mat4 lightProjection, lightView;
glm::mat4 lightSpaceMatrix;
GLfloat near_plane = 1.0f, far_plane = 7.5f;
// lightProjection = glm::perspective(glm::radians(45.0f), (GLfloat)SHADOW_WIDTH / (GLfloat)SHADOW_HEIGHT, near_plane, far_plane);
lightProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, near_plane, far_plane);
lightView = glm::lookAt(lightPos, glm::vec3(0.0f), glm::vec3(0.0, 1.0, 0.0));
lightSpaceMatrix = lightProjection * lightView;
// - render scene from light's point of view
simpleDepthShader.use();
glUniformMatrix4fv(glGetUniformLocation(simpleDepthShader.ID, "lightSpaceMatrix"), 1, GL_FALSE, glm::value_ptr(lightSpaceMatrix));
glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
glClear(GL_DEPTH_BUFFER_BIT);
RenderScene(simpleDepthShader);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Reset viewport
glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glCullFace(GL_BACK);
// 2. render scene as normal using the generated depth/shadow map
// --------------------------------------------------------------
glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shader.use();
glm