From 5200ba4dbef94d0113a8293ad1d807924b4ade7f Mon Sep 17 00:00:00 2001 From: elipzer Date: Fri, 14 Sep 2018 23:30:14 -0400 Subject: [PATCH] Specular Lighting Next up is attenuation --- OpenGLEngine/BuiltinTypes.h | 25 ++++++++++++++++++++++--- OpenGLEngine/Camera.h | 3 +++ OpenGLEngine/Camera2D.h | 1 - OpenGLEngine/Camera3D.h | 1 - OpenGLEngine/GLUtil.cpp | 11 +++++++++++ OpenGLEngine/GLUtil.h | 2 ++ OpenGLEngine/LitBatch.cpp | 15 +++++++++------ OpenGLEngine/LitFS.glsl | 14 +++++++++++++- OpenGLEngine/LitScene.cpp | 4 +++- OpenGLEngine/LitScene.h | 6 +++++- OpenGLEngine/LitVS.glsl | 5 ++++- OpenGLEngine/MeshGenerator.h | 11 +++++++++++ OpenGLEngine/MyBuiltinLitScene.cpp | 7 ++++++- 13 files changed, 89 insertions(+), 16 deletions(-) diff --git a/OpenGLEngine/BuiltinTypes.h b/OpenGLEngine/BuiltinTypes.h index 38e4908..203d214 100644 --- a/OpenGLEngine/BuiltinTypes.h +++ b/OpenGLEngine/BuiltinTypes.h @@ -16,6 +16,7 @@ namespace charcoal typedef vec4 ColorRGBA; typedef vec3 ColorRGB; typedef vec2 UV; + typedef float SpecularExponent; typedef unsigned int Index; @@ -37,12 +38,30 @@ namespace charcoal Normal normal; }; + struct PNSVertex + { + void set_position(const Position& position) { this->position = position; } + void set_normal(const Normal& normal) { this->normal = normal; } + void set_specular_exponent(const SpecularExponent& specular_exponent) { this->specular_exponent = specular_exponent; } + + Position position; + Normal normal; + SpecularExponent specular_exponent; + }; + // Other Data Types struct Light { - Light(const Position& position, const ColorRGB& ambient, const ColorRGB& diffuse) - : position(position), ambient(ambient), diffuse(diffuse) {} + Light( + const Position& position, + const ColorRGB& ambient, + const ColorRGB& diffuse + ) + : position(position), + ambient(ambient), + diffuse(diffuse) + {} Position position; ColorRGB ambient; @@ -55,7 +74,7 @@ namespace charcoal typedef Index BasicIndex; typedef Renderable BasicRenderable; - typedef PNVertex LitVertex; + typedef PNSVertex LitVertex; typedef Index LitIndex; typedef Renderable LitRenderable; } diff --git a/OpenGLEngine/Camera.h b/OpenGLEngine/Camera.h index f1298f0..8bd1146 100644 --- a/OpenGLEngine/Camera.h +++ b/OpenGLEngine/Camera.h @@ -15,11 +15,14 @@ namespace charcoal mat4 get_world_to_view_matrix() const { return m_projection_matrix * m_view_matrix; } + const vec3& get_position() const { return m_position; } + const mat4& get_view_matrix() const { return m_view_matrix; } const mat4& get_projection_matrix() const { return m_projection_matrix; } protected: + vec3 m_position; mat4 m_view_matrix; mat4 m_projection_matrix; }; diff --git a/OpenGLEngine/Camera2D.h b/OpenGLEngine/Camera2D.h index 962f568..7fbb772 100644 --- a/OpenGLEngine/Camera2D.h +++ b/OpenGLEngine/Camera2D.h @@ -29,6 +29,5 @@ namespace charcoal void update_scale(); vec3 m_size; - vec3 m_position; }; } diff --git a/OpenGLEngine/Camera3D.h b/OpenGLEngine/Camera3D.h index 5b58f8e..ac63ebc 100644 --- a/OpenGLEngine/Camera3D.h +++ b/OpenGLEngine/Camera3D.h @@ -42,7 +42,6 @@ namespace charcoal vec3 get_right() const { return vec3(m_right); } private: - vec3 m_position; vec4 m_forward; vec4 m_up; vec4 m_right; diff --git a/OpenGLEngine/GLUtil.cpp b/OpenGLEngine/GLUtil.cpp index 00bbfe8..ac1cddd 100644 --- a/OpenGLEngine/GLUtil.cpp +++ b/OpenGLEngine/GLUtil.cpp @@ -23,6 +23,16 @@ namespace charcoal glUniform1ui(uniform_index, value); } + void uniform_float(int uniform_index, float value) + { + glUniform1f(uniform_index, value); + } + + void uniform_vec3(int uniform_index, const vec3& value) + { + glUniform3fv(uniform_index, 1, &value[0]); + } + void uniform_matrix(int uniform_index, const mat4& matrix, bool transpose) { glUniformMatrix4fv(uniform_index, 1, transpose ? GL_TRUE : GL_FALSE, &matrix[0][0]); @@ -33,6 +43,7 @@ namespace charcoal const int position_size = 1; const int ambient_size = 1; const int diffuse_size = 1; + const int specular_exponent_size = 1; int current_location = uniform_index; for (std::vector::size_type i = 0; i < lights.size(); ++i) { diff --git a/OpenGLEngine/GLUtil.h b/OpenGLEngine/GLUtil.h index c43c918..88bfbc7 100644 --- a/OpenGLEngine/GLUtil.h +++ b/OpenGLEngine/GLUtil.h @@ -16,6 +16,8 @@ namespace charcoal void clear_screen(); void uniform_int(int uniform_index, int value); void uniform_uint(int uniform_index, unsigned int value); + void uniform_float(int uniform_index, float value); + void uniform_vec3(int uniform_index, const vec3& value); void uniform_matrix(int uniform_index, const mat4& matrix, bool transpose = false); void uniform_lights(int uniform_index, const std::vector& lights); // TODO: This may want to be moved somewhere else } diff --git a/OpenGLEngine/LitBatch.cpp b/OpenGLEngine/LitBatch.cpp index 4fa233d..f511ac3 100644 --- a/OpenGLEngine/LitBatch.cpp +++ b/OpenGLEngine/LitBatch.cpp @@ -9,24 +9,27 @@ namespace charcoal glBindBuffer(GL_ARRAY_BUFFER, m_vertex_vbo); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); + glEnableVertexAttribArray(2); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(LitVertex), (void*)(offsetof(LitVertex, position))); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(LitVertex), (void*)(offsetof(LitVertex, normal))); + glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, sizeof(LitVertex), (void*)(offsetof(LitVertex, specular_exponent))); glBindBuffer(GL_ARRAY_BUFFER, m_element_buffers[0]); - glEnableVertexAttribArray(2); glEnableVertexAttribArray(3); glEnableVertexAttribArray(4); glEnableVertexAttribArray(5); - glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(Poseable), (void*)(0 * sizeof(vec4))); - glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(Poseable), (void*)(1 * sizeof(vec4))); - glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(Poseable), (void*)(2 * sizeof(vec4))); - glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(Poseable), (void*)(3 * sizeof(vec4))); + glEnableVertexAttribArray(6); + glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(Poseable), (void*)(0 * sizeof(vec4))); + glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(Poseable), (void*)(1 * sizeof(vec4))); + glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(Poseable), (void*)(2 * sizeof(vec4))); + glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(Poseable), (void*)(3 * sizeof(vec4))); glVertexAttribDivisor(0, 0); // Send the mesh data once glVertexAttribDivisor(1, 0); // Send the mesh data once - glVertexAttribDivisor(2, 1); // Send the offset data for each instance drawn + glVertexAttribDivisor(2, 0); // Send the mesh data once glVertexAttribDivisor(3, 1); // Send the offset data for each instance drawn glVertexAttribDivisor(4, 1); // Send the offset data for each instance drawn glVertexAttribDivisor(5, 1); // Send the offset data for each instance drawn + glVertexAttribDivisor(6, 1); // Send the offset data for each instance drawn } } } \ No newline at end of file diff --git a/OpenGLEngine/LitFS.glsl b/OpenGLEngine/LitFS.glsl index 5a8484a..5ac787a 100644 --- a/OpenGLEngine/LitFS.glsl +++ b/OpenGLEngine/LitFS.glsl @@ -9,23 +9,35 @@ struct Light in vec3 fragment_position; in vec3 fragment_normal; +in float fragment_specular_exponent; #define MAX_LIGHTS 16 layout(location = 4) uniform Light lights[MAX_LIGHTS]; -layout(location = 52) uniform uint num_lights; +layout(location = 68) uniform uint num_lights; +layout(location = 69) uniform vec3 eye_position; out vec4 frag_color; + void main() { + vec3 hard_eye_position = vec3(0.0f, 0.0f, -5.0f); vec3 norm_normal = normalize(fragment_normal); + vec3 norm_eye_vector = normalize(eye_position - fragment_position); + vec3 accum = vec3(0.0); + float diffuse_multiplier; + float specular_multiplier; vec3 light_vector; + vec3 reflected_light_vector; for (uint i = 0; i < MAX_LIGHTS && i < num_lights; ++i) { light_vector = normalize(lights[i].position - fragment_position); + reflected_light_vector = reflect(-light_vector, norm_normal); diffuse_multiplier = clamp(dot(light_vector, norm_normal), 0.0, 1.0); + specular_multiplier = pow(clamp(dot(reflected_light_vector, norm_eye_vector), 0.0, 1.0), fragment_specular_exponent); accum += lights[i].ambient; accum += diffuse_multiplier * lights[i].diffuse; + accum += specular_multiplier * lights[i].diffuse; } frag_color = vec4(accum, 1.0); } \ No newline at end of file diff --git a/OpenGLEngine/LitScene.cpp b/OpenGLEngine/LitScene.cpp index 58a4105..e634720 100644 --- a/OpenGLEngine/LitScene.cpp +++ b/OpenGLEngine/LitScene.cpp @@ -42,7 +42,9 @@ namespace charcoal CHECK_GL_ERR(); glutil::uniform_lights(4, m_lights); CHECK_GL_ERR(); - glutil::uniform_uint(52, (unsigned int)m_lights.size()); + glutil::uniform_uint(68, (unsigned int)m_lights.size()); + CHECK_GL_ERR(); + glutil::uniform_vec3(69, m_p_camera->get_position()); CHECK_GL_ERR(); for (auto iter = m_batches.begin(); iter != m_batches.end(); ++iter) { diff --git a/OpenGLEngine/LitScene.h b/OpenGLEngine/LitScene.h index 0d203ce..511fec8 100644 --- a/OpenGLEngine/LitScene.h +++ b/OpenGLEngine/LitScene.h @@ -30,7 +30,11 @@ namespace charcoal protected: void set_camera(const Camera* p_camera) { m_p_camera = p_camera; } - void add_light(const Position& position, const ColorRGB& ambient, const ColorRGB& diffuse) + void add_light( + const Position& position, + const ColorRGB& ambient, + const ColorRGB& diffuse + ) { m_lights.emplace_back(position, ambient, diffuse); } diff --git a/OpenGLEngine/LitVS.glsl b/OpenGLEngine/LitVS.glsl index 0b55d95..17a06a4 100644 --- a/OpenGLEngine/LitVS.glsl +++ b/OpenGLEngine/LitVS.glsl @@ -1,12 +1,14 @@ #version 430 layout(location = 0) in vec3 vertex_position; layout(location = 1) in vec3 vertex_normal; -layout(location = 2) in mat4 model_to_world; +layout(location = 2) in float vertex_specular_exponent; +layout(location = 3) in mat4 model_to_world; layout(location = 0) uniform mat4 world_to_projection; out vec3 fragment_position; out vec3 fragment_normal; +out float fragment_specular_exponent; void main() { @@ -15,4 +17,5 @@ void main() gl_Position = world_to_projection * model_position; fragment_position = model_position.xyz; fragment_normal = model_normal.xyz; + fragment_specular_exponent = vertex_specular_exponent; } \ No newline at end of file diff --git a/OpenGLEngine/MeshGenerator.h b/OpenGLEngine/MeshGenerator.h index bf7f2b9..da31ecf 100644 --- a/OpenGLEngine/MeshGenerator.h +++ b/OpenGLEngine/MeshGenerator.h @@ -4,6 +4,7 @@ #include "MeshFactory.h" #include "Mesh.h" +#include "BuiltinTypes.h" // TODO: Consider a mesh generator for every render type (i.e. basic::meshgenerator, lit::meshgenerator, etc.) @@ -14,6 +15,16 @@ namespace charcoal // Uses MeshFactory to generate meshes for the builtin vertex types. namespace meshgenerator { + template + Mesh* apply_specular_exponent(Mesh* mesh, const SpecularExponent& specular_exponent) + { + for (unsigned int i = 0; i < mesh->vertex_count; ++i) + { + mesh->vertices[i].set_specular_exponent(specular_exponent); + } + return mesh; + } + template Mesh* gen_cube_p(const DrawMode& draw_mode, float width, float height, float depth) { diff --git a/OpenGLEngine/MyBuiltinLitScene.cpp b/OpenGLEngine/MyBuiltinLitScene.cpp index d86fed8..5552143 100644 --- a/OpenGLEngine/MyBuiltinLitScene.cpp +++ b/OpenGLEngine/MyBuiltinLitScene.cpp @@ -6,7 +6,12 @@ MyBuiltinLitScene::MyBuiltinLitScene(Application& application) : LitScene(application), - m_shape(meshgenerator::gen_cube_pn(DRAW_TRIANGLES, 2.0f, 2.0f, 2.0f), DrawMode::DRAW_TRIANGLES), + m_shape( + meshgenerator::apply_specular_exponent( + meshgenerator::gen_cube_pn(DRAW_TRIANGLES, 2.0f, 2.0f, 2.0f), + 2 + ), DrawMode::DRAW_TRIANGLES + ), m_camera((float)TAU_1_4, (float)m_screen_size.x / m_screen_size.y, 1.0f, 10.0f, vec3(0.0f, 0.0f, -5.0f)), m_batch(add_batch(&m_shape, 1)) {