我目前正在尝试实现屏幕空间环境遮挡。我的想法是,按照标准,使用多通道渲染,其中我使用上一遍的深度信息来计算遮挡因子。因此,在我的“安装”代码中,我创建了一个框架缓冲区和纹理对象,并将它们绑定在一起。纹理是使用GL_DEPTH_COMPONENT24作为内部格式创建的,我发出一个glDrawBuffer(GL_NONE)调用,因为我不想输出任何颜色。
此外,我有3个名为AnimatedObject的类实例,它们有自己的绘图方法,还有一个渲染类,用于在绘图时包装所有类。目前,我的渲染者做了一些类似于
drawIntoDepthBuffer();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
drawOntoScreen();在上面的片段中,drawIntoDepthBuffer()使用我的深度缓冲程序,drawOntoScreen()使用主顶点和片段着色器。我现在面临的问题是:我根本无法访问我在第二次绘图调用中呈现的纹理。所有的着色器都编译和链接良好。使用深度缓冲程序绘制到屏幕产生完美的精细输出,也不使用渲染纹理在主着色器产生预期的结果。
我得到的错误是泛型OpenGL错误。
错误: OpenGL错误:无效操作(1282)
我也尝试过在主着色器中使用sampler2Dshadow制服,但在这种情况下,我真的不知道如何访问它,因为您需要一个vec3来对它进行采样,这在我的情况下是没有意义的。
以下是不同的代码片段:
“主”片段着色器:
#version 430 core
layout (binding = 0) uniform sampler2D texture_main;
layout (binding = 1) uniform sampler2D depth_map;
in vec3 normal;
in vec2 uv;
out vec4 outColor;
void main()
{
float test = texture(depth_map, gl_FragCoord.xy / textureSize(depth_map, 0)).r; //<---- this fails
float lambert = clamp(dot(normalize(normal), normalize(vec3(-0.5,1,1))), 0.2f, 1);
outColor = test * lambert * texture(texture_main, uv);
}深度碎片着色器:
#version 430 core
layout(location = 0) out float fragment_depth;
void main() {
fragment_depth = gl_FragCoord.z;
}两个阶段的顶点着色器是相同的,如下所示:
#version 430 core
layout (location = 0) in vec3 inPos;
layout (location = 1) in vec3 inNormal;
layout (location = 2) in vec2 inUv;
uniform mat4 mvp;
out vec3 normal;
out vec2 uv;
void main()
{
gl_Position = mvp * inPos;
normal = inverse(transpose(mvp)) * inNormal;
uv = inUv;
}相应的抽签调用看起来是这样的:
void draw_screen(GLuint depth_texture)
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glUseProgram(main_program);
glActiveTexture(GL_TEXTURE0 + 1);
glBindTexture(GL_TEXTURE_2D, depth_texture);
for (const auto& surface : surfaces)
{
glActiveTexture(GL_TEXTURE0));
glBindTexture(GL_TEXTURE_2D, surface);
glDrawArrays(GL_TRIANGLES, pos, count);
pos += pos_increment;
}
}
void draw_depth(GLuint framebuffer_id)
{
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_id);
glUseProgram(depth_program);
for (const auto& surface : surfaces)
{
glBindTexture(GL_TEXTURE_2D, surface);
glDrawArrays(GL_TRIANGLES, pos, count);
pos += pos_increment;
}
}下面是framebuffer对象的设置:
glGenFramebuffers(1, &depth_framebuffer_id);
glBindFramebuffer(GL_FRAMEBUFFER, depth_framebuffer_id);
glGenTextures(1, &depth_texture_id);
glBindTexture(GL_TEXTURE_2D, depth_texture_id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, viewport_width, viewport_height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depth_texture_id, 0);
glDrawBuffer(GL_NONE);我很抱歉有这么多代码,但这正是它需要将所有这些联系在一起的原因。任何帮助都将不胜感激。
编辑:在摆弄了几个小时后,我发现这个错误是通过调用glUniformMatrix4fv(location_mvp, 1, GL_TRUE, mvp._m) (顾名思义)来产生的,它设置了MVP矩阵统一。当我注释掉这一行时,depth_map采样器可以从纹理中读取(但它显然只包含垃圾值)。另一方面,如果我加入这一行,只有当我不访问depth_map采样器时,代码才能工作。这可能是什么原因?
嗯,似乎mvp矩阵的位置在第一次运行阴影程序后发生了变化。它可以很好地呈现第一个对象,但是当要呈现第二个对象时,会弹出错误。我只是通过使用glGetUniformLocation查找位置来修复它,但是我仍然不明白为什么这个问题会以一种奇怪的方式出现。首先,完全相同的代码适用于主阴影程序(顶点着色程序和调用代码完全相同),其次,当我没有使用深度纹理时,我不知道程序是如何运行的。驱动程序是否能够在以后的传递中不使用时优化整个呈现传递?
发布于 2018-01-04 08:20:27
基本上,您可以以与任何其他纹理相同的方式访问深度地图。但是,虽然gl_FragCoord.xy提供窗口坐标,但texture需要范围为0.0、1.0的浮点坐标。
如果深度图的大小与视口的大小相等(在您的情况下应该是这样),那么使用texelFetch
float test = texelFetch(depth_map, ivec2(gl_FragCoord.xy), 0).r;或者你必须除以纹理的大小(textureSize):
float test = texture(depth_map, gl_FragCoord.xy / textureSize(depth_map, 0)).r;注意,如果深度图的大小与视口大小不相等,则必须将视口大小作为统一变量提供:
uniform vec2 vp_size;
float test = texture(depth_map, gl_FragCoord.xy / vp_size).r;请参阅GLSL - OpenGL阴影语言- 4.4.1.3片段着色器输入,第65页
4.4.1.3片段着色器输入 默认情况下,gl_FragCoord假设窗口坐标的左下角,并假定像素中心位于半像素坐标。
延长答复:
第一关是“深度唯一”的传球。你不附加任何颜色平面到框架缓冲区,所以你不应该写到任何彩色平面,在片段着色器,也。您必须使用空的main
void main( void )
{
}注意,如果您想设置片段深度显式体,那么您必须写到gl_FragDepth。默认情况下,将z组件的gl_FragCoord分配给gl_FragDepth:
void main( void )
{
gl_FragDepth = gl_FragCoord.z;
}此外,如果为统一变量设置值,则必须先安装当前程序(glUseProgram) ,然后才能设置统一变量(glUniformMatrix4fv),因为glUniform*为当前程序对象指定统一变量的值。
https://stackoverflow.com/questions/48091045
复制相似问题