首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >访问GL_DEPTH_COMPONENT纹理

访问GL_DEPTH_COMPONENT纹理
EN

Stack Overflow用户
提问于 2018-01-04 08:03:57
回答 1查看 1.6K关注 0票数 2

我目前正在尝试实现屏幕空间环境遮挡。我的想法是,按照标准,使用多通道渲染,其中我使用上一遍的深度信息来计算遮挡因子。因此,在我的“安装”代码中,我创建了一个框架缓冲区和纹理对象,并将它们绑定在一起。纹理是使用GL_DEPTH_COMPONENT24作为内部格式创建的,我发出一个glDrawBuffer(GL_NONE)调用,因为我不想输出任何颜色。

此外,我有3个名为AnimatedObject的类实例,它们有自己的绘图方法,还有一个渲染类,用于在绘图时包装所有类。目前,我的渲染者做了一些类似于

代码语言:javascript
复制
drawIntoDepthBuffer(); 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
drawOntoScreen();

在上面的片段中,drawIntoDepthBuffer()使用我的深度缓冲程序,drawOntoScreen()使用主顶点和片段着色器。我现在面临的问题是:我根本无法访问我在第二次绘图调用中呈现的纹理。所有的着色器都编译和链接良好。使用深度缓冲程序绘制到屏幕产生完美的精细输出,也不使用渲染纹理在主着色器产生预期的结果。

我得到的错误是泛型OpenGL错误。

错误: OpenGL错误:无效操作(1282)

我也尝试过在主着色器中使用sampler2Dshadow制服,但在这种情况下,我真的不知道如何访问它,因为您需要一个vec3来对它进行采样,这在我的情况下是没有意义的。

以下是不同的代码片段:

“主”片段着色器:

代码语言:javascript
复制
#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);
}

深度碎片着色器:

代码语言:javascript
复制
#version 430 core

layout(location = 0) out float fragment_depth;

void main() {
    fragment_depth = gl_FragCoord.z;
}

两个阶段的顶点着色器是相同的,如下所示:

代码语言:javascript
复制
#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;
}

相应的抽签调用看起来是这样的:

代码语言:javascript
复制
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对象的设置:

代码语言:javascript
复制
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查找位置来修复它,但是我仍然不明白为什么这个问题会以一种奇怪的方式出现。首先,完全相同的代码适用于主阴影程序(顶点着色程序和调用代码完全相同),其次,当我没有使用深度纹理时,我不知道程序是如何运行的。驱动程序是否能够在以后的传递中不使用时优化整个呈现传递?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-01-04 08:20:27

基本上,您可以以与任何其他纹理相同的方式访问深度地图。但是,虽然gl_FragCoord.xy提供窗口坐标,但texture需要范围为0.0、1.0的浮点坐标。

如果深度图的大小与视口的大小相等(在您的情况下应该是这样),那么使用texelFetch

代码语言:javascript
复制
float test = texelFetch(depth_map, ivec2(gl_FragCoord.xy), 0).r;

或者你必须除以纹理的大小(textureSize):

代码语言:javascript
复制
float test = texture(depth_map, gl_FragCoord.xy / textureSize(depth_map, 0)).r;

注意,如果深度图的大小与视口大小不相等,则必须将视口大小作为统一变量提供:

代码语言:javascript
复制
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

代码语言:javascript
复制
void main( void )
{
}

注意,如果您想设置片段深度显式体,那么您必须写到gl_FragDepth。默认情况下,将z组件的gl_FragCoord分配给gl_FragDepth

代码语言:javascript
复制
void main( void )
{
    gl_FragDepth = gl_FragCoord.z;
}

此外,如果为统一变量设置值,则必须先安装当前程序(glUseProgram) ,然后才能设置统一变量(glUniformMatrix4fv),因为glUniform*为当前程序对象指定统一变量的值。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48091045

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档