尝试渲染到多个纹理以实现延迟渲染.但所有的纹理都是平等的 [英] Trying to render to several textures to implement deferred rendering. But all textures are equal

查看:33
本文介绍了尝试渲染到多个纹理以实现延迟渲染.但所有的纹理都是平等的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我试图在 opengl 中实现延迟渲染.为此,我创建了一个 FBO,它渲染到 3 个纹理(一个用于位置,一个用于正常,一个用于材质信息)但是因为我没有完成,所以第三个纹理只是片段的最终颜色.以及最后一个深度缓冲区,用于稍后实现阴影.

So I'm trying to implemtent deferred rendering in opengl. To do so I create a FBO which renders to 3 textures (one for position, one for normal, one for material info) however since I'm not finished the 3rd texture is instead just the final color of the fragment. And one last depth buffer to later implement shadows.

然后将此纹理传递给另一个着色器(并使用默认的帧缓冲区),该着色器计算像素的最终颜色.然而,所有 3 个纹理都包含相同的信息,即几何传递着色器的第一个输出变量.

This textures then are passed to another shader (and with the default Frame Buffer) which calculates the final color of the pixel. However all 3 textures contain the same information which is the first output variable from the geometry pass shader.

#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 个输出此图像:

All 3 output this image:

这是我的几何片段着色器:

And here is my geometry fragment shader:

#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);
}

但是似乎只完成了第一个输出变量,因为如果我改变它:

However it seems that only the first output variable is done because if I change this:

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);
}

推荐答案

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 之前,我发现对这个函数的调用明显缺乏.因此,您需要执行以下操作之一:

glUniform acts on the current program, as defined by glUseProgram. I see a distinct lack of calls to this function before you call setUniformLighting. So you need to do one of the following:

  1. 事先让调用 setUniformLighting 的代码调用 glUseProgram(lightPassShader).
  2. setUniformLighting 自己在内部进行调用.
  3. 使用 glProgramUniform,它作用于您指定的程序,而不是当前绑定的程序.请注意,此函数需要 GL 4.1/ARB_separate_shader_object.
  1. Have the code that calls setUniformLighting call glUseProgram(lightPassShader) beforehand.
  2. Have setUniformLighting itself internally make that call.
  3. Use glProgramUniform, which acts on the program you specify, rather than the currently bound one. Note that this function require GL 4.1/ARB_separate_shader_object.

这篇关于尝试渲染到多个纹理以实现延迟渲染.但所有的纹理都是平等的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆