From 9920dfc25b942f7fb411a2e6cf99b3f01b2deab5 Mon Sep 17 00:00:00 2001 From: elipzer Date: Fri, 14 Sep 2018 21:29:05 -0400 Subject: [PATCH] Added Diffuse Light to LitScene YES! FINALLY LIGHTING! Next up is specular light! --- OpenGLEngine/BasicBatch.cpp | 29 ++++++++++++++++++++ OpenGLEngine/BasicBatch.h | 30 +++++++++++++++++++++ OpenGLEngine/BasicScene.h | 1 + OpenGLEngine/BuiltinTypes.h | 7 ++--- OpenGLEngine/GLUtil.cpp | 6 +++++ OpenGLEngine/LitBatch.cpp | 32 +++++++++++++++++++++++ OpenGLEngine/LitBatch.h | 30 +++++++++++++++++++++ OpenGLEngine/LitFS.glsl | 15 +++++++++-- OpenGLEngine/LitScene.cpp | 3 ++- OpenGLEngine/LitScene.h | 6 ++++- OpenGLEngine/LitVS.glsl | 12 +++++++-- OpenGLEngine/MyBuiltinLitScene.cpp | 6 ++--- OpenGLEngine/OpenGLEngine.vcxproj | 4 +++ OpenGLEngine/OpenGLEngine.vcxproj.filters | 12 +++++++++ OpenGLEngine/PoseableBatch.h | 27 ++----------------- OpenGLEngine/Shader.cpp | 10 +++---- OpenGLEngine/ShaderProgram.cpp | 16 +++++++++++- 17 files changed, 203 insertions(+), 43 deletions(-) create mode 100644 OpenGLEngine/BasicBatch.cpp create mode 100644 OpenGLEngine/BasicBatch.h create mode 100644 OpenGLEngine/LitBatch.cpp create mode 100644 OpenGLEngine/LitBatch.h diff --git a/OpenGLEngine/BasicBatch.cpp b/OpenGLEngine/BasicBatch.cpp new file mode 100644 index 0000000..128ac8c --- /dev/null +++ b/OpenGLEngine/BasicBatch.cpp @@ -0,0 +1,29 @@ +#include "BasicBatch.h" + +namespace charcoal +{ + namespace builtin + { + void BasicBatch::setup_vao() + { + glBindBuffer(GL_ARRAY_BUFFER, m_vertex_vbo); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(BasicVertex), NULL); + glBindBuffer(GL_ARRAY_BUFFER, m_element_buffers[0]); + glEnableVertexAttribArray(1); + glEnableVertexAttribArray(2); + glEnableVertexAttribArray(3); + glEnableVertexAttribArray(4); + glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(Poseable), (void*)(0 * sizeof(vec4))); + glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(Poseable), (void*)(1 * sizeof(vec4))); + glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(Poseable), (void*)(2 * sizeof(vec4))); + glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(Poseable), (void*)(3 * sizeof(vec4))); + + glVertexAttribDivisor(0, 0); // Send the mesh data once + glVertexAttribDivisor(1, 1); // Send the offset data for each instance drawn + glVertexAttribDivisor(2, 1); // Send the offset data for each instance drawn + glVertexAttribDivisor(3, 1); // Send the offset data for each instance drawn + glVertexAttribDivisor(4, 1); // Send the offset data for each instance drawn + } + } +} diff --git a/OpenGLEngine/BasicBatch.h b/OpenGLEngine/BasicBatch.h new file mode 100644 index 0000000..3a84228 --- /dev/null +++ b/OpenGLEngine/BasicBatch.h @@ -0,0 +1,30 @@ +#pragma once + +#include "PoseableBatch.h" +#include "BuiltinTypes.h" + +namespace charcoal +{ + namespace builtin + { + class BasicBatch : public PoseableBatch + { + public: + BasicBatch( + BasicRenderable* renderable, + int element_count + ) : PoseableBatch(renderable, element_count) + {} + + BasicBatch( + BasicRenderable* renderable, + int element_count, + int element_render_count + ) : PoseableBatch(renderable, element_count, element_render_count) + {} + + protected: + void setup_vao() override; + }; + } +} \ No newline at end of file diff --git a/OpenGLEngine/BasicScene.h b/OpenGLEngine/BasicScene.h index 4a91590..1a64ffc 100644 --- a/OpenGLEngine/BasicScene.h +++ b/OpenGLEngine/BasicScene.h @@ -8,6 +8,7 @@ #include "BuiltinTypes.h" #include "Camera2D.h" #include "Batched.h" +#include "BasicBatch.h" #include "constants.h" diff --git a/OpenGLEngine/BuiltinTypes.h b/OpenGLEngine/BuiltinTypes.h index 410b3b7..38e4908 100644 --- a/OpenGLEngine/BuiltinTypes.h +++ b/OpenGLEngine/BuiltinTypes.h @@ -41,9 +41,12 @@ namespace charcoal struct Light { - Light(const ColorRGB& ambient) : ambient(ambient) {} + Light(const Position& position, const ColorRGB& ambient, const ColorRGB& diffuse) + : position(position), ambient(ambient), diffuse(diffuse) {} + Position position; ColorRGB ambient; + ColorRGB diffuse; }; // typedefs for builtin types @@ -51,11 +54,9 @@ namespace charcoal typedef PVertex BasicVertex; typedef Index BasicIndex; typedef Renderable BasicRenderable; - typedef PoseableBatch BasicBatch; typedef PNVertex LitVertex; typedef Index LitIndex; typedef Renderable LitRenderable; - typedef PoseableBatch LitBatch; } } \ No newline at end of file diff --git a/OpenGLEngine/GLUtil.cpp b/OpenGLEngine/GLUtil.cpp index 3bd3db4..00bbfe8 100644 --- a/OpenGLEngine/GLUtil.cpp +++ b/OpenGLEngine/GLUtil.cpp @@ -30,12 +30,18 @@ namespace charcoal void uniform_lights(int uniform_index, const std::vector& lights) { + const int position_size = 1; const int ambient_size = 1; + const int diffuse_size = 1; int current_location = uniform_index; for (std::vector::size_type i = 0; i < lights.size(); ++i) { + glUniform3fv(current_location, 1, &lights[i].position[0]); + current_location += position_size; glUniform3fv(current_location, 1, &lights[i].ambient[0]); current_location += ambient_size; + glUniform3fv(current_location, 1, &lights[i].diffuse[0]); + current_location += diffuse_size; } } } diff --git a/OpenGLEngine/LitBatch.cpp b/OpenGLEngine/LitBatch.cpp new file mode 100644 index 0000000..4fa233d --- /dev/null +++ b/OpenGLEngine/LitBatch.cpp @@ -0,0 +1,32 @@ +#include "LitBatch.h" + +namespace charcoal +{ + namespace builtin + { + void LitBatch::setup_vao() + { + glBindBuffer(GL_ARRAY_BUFFER, m_vertex_vbo); + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + 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))); + 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))); + + 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(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 + } + } +} \ No newline at end of file diff --git a/OpenGLEngine/LitBatch.h b/OpenGLEngine/LitBatch.h new file mode 100644 index 0000000..f20afa1 --- /dev/null +++ b/OpenGLEngine/LitBatch.h @@ -0,0 +1,30 @@ +#pragma once + +#include "PoseableBatch.h" +#include "BuiltinTypes.h" + +namespace charcoal +{ + namespace builtin + { + class LitBatch : public PoseableBatch + { + public: + LitBatch( + LitRenderable* renderable, + int element_count + ) : PoseableBatch(renderable, element_count) + {} + + LitBatch( + LitRenderable* renderable, + int element_count, + int element_render_count + ) : PoseableBatch(renderable, element_count, element_render_count) + {} + + protected: + void setup_vao() override; + }; + } +} \ No newline at end of file diff --git a/OpenGLEngine/LitFS.glsl b/OpenGLEngine/LitFS.glsl index 2ea7300..5a8484a 100644 --- a/OpenGLEngine/LitFS.glsl +++ b/OpenGLEngine/LitFS.glsl @@ -2,19 +2,30 @@ struct Light { + vec3 position; vec3 ambient; + vec3 diffuse; }; +in vec3 fragment_position; +in vec3 fragment_normal; + #define MAX_LIGHTS 16 layout(location = 4) uniform Light lights[MAX_LIGHTS]; -layout(location = 20) uniform uint num_lights; +layout(location = 52) uniform uint num_lights; out vec4 frag_color; void main() { + vec3 norm_normal = normalize(fragment_normal); vec3 accum = vec3(0.0); + float diffuse_multiplier; + vec3 light_vector; for (uint i = 0; i < MAX_LIGHTS && i < num_lights; ++i) { - accum = accum + lights[i].ambient; + light_vector = normalize(lights[i].position - fragment_position); + diffuse_multiplier = clamp(dot(light_vector, norm_normal), 0.0, 1.0); + accum += lights[i].ambient; + accum += diffuse_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 c3ad07a..58a4105 100644 --- a/OpenGLEngine/LitScene.cpp +++ b/OpenGLEngine/LitScene.cpp @@ -35,13 +35,14 @@ namespace charcoal void LitScene::render() { glutil::clear_screen(); + CHECK_GL_ERR(); m_shader_program.use(); CHECK_GL_ERR(); glutil::uniform_matrix(0, m_p_camera->get_world_to_view_matrix()); CHECK_GL_ERR(); glutil::uniform_lights(4, m_lights); CHECK_GL_ERR(); - glutil::uniform_uint(20, m_lights.size()); + glutil::uniform_uint(52, (unsigned int)m_lights.size()); 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 8059aad..0d203ce 100644 --- a/OpenGLEngine/LitScene.h +++ b/OpenGLEngine/LitScene.h @@ -6,6 +6,7 @@ #include "BuiltinTypes.h" #include "Camera.h" #include "Batched.h" +#include "LitBatch.h" #include "LitShaderProgram.h" namespace charcoal @@ -29,7 +30,10 @@ namespace charcoal protected: void set_camera(const Camera* p_camera) { m_p_camera = p_camera; } - void add_light(const ColorRGB& ambient) { m_lights.emplace_back(ambient); } + void add_light(const Position& position, const ColorRGB& ambient, const ColorRGB& diffuse) + { + m_lights.emplace_back(position, ambient, diffuse); + } private: LitShaderProgram m_shader_program; diff --git a/OpenGLEngine/LitVS.glsl b/OpenGLEngine/LitVS.glsl index 70f1cdf..0b55d95 100644 --- a/OpenGLEngine/LitVS.glsl +++ b/OpenGLEngine/LitVS.glsl @@ -1,10 +1,18 @@ #version 430 layout(location = 0) in vec3 vertex_position; -layout(location = 1) in mat4 model_to_world; +layout(location = 1) in vec3 vertex_normal; +layout(location = 2) in mat4 model_to_world; layout(location = 0) uniform mat4 world_to_projection; +out vec3 fragment_position; +out vec3 fragment_normal; + void main() { - gl_Position = world_to_projection * model_to_world * vec4(vertex_position, 1.0); + vec4 model_position = model_to_world * vec4(vertex_position, 1.0); + vec4 model_normal = model_to_world * vec4(vertex_normal, 0.0); + gl_Position = world_to_projection * model_position; + fragment_position = model_position.xyz; + fragment_normal = model_normal.xyz; } \ No newline at end of file diff --git a/OpenGLEngine/MyBuiltinLitScene.cpp b/OpenGLEngine/MyBuiltinLitScene.cpp index cc665a7..d86fed8 100644 --- a/OpenGLEngine/MyBuiltinLitScene.cpp +++ b/OpenGLEngine/MyBuiltinLitScene.cpp @@ -6,15 +6,15 @@ MyBuiltinLitScene::MyBuiltinLitScene(Application& application) : LitScene(application), - m_shape(meshgenerator::gen_cube_p(DRAW_TRIANGLES, 2.0f, 2.0f, 2.0f), DrawMode::DRAW_TRIANGLES), + m_shape(meshgenerator::gen_cube_pn(DRAW_TRIANGLES, 2.0f, 2.0f, 2.0f), 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)) { add_prerenderable(&m_camera); set_camera(&m_camera); - add_light(ColorRGB(0.0f, 0.0f, 1.0f)); - add_light(ColorRGB(0.0f, 1.0f, 0.0f)); + // Something is off here... The light seems to be rotating... + add_light(Position(0.0f, 2.0f, -2.0f), ColorRGB(0.2f, 0.2f, 0.2f), ColorRGB(1.0f, 1.0f, 1.0f)); } void MyBuiltinLitScene::update(float delta_time, clock_t clock) diff --git a/OpenGLEngine/OpenGLEngine.vcxproj b/OpenGLEngine/OpenGLEngine.vcxproj index 35ae1b2..875c13c 100644 --- a/OpenGLEngine/OpenGLEngine.vcxproj +++ b/OpenGLEngine/OpenGLEngine.vcxproj @@ -153,10 +153,12 @@ + + @@ -183,6 +185,7 @@ + @@ -197,6 +200,7 @@ + diff --git a/OpenGLEngine/OpenGLEngine.vcxproj.filters b/OpenGLEngine/OpenGLEngine.vcxproj.filters index ae3961a..ff626ea 100644 --- a/OpenGLEngine/OpenGLEngine.vcxproj.filters +++ b/OpenGLEngine/OpenGLEngine.vcxproj.filters @@ -138,6 +138,12 @@ Source Files\Engine\Rendering + + Source Files\Engine\builtin + + + Source Files\Engine\builtin + @@ -275,6 +281,12 @@ Header Files\Example\Application + + Header Files\Engine\builtin + + + Header Files\Engine\builtin + diff --git a/OpenGLEngine/PoseableBatch.h b/OpenGLEngine/PoseableBatch.h index 86bf62a..a102d25 100644 --- a/OpenGLEngine/PoseableBatch.h +++ b/OpenGLEngine/PoseableBatch.h @@ -33,35 +33,13 @@ namespace charcoal const Poseable& get_pose(int index) const { return m_pose_elements[index]; } protected: - void setup_element_buffers() override + void setup_element_buffers() { glBindBuffer(GL_ARRAY_BUFFER, charcoal::Batch::m_element_buffers[0]); glBufferData(GL_ARRAY_BUFFER, m_pose_elements.size() * sizeof(Poseable), NULL, GL_STREAM_DRAW); } - void setup_vao() override - { - glBindBuffer(GL_ARRAY_BUFFER, charcoal::Batch::m_vertex_vbo); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexType), NULL); - glBindBuffer(GL_ARRAY_BUFFER, charcoal::Batch::m_element_buffers[0]); - glEnableVertexAttribArray(1); - glEnableVertexAttribArray(2); - glEnableVertexAttribArray(3); - glEnableVertexAttribArray(4); - glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(Poseable), (void*)(0 * sizeof(vec4))); - glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(Poseable), (void*)(1 * sizeof(vec4))); - glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(Poseable), (void*)(2 * sizeof(vec4))); - glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(Poseable), (void*)(3 * sizeof(vec4))); - - glVertexAttribDivisor(0, 0); // Send the mesh data once - glVertexAttribDivisor(1, 1); // Send the offset data for each instance drawn - glVertexAttribDivisor(2, 1); // Send the offset data for each instance drawn - glVertexAttribDivisor(3, 1); // Send the offset data for each instance drawn - glVertexAttribDivisor(4, 1); // Send the offset data for each instance drawn - } - - void update_element_buffers() override + void update_element_buffers() { // TODO: There are probably better ways to do this. Should check with the old engine to see what I did there. glBindBuffer(GL_ARRAY_BUFFER, charcoal::Batch::m_element_buffers[0]); @@ -69,7 +47,6 @@ namespace charcoal glBufferSubData(GL_ARRAY_BUFFER, 0, m_pose_elements.size() * sizeof(Poseable), m_pose_elements.data()); } - private: std::vector m_pose_elements; }; } diff --git a/OpenGLEngine/Shader.cpp b/OpenGLEngine/Shader.cpp index bc04b80..1efa43b 100644 --- a/OpenGLEngine/Shader.cpp +++ b/OpenGLEngine/Shader.cpp @@ -31,12 +31,12 @@ namespace charcoal glGetShaderiv(m_shader, GL_COMPILE_STATUS, &compiled); if (compiled != GL_TRUE) { - char buffer[1024]; - GLsizei log_length; - glGetShaderInfoLog(m_shader, 1023, &log_length, buffer); - buffer[log_length] = '\0'; // Add null terminator + GLsizei log_length = 0; + GLchar message[1024]; + glGetShaderInfoLog(m_shader, 1023, &log_length, message); + message[log_length] = '\0'; // Add null terminator OutputDebugString("Error Compiling Shader:\n"); - OutputDebugString(buffer); + OutputDebugString(message); OutputDebugString("\nSource:\n"); OutputDebugString(source.c_str()); OutputDebugString("\n"); diff --git a/OpenGLEngine/ShaderProgram.cpp b/OpenGLEngine/ShaderProgram.cpp index 702de4b..6b8d747 100644 --- a/OpenGLEngine/ShaderProgram.cpp +++ b/OpenGLEngine/ShaderProgram.cpp @@ -19,7 +19,21 @@ namespace charcoal void ShaderProgram::link() { glLinkProgram(m_program); - // TODO: Error handling + + GLint program_linked; + glGetProgramiv(m_program, GL_LINK_STATUS, &program_linked); + if (program_linked != GL_TRUE) + { + GLsizei log_length = 0; + GLchar message[1024]; + glGetProgramInfoLog(m_program, 1023, &log_length, message); + message[log_length] = '\0'; // Add null terminator + OutputDebugString("Error Linking Shader Program:\n"); + OutputDebugString(message); + OutputDebugString("\n"); + throw EXCEPTION("Error linking Shader Program."); + } + } void ShaderProgram::use() const