我正在尝试在 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;
}
我做错了什么?请问有什么帮助吗?