使用带有延迟渲染 Opengl 3.3 的阴影贴图的问题

Posted

技术标签:

【中文标题】使用带有延迟渲染 Opengl 3.3 的阴影贴图的问题【英文标题】:Problems with using a shadow map with deferred rendering Opengl 3.3 【发布时间】:2018-06-08 00:49:01 【问题描述】:

我正在尝试为我正在进行的项目实现简单的阴影映射。我可以将深度纹理渲染到屏幕上,所以我知道它就在那里,问题是当我使用阴影纹理坐标对阴影贴图进行采样时,似乎坐标已关闭。

这是我的光空间矩阵计算

mat4x4 lightViewMatrix;

vec3 sun_pos = SUN_OFFSET  * the_sun->direction[0],
                SUN_OFFSET  * the_sun->direction[1],
                SUN_OFFSET  * the_sun->direction[2];

mat4x4_look_at(lightViewMatrix,sun_pos,player->pos,up);

mat4x4_mul(lightSpaceMatrix,lightProjMatrix,lightViewMatrix);

我将调整阴影贴图的大小和截锥体的值,但现在我只想在玩家位置周围绘制阴影

the_sun->direction 是一个归一化向量,所以我将它乘以一个常数来得到位置。

player->pos 是世界空间中的相机位置

光投影矩阵是这样计算的:

 mat4x4_ortho(lightProjMatrix,-SHADOW_FAR,SHADOW_FAR,-SHADOW_FAR,SHADOW_FAR,NEAR,SHADOW_FAR);

阴影顶点着色器:

uniform mat4 light_space_matrix;

 void main()
 
     gl_Position = light_space_matrix * transfMatrix * vec4(position, 1.0f); 
 

阴影片段着色器:

out float fragDepth;
void main()

    fragDepth = gl_FragCoord.z;

我正在使用 延迟渲染,所以我的所有世界位置都在 g_positions 缓冲区中

我在延迟片段着色器中的阴影计算:

float get_shadow_fac(vec4 light_space_pos)

    vec3 shadow_coords = light_space_pos.xyz / light_space_pos.w;
    shadow_coords      = shadow_coords * 0.5 + 0.5;

    float closest_depth = texture(shadow_map, shadow_coords.xy).r;
    float current_depth = shadow_coords.z;

    float shadow_fac = 1.0;

    if(closest_depth < current_depth)
       shadow_fac   = 0.5;

    return shadow_fac;
 

我这样调用函数:

get_shadow_fac(light_space_matrix * vec4(position,1.0));

position 是我从 g_position 缓冲区中采样得到的值

这是我的深度纹理(我知道它会产生低质量的阴影,但我现在只想让它工作):

对不起,因为压缩,黑色的污迹是树... https://i.stack.imgur.com/T43aK.jpg

编辑:深度纹理附件:

glTexImage2D(GL_TEXTURE_2D, 0,GL_DEPTH_COMPONENT24,fbo->width,fbo->height,0,GL_DEPTH_COMPONENT,GL_FLOAT,NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, fbo->depthTexture, 0);

【问题讨论】:

【参考方案1】:

我发现了问题所在,我的 g_positions 缓冲区纹理具有 GL_RGBA8 的内部格式,并且太小而无法在世界空间中保存位置

glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,fbo->width,fbo->height,0,GL_RGBA,GL_UNSIGNED_BYTE,NULL);

所以当我改成

glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA32F,fbo->width,fbo->height,0,GL_RGB,GL_FLOAT,NULL);

阴影出现了:D

【讨论】:

在 gbuffer 中存储世界空间位置是对内存带宽的巨大浪费。您只需要窗口空间 z(深度缓冲区,无论如何都要使用),您可以轻松地取消投影回世界空间。 呵呵,我在研究如何解决这个问题时读过一些关于它的东西,但从未想过它。感谢您提及它,我会尽快实施。

以上是关于使用带有延迟渲染 Opengl 3.3 的阴影贴图的问题的主要内容,如果未能解决你的问题,请参考以下文章

带有立方体贴图的 OpenGL 点光阴影映射

OpenGL 阴影贴图

✠OpenGL-8-阴影

Linux OpenGL 实践篇-11-shadow

使用立方体贴图(OpenGL/GLSL)的点光源是不是可以实现软阴影?

OpenGL:渲染天空盒立方体贴图问题