diff --git a/assets/krita/clay_texture_1k.kra b/assets/krita/clay_texture_1k.kra new file mode 100644 index 0000000..6cf5af0 Binary files /dev/null and b/assets/krita/clay_texture_1k.kra differ diff --git a/assets/krita/plaster_texture_1k.kra b/assets/krita/plaster_texture_1k.kra new file mode 100644 index 0000000..00a66e0 Binary files /dev/null and b/assets/krita/plaster_texture_1k.kra differ diff --git a/shaders/shader.frag b/shaders/shader.frag index a5a7214..0b548ee 100644 --- a/shaders/shader.frag +++ b/shaders/shader.frag @@ -3,6 +3,7 @@ in vec4 vertex_color; in vec2 texture_coord; in vec3 normal; +in vec3 frag_pos; out vec4 color; @@ -13,8 +14,16 @@ struct Directional_Light { float diffuse_intensity; }; +struct Material { + float shininess; + float specular_intensity; +}; + uniform sampler2D tex; uniform Directional_Light sun; +uniform Material material; +uniform vec3 eye_position; + void main() { vec4 ambient_color = vec4(sun.color, 1.0f) * sun.ambient_intensity; @@ -22,5 +31,18 @@ void main() { float diffuse_factor = max(dot(normalize(normal), normalize(sun.direction)), 0.0f); vec4 diffuse_color = vec4(sun.color, 1.0f) * sun.diffuse_intensity * diffuse_factor; - color = texture(tex, texture_coord) * (ambient_color + diffuse_color); + vec4 specular_color = vec4(0, 0, 0, 0); + + if (diffuse_factor > 0.0f) { + vec3 frag_to_eye = normalize(eye_position - frag_pos); + vec3 reflected_vertex = normalize(reflect(sun.direction, normalize(normal))); + float specular_factor = dot(frag_to_eye, reflected_vertex); + + if (specular_factor > 0) { + specular_factor = pow(specular_factor, material.shininess); + specular_color = vec4(sun.color * material.specular_intensity * specular_factor, 1.0f); + } + } + + color = texture(tex, texture_coord) * (ambient_color + diffuse_color + specular_color); } diff --git a/shaders/shader.vert b/shaders/shader.vert index a3e4c6c..b76fb16 100644 --- a/shaders/shader.vert +++ b/shaders/shader.vert @@ -7,6 +7,7 @@ layout (location = 2) in vec3 norm; out vec4 vertex_color; out vec2 texture_coord; out vec3 normal; +out vec3 frag_pos; uniform mat4 projection; uniform mat4 model; @@ -17,4 +18,5 @@ void main() { vertex_color = vec4(clamp(pos, 0.0f, 1.0f), 1.0f); texture_coord = tex; normal = mat3(transpose(inverse(model))) * norm; + frag_pos = (model * vec4(pos, 1.0)).xyz; } diff --git a/src/light.h b/src/light.h index 334e7c4..8ab0d12 100644 --- a/src/light.h +++ b/src/light.h @@ -16,4 +16,5 @@ struct Light { ~Light() = default; }; +// Some of these should be u32 void use_light(Light *light, f32 color_location, f32 ambient_intensity_location, f32 direction_location, f32 diffuse_intensity_location); diff --git a/src/main.cpp b/src/main.cpp index 291c8f3..edfe396 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,6 +6,7 @@ #include "camera.h" #include "texture.h" #include "light.h" +#include "material.h" static const char *vertex_shader_code = "shaders/shader.vert"; @@ -63,6 +64,9 @@ int main() { Texture plaster_texture = Texture((char *)"assets/textures/plaster_texture_1k.png"); load_texture(&plaster_texture); + Material shiny_material(1.0f, 32.0f); + Material dull_material(0.3f, 4.0f); + Light sun_light(Vector3(1.0f, 1.0f, 1.0f), 0.2f, Vector3(2.0f, -1.0, -2.0f), 1.0f); Matrix4 projection = glm::perspective(45.0f, (f32)window.buffer_width / (f32)window.buffer_height, 0.1f, 100.0f); @@ -96,32 +100,32 @@ int main() { shaders[0].uniform_diffuse_direction, shaders[0].uniform_diffuse_intensity ); + glUniformMatrix4fv(shaders[0].uniform_projection, 1, GL_FALSE, glm::value_ptr(projection)); + Matrix4 view = calculate_view_matrix(&camera); + glUniformMatrix4fv(shaders[0].uniform_view, 1, GL_FALSE, glm::value_ptr(view)); + glUniform3f(shaders[0].uniform_eye_position, camera.position.x, camera.position.y, camera.position.z); + { Matrix4 model(1.0f); - model = glm::translate(model, Vector3(0.0f, 0.0f, -2.5f)); - model = glm::scale(model, Vector3(0.4f, 0.4f, 1.0f)); + model = glm::translate(model, Vector3(0.0f, 3.0f, 2.5f)); + // model = glm::scale(model, Vector3(0.4f, 0.4f, 1.0f)); glUniformMatrix4fv(shaders[0].uniform_model, 1, GL_FALSE, glm::value_ptr(model)); - glUniformMatrix4fv(shaders[0].uniform_projection, 1, GL_FALSE, glm::value_ptr(projection)); use_texture(&clay_texture); + use_material(&shiny_material, shaders[0].uniform_shininess, shaders[0].uniform_specular_intensity); render_mesh(meshes[0]); } { Matrix4 model(1.0f); - model = glm::translate(model, Vector3(0.0f, 0.0f, -3.5f)); - model = glm::scale(model, Vector3(0.4f, 0.4f, 1.0f)); + model = glm::translate(model, Vector3(0.0f, 0.0f, 3.5f)); glUniformMatrix4fv(shaders[0].uniform_model, 1, GL_FALSE, glm::value_ptr(model)); - glUniformMatrix4fv(shaders[0].uniform_projection, 1, GL_FALSE, glm::value_ptr(projection)); use_texture(&plaster_texture); + use_material(&dull_material, shaders[0].uniform_shininess, shaders[0].uniform_specular_intensity); render_mesh(meshes[1]); } - Matrix4 view = calculate_view_matrix(&camera); - glUniformMatrix4fv(shaders[0].uniform_view, 1, GL_FALSE, glm::value_ptr(view)); - - glUseProgram(0); // We usually have two buffers, the first is hidden and that's diff --git a/src/material.cpp b/src/material.cpp new file mode 100644 index 0000000..23b5caf --- /dev/null +++ b/src/material.cpp @@ -0,0 +1,10 @@ +#include "material.h" + + +Material::Material(f32 specular_intensity, f32 shininess) : specular_intensity(specular_intensity), shininess(shininess) {} + +void use_material(Material *material, u32 shininess_location, u32 specular_intensity_location) { + glUniform1f(shininess_location, material->shininess); + glUniform1f(specular_intensity_location, material->specular_intensity); +} + diff --git a/src/material.h b/src/material.h new file mode 100644 index 0000000..7761e47 --- /dev/null +++ b/src/material.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include "math.h" + +/* +The kind of a thing +*/ +struct Material { + f32 shininess; + f32 specular_intensity; + + Material(f32 specular_intensity, f32 shininess); + ~Material() = default; +}; + +void use_material(Material *material, u32 shininess_location, u32 specular_intensity_location); diff --git a/src/mesh.h b/src/mesh.h index 39454c0..00e2cf6 100644 --- a/src/mesh.h +++ b/src/mesh.h @@ -3,6 +3,9 @@ #include "math.h" #include +/* +The shape of a thing +*/ struct Mesh { u32 VAO, VBO, IBO; u32 index_count; diff --git a/src/shader.cpp b/src/shader.cpp index 64ac064..fe781f0 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -64,13 +64,16 @@ bool create_shader(Shader *shader, const char *vertex_shader_path, const char *f shader->uniform_projection = glGetUniformLocation(shader->id, "projection"); shader->uniform_model = glGetUniformLocation(shader->id, "model"); shader->uniform_view = glGetUniformLocation(shader->id, "view"); + shader->uniform_eye_position = glGetUniformLocation(shader->id, "eye_position"); shader->uniform_ambient_color = glGetUniformLocation(shader->id, "sun.color"); shader->uniform_ambient_intensity = glGetUniformLocation(shader->id, "sun.ambient_intensity"); - shader->uniform_diffuse_direction = glGetUniformLocation(shader->id, "sun.direction"); shader->uniform_diffuse_intensity = glGetUniformLocation(shader->id, "sun.diffuse_intensity"); + shader->uniform_shininess = glGetUniformLocation(shader->id, "material.shininess"); + shader->uniform_specular_intensity = glGetUniformLocation(shader->id, "material.specular_intensity"); + return true; } diff --git a/src/shader.h b/src/shader.h index 5339245..0ee38d6 100644 --- a/src/shader.h +++ b/src/shader.h @@ -15,11 +15,17 @@ struct Shader { u32 uniform_projection; u32 uniform_model; u32 uniform_view; + u32 uniform_eye_position; + u32 uniform_ambient_color; u32 uniform_ambient_intensity; + u32 uniform_diffuse_direction; u32 uniform_diffuse_intensity; + u32 uniform_shininess; + u32 uniform_specular_intensity; + Shader(); ~Shader(); }; diff --git a/src/window.h b/src/window.h index 67fd18e..5d4bb61 100644 --- a/src/window.h +++ b/src/window.h @@ -9,7 +9,7 @@ #include "math.h" struct Window { - u32 width = 800, height = 600; + u32 width = 1024, height = 768; s32 buffer_width, buffer_height; GLFWwindow *gl_window = nullptr; bool ascii_keys[1024];