我有一个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 };
答案 0 :(得分:0)
您的代码看起来像是对片段着色器输出的工作方式做出了无效的假设。似乎假设如果没有值写入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,所以在你的情况下这不是问题。