我一直试图在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;
}
&LT 1为卤素; AMD硬件问题 - 还有人认为这可能是GPU的一个问题,但我发现很难相信它是 Radeon HD 6670 。是否值得用一张Nvidia卡来测试这个理论?
&LT 2 - ;建议更改 - 我从评论和答案中做了一些建议的更改:
首先,我将光的透视投影改为正射投影,这使我在阴影贴图中获得了所需的精度,这样现在我可以清楚地看到深度(即 - &gt;它&#39; s不是全白)。此外,它消除了对透视分割的需要,因此我使用三维坐标来测试它。以下是截图:
其次,我将纹理采样更改为:visibility = texture(shadowMap,shadowCoord.xyz);
现在总是返回0,因此我无法看到场景,因为它被认为是完全阴影。
第三,也是最后,我从GL_LEQUAL
到GL_LESS
进行了交换,表明没有发生任何变化。
答案 0 :(得分:2)
uniform sampler2DShadow shadowMap; // NOTE: Shadow samplers perform comparison !!
...
if (texture(shadowMap, shadowCoord.xyz) < shadowCoord.z)
您启用了纹理比较与参考。这意味着3 rd 纹理坐标将由texture (...)
函数进行比较,返回的值将是测试函数的结果(GL_LEQUAL
情况)。
换句话说,texture (...)
将通过比较shadowCoord.xy
处的查找深度,返回 0.0 (失败)或 1.0 (过去)到shadowCoord.z
的值。你正在做两次这个测试。
float visibility = texture(shadowMap, shadowCoord.xyz);
这不会产生你想要的结果,因为你的比较函数是GL_LEQUAL
,但它是一个开始。考虑将比较函数更改为GL_LESS
以获得精确的函数匹配。