From cc9db0598705595d55f631d5d7e6e93059ba89e8 Mon Sep 17 00:00:00 2001 From: Elipzer Date: Tue, 18 Sep 2018 16:55:32 -0400 Subject: [PATCH] Added Baseline for LitShadowedScene --- OpenGLEngine/BuiltinTypes.h | 4 ++ OpenGLEngine/LitShadowedBatch.cpp | 35 +++++++++++ OpenGLEngine/LitShadowedBatch.h | 30 ++++++++++ OpenGLEngine/LitShadowedFS.glsl | 58 ++++++++++++++++++ OpenGLEngine/LitShadowedScene.cpp | 49 +++++++++++++++ OpenGLEngine/LitShadowedScene.h | 53 +++++++++++++++++ OpenGLEngine/LitShadowedShaderProgram.h | 16 +++++ OpenGLEngine/LitShadowedVS.glsl | 28 +++++++++ OpenGLEngine/MyApplication.cpp | 8 ++- OpenGLEngine/MyApplication.h | 2 + OpenGLEngine/MyBuiltinLitShadowedScene.cpp | 69 ++++++++++++++++++++++ OpenGLEngine/MyBuiltinLitShadowedScene.h | 19 ++++++ OpenGLEngine/OpenGLEngine.vcxproj | 9 +++ OpenGLEngine/OpenGLEngine.vcxproj.filters | 33 +++++++++++ 14 files changed, 412 insertions(+), 1 deletion(-) create mode 100644 OpenGLEngine/LitShadowedBatch.cpp create mode 100644 OpenGLEngine/LitShadowedBatch.h create mode 100644 OpenGLEngine/LitShadowedFS.glsl create mode 100644 OpenGLEngine/LitShadowedScene.cpp create mode 100644 OpenGLEngine/LitShadowedScene.h create mode 100644 OpenGLEngine/LitShadowedShaderProgram.h create mode 100644 OpenGLEngine/LitShadowedVS.glsl create mode 100644 OpenGLEngine/MyBuiltinLitShadowedScene.cpp create mode 100644 OpenGLEngine/MyBuiltinLitShadowedScene.h diff --git a/OpenGLEngine/BuiltinTypes.h b/OpenGLEngine/BuiltinTypes.h index a06738e..0c2e1a7 100644 --- a/OpenGLEngine/BuiltinTypes.h +++ b/OpenGLEngine/BuiltinTypes.h @@ -110,6 +110,10 @@ namespace charcoal typedef Index LitIndex; typedef Renderable LitRenderable; + typedef PNMVertex LitShadowedVertex; + typedef Index LitShadowedIndex; + typedef Renderable LitShadowedRenderable; + typedef PTVertex TexturedVertex; typedef Index TexturedIndex; typedef TextureRenderable TexturedRenderable; diff --git a/OpenGLEngine/LitShadowedBatch.cpp b/OpenGLEngine/LitShadowedBatch.cpp new file mode 100644 index 0000000..4c5c274 --- /dev/null +++ b/OpenGLEngine/LitShadowedBatch.cpp @@ -0,0 +1,35 @@ +#include "LitShadowedBatch.h" + +namespace charcoal +{ + namespace builtin + { + void LitShadowedBatch::setup_vao() + { + 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, 4, GL_FLOAT, GL_FALSE, sizeof(LitVertex), (void*)(offsetof(LitVertex, material))); + glBindBuffer(GL_ARRAY_BUFFER, m_element_buffers[0]); + glEnableVertexAttribArray(3); + glEnableVertexAttribArray(4); + glEnableVertexAttribArray(5); + 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, 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/LitShadowedBatch.h b/OpenGLEngine/LitShadowedBatch.h new file mode 100644 index 0000000..b67e9ab --- /dev/null +++ b/OpenGLEngine/LitShadowedBatch.h @@ -0,0 +1,30 @@ +#pragma once + +#include "PoseableBatch.h" +#include "BuiltinTypes.h" + +namespace charcoal +{ + namespace builtin + { + class LitShadowedBatch : public PoseableBatch + { + public: + LitShadowedBatch( + LitRenderable* renderable, + int element_count + ) : PoseableBatch(renderable, element_count) + {} + + LitShadowedBatch( + 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/LitShadowedFS.glsl b/OpenGLEngine/LitShadowedFS.glsl new file mode 100644 index 0000000..b4bd0fb --- /dev/null +++ b/OpenGLEngine/LitShadowedFS.glsl @@ -0,0 +1,58 @@ +#version 430 + +struct Fragment +{ + vec3 position; + vec3 normal; + vec4 material; +}; + +struct Light +{ + vec3 position; + vec3 power; // x = ambient, y = diffuse, z = specular + vec3 ambient; + vec3 diffuse; + vec3 specular; + vec3 fade; // x = constant, y = linear, z = quadratic +}; + +in Fragment fragment; + +#define MAX_LIGHTS 16 +layout(location = 4) uniform vec3 eye_position; +layout(location = 5) uniform uint num_lights; +layout(location = 6) uniform Light lights[MAX_LIGHTS]; + +out vec4 frag_color; + +void main() +{ + vec3 accumulator = vec3(0.0); + + vec3 normal = normalize(fragment.normal); + + for (uint i = 0; i < MAX_LIGHTS && i < num_lights; ++i) + { + vec3 to_eye = eye_position - fragment.position; + vec3 to_light = lights[i].position - fragment.position; + + float dist = length(to_light); + vec3 to_light_norm = to_light / dist; // normalize(to_light); + + vec3 reflected = reflect(-to_light_norm, normal); + + float fade = lights[i].fade.x + lights[i].fade.y * dist + lights[i].fade.z * dist * dist; + + // Multipliers + // a = ambient, d = diffuse, s = specular + float a = lights[i].power.x * fragment.material.x / fade; + float d = lights[i].power.y * fragment.material.y / fade * clamp(dot(to_light_norm, normal), 0.0, 1.0); + float s = lights[i].power.z * fragment.material.z / fade * pow(clamp(dot(reflected, normal), 0.0, 1.0), clamp(fragment.material.w, 1.0, 1000.0)); // Seems like weird things happen if w is set to 0 and not clamped (maybe it is not exactly 0) + + vec3 color = a * lights[i].ambient + d * lights[i].diffuse + s * lights[i].specular; + accumulator += color; + } + + frag_color = vec4(accumulator, 1.0); +} \ No newline at end of file diff --git a/OpenGLEngine/LitShadowedScene.cpp b/OpenGLEngine/LitShadowedScene.cpp new file mode 100644 index 0000000..da2f22e --- /dev/null +++ b/OpenGLEngine/LitShadowedScene.cpp @@ -0,0 +1,49 @@ +#include "LitShadowedScene.h" + +#include "stdafx.h" + +#include "Util.h" +#include "GLUtil.h" +#include "MeshFactory.h" + +namespace charcoal +{ + namespace builtin + { + void LitShadowedScene::init() + { + for (auto iter = m_batches.begin(); iter != m_batches.end(); ++iter) + { + LitShadowedBatch& batch = *iter; + batch.init(); + add_prerenderable(&batch); + } + } + + void LitShadowedScene::use() + { + // TODO: move to glutil + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + } + + void LitShadowedScene::unuse() + { + + } + + void LitShadowedScene::render() + { + glutil::clear_screen(); + m_shader_program.use(); + glutil::uniform_matrix(0, m_p_camera->get_world_to_view_matrix()); + glutil::uniform_vec3(4, m_p_camera->get_position()); + glutil::uniform_uint(5, (unsigned int)m_lights.size()); + glutil::uniform_lights(6, m_lights); + for (auto iter = m_batches.begin(); iter != m_batches.end(); ++iter) + { + iter->render(); + } + } + } +} \ No newline at end of file diff --git a/OpenGLEngine/LitShadowedScene.h b/OpenGLEngine/LitShadowedScene.h new file mode 100644 index 0000000..782e0b1 --- /dev/null +++ b/OpenGLEngine/LitShadowedScene.h @@ -0,0 +1,53 @@ +#pragma once + +#include + +#include "AutoPrerenderingScene.h" +#include "BuiltinTypes.h" +#include "Camera.h" +#include "Batched.h" +#include "LitShadowedBatch.h" +#include "LitShadowedShaderProgram.h" + +namespace charcoal +{ + namespace builtin + { + // A scene lit by the Phong Reflection Model (See https://en.wikipedia.org/wiki/Phong_reflection_model ) + class LitShadowedScene : public AutoPrerenderingScene, public Batched + { + public: + LitShadowedScene(Application& application) : AutoPrerenderingScene(application) {} + virtual ~LitShadowedScene() {} + + void init() override; + + void use() override; + + void unuse() override; + + void render() override; + + protected: + void set_camera(const Camera* p_camera) { m_p_camera = p_camera; } + + Light& add_light( + const Position& position, + const Light::Power& power, + const ColorRGB ambient, + const ColorRGB diffuse, + const ColorRGB specular, + const Light::Fade& fade + ) + { + m_lights.emplace_back(position, power, ambient, diffuse, specular, fade); + return m_lights.back(); + } + + private: + LitShadowedShaderProgram m_shader_program; + const Camera* m_p_camera = nullptr; + std::vector m_lights; + }; + } +} \ No newline at end of file diff --git a/OpenGLEngine/LitShadowedShaderProgram.h b/OpenGLEngine/LitShadowedShaderProgram.h new file mode 100644 index 0000000..613634d --- /dev/null +++ b/OpenGLEngine/LitShadowedShaderProgram.h @@ -0,0 +1,16 @@ +#pragma once + +#include "VertexFragmentShaderProgram.h" + +namespace charcoal +{ + namespace builtin + { + // TODO: Add constatns for the uniform and vertex attribute locations (for all shader programs) + class LitShadowedShaderProgram : public VertexFragmentShaderProgram + { + public: + LitShadowedShaderProgram() : VertexFragmentShaderProgram(SHADER_PATH "LitShadowedVS.glsl", SHADER_PATH "LitShadowedFS.glsl") {} + }; + } +} diff --git a/OpenGLEngine/LitShadowedVS.glsl b/OpenGLEngine/LitShadowedVS.glsl new file mode 100644 index 0000000..5085434 --- /dev/null +++ b/OpenGLEngine/LitShadowedVS.glsl @@ -0,0 +1,28 @@ +#version 430 + +struct Fragment +{ + vec3 position; + vec3 normal; + vec4 material; +}; + +layout(location = 0) in vec3 vertex_position; +layout(location = 1) in vec3 vertex_normal; +layout(location = 2) in vec4 vertex_material; + +layout(location = 3) in mat4 model_to_world; + +layout(location = 0) uniform mat4 world_to_projection; + +out Fragment fragment; + +void main() +{ + 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; + fragment.material = vertex_material; +} \ No newline at end of file diff --git a/OpenGLEngine/MyApplication.cpp b/OpenGLEngine/MyApplication.cpp index b5765dc..5fc5da8 100644 --- a/OpenGLEngine/MyApplication.cpp +++ b/OpenGLEngine/MyApplication.cpp @@ -8,7 +8,8 @@ MyApplication::MyApplication(int width, int height) m_simple_cube_scene(*this), m_builtin_basic_cube_scene(*this), m_builtin_lit_scene(*this), - m_builtin_textured_scene(*this) + m_builtin_textured_scene(*this), + m_builtin_lit_shadowed_scene(*this) {} void MyApplication::init() @@ -20,6 +21,7 @@ void MyApplication::init() m_builtin_basic_cube_scene.init(); m_builtin_lit_scene.init(); m_builtin_textured_scene.init(); + m_builtin_lit_shadowed_scene.init(); m_p_current_scene = &m_basic_scene; m_p_current_scene->use(); @@ -55,6 +57,10 @@ void MyApplication::update(float delta_time, clock_t clock) { swap_scene(&m_builtin_textured_scene); } + else if (m_glfw_input_manager.is_key_pressed(GLFW_KEY_8)) + { + swap_scene(&m_builtin_lit_shadowed_scene); + } m_p_current_scene->update(delta_time, clock); } diff --git a/OpenGLEngine/MyApplication.h b/OpenGLEngine/MyApplication.h index 6a0323e..5679e8b 100644 --- a/OpenGLEngine/MyApplication.h +++ b/OpenGLEngine/MyApplication.h @@ -8,6 +8,7 @@ #include "MyBuiltinCubeScene.h" #include "MyBuiltinLitScene.h" #include "MyBuiltinTexturedScene.h" +#include "MyBuiltinLitShadowedScene.h" using namespace charcoal; @@ -39,5 +40,6 @@ private: MyBuiltinCubeScene m_builtin_basic_cube_scene; MyBuiltinLitScene m_builtin_lit_scene; MyBuiltinTexturedScene m_builtin_textured_scene; + MyBuiltinLitShadowedScene m_builtin_lit_shadowed_scene; }; diff --git a/OpenGLEngine/MyBuiltinLitShadowedScene.cpp b/OpenGLEngine/MyBuiltinLitShadowedScene.cpp new file mode 100644 index 0000000..982b5cd --- /dev/null +++ b/OpenGLEngine/MyBuiltinLitShadowedScene.cpp @@ -0,0 +1,69 @@ +#include "MyBuiltinLitShadowedScene.h" + +#include "MeshGenerator.h" + +#include "constants.h" + +MyBuiltinLitShadowedScene::MyBuiltinLitShadowedScene(Application& application) + : LitShadowedScene(application), + m_shape( + meshgenerator::set_material( + meshgenerator::gen_cube_pn(DRAW_TRIANGLES, 2.0f, 2.0f, 2.0f), + Material(1.0f, 1.0f, 0.2f, 1.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( + Position(0.0f, 2.0f, -2.0f), + Light::Power(0.2f, 1.0f, 1.0f), + ColorRGB(1.0f, 1.0f, 1.0f), + ColorRGB(1.0f, 1.0f, 1.0f), + ColorRGB(1.0f, 1.0f, 1.0f), + Light::Fade(1.0f, 0.1f, 0.01f) + ); +} + +void MyBuiltinLitShadowedScene::update(float delta_time, clock_t clock) +{ + float brightness; + float radians; + + clock_t c; + const clock_t intervals = 512 * CLOCKS_PER_SEC / 100; + const clock_t half_interval = 256 * CLOCKS_PER_SEC / 100; + c = clock % intervals; + if (c < half_interval) + brightness = (float)c / half_interval; + else + brightness = (float)(intervals - c) / half_interval; + + radians = (float)TAU * c / intervals; + + { + Poseable& pose = m_batch.get_pose(0); + pose.rotate(glm::normalize(vec3(1.0f, 1.0f, 0.0f)), (float)TAU_1_8 * delta_time); + pose.update_position(vec3(3 * (float)cos(radians), 0.0f, 0.0f)); + } + + vec3 camera_translation(0.0f, 0.0f, 0.0f); + + if (m_input_manager.is_key_down(GLFW_KEY_W)) camera_translation.y += 1; + if (m_input_manager.is_key_down(GLFW_KEY_S)) camera_translation.y -= 1; + if (m_input_manager.is_key_down(GLFW_KEY_A)) camera_translation.x -= 1; + if (m_input_manager.is_key_down(GLFW_KEY_D)) camera_translation.x += 1; + if (m_input_manager.is_key_down(GLFW_KEY_Q)) camera_translation.z -= 1; + if (m_input_manager.is_key_down(GLFW_KEY_E)) camera_translation.z += 1; + + float camera_rotation = 0.0f; + if (m_input_manager.is_key_down(GLFW_KEY_Z)) camera_rotation += 1; + if (m_input_manager.is_key_down(GLFW_KEY_C)) camera_rotation -= 1; + + m_camera.translate(camera_translation * delta_time); + m_camera.rotate(vec3(0.0f, 1.0f, 0.0f), camera_rotation * (float)TAU_1_8 * delta_time); +} + diff --git a/OpenGLEngine/MyBuiltinLitShadowedScene.h b/OpenGLEngine/MyBuiltinLitShadowedScene.h new file mode 100644 index 0000000..9203205 --- /dev/null +++ b/OpenGLEngine/MyBuiltinLitShadowedScene.h @@ -0,0 +1,19 @@ +#pragma once + +#include "LitShadowedScene.h" +#include "BuiltinCamera3D.h" + +using namespace charcoal; +using namespace charcoal::builtin; + +class MyBuiltinLitShadowedScene : public LitShadowedScene +{ +public: + MyBuiltinLitShadowedScene(Application& application); + + void update(float delta_time, clock_t clock) override; +private: + LitShadowedRenderable m_shape; + builtin::Camera3D m_camera; + LitShadowedBatch& m_batch; +}; \ No newline at end of file diff --git a/OpenGLEngine/OpenGLEngine.vcxproj b/OpenGLEngine/OpenGLEngine.vcxproj index 94642cb..2519a8d 100644 --- a/OpenGLEngine/OpenGLEngine.vcxproj +++ b/OpenGLEngine/OpenGLEngine.vcxproj @@ -160,12 +160,15 @@ + + + @@ -207,8 +210,12 @@ + + + + @@ -247,6 +254,8 @@ + + diff --git a/OpenGLEngine/OpenGLEngine.vcxproj.filters b/OpenGLEngine/OpenGLEngine.vcxproj.filters index e6acbf9..879f2bc 100644 --- a/OpenGLEngine/OpenGLEngine.vcxproj.filters +++ b/OpenGLEngine/OpenGLEngine.vcxproj.filters @@ -79,6 +79,12 @@ {4c6497d4-160a-45a1-a23b-7bf905de0824} + + {2f2c0657-4ba3-4314-86dd-a600f533f746} + + + {ca87b30d-8b69-4c09-90a5-1fe317322c4c} + @@ -174,6 +180,15 @@ Source Files\Engine + + Source Files\Engine\builtin\LitShadowed + + + Source Files\Engine\builtin\LitShadowed + + + Source Files\Example\Application + @@ -344,6 +359,18 @@ Header Files\Engine\builtin + + Header Files\Engine\builtin\LitShadowed + + + Header Files\Engine\builtin\LitShadowed + + + Header Files\Engine\builtin\LitShadowed + + + Header Files\Example\Application + @@ -376,5 +403,11 @@ Source Files\Engine\builtin\Shaders + + Source Files\Engine\builtin\Shaders + + + Source Files\Engine\builtin\Shaders + \ No newline at end of file