【问题标题】:OpenGL not rendering to correct targetOpenGL没有渲染到正确的目标
【发布时间】:2015-03-21 14:38:03
【问题描述】:

我有一个 fbo,里面有 8 个纹理(g-buffer)。我要做的是将不透明对象的所有信息渲染到前四个(颜色、法线、位置、深度),并将透明对象的信息渲染到最后四个纹理。但是,无论我做什么,openGL 似乎都只想渲染到第四个。此外,应用程序启动时的第一帧是我用于透明对象的纹理的一些奇怪原因。

写入 g-buffer 的着色器:

in vec2 texcoord;
in vec3 worldpos;
in mat3 tbnmatrix;

uniform sampler2d diffuse;
uniform sampler2d normalmap;
uniform sampler2d dispmap;

uniform float dispmapbias;
uniform float dispmapscale;

uniform float specularintensity;
uniform float specularpower;

uniform float opacity;

uniform vec3 c_eyepos;

layout (location = 0) out vec4 diffuseColor;
layout (location = 1) out vec4 normalColor;
layout (location = 2) out vec4 positionColor;
layout (location = 3) out float depthcolor;
layout (location = 4) out vec4 diffuseColorT;
layout (location = 5) out vec4 normalColorT;
layout (location = 6) out vec4 positionColorT;
layout (location = 7) out float depthColorT;

void main(){

//只计算位移的纹理坐标 vec2 texcoords = calcParallaxTexcoords(dispmap, tbnmatrix, normalize(c_eyepos - worldpos), texcoord, dispmapscale, dispmapbias);

//Calculating normals
vec3 n = normalize(tbnmatrix * (255.0/128.0 * texture(normalmap, texcoords).xyz - 1)); 


if(opacity == 1){


diffuseColor = vec4(texture(diffuse, texcoords).xyz, 1);
normalColor = vec4(n, specularintensity);

positionColor = vec4(worldpos, specularpower);
depthColor = gl_FragCoord.z;

}

else{
    diffuseColorT = vec4(texture(diffuse, texcoords).xyz, opacity);
    normalColorT = vec4(n, specularintensity);
    positionColorT = vec4(worldpos, specularpower);
    depthColorT = gl_FragCoord.z;
}




}

我会发布创建我的 FBO 的代码,但这将是非常多的代码,并且难以理解(因为我的架构)。以下是我传入的值:

//Filters to be used in rendertargets
    GLenum filters[8] = { GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_LINEAR,
 GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_LINEAR, 
GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_LINEAR };

//What I pass in to the third parameter of glTexImage2D
        GLenum internalFormats[8] = { GL_RGBA, GL_RGBA16F, GL_RGBA16F, GL_R32F, GL_RGBA, GL_RGBA16F, GL_RGBA16F, GL_R32F };

//Formats, not really important here
        GLenum formats[8] = { GL_RGBA, GL_RGBA, GL_RGBA, GL_RGBA, GL_RGBA, GL_RGBA, GL_RGBA, GL_RGBA };

    //Attachment to be used in glFramebufferTexture2D (and glDrawBuffers)
            GLenum attachments[8] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, 
GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3, GL_COLOR_ATTACHMENT4, GL_COLOR_ATTACHMENT5, 
GL_COLOR_ATTACHMENT6, GL_COLOR_ATTACHMENT7 };

【问题讨论】:

  • 你检查过GL_MAX_COLOR_ATTACHMENTS吗?
  • 你在哪里打电话给glCheckFramebufferStatus​()?也许,它是否返回GL_FRAMEBUFFER_UNSUPPORTED?据我了解,支持超过 4 种颜色附件的实现相当罕见,而且它们通常必须具有相同的像素格式。
  • 好吧,我正在调用它,它正在返回 GL_FRAMEBUFFER_COMPLETE。如果真的很难支持它,也许我最好把它分成 2 个 4 纹理 fbo

标签: opengl textures fragment-shader fbo


【解决方案1】:

您的代码似乎对片段着色器输出的工作方式做出了无效假设。似乎假设如果没有值写入out 变量,则相应渲染缓冲区中的值将保持不变。这不是它的工作原理。

如果您没有为片段着色器中的out 变量赋值,这意味着当着色器完成时它有一个未定义的值。然后这个未定义的值将被写入渲染目标。

不向渲染目标写入值的唯一方法是在片段着色器中使用discard。但这会丢弃整个片段。我不知道动态丢弃特定渲染目标的片段的方法。

对于仅更改在着色器运行时确定的选定渲染目标,想到的最佳解决方案是启用混合。使用标准混合方程:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);

您可以通过将相应输出的 alpha 分量设置为零来保持选定的渲染目标不变。在您的着色器中(仅显示漫反射输出):

if (opacity == 1.0) {
    diffuseColor = vec4(texture(diffuse, texcoords).xyz, 1.0);
    diffuseColorT = vec4(0.0);
} else {
    diffuseColor = vec4(0.0);
    diffuseColorT = vec4(texture(diffuse, texcoords).xyz, opacity);
}

当然,另一种方法是使用两个渲染通道,在一个通道中渲染不透明对象,在第二通道中渲染透明对象,每个通道只有相应的 4 个渲染目标。

通常,您还需要确保使用的渲染目标不超过GL_MAX_COLOR_ATTACHMENTS。但这在 OpenGL 3.x 中保证至少为 8,因此在您的情况下这不是问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-14
    • 2021-08-28
    • 2021-07-22
    • 2019-06-30
    相关资源
    最近更新 更多