Add ability to draw normals

This commit is contained in:
Abdelrahman Said 2024-12-30 17:31:54 +00:00
parent f65410b7ad
commit acefc1d254
4 changed files with 117 additions and 23 deletions

7
shaders/normal_frag.glsl Normal file
View File

@ -0,0 +1,7 @@
#version 330 core
out vec4 color;
void main() {
color = vec4(1.0, 1.0, 0.0, 1.0);
}

34
shaders/normal_geo.glsl Normal file
View File

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

25
shaders/normal_vert.glsl Normal file
View File

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

View File

@ -48,6 +48,10 @@
#define max(a, b) (a > b ? a : b) #define max(a, b) (a > b ? a : b)
#define clamp(v, a, b) (min(max(v, 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 { enum exit_codes : int {
EXIT_CODE_SUCCESS, EXIT_CODE_SUCCESS,
EXIT_CODE_SDL_INIT_FAILED, EXIT_CODE_SDL_INIT_FAILED,
@ -59,7 +63,7 @@ enum exit_codes : int {
class Shader { class Shader {
public: 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(); ~Shader();
void activate(); void activate();
void set_int(const char *name, int value); 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); void set_uniform_block_binding_point(const char *block_name, GLuint binding_point);
GLuint program; GLuint program;
private: 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); GLuint load_and_compile_shader(const std::string &filepath, GLenum shader_type);
std::string load_shader_from_file(const std::string &filepath); std::string load_shader_from_file(const std::string &filepath);
static const char *get_shader_type_string(GLenum shader_type); static const char *get_shader_type_string(GLenum shader_type);
@ -269,6 +273,7 @@ int main() {
Mesh screen = {screen_vertices, screen_indices, {}}; Mesh screen = {screen_vertices, screen_indices, {}};
Shader main_shader {"shaders/vert.glsl", "shaders/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 light_shader {"shaders/vert.glsl", "shaders/light_frag.glsl"};
Shader skybox_shader {"shaders/sb_vert.glsl", "shaders/sb_frag.glsl"}; Shader skybox_shader {"shaders/sb_vert.glsl", "shaders/sb_frag.glsl"};
Shader reflective_shader {"shaders/vert.glsl", "shaders/reflective_frag.glsl"}; Shader reflective_shader {"shaders/vert.glsl", "shaders/reflective_frag.glsl"};
@ -372,6 +377,7 @@ int main() {
// Set the shaders binding points // Set the shaders binding points
main_shader.set_uniform_block_binding_point ("Common", ubo_binding_point); 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); light_shader.set_uniform_block_binding_point ("Common", ubo_binding_point);
skybox_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); reflective_shader.set_uniform_block_binding_point("Common", ubo_binding_point);
@ -489,6 +495,14 @@ int main() {
main_shader.set_mat3("normal_mat", normal_mat); main_shader.set_mat3("normal_mat", normal_mat);
suzanne.draw(main_shader); suzanne.draw(main_shader);
#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)); model = glm::translate(glm::mat4(1.0f), glm::vec3(3.0f, 0.0f, 0.0f));
normal_mat = glm::transpose(glm::inverse(model)); normal_mat = glm::transpose(glm::inverse(model));
reflective_shader.set_mat4("model", model); reflective_shader.set_mat4("model", model);
@ -503,15 +517,17 @@ int main() {
suzanne.draw(refractive_shader); suzanne.draw(refractive_shader);
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
#if POINT_LIGHTS
// Draw point lights // Draw point lights
// for (int i = 0; i < point_light_positions.size(); ++i) { for (int i = 0; i < point_light_positions.size(); ++i) {
// model = glm::translate(glm::mat4(1.0f), point_light_positions[i]); model = glm::translate(glm::mat4(1.0f), point_light_positions[i]);
// model = glm::scale(model, glm::vec3(0.2f)); model = glm::scale(model, glm::vec3(0.2f));
// light_shader.activate(); light_shader.activate();
// light_shader.set_mat4("model", model); light_shader.set_mat4("model", model);
// light_shader.set_vec3("light_diffuse", light_diffuse); light_shader.set_vec3("light_diffuse", light_diffuse);
// light.draw(light_shader); light.draw(light_shader);
// } }
#endif
// Draw skybox // Draw skybox
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
@ -521,8 +537,10 @@ int main() {
skybox_shader.set_int("cubemap", 0); skybox_shader.set_int("cubemap", 0);
skybox.draw(skybox_shader); skybox.draw(skybox_shader);
#if WIREFRAME
// wireframe mode // wireframe mode
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
#endif
// Post processing pass // Post processing pass
glBindFramebuffer(GL_FRAMEBUFFER, 0); 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 vert = load_and_compile_shader(vert_file, GL_VERTEX_SHADER);
GLuint frag = load_and_compile_shader(frag_file, GL_FRAGMENT_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(vert);
glDeleteShader(frag); glDeleteShader(frag);
if (geo > 0) {
glDeleteShader(geo);
}
} }
Shader::~Shader() { 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); 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(); program = glCreateProgram();
glAttachShader(program, vert); glAttachShader(program, vert);
glAttachShader(program, frag); glAttachShader(program, frag);
if (geo > 0) {
glAttachShader(program, geo);
}
glLinkProgram(program); glLinkProgram(program);
GLint program_linked; GLint program_linked;