尝试渲染到多个纹理以实现延迟渲染。但所有纹理都是平等的
Posted
技术标签:
【中文标题】尝试渲染到多个纹理以实现延迟渲染。但所有纹理都是平等的【英文标题】:Trying to render to several textures to implement deferred rendering. But all textures are equal 【发布时间】:2017-01-13 19:26:33 【问题描述】:所以我试图在 opengl 中实现延迟渲染。为此,我创建了一个渲染到 3 个纹理的 FBO(一个用于位置,一个用于正常,一个用于材质信息)但是由于我还没有完成第三个纹理,而只是片段的最终颜色。最后一个深度缓冲区用于稍后实现阴影。
这些纹理然后被传递给另一个着色器(并使用默认的帧缓冲区)计算像素的最终颜色。然而,所有 3 个纹理都包含相同的信息,即几何通道着色器的第一个输出变量。
#version 330
//Fragment shader from the lighting pass
in vec2 vTexCoord;
uniform sampler2D uPosTexture;
uniform sampler2D uNormalTexture;
uniform sampler2D uColorTexture;
out vec4 fFragColor;
void main()
//All of the following lines output the same image
vec3 color = texture(uNormalTexture, vTexCoord).rgb;
//vec3 color = texture(uPosTexture, vTexCoord).rgb;
//vec3 color = texture(uColorTexture, vTexCoord).rgb;
fFragColor = vec4(color,1);
所有 3 输出此图像:
这是我的几何片段着色器:
#version 330
in vec3 vECPos; // S.R. Vista
in vec3 vECNorm; // S.R. Vista
in vec4 vShadowCoord;
layout (location = 0) out vec3 fPosition;
layout (location = 1) out vec3 fNormal;
layout (location = 2) out vec4 fFragColor;
uniform sampler2DShadow uShadowMap;
uniform int uTipoFiltro;
struct LightInfo
vec4 lightPos; // Posición de la luz (S.R. de la vista)
vec3 intensity;
;
uniform LightInfo uLight;
struct MaterialInfo
vec3 ambient;
vec3 diffuse;
vec3 specular;
float shininess;
;
uniform MaterialInfo uMaterial;
vec3 phongModelDiffAndSpec ()
vec3 ldir = normalize(vec3(uLight.lightPos) - vECPos);
vec3 view = normalize(vec3(-vECPos));
vec3 r = reflect(-ldir,vECNorm);
vec3 color = uLight.intensity * ( uMaterial.diffuse * max(dot(ldir,vECNorm), 0.0) +
uMaterial.specular * pow(max(dot(r,view),0),uMaterial.shininess) );
return clamp(color, 0.0, 1.0);
void main()
vec3 ambient = uLight.intensity * uMaterial.ambient;
vec3 diffAndSpec = phongModelDiffAndSpec();
fPosition = vECPos;
fNormal = normalize(vECNorm);
fFragColor = vec4(ambient + diffAndSpec,1.0);
但是似乎只完成了第一个输出变量,因为如果我改变这个:
layout (location = 1) out vec3 fPosition;
layout (location = 2) out vec3 fNormal;
layout (location = 0) out vec4 fFragColor;
这表明:
还有其他重要的功能
bool init()
glClearColor(0.93f, 0.93f, 0.93f, 0.0f);
glEnable(GL_DEPTH_TEST);
//glDepthFunc(GL_LESS);
//glClearDepth(1.0f);
//glShadeModel(GL_SMOOTH);
//Create shaders
createShader(geometryPassShader, "geometry.vert", "geometry.frag");
setUniformGeometry();
createShader(lightPassShader, "lighting.vert", "lighting.frag");
setUniformLighting();
initFBO();
passTexturesToStdFBO();
//Init objects
numVertTeapot = initTeapot(5, glm::mat4(1.0f));
numVertSphere = initSphere(1.0f, 20, 30);
numVertPlane = initPlane(10.0f, 10.0f, 2, 2);
numVertTorus = initTorus(0.5f, 0.25f, 20, 40);
initQuad();
return true;
void initFBO()
//Crear 1 FBO
glGenFramebuffers(1, &gBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
//Crear textura que guarda posicion
glGenTextures(1, &gPositionTex);
//glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, gPositionTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, g_Width, g_Height, 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);
//Añadir la textura al FBO
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gPositionTex, 0);
//Crear textura que guarda normal
glGenTextures(1, &gNormalTex);
//glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, gNormalTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, g_Width, g_Height, 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);
//Añadir textura al FBO
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, gNormalTex, 0);
//Crear textura que guarda informacion del material del "pixel"
glGenTextures(1, &gMaterialTex);
//glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, gMaterialTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, g_Width, g_Height, 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_ATTACHMENT2, GL_TEXTURE_2D, gMaterialTex, 0);
//Crear depth buffer
glGenTextures(1, &depth_texture);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, depth_texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, g_Width, g_Height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//Indicamos que buffers (texturas) seran escritos con el output del fragment shader
glDrawBuffers(3, attachments); //attachments[3] = GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 ;
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_texture, 0);
GLenum result = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (result == GL_FRAMEBUFFER_COMPLETE)
std::cout << "Frame buffer complete" << std::endl;
else
std::cout << "Frame buffer is not complete" << std::endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
void display()
//glClear of this FBO is done inside drawFBO()
glUseProgram(geometryPassShader);
drawFBO();
glUseProgram(0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(lightPassShader);
//passTexturesToStdFBO();
drawQuad();
glUseProgram(0);
glutSwapBuffers();
void drawFBO()
glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
glViewport(0, 0, g_Width, g_Height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
drawScene();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
void passTexturesToStdFBO()
glBindBuffer(GL_FRAMEBUFFER, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, gPositionTex);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, gNormalTex);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, gMaterialTex);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, depth_texture);
void setUniformLighting()
GLuint loc0 = glGetUniformLocation(lightPassShader, "uPosTexture");
glUniform1i(loc0, 0);
GLuint loc1 = glGetUniformLocation(lightPassShader, "uNormalTexture");
glUniform1i(loc1, 1);
GLuint loc2 = glGetUniformLocation(lightPassShader, "uColorTexture");
glUniform1i(loc2, 2);
【问题讨论】:
【参考方案1】:void setUniformLighting()
GLuint loc0 = glGetUniformLocation(lightPassShader, "uPosTexture");
glUniform1i(loc0, 0);
GLuint loc1 = glGetUniformLocation(lightPassShader, "uNormalTexture");
glUniform1i(loc1, 1);
GLuint loc2 = glGetUniformLocation(lightPassShader, "uColorTexture");
glUniform1i(loc2, 2);
glUniform
作用于 current 程序,由glUseProgram
定义。在您调用 setUniformLighting
之前,我发现对这个函数的调用明显缺乏。因此,您需要执行以下操作之一:
-
事先将调用
setUniformLighting
的代码调用glUseProgram(lightPassShader)
。
让setUniformLighting
自己在内部进行调用。
使用glProgramUniform
,它作用于您指定的程序,而不是当前绑定的程序。请注意,此函数需要 GL 4.1/ARB_separate_shader_object。
【讨论】:
以上是关于尝试渲染到多个纹理以实现延迟渲染。但所有纹理都是平等的的主要内容,如果未能解决你的问题,请参考以下文章