我正在使用Blinn-Phong算法来计算场景中的光照,而我还没有考虑距离。在修复第一个问题之前,我还禁用了HDR和Specular计算。
我大约95%肯定在我的片段着色器中出现了错误,但我正在设置一个完整的MCVE以防万一我在其他地方犯了错误。
R"DATA(#version 430
layout(location = 0) in vec3 vertex_color;
layout(location = 1) in vec3 vertex_normal;
layout(location = 2) in vec3 vertex_position;
layout(location = 0) out vec4 fragment_color;
uniform float ambient_factor = 0.05;
uniform float diffuse_factor = 1;
//Specular Lighting is disabled until I figure out where the mistake is.
uniform float specular_factor = 0;
uniform float specular_shininess = 15;
uniform vec4 light_position = vec4(2, 0, 2, 1);
uniform vec4 light_color = vec4(1, 1, 1, 1);
uniform float exposure = 1;
uniform vec4 eye;
void main() {
vec3 texture_color = vertex_color;
vec3 normalized_fragment_normal = normalize(vertex_normal);
vec3 light_direction = normalize(light_position.xyz - vertex_position);
vec3 eye_direction = normalize(eye.xyz - vertex_position);
vec3 halfway_vector = normalize(light_direction + eye_direction);
float diffuse_strength = clamp(dot(normalized_fragment_normal, light_direction), 0, 1);
float blinn_phong_specular_strength = max(dot(normalized_fragment_normal, halfway_vector), 0);
vec3 working_color = vec3(
texture_color * ambient_factor +
light_color.xyz * light_color.w * texture_color * diffuse_strength * diffuse_factor +
light_color.xyz * light_color.w * pow(blinn_phong_specular_strength, specular_shininess) * specular_factor
);
//For handling HDR, but disabling for now so that the lighting differences/mistakes are more obvious.
//const float gamma = 2.2;
//vec3 mapped = vec3(1) - exp(-working_color * exposure);
//mapped = pow(mapped, vec3(1 / gamma));
//fragment_color = vec4(mapped, 1);
fragment_color = vec4(working_color, 1);
})DATA"
顶点着色器:
R"DATA(#version 430
layout(location = 0) in vec3 position;
layout(location = 1) in vec3 color;
layout(location = 2) in vec3 normal;
layout(location = 0) out vec3 vertex_color;
layout(location = 1) out vec3 vertex_normal;
layout(location = 2) out vec3 vertex_position;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model_position;
uniform mat4 model_normal;
void main() {
gl_Position = projection * view * model_position * vec4(position, 1);
vertex_color = color;
vertex_normal = (model_normal * vec4(normal, 0)).xyz;
vertex_position = (model_position * vec4(position, 1)).xyz;
})DATA"
Shaders.h:
#pragma once
#pragma warning( push )
#pragma warning( once : 4251)
#include<glbinding\gl\gl.h>
#include<glbinding\Binding.h>
#pragma warning( pop )
const char * vert_src = ""
#include "Cube.vert.glsl"
;
const char * frag_src = ""
#include "Cube.frag.glsl"
;
//The two Light shaders are just pass-through shaders that make the cube look pure white.
const char * light_vert_src = ""
#include "Light.vert.glsl"
;
const char * light_frag_src = ""
#include "Light.frag.glsl"
;
namespace shaders {
using namespace gl;
class failed_shader_compilation_exception : public std::runtime_error {
std::string error_log;
public:
failed_shader_compilation_exception(std::string const& why, std::string const& err) :
std::runtime_error(why),
error_log(err) {}
std::string get_log() const {
return error_log;
}
};
void handle_shader_error(GLuint shader, std::string const& type, bool is_shader = true) {
int log_length;
if (is_shader)
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
else
glGetProgramiv(shader, GL_INFO_LOG_LENGTH, &log_length);
std::string errlog;
errlog.resize(log_length);
if (is_shader)
glGetShaderInfoLog(shader, log_length, nullptr, &errlog[0]);
else
glGetProgramInfoLog(shader, log_length, nullptr, &errlog[0]);
if (is_shader)
glDeleteShader(shader);
else
glDeleteProgram(shader);
throw failed_shader_compilation_exception("The " + type + " failed to Compile", errlog);
}
GLuint get_program(const char * vsrc, const char * fsrc) {
GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
int ret;
glShaderSource(vertex_shader, 1, &vsrc, nullptr);
glCompileShader(vertex_shader);
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &ret);
if (!ret) {
handle_shader_error(vertex_shader, "Vertex Shader");
}
GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fsrc, nullptr);
glCompileShader(fragment_shader);
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &ret);
if (!ret) {
glDeleteShader(vertex_shader);
handle_shader_error(fragment_shader, "Fragment Shader");
}
GLuint program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
glGetProgramiv(program, GL_LINK_STATUS, &ret);
if (!ret) {
handle_shader_error(program, "Program", false);
}
return program;
}
}
Main.cpp的:
#define GLFW_INCLUDE_NONE
#include<GLFW\glfw3.h>
#pragma warning( push )
#pragma warning( once : 4251)
#include<glbinding\gl43core\gl.h>
#include<glbinding\Binding.h>
#pragma warning( pop )
#include<iostream>
#include<glm/glm.hpp>
#include<glm/gtc/matrix_transform.hpp>
#include<glm/gtc/type_ptr.hpp>
#include "Shaders.h"
float vertex_data[] {
0, 0, 0, 1, 0, 0, 0, 0, 1,
1, 0, 0, 1, 0, 0, 0, 0, 1,
1, 1, 0, 1, 0, 0, 0, 0, 1,
0, 0, 0, 1, 0, 0, 0, 0, 1,
1, 1, 0, 1, 0, 0, 0, 0, 1,
0, 1, 0, 1, 0, 0, 0, 0, 1,
1, 0, 0, 0, 1, 0, 1, 0, 0,
1, 0, -1, 0, 1, 0, 1, 0, 0,
1, 1, -1, 0, 1, 0, 1, 0, 0,
1, 0, 0, 0, 1, 0, 1, 0, 0,
1, 1, -1, 0, 1, 0, 1, 0, 0,
1, 1, 0, 0, 1, 0, 1, 0, 0,
1, 0, -1, 0, 1, 1, 0, 0, -1,
0, 0, -1, 0, 1, 1, 0, 0, -1,
0, 1, -1, 0, 1, 1, 0, 0, -1,
1, 0, -1, 0, 1, 1, 0, 0, -1,
0, 1, -1, 0, 1, 1, 0, 0, -1,
1, 1, -1, 0, 1, 1, 0, 0, -1,
0, 0, -1, 1, 0, 1, -1, 0, 0,
0, 0, 0, 1, 0, 1, -1, 0, 0,
0, 1, 0, 1, 0, 1, -1, 0, 0,
0, 0, -1, 1, 0, 1, -1, 0, 0,
0, 1, 0, 1, 0, 1, -1, 0, 0,
0, 1, -1, 1, 0, 1, -1, 0, 0,
0, 1, 0, 0, 0, 1, 0, 1, 0,
1, 1, 0, 0, 0, 1, 0, 1, 0,
1, 1, -1, 0, 0, 1, 0, 1, 0,
0, 1, 0, 0, 0, 1, 0, 1, 0,
1, 1, -1, 0, 0, 1, 0, 1, 0,
0, 1, -1, 0, 0, 1, 0, 1, 0,
0, 0, 0, 1, 1, 0, 0, -1, 0,
0, 0, -1, 1, 1, 0, 0, -1, 0,
1, 0, -1, 1, 1, 0, 0, -1, 0,
0, 0, 0, 1, 1, 0, 0, -1, 0,
1, 0, -1, 1, 1, 0, 0, -1, 0,
1, 0, 0, 1, 1, 0, 0, -1, 0,
};
float light_cube_data[]{
0, 0, 0, 1, 0, 0, 1, 1, 0,
0, 0, 0, 1, 1, 0, 0, 1, 0,
1, 0, 0, 1, 0, -1, 1, 1, -1,
1, 0, 0, 1, 1, -1, 1, 1, 0,
1, 0, -1, 0, 0, -1, 0, 1, -1,
1, 0, -1, 0, 1, -1, 1, 1, -1,
0, 0, -1, 0, 0, 0, 0, 1, 0,
0, 0, -1, 0, 1, 0, 0, 1, -1,
0, 1, 0, 1, 1, 0, 1, 1, -1,
0, 1, 0, 1, 1, -1, 0, 1, -1,
0, 0, 0, 0, 0, -1, 1, 0, -1,
0, 0, 0, 1, 0, -1, 1, 0, 0,
};
int main() {
glfwInit();
GLFWwindow * window = glfwCreateWindow(300, 300, "bluh", nullptr, nullptr);
glfwMakeContextCurrent(window);
glbinding::Binding::initialize();
using namespace gl43core;
GLuint program = 0, light_program = 0;
try {
program = shaders::get_program(vert_src, frag_src);
light_program = shaders::get_program(light_vert_src, light_frag_src);
}
catch (shaders::failed_shader_compilation_exception const& e) {
std::cerr << e.what() << std::endl;
std::cerr << e.get_log() << std::endl;
system("pause");
return 1;
}
glUseProgram(program);
GLuint vao, vbo;
GLuint light_vao, light_vbo;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 9 * sizeof(GLfloat), (void*)0);
glVertexAttribPointer(1, 3, GL_FLOAT, false, 9 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));
glVertexAttribPointer(2, 3, GL_FLOAT, false, 9 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));
glGenVertexArrays(1, &light_vao);
glBindVertexArray(light_vao);
glGenBuffers(1, &light_vbo);
glBindBuffer(GL_ARRAY_BUFFER, light_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(light_cube_data), light_cube_data, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 3 * sizeof(GLfloat), (void*)0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glm::mat4 view = glm::lookAt(glm::vec3(2, 3, 3), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
struct manip_data {
glm::quat view_quat;
glm::vec3 view_position;
glm::vec4 light_position{ 3, 0, 3, 1 };
glm::vec4 light_color{ 1, 1, 1, 1 };
double prior_time;
double current_time;
};
manip_data data;
data.view_quat = glm::quat(view);
data.view_position = glm::vec3(glm::inverse(view)[3]);
data.prior_time = data.current_time = glfwGetTime();
glfwSetWindowUserPointer(window, &data);
glfwSetKeyCallback(window, [](GLFWwindow * window, int key, int code, int action, int modifier) {
manip_data & data = *(reinterpret_cast<manip_data *>(glfwGetWindowUserPointer(window)));
data.current_time = glfwGetTime();
double dt = data.current_time - data.prior_time;
if (action == GLFW_PRESS || action == GLFW_REPEAT) {
switch (key) {
case GLFW_KEY_W: data.view_position += glm::inverse(data.view_quat) * glm::vec3(0, 0, -1) * float(dt) * 50.f; break;
case GLFW_KEY_S: data.view_position += glm::inverse(data.view_quat) * glm::vec3(0, 0, 1) * float(dt) * 50.f; break;
case GLFW_KEY_A: data.view_position += glm::inverse(data.view_quat) * glm::vec3(-1, 0, 0) * float(dt) * 50.f; break;
case GLFW_KEY_D: data.view_position += glm::inverse(data.view_quat) * glm::vec3(1, 0, 0) * float(dt) * 50.f; break;
case GLFW_KEY_LEFT_SHIFT: data.view_position += glm::inverse(data.view_quat) * glm::vec3(0, 1, 0) * float(dt) * 50.f; break;
case GLFW_KEY_LEFT_CONTROL: data.view_position += glm::inverse(data.view_quat) * glm::vec3(0, -1, 0) * float(dt) * 50.f; break;
case GLFW_KEY_KP_8: data.view_quat = glm::angleAxis(-float(dt) * 50, glm::vec3(1, 0, 0)) * data.view_quat; break;
case GLFW_KEY_KP_2: data.view_quat = glm::angleAxis(float(dt) * 50, glm::vec3(1, 0, 0)) * data.view_quat; break;
case GLFW_KEY_KP_4: data.view_quat = glm::angleAxis(-float(dt) * 50, glm::vec3(0, 1, 0)) * data.view_quat; break;
case GLFW_KEY_KP_6: data.view_quat = glm::angleAxis(float(dt) * 50, glm::vec3(0, 1, 0)) * data.view_quat; break;
case GLFW_KEY_KP_9: data.view_quat = glm::angleAxis(-float(dt) * 50, glm::vec3(0, 0, -1)) * data.view_quat; break;
case GLFW_KEY_KP_7: data.view_quat = glm::angleAxis(float(dt) * 50, glm::vec3(0, 0, -1)) * data.view_quat; break;
}
}
data.prior_time = data.current_time;
});
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
data.prior_time = glfwGetTime();
int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glm::mat4 projection = glm::perspective(glm::radians(60.f), float(width) / height, 0.1f, 100.f);
glm::mat4 model;
glm::mat4 normal_model;
view = glm::translate(glm::mat4_cast(data.view_quat), -data.view_position);
glm::vec4 eye = glm::inverse(view)[3];
glm::vec4 light_position{ 1.25, 0.5, 1.25, 1 };
glUseProgram(program);
glBindVertexArray(vao);
glUniformMatrix4fv(glGetUniformLocation(program, "projection"), 1, false, glm::value_ptr(projection));
glUniformMatrix4fv(glGetUniformLocation(program, "view"), 1, false, glm::value_ptr(view));
glUniformMatrix4fv(glGetUniformLocation(program, "model_position"), 1, false, glm::value_ptr(model));
glUniformMatrix4fv(glGetUniformLocation(program, "model_normal"), 1, false, glm::value_ptr(normal_model));
glUniform4fv(glGetUniformLocation(program, "eye"), 1, glm::value_ptr(eye));
glUniform4fv(glGetUniformLocation(program, "light_position"), 1, glm::value_ptr(light_position));
glDrawArrays(GL_TRIANGLES, 0, sizeof(vertex_data) / sizeof(GLfloat) / 9);
model = glm::translate(model, glm::vec3(light_position));
model = glm::scale(model, glm::vec3(0.25, 0.25, 0.25));
glUseProgram(light_program);
glBindVertexArray(light_vao);
glUniformMatrix4fv(glGetUniformLocation(light_program, "projection"), 1, false, glm::value_ptr(projection));
glUniformMatrix4fv(glGetUniformLocation(light_program, "view"), 1, false, glm::value_ptr(view));
glUniformMatrix4fv(glGetUniformLocation(light_program, "model_position"), 1, false, glm::value_ptr(model));
glDrawArrays(GL_TRIANGLES, 0, sizeof(light_cube_data) / sizeof(GLfloat) / 3);
glfwSwapBuffers(window);
}
return 0;
}
这是默认渲染位置的图片,我添加了一些注释来识别我知道灯光是错误的。
我正在使用GLFW和glbinding进行OpenGL API访问,但是如果你使用它而不是glbinding,GLEW实际上有相同的代码。我也在使用GLM进行数学运算。
答案 0 :(得分:3)
您正在重复使用顶点颜色作为法线,并且从不使用数组中的实际法线:
glVertexAttribPointer(1, 3, GL_FLOAT, false, 9 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));
glVertexAttribPointer(2, 3, GL_FLOAT, false, 9 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));