所以我试图在opengl中实现延迟渲染。为此,我创建了一个FBO,它渲染了3个纹理(一个用于位置,一个用于法线,一个用于材质信息)但是由于我没有完成第三个纹理而只是片段的最终颜色。最后一个深度缓冲区,以便以后实现阴影。
然后将此纹理传递给另一个着色器(并使用默认的帧缓冲区),该着色器计算像素的最终颜色。但是,所有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);
}
答案 0 :(得分:2)
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
作用于当前程序,由glUseProgram
定义。在您致电setUniformLighting
之前,我看到了对此功能的明显缺少。因此,您需要执行以下操作之一:
setUniformLighting
致电glUseProgram(lightPassShader)
的代码。setUniformLighting
在内部拨打电话。glProgramUniform
,它对您指定的程序起作用,而不是当前绑定的程序。请注意,此功能需要GL 4.1 / ARB_separate_shader_object。