1

我正在尝试在 OpenGL 中制作一个简单的延迟光照场景,但是在实施 1 点光照后出现问题,我得到了 180 度光照表面:

截图 1:

在此处输入图像描述

截图 2:

在此处输入图像描述

这是我的代码:

Material shaderGeometryPass("Shaders/deff_shader.vers", "Shaders/deff_shader.frags");

Material shaderLightingPass("Shaders/deff_light.vers", "Shaders/deff_light.frags");
shaderLightingPass.Use();
shaderLightingPass.setInt("gPosition", 0);
shaderLightingPass.setInt("gNormal", 1);
shaderLightingPass.setInt("gAlbedoSpec", 2);

// configure g-buffer framebuffer
// ------------------------------
unsigned int gBuffer;
glGenFramebuffers(1, &gBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
unsigned int gPosition, gNormal, gAlbedoSpec;
// position color buffer
glGenTextures(1, &gPosition);
glBindTexture(GL_TEXTURE_2D, gPosition);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, SCR_weight, SCR_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);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gPosition, 0);
// normal color buffer
glGenTextures(1, &gNormal);
glBindTexture(GL_TEXTURE_2D, gNormal);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, SCR_weight, SCR_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);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, gNormal, 0);
// color + specular color buffer
glGenTextures(1, &gAlbedoSpec);
glBindTexture(GL_TEXTURE_2D, gAlbedoSpec);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SCR_weight, SCR_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, gAlbedoSpec, 0);
// tell OpenGL which color attachments we'll use (of this framebuffer) for rendering 
unsigned int attachments[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
glDrawBuffers(3, attachments);
// create and attach depth buffer (renderbuffer)
unsigned int rboDepth;
glGenRenderbuffers(1, &rboDepth);
glBindRenderbuffer(GL_RENDERBUFFER, rboDepth);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, SCR_weight, SCR_height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboDepth);
// finally check if framebuffer is complete
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
    std::cout << "Framebuffer not complete!" << std::endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);

while (!glfwWindowShouldClose(window) == 0)
{
    camera.ComputeMatrices();

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // 1. geometry pass: render scene's geometry/color data into gbuffer
    // -----------------------------------------------------------------
    glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    for (size_t i = 0; i < mScene.all_children.size(); i++)
    {
        if (mScene.all_children[i]->Get_component_id(Comp_Mesh) >= 0)
        {
            bool get_suc = false;
            RMesh &get_mesh = meshs.GetMesh(mScene.all_children[i]->Get_component_id(Comp_Mesh), get_suc);

            if (get_suc)
            {
                if (!get_mesh.mesh_available) continue;

                get_mesh.UseVertex();

                shaderGeometryPass.Use();

                glm::mat4 ModelMatrix = glm::scale(translate(mat4(1.0), mScene.all_children[i]->transform.Position), mScene.all_children[i]->transform.Scale);

                shaderGeometryPass.SetMat4("projection", camera.GetProjectionMatrix());
                shaderGeometryPass.SetMat4("view", camera.GetViewMatrix());
                shaderGeometryPass.SetMat4("model", ModelMatrix);

                // Bind our texture in Texture Unit 0
                glActiveTexture(GL_TEXTURE0);
                glBindTexture(GL_TEXTURE_2D, texture1));

                glActiveTexture(GL_TEXTURE1);
                glBindTexture(GL_TEXTURE_2D, texture2));


                // Set our "myTextureSampler" sampler to use Texture Unit 0
                glUniform1i(shaderGeometryPass.GetUniform("texture_diffuse"), 0);
                glUniform1i(shaderGeometryPass.GetUniform("texture_specular"), 1);

                // 1rst attribute buffer : vertices
                glEnableVertexAttribArray(0);
                glBindBuffer(GL_ARRAY_BUFFER, get_mesh.vertexbuffer);
                glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

                // 2nd attribute buffer : UVs
                glEnableVertexAttribArray(1);
                glBindBuffer(GL_ARRAY_BUFFER, get_mesh.uvbuffer);
                glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);

                // 3rd attribute buffer : normals
                glEnableVertexAttribArray(2);
                glBindBuffer(GL_ARRAY_BUFFER, get_mesh.normalbuffer);
                glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

                // Index buffer
                glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, get_mesh.elementbuffer);

                // Draw the triangles !
                glDrawElements(GL_TRIANGLES, get_mesh.indices.size(), GL_UNSIGNED_SHORT, (void*)0);

                glDisableVertexAttribArray(0);
                glDisableVertexAttribArray(1);
                glDisableVertexAttribArray(2);

                get_mesh.EndVertex();
            }
        }
    }
    glBindFramebuffer(GL_FRAMEBUFFER, 0);


    // 2. lighting pass: calculate lighting by iterating over a screen filled quad pixel-by-pixel using the gbuffer's content.
    // -----------------------------------------------------------------------------------------------------------------------
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    shaderLightingPass.Use();

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, gPosition);
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, gNormal);
    glActiveTexture(GL_TEXTURE2);
    glBindTexture(GL_TEXTURE_2D, gAlbedoSpec);

    // send light relevant uniforms
    for (size_t i = 0; i < mScene.all_children.size(); i++)
    {
        if (mScene.all_children[i]->Get_component_id(Comp_PointLight) >= 0)
        {
            int g;
            if (Point_lights.GetLight(mScene.all_children[i]->Get_component_id(Comp_PointLight), &g))
            {
                if (Point_lights.lights[g].light_id == mScene.all_children[i]->Get_component_id(Comp_PointLight))
                {
                    Point_lights.lights[g].Position = mScene.all_children[i]->transform.Position;
                }
            }
        }

        if (Point_lights.lights.size() > 0)
        {
            shaderLightingPass.SetVec3("lights[0].Position", Point_lights.lights[0].Position);
            shaderLightingPass.SetVec3("lights[0].Color", Point_lights.lights[0].Color);
            // update attenuation parameters and calculate radius
            const float constant = 1.0; 
            const float linear = Point_lights.lights[0].Range;
            const float quadratic = 1.8;
            shaderLightingPass.SetFloat("lights[0].Linear", linear);
            shaderLightingPass.SetFloat("lights[0].Quadratic", quadratic);
            // then calculate radius of light volume/sphere
            const float maxBrightness = Point_lights.lights[0].Energy; //std::fmaxf(std::fmaxf(Point_lights.lights[0].Color.r, Point_lights.lights[0].Color.g), Point_lights.lights[0].Color.b);
            float radius = (-linear + std::sqrt(linear * linear - 4 * quadratic * (constant - (256.0f ) * maxBrightness))) / (2.0f * quadratic);
            shaderLightingPass.SetFloat("lights[0].Radius", radius);
        }
    }

    shaderLightingPass.SetVec3("viewPos", camera.transform.Position);

    renderQuad();

    // Swap buffers
    glfwSwapBuffers(window);
    glfwPollEvents();
}

“deff_light.vers”着色器:

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoords;

out vec2 TexCoords;

void main()
{
    TexCoords = aTexCoords;
    gl_Position = vec4(aPos, 1.0);
} 

“deff_light.frags”着色器:

#version 330 core
out vec4 FragColor;

in vec2 TexCoords;

uniform sampler2D gPosition;
uniform sampler2D gNormal;
uniform sampler2D gAlbedoSpec;

struct Light {
    vec3 Position;
    vec3 Color;

    float Linear;
    float Quadratic;
    float Radius;
};
const int NR_LIGHTS = 1;
uniform Light lights[NR_LIGHTS];
uniform vec3 viewPos;

void main()
{             
    // retrieve data from gbuffer
    vec3 FragPos = texture(gPosition, TexCoords).rgb;
    vec3 Normal = texture(gNormal, TexCoords).rgb;
    vec3 Diffuse = texture(gAlbedoSpec, TexCoords).rgb;
    float Specular = texture(gAlbedoSpec, TexCoords).a;

    // then calculate lighting as usual
    vec3 lighting  = Diffuse * 0.1; // hard-coded ambient component
    vec3 viewDir  = normalize(viewPos - FragPos);
    for(int i = 0; i < NR_LIGHTS; ++i)
    {
        // calculate distance between light source and current fragment
        float distance = length(lights[i].Position - FragPos);
        if(distance < lights[i].Radius)
        {
            // diffuse
            vec3 lightDir = normalize(lights[i].Position - FragPos);
            vec3 diffuse = max(dot(Normal, lightDir), 0.0) * Diffuse * lights[i].Color;
            // specular
            vec3 halfwayDir = normalize(lightDir + viewDir);  
            float spec = pow(max(dot(Normal, halfwayDir), 0.0), 16.0);
            vec3 specular = lights[i].Color * spec * Specular;
            // attenuation
            float attenuation = 1.0 / (1.0 + lights[i].Linear * distance + lights[i].Quadratic * distance * distance);
            diffuse *= attenuation;
            specular *= attenuation;
            lighting += diffuse + specular;
        }
    }    
    FragColor = vec4(lighting, 1.0);
}

“deff_shader.vers”着色器:

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;

out vec3 FragPos;
out vec2 TexCoords;
out vec3 Normal;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    vec4 worldPos = model * vec4(aPos, 1.0);
    FragPos = worldPos.xyz; 
    TexCoords = aTexCoords;

    mat3 normalMatrix = transpose(inverse(mat3(model)));
    Normal = normalMatrix * aNormal;

    gl_Position = projection * view * worldPos;
}

“deff_shader.frags”着色器:

#version 330 core
layout (location = 0) out vec3 gPosition;
layout (location = 1) out vec3 gNormal;
layout (location = 2) out vec4 gAlbedoSpec;

in vec2 TexCoords;
in vec3 FragPos;
in vec3 Normal;

uniform sampler2D texture_diffuse1;
uniform sampler2D texture_specular1;

void main()
{    
    // store the fragment position vector in the first gbuffer texture
    gPosition = FragPos;

    // also store the per-fragment normals into the gbuffer
    gNormal = normalize(Normal);

    // and the diffuse per-fragment color
    gAlbedoSpec.rgb = texture(texture_diffuse1, TexCoords).rgb;

    // store specular intensity in gAlbedoSpec's alpha component
    gAlbedoSpec.a = texture(texture_specular1, TexCoords).r;
}

我做错了什么?请问有什么帮助吗?

4

0 回答 0