diff --git a/shaders/normal_frag.glsl b/shaders/normal_frag.glsl new file mode 100644 index 0000000..21d090c --- /dev/null +++ b/shaders/normal_frag.glsl @@ -0,0 +1,7 @@ +#version 330 core + +out vec4 color; + +void main() { + color = vec4(1.0, 1.0, 0.0, 1.0); +} diff --git a/shaders/normal_geo.glsl b/shaders/normal_geo.glsl new file mode 100644 index 0000000..b3c84e2 --- /dev/null +++ b/shaders/normal_geo.glsl @@ -0,0 +1,34 @@ +#version 330 core + +#define MAGNITUDE 0.1 + +layout (triangles) in; +layout (line_strip, max_vertices = 6) out; + +uniform float time; + +in VS_OUT { + vec3 vert_normal; +} gs_in[]; + +layout (std140) uniform Common { + mat4 projection; + mat4 view; + vec3 camera_position; +}; + +void generate_line(int index) { + gl_Position = projection * gl_in[index].gl_Position; + EmitVertex(); + + gl_Position = projection * (gl_in[index].gl_Position + vec4(gs_in[index].vert_normal, 1.0) * MAGNITUDE); + EmitVertex(); + + EndPrimitive(); +} + +void main() { + for (int i = 0; i < 3; ++i) { + generate_line(i); + } +} diff --git a/shaders/normal_vert.glsl b/shaders/normal_vert.glsl new file mode 100644 index 0000000..8edb3a8 --- /dev/null +++ b/shaders/normal_vert.glsl @@ -0,0 +1,25 @@ +#version 330 core + +layout(location=0) in vec3 position; +layout(location=1) in vec3 normal; +layout(location=2) in vec2 uv; + +uniform mat3 normal_mat; +uniform mat4 model; + +layout (std140) uniform Common { + mat4 projection; + mat4 view; + vec3 camera_position; +}; + +// interface block +out VS_OUT { + vec3 vert_normal; +} vs_out; + +void main() { + vs_out.vert_normal = normal_mat * normal; + + gl_Position = view * model * vec4(position, 1.0); +}; diff --git a/src/main.cc b/src/main.cc index 905d6b4..841c326 100644 --- a/src/main.cc +++ b/src/main.cc @@ -48,6 +48,10 @@ #define max(a, b) (a > b ? a : b) #define clamp(v, a, b) (min(max(v, a), b)) +#define WIREFRAME 0 +#define NORMALS 0 +#define POINT_LIGHTS 0 + enum exit_codes : int { EXIT_CODE_SUCCESS, EXIT_CODE_SDL_INIT_FAILED, @@ -59,7 +63,7 @@ enum exit_codes : int { class Shader { public: - Shader(const std::string &vert_file, const std::string &frag_file); + Shader(const std::string &vert_file, const std::string &frag_file, const std::string &geo_file = ""); ~Shader(); void activate(); void set_int(const char *name, int value); @@ -71,7 +75,7 @@ class Shader { void set_uniform_block_binding_point(const char *block_name, GLuint binding_point); GLuint program; private: - void link_program(GLuint vert, GLuint frag); + void link_program(GLuint vert, GLuint frag, GLuint geo); GLuint load_and_compile_shader(const std::string &filepath, GLenum shader_type); std::string load_shader_from_file(const std::string &filepath); static const char *get_shader_type_string(GLenum shader_type); @@ -268,12 +272,13 @@ int main() { Mesh screen = {screen_vertices, screen_indices, {}}; - Shader main_shader {"shaders/vert.glsl", "shaders/frag.glsl"}; - Shader light_shader {"shaders/vert.glsl", "shaders/light_frag.glsl"}; - Shader skybox_shader {"shaders/sb_vert.glsl", "shaders/sb_frag.glsl"}; - Shader reflective_shader {"shaders/vert.glsl", "shaders/reflective_frag.glsl"}; - Shader refractive_shader {"shaders/vert.glsl", "shaders/refractive_frag.glsl"}; - Shader post_processing {"shaders/pp_vert.glsl", "shaders/pp_frag.glsl"}; + Shader main_shader {"shaders/vert.glsl", "shaders/frag.glsl"}; + Shader normal_vis_shader {"shaders/normal_vert.glsl", "shaders/normal_frag.glsl", "shaders/normal_geo.glsl"}; + Shader light_shader {"shaders/vert.glsl", "shaders/light_frag.glsl"}; + Shader skybox_shader {"shaders/sb_vert.glsl", "shaders/sb_frag.glsl"}; + Shader reflective_shader {"shaders/vert.glsl", "shaders/reflective_frag.glsl"}; + Shader refractive_shader {"shaders/vert.glsl", "shaders/refractive_frag.glsl"}; + Shader post_processing {"shaders/pp_vert.glsl", "shaders/pp_frag.glsl"}; const float camera_speed = 25.0f; glm::vec3 camera_position = glm::vec3(-2.5f, 0.0f, 8.0f); @@ -372,6 +377,7 @@ int main() { // Set the shaders binding points main_shader.set_uniform_block_binding_point ("Common", ubo_binding_point); + normal_vis_shader.set_uniform_block_binding_point("Common", ubo_binding_point); light_shader.set_uniform_block_binding_point ("Common", ubo_binding_point); skybox_shader.set_uniform_block_binding_point ("Common", ubo_binding_point); reflective_shader.set_uniform_block_binding_point("Common", ubo_binding_point); @@ -482,36 +488,46 @@ int main() { glDepthFunc(GL_LEQUAL); glEnable(GL_CULL_FACE); - model = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 0.0f)); + model = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 0.0f)); normal_mat = glm::transpose(glm::inverse(model)); main_shader.activate(); main_shader.set_mat4("model", model); main_shader.set_mat3("normal_mat", normal_mat); suzanne.draw(main_shader); - model = glm::translate(glm::mat4(1.0f), glm::vec3(3.0f, 0.0f, 0.0f)); +#if NORMALS + normal_mat = glm::transpose(glm::inverse(view * model)); + normal_vis_shader.activate(); + normal_vis_shader.set_mat4("model", model); + normal_vis_shader.set_mat3("normal_mat", normal_mat); + suzanne.draw(normal_vis_shader); +#endif + + model = glm::translate(glm::mat4(1.0f), glm::vec3(3.0f, 0.0f, 0.0f)); normal_mat = glm::transpose(glm::inverse(model)); reflective_shader.set_mat4("model", model); reflective_shader.set_mat3("normal_mat", normal_mat); suzanne.draw(reflective_shader); glDisable(GL_CULL_FACE); - model = glm::translate(glm::mat4(1.0f), glm::vec3(-3.0f, 0.0f, 0.0f)); + model = glm::translate(glm::mat4(1.0f), glm::vec3(-3.0f, 0.0f, 0.0f)); normal_mat = glm::transpose(glm::inverse(model)); refractive_shader.set_mat4("model", model); refractive_shader.set_mat3("normal_mat", normal_mat); suzanne.draw(refractive_shader); glEnable(GL_CULL_FACE); +#if POINT_LIGHTS // Draw point lights - // for (int i = 0; i < point_light_positions.size(); ++i) { - // model = glm::translate(glm::mat4(1.0f), point_light_positions[i]); - // model = glm::scale(model, glm::vec3(0.2f)); - // light_shader.activate(); - // light_shader.set_mat4("model", model); - // light_shader.set_vec3("light_diffuse", light_diffuse); - // light.draw(light_shader); - // } + for (int i = 0; i < point_light_positions.size(); ++i) { + model = glm::translate(glm::mat4(1.0f), point_light_positions[i]); + model = glm::scale(model, glm::vec3(0.2f)); + light_shader.activate(); + light_shader.set_mat4("model", model); + light_shader.set_vec3("light_diffuse", light_diffuse); + light.draw(light_shader); + } +#endif // Draw skybox glDisable(GL_CULL_FACE); @@ -521,8 +537,10 @@ int main() { skybox_shader.set_int("cubemap", 0); skybox.draw(skybox_shader); +#if WIREFRAME // wireframe mode - // glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +#endif // Post processing pass glBindFramebuffer(GL_FRAMEBUFFER, 0); @@ -549,12 +567,19 @@ int main() { } -Shader::Shader(const std::string &vert_file, const std::string &frag_file) { +Shader::Shader(const std::string &vert_file, const std::string &frag_file, const std::string &geo_file) { GLuint vert = load_and_compile_shader(vert_file, GL_VERTEX_SHADER); GLuint frag = load_and_compile_shader(frag_file, GL_FRAGMENT_SHADER); - link_program(vert, frag); + GLuint geo = 0; + if (geo_file.size() > 0) { + geo = load_and_compile_shader(geo_file, GL_GEOMETRY_SHADER); + } + link_program(vert, frag, geo); glDeleteShader(vert); glDeleteShader(frag); + if (geo > 0) { + glDeleteShader(geo); + } } Shader::~Shader() { @@ -604,10 +629,13 @@ void Shader::set_uniform_block_binding_point(const char *block_name, GLuint bind glUniformBlockBinding(program, block_index, binding_point); } -void Shader::link_program(GLuint vert, GLuint frag) { +void Shader::link_program(GLuint vert, GLuint frag, GLuint geo) { program = glCreateProgram(); glAttachShader(program, vert); glAttachShader(program, frag); + if (geo > 0) { + glAttachShader(program, geo); + } glLinkProgram(program); GLint program_linked;