From 4a866fdcd4838945079391b74e59a0c19daf0bb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20Petter=20Sk=C3=A5lerud?= <np_skalerud@hotmail.com> Date: Sun, 24 Mar 2019 12:29:31 +0100 Subject: [PATCH] Added support for colored point lights. Updated RenderSystem, shaders and components for colored light support. Tried working on the Utility::Color struct, still WIP. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nils Petter Skålerud <np_skalerud@hotmail.com> --- Data/Shaders/Mesh/Mesh.frag | 21 ++++---- Data/Shaders/Mesh/Mesh.vert | 2 +- src/Engine/Application.cpp | 2 - src/Engine/Components/PointLight.cpp | 3 +- src/Engine/Components/PointLight.hpp | 2 + src/Engine/Engine.cpp | 4 ++ src/Engine/Renderer/OpenGL.cpp | 26 +++++++-- src/Engine/Renderer/Renderer.hpp | 13 ++--- src/Engine/Systems/RenderSystem.cpp | 7 ++- src/Engine/Utility/Color.hpp | 81 ++++++++++++++++++++++++++-- 10 files changed, 130 insertions(+), 31 deletions(-) diff --git a/Data/Shaders/Mesh/Mesh.frag b/Data/Shaders/Mesh/Mesh.frag index 9adfd48..8c4156b 100644 --- a/Data/Shaders/Mesh/Mesh.frag +++ b/Data/Shaders/Mesh/Mesh.frag @@ -2,13 +2,15 @@ layout(std140, binding = 0) uniform CameraData { - vec4 wsPosition; + vec3 wsPosition; mat4 viewProjection; } cameraData; layout(std140, binding = 1) uniform LightData { + vec4 ambientLight; uint pointLightCount; + vec4 pointLightIntensity[10]; vec4 pointLightPos[10]; } lightData; @@ -23,26 +25,25 @@ layout(location = 0) out vec4 frag_color; void main() { - vec3 pointToCamera = cameraData.wsPosition.xyz - fragData.wsPosition; + vec3 pointToCamera = cameraData.wsPosition - fragData.wsPosition; vec3 pointToCameraDir = normalize(pointToCamera); - float test = 0.0; + vec3 diffuse; + vec3 specular; for (int i = 0; i < lightData.pointLightCount; i++) { vec3 pointToLight = lightData.pointLightPos[i].xyz - fragData.wsPosition; vec3 pointToLightDir = normalize(pointToLight); - float diff = max(0, dot(pointToLightDir, fragData.wsNormal)); - test += diff; + diffuse += max(0, dot(pointToLightDir, fragData.wsNormal)) * vec3(lightData.pointLightIntensity[i]); vec3 lightToPointDir = -pointToLightDir; vec3 reflectDir = reflect(lightToPointDir, fragData.wsNormal); - float spec = pow(max(dot(pointToCameraDir, reflectDir), 0.0), 50); - - test += spec; - + const float coefficient = 50; + specular += pow(max(dot(pointToCameraDir, reflectDir), 0.0), coefficient) * vec3(1); } - frag_color = vec4(test); + + frag_color = vec4(vec3(lightData.ambientLight) + diffuse + specular, 1.0); } diff --git a/Data/Shaders/Mesh/Mesh.vert b/Data/Shaders/Mesh/Mesh.vert index af8162a..0c2a91e 100644 --- a/Data/Shaders/Mesh/Mesh.vert +++ b/Data/Shaders/Mesh/Mesh.vert @@ -6,7 +6,7 @@ layout(location = 2) in vec3 vtxNormal; layout(std140, binding = 0) uniform CameraData { - vec4 wsPosition; + vec3 wsPosition; mat4 viewProjection; } cameraData; diff --git a/src/Engine/Application.cpp b/src/Engine/Application.cpp index 72df58e..a30f9e5 100644 --- a/src/Engine/Application.cpp +++ b/src/Engine/Application.cpp @@ -23,8 +23,6 @@ namespace Engine Application::API3D activeAPI; void* windowHandle = nullptr; - - }; static std::unique_ptr<Data> data; diff --git a/src/Engine/Components/PointLight.cpp b/src/Engine/Components/PointLight.cpp index da60b31..9f42003 100644 --- a/src/Engine/Components/PointLight.cpp +++ b/src/Engine/Components/PointLight.cpp @@ -11,7 +11,8 @@ namespace Engine PointLight::PointLight(SceneObject& owningObject) : ParentType(owningObject), positionOffset(), - intensity(1) + intensity(1), + color{1.f, 1.f, 1.f} { } diff --git a/src/Engine/Components/PointLight.hpp b/src/Engine/Components/PointLight.hpp index 5bbe42c..edf6078 100644 --- a/src/Engine/Components/PointLight.hpp +++ b/src/Engine/Components/PointLight.hpp @@ -6,6 +6,7 @@ #include "DMath/Vector/Vector.hpp" #include "DMath/Matrix/Matrix.hpp" +#include "../Utility/Color.hpp" namespace Engine { @@ -20,6 +21,7 @@ namespace Engine ~PointLight(); float intensity; + Math::Vector3D color; Math::Vector3D positionOffset; [[nodiscard]] Math::Matrix<4, 3> GetModel_Reduced(Space space) const; diff --git a/src/Engine/Engine.cpp b/src/Engine/Engine.cpp index a89788a..27a9e38 100644 --- a/src/Engine/Engine.cpp +++ b/src/Engine/Engine.cpp @@ -56,11 +56,14 @@ void Engine::Core::Run() Input::Core::Initialize(); Physics2D::Core::Initialize(); + Renderer::CreateInfo rendererCreateInfo; rendererCreateInfo.preferredAPI = Renderer::API::OpenGL; rendererCreateInfo.surfaceDimensions = Application::GetWindowSize(); rendererCreateInfo.surfaceHandle = Application::Core::GetMainWindowHandle(); + rendererCreateInfo.openGLCreateInfo.glSwapBuffers = Application::Core::GL_SwapWindow; + Renderer::Core::Initialize(std::move(rendererCreateInfo)); // Create scene and make viewport 0 point to scene 0. @@ -89,6 +92,7 @@ void Engine::Core::Run() auto& lightObj = scene1.NewSceneObject(); lightObj.transform.localPosition = { 2.5f, 2.5f, 2.5f }; Components::PointLight& light1 = lightObj.AddComponent<Components::PointLight>().first.get(); + light1.color = { 1.f, 0.5f, 0.f }; auto& mesh3 = lightObj.AddComponent<Components::MeshRenderer>().first.get(); mesh3.SetMesh(Asset::Mesh::Cube); mesh3.scale = { 0.1f, 0.1f, 0.1f }; diff --git a/src/Engine/Renderer/OpenGL.cpp b/src/Engine/Renderer/OpenGL.cpp index 8648cc9..13e5bcd 100644 --- a/src/Engine/Renderer/OpenGL.cpp +++ b/src/Engine/Renderer/OpenGL.cpp @@ -55,14 +55,17 @@ namespace Engine struct Engine::Renderer::OpenGL::CameraDataUBO { - Math::Vector4D wsPosition; + Math::Vector3D wsPosition; + float padding1; Math::Matrix<4, 4, float> viewProjection; }; struct Engine::Renderer::OpenGL::LightDataUBO { + Math::Vector4D ambientLight; uint32_t pointLightCount; std::array<uint32_t, 3> padding1; + std::array<Math::Vector4D, 10> pointLightIntensity; std::array<Math::Vector4D, 10> pointLightPos; }; @@ -306,6 +309,9 @@ void Engine::Renderer::OpenGL::Initialize(std::any& apiData, CreateInfo&& create glEnable(GL_CULL_FACE); glCullFace(GL_BACK); + //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + //LoadSpriteShader(data); LoadMeshShader(data); @@ -338,11 +344,25 @@ void Engine::Renderer::OpenGL::PrepareRenderingEarly(const std::vector<SpriteID> UpdateIBODatabase(data, spriteLoadQueue); UpdateVBODatabase(data, meshLoadQueue); - // Update light count const auto& renderGraph = Core::GetRenderGraph(); + + // Update ambient light + constexpr GLintptr ambientLightOffset = offsetof(LightDataUBO, LightDataUBO::ambientLight); + glNamedBufferSubData(data.lightDataUBO, ambientLightOffset, sizeof(renderGraph.ambientLight), renderGraph.ambientLight.Data()); + + // Update light count auto pointLightCount = static_cast<uint32_t>(renderGraph.pointLights.size()); constexpr GLintptr pointLightCountDataOffset = offsetof(LightDataUBO, LightDataUBO::pointLightCount); glNamedBufferSubData(data.lightDataUBO, pointLightCountDataOffset, sizeof(pointLightCount), &pointLightCount); + + // Update intensities + const size_t elements = Math::Min(10, renderGraph.pointLights.size()); + std::array<Math::Vector4D, 10> intensityData; + for (size_t i = 0; i < elements; i++) + intensityData[i] = renderGraph.pointLights[i].AsVec4(); + size_t byteLength = sizeof(Math::Vector4D) * elements; + constexpr GLintptr pointLightIntensityOffset = offsetof(LightDataUBO, LightDataUBO::pointLightIntensity); + glNamedBufferSubData(data.lightDataUBO, pointLightIntensityOffset, byteLength, intensityData.data()); } bool testing = false; @@ -365,7 +385,7 @@ void Engine::Renderer::OpenGL::PrepareRenderingLate() // Update camera UBO auto& cameraInfo = Renderer::Core::GetCameraInfo(); - const Math::Vector4D& cameraWSPosition = cameraInfo.worldSpacePos.AsVec4(); + const Math::Vector3D& cameraWSPosition = cameraInfo.worldSpacePos; constexpr GLintptr cameraWSPositionDataOffset = offsetof(CameraDataUBO, CameraDataUBO::wsPosition); glBindBuffer(GL_UNIFORM_BUFFER, data.cameraDataUBO); glBufferSubData(GL_UNIFORM_BUFFER, cameraWSPositionDataOffset, sizeof(cameraWSPosition), cameraWSPosition.Data()); diff --git a/src/Engine/Renderer/Renderer.hpp b/src/Engine/Renderer/Renderer.hpp index 22d9a53..98987a3 100644 --- a/src/Engine/Renderer/Renderer.hpp +++ b/src/Engine/Renderer/Renderer.hpp @@ -5,10 +5,9 @@ #include "OpenGLCreateInfo.hpp" #include "../Utility/ImgDim.hpp" -#include "../Utility/Color.hpp" #include "DMath/Vector/Vector.hpp" -#include "DMath/UnitQuaternion.hpp" +#include "DMath/Matrix/Matrix.hpp" #include <memory> #include <vector> @@ -59,19 +58,17 @@ namespace Engine API preferredAPI = API::None; Utility::ImgDim surfaceDimensions{}; void* surfaceHandle = nullptr; + std::function<void(std::string_view)> errorMessageCallback; OpenGL::CreateInfo openGLCreateInfo{}; }; - struct Renderer::PointLight - { - float intensity; - }; - struct Renderer::RenderGraph { std::vector<SpriteID> sprites; std::vector<MeshID> meshes; - std::vector<PointLight> pointLights; + + Math::Vector3D ambientLight; + std::vector<Math::Vector<3, float>> pointLights; }; struct Renderer::RenderGraphTransform diff --git a/src/Engine/Systems/RenderSystem.cpp b/src/Engine/Systems/RenderSystem.cpp index d48089d..be48bf5 100644 --- a/src/Engine/Systems/RenderSystem.cpp +++ b/src/Engine/Systems/RenderSystem.cpp @@ -42,7 +42,12 @@ namespace Engine const auto& pointLightComponents = *pointLightComponentsPtr; graph.pointLights.resize(pointLightComponents.size()); for (size_t i = 0; i < pointLightComponents.size(); i++) - graph.pointLights[i] = Renderer::PointLight{ pointLightComponents[i].intensity }; + { + Math::Vector3D color = pointLightComponents[i].color; + for (auto& element : color) + element = Math::Clamp(element, 0.f, 1.f) * pointLightComponents[i].intensity; + graph.pointLights[i] = color; + } } } diff --git a/src/Engine/Utility/Color.hpp b/src/Engine/Utility/Color.hpp index c8b305b..673d2fa 100644 --- a/src/Engine/Utility/Color.hpp +++ b/src/Engine/Utility/Color.hpp @@ -1,15 +1,33 @@ #pragma once +#include <cstdint> +#include <cassert> + namespace Utility { struct Color { - static constexpr unsigned char length = 4; + public: + static constexpr uint8_t length = 4; + + using ValueType = float; + + ValueType r; + ValueType g; + ValueType b; + ValueType a; + + constexpr void Clamp(); + constexpr Color GetClamped() const; + + constexpr void Normalize(); + constexpr Color GetNormalized() const; + + constexpr ValueType& At(size_t i); + constexpr const ValueType& At(size_t i) const; - float r; - float g; - float y; - float x; + constexpr ValueType& operator[](size_t i); + constexpr const ValueType& operator[](size_t i) const; static constexpr Color Black(); static constexpr Color White(); @@ -19,6 +37,59 @@ namespace Utility static constexpr Color Blue(); }; + constexpr void Color::Clamp() + { + for (size_t i = 0; i < length; i++) + { + ValueType& element = At(i); + if (element < 0) + element = 0; + else if (element > 1) + element = 1; + } + } + + constexpr Color Color::GetClamped() const + { + Color newColor = *this; + newColor.Clamp(); + return newColor; + } + + constexpr Color::ValueType& Color::At(size_t i) + { + return const_cast<ValueType&>(std::as_const(*this).At(i)); + } + + constexpr const Color::ValueType& Color::At(size_t i) const + { + assert(0 <= i && i < length); + switch (i) + { + case 0: + return r; + case 1: + return g; + case 2: + return b; + case 3: + return a; + default: + assert(false); + return r; + } + } + + constexpr Color::ValueType& Color::operator[](size_t i) + { + return At(i); + } + + constexpr const Color::ValueType& Color::operator[](size_t i) const + { + return At(i); + } + constexpr Color Color::Black() { return { 0, 0, 0, 1 }; } constexpr Color Color::White() { return { 1, 1, 1, 1 }; } -- GitLab