【问题标题】:Deferred Shading OpenGL implementation延迟着色 OpenGL 实现
【发布时间】:2016-09-04 14:23:32
【问题描述】:

我目前正在尝试在 OpenGL 3.2 中实现延迟着色,并且遇到了一个无论我如何尝试都无法解决的问题。

我按照预期分两步(几何传递和光照传递)实现了它。编译并运行它后,屏幕显示了我准备的场景,几乎就像人们期望的那样。物体的颜色是正确的,它们也被放置在我想要的位置和位置。

问题是,光线计算似乎对颜色没有影响,无论如何。很多小时后,我发现位置和法线的纹理似乎包含与颜色纹理相同的内容。

如果将光照片段着色器中的最后一行从fragColor = lightIntensity * color; 更改为fragColor = lightIntensity * norm;fragColor = lightIntensity * pos;,它绝对不会影响屏幕的渲染方式。

我已经尝试了很多来找出问题所在,但老实说不知道它可能是什么。
如果有人可以帮助我,那就太好了。

我的渲染方法如下所示:

void render()
{

    //geometry pass
    gBuffer->bindForWriting();
    geometryShader->use(true);
    calculateGBuffer();


    //lighting pass 
    gBuffer->bindForReading(lightShader->programID());
    lightShader->use(true);
    drawOnScreen();

}

gBuffer对象的初始化是这样的:

void GBuffer::initializeFBO(int viewWidth, int viewHeight)
{

    //initialize fbo and corresponding textures;
    glGenFramebuffers(1, &fbo_ID);
    glBindFramebuffer(GL_FRAMEBUFFER, fbo_ID);

    glGenTextures(1, &colorTexture_ID);
    glBindTexture(GL_TEXTURE_2D, colorTexture_ID);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, viewWidth, viewHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture_ID, 0);

    glGenTextures(1, &posTexture_ID);
    glBindTexture(GL_TEXTURE_2D, posTexture_ID);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, viewWidth, viewHeight, 0, GL_RGB, GL_FLOAT, NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, posTexture_ID, 0);

    glGenTextures(1, &normTexture_ID);
    glBindTexture(GL_TEXTURE_2D, normTexture_ID);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, viewWidth, viewHeight, 0, GL_RGB, GL_FLOAT, NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, normTexture_ID, 0);

    GLuint attachments[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
    glDrawBuffers(3, attachments);

    glGenRenderbuffers(1, &depthBuffer_ID);
    glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer_ID);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, viewWidth, viewHeight);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer_ID);



    //Check Status
    if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
        qDebug() << "error while initializing framebuffer" << glCheckFramebufferStatus(GL_FRAMEBUFFER);
    else{
        qDebug() << "framebuffer successfully created";
        initialized = true;
    }

    glBindFramebuffer(GL_FRAMEBUFFER, 0);

}

bindForReadingbindForWriting 方法:

void GBuffer::bindForWriting()
{
    glBindFramebuffer(GL_FRAMEBUFFER, fbo_ID);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}

void GBuffer::bindForReading(GLuint programID)
{
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, colorTexture_ID);
    GLuint samplerTexture_ID = glGetUniformLocation(programID, "colorTexture");
    glUniform1i(samplerTexture_ID, 0);

    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, posTexture_ID);
    samplerTexture_ID = glGetUniformLocation(programID, "positionTexture");
    glUniform1i(samplerTexture_ID, 1);

    glActiveTexture(GL_TEXTURE2);
    glBindTexture(GL_TEXTURE_2D, normTexture_ID);
    samplerTexture_ID = glGetUniformLocation(programID, "normTexture");
    glUniform1i(samplerTexture_ID, 2);

}

最后还有 4 个着色器:

几何顶点着色器:

#version 150
#extension GL_ARB_separate_shader_objects : enable
uniform mat4 MVPMatrix;
uniform mat4 modelMatrix;

in vec4 in_position;
in vec4 in_color;
in vec2 in_texcoord;
in vec3 in_norm;

out vec4 color_varying;
out vec3 frag_position;
out vec3 norm_vec;
out vec2 texcoord_varying;

void main()
{
    gl_Position = MVPMatrix * in_position;
    vec4 worldPosition = (modelMatrix * in_position);
    frag_position = worldPosition.xyz;
    norm_vec = in_norm;

    color_varying = in_color;
    texcoord_varying = in_texcoord;
}

几何片段着色器:

#version 150
#extension GL_ARB_explicit_attrib_location : enable

in vec4 color_varying;
in vec3 frag_position;
in vec3 norm_vec;
in vec2 texcoord_varying;

layout (location = 0) out vec4 fragColor;
layout (location = 1) out vec3 fragPosition;
layout (location = 2) out vec3 frag_norm_vec;

uniform sampler2D myTexture;

void main()
{
    vec4 texel = texture(myTexture, texcoord_varying);
    fragColor = texel * color_varying;
    fragPosition = frag_position;
    frag_norm_vec = normalize(norm_vec);
}

光照顶点着色器:

#version 150
#extension GL_ARB_explicit_attrib_location : enable
layout (location = 0) in vec2 in_position;

out vec2 texCoord;

void main()
{
    gl_Position = vec4(in_position, 0, 1.0f);

    texCoord = in_position;
    if(texCoord.x == -1.0f)
        texCoord.x = 0.0f;
    if(texCoord.y == -1.0f)
        texCoord.y = 0.0f;
}

Lighting Fragment Shader(没有光照计算使其更短)

#version 150
#extension GL_ARB_separate_shader_objects : enable

out vec4 fragColor;
in vec2 texCoord;


uniform sampler2D colorTexture;
uniform sampler2D positionTexture;
uniform sampler2D normTexture;

void main()
{
    //extract fragment data from fbo
    vec3 pos = texture(positionTexture, texCoord).rgb;
    vec3 norm = texture(normTexture, texCoord).rgb;
    vec4 color = texture(colorTexture, texCoord);


    fragColor = lightIntensity * color;
}

为代码垃圾邮件道歉,但我无法缩小错误范围。

【问题讨论】:

  • "几何顶点着色器:" 小心在“着色器”旁边使用“几何”等术语。因为我们有一个着色器阶段,我第一次读到这个名字让我觉得这就是你使用的。
  • "OpenGL 3.1" 那么为什么你的着色器使用#version 150?那是从 GL 3.2 开始的。这不是你的问题,但你应该清楚你使用的是什么版本的 OpenGL。
  • 哦.. 当然我是在 3.2 版下开发的,我编辑过。
  • “几何着色器”这个词有什么问题?着色器不只是在 gpu 上运行的程序吗?在那种情况下,它正在计算场景的几何形状?
  • 因为术语“Geometry Shader”是为特定的着色器阶段保留的。这是一种独立于顶点着色器和片段着色器的着色器。 OpenGL 3.2 是他们进入核心 OpenGL 的第一个版本,所以你可以一直在谈论/使用它。

标签: c++ opengl


【解决方案1】:

问题很可能出在您的操作顺序上:

gBuffer->bindForReading(lightShader->programID());
lightShader->use(true);

bindForReading() 中,您有这样的调用:

samplerTexture_ID = glGetUniformLocation(programID, "positionTexture");
glUniform1i(samplerTexture_ID, 1);

glUniform*() 调用在当前活动程序上设置统一值。由于您使 lightShader 在您进行这些调用之后 处于活动状态,因此统一值将在先前活动的程序上设置,该程序甚至可能没有这些统一。 p>

仅仅改变这些调用的顺序可能已经解决了这个问题:

lightShader->use(true);
gBuffer->bindForReading(lightShader->programID());

另外,您使用GL_RGB16F 作为两个缓冲区的格式。您使用的 OpenGL 实现可能支持这一点,但这不是规范中要求颜色渲染的格式。如果你想让你的代码跨平台工作,你应该使用GL_RGBA16F,它保证是可渲染的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多