【发布时间】:2014-08-24 23:50:58
【问题描述】:
问题
一段时间以来,我一直在尝试在 OpenGL 中实现阴影。我终于让它进入半工作状态,阴影出现但在奇怪的地方覆盖了场景[即 - 它与光无关]
为了进一步解释上面的 gif:当我将光源从场景(向左)移动到更远的 远离 - 阴影延伸得更远。为什么?如果有的话,它应该显示更多的场景。
更新 - 我弄乱了灯的位置,现在得到了这个结果(令人困惑):
深度图
这里是:
代码
因为这是一个难以确定的问题 - 我将发布我在此应用程序中使用的大量代码。
帧缓冲区和深度纹理 - 我需要的第一件事是一个帧缓冲区来记录所有绘制对象的深度值,然后我需要将这些值转储到深度纹理中(阴影-地图):
// Create Framebuffer
FramebufferName = 0;
glGenFramebuffers(1, &FramebufferName);
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
// Create and Load Depth Texture
glGenTextures(1, &depthTexture);
glBindTexture(GL_TEXTURE_2D, depthTexture);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
glTexImage2D(GL_TEXTURE_2D, 0,GL_DEPTH_COMPONENT24, 1024, 1024, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);
//Attach Texture To Framebuffer
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
//Check for errors
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
Falcon::Debug::error("ShadowBuffer [Framebuffer] could not be initialized.");
渲染场景 - 首先我做阴影通道,它只通过一些基本的着色器并输出到帧缓冲区,然后我做第二个常规通道,实际绘制场景并执行 GLSL阴影贴图采样:
//Clear
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//Select Main Shader
normalShader->useShader();
//Bind + Update + Draw
/* Render Shadows */
shadowShader->useShader();
glBindFramebuffer(GL_FRAMEBUFFER, Shadows::framebuffer());
//Viewport
glViewport(0,0,640,480);
//GLM Matrix Definitions
glm::mat4 shadow_matrix_view;
glm::mat4 shadow_matrix_projection;
//View And Projection Calculations
shadow_matrix_view = glm::lookAt(glm::vec3(light.x,light.y,light.z), glm::vec3(0,0,0), glm::vec3(0,1,0));
shadow_matrix_projection = glm::perspective(45.0f, 1.0f, 0.1f, 1000.0f);
//Calculate MVP(s)
glm::mat4 shadow_depth_mvp = shadow_matrix_projection * shadow_matrix_view * glm::mat4(1.0);
glm::mat4 shadow_depth_bias = glm::mat4(0.5,0,0,0,0,0.5,0,0,0,0,0.5,0,0.5,0.5,0.5,1) * shadow_depth_mvp;
//Send Data To The GPU
glUniformMatrix4fv(glGetUniformLocation(shadowShader->getShader(),"depth_matrix"), 1, GL_FALSE, &shadow_depth_mvp[0][0]);
glUniformMatrix4fv(glGetUniformLocation(normalShader->getShader(),"depth_matrix_bias"), 1, GL_FALSE, &shadow_depth_bias[0][0]);
renderScene();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
/* Clear */
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* Shader */
normalShader->useShader();
/* Shadow-map */
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, Shadows::shadowmap());
glUniform1f(glGetUniformLocation(normalShader->getShader(),"shadowMap"),0);
/* Render Scene */
glViewport(0,0,640,480);
renderScene();
片段着色器 - 这是我计算要输出的最终颜色并进行深度纹理/阴影贴图采样的地方。这可能是我出错的根源:
//Shadows
uniform sampler2DShadow shadowMap;
in vec4 shadowCoord;
void main()
{
//Lighting Calculations...
//Shadow Sampling:
float visibility = 1.0;
if (texture(shadowMap, shadowCoord.xyz) < shadowCoord.z){
visibility = 0.1;
}
//Final Output
outColor = finalColor * visibility;
}
编辑
AMD 硬件问题 - 也有人认为这可能是 GPU 的问题,但我觉得这很难相信,因为它是 Radeon HD 6670。是否值得放入 Nvidia 卡来测试这个理论?
建议更改 - 我根据 cmets 和答案做了一些建议更改:
首先,我将灯光的透视投影更改为正交投影,这为我提供了阴影贴图中所需的精度,因此现在我可以清楚地看到深度(即 -> 它不是全白的)。此外,它消除了对透视分割的需要,因此我使用 3 维坐标进行测试。下面是截图:
其次,我将纹理采样更改为:visibility = texture(shadowMap,shadowCoord.xyz); 现在总是返回 0,因此我看不到场景,因为它被认为是完全阴影的。
第三也是最后,我按照建议从GL_LEQUAL 交换到GL_LESS,没有发生任何变化。
【问题讨论】:
-
1.我没有看到小长方体投射到地平面上的阴影——也许相机视角没有让我看到它,但你没有提到它仍然很奇怪。
-
2.我们看到的阴影是什么?
-
3.如果您的目标是 1024 平方像素,为什么要在 RTT 部分设置如此小的视口 640x480?
-
4.你的阴影贴图看起来还好吗?
-
Yeezus - 请避免这样的多个 cmet。
标签: c++ opengl c++11 glsl shadow