From 69d4ff022e19061166d274aa6e67ab247155e864 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20Petter=20Sk=C3=A5lerud?= <np_skalerud@hotmail.com> Date: Fri, 22 Mar 2019 22:32:48 +0100 Subject: [PATCH] Submodule DMath updated to latest version. Made significant progress on lighting. Mesh shader updated. Made up, down, left, right arrow keys work again. Required OpenGL version is now 4.2 Simple lighting test in Engine.cpp Made UBO for pointlights. 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 | 16 +++-- external/DMath | 2 +- src/Engine/Application.cpp | 13 +++- src/Engine/Engine.cpp | 29 ++++++-- src/Engine/Renderer/OpenGL.cpp | 111 +++++++++++++++++++++---------- src/Engine/Renderer/Renderer.cpp | 20 +++--- 6 files changed, 137 insertions(+), 54 deletions(-) diff --git a/Data/Shaders/Mesh/Mesh.frag b/Data/Shaders/Mesh/Mesh.frag index 183e675..72a9dae 100644 --- a/Data/Shaders/Mesh/Mesh.frag +++ b/Data/Shaders/Mesh/Mesh.frag @@ -1,5 +1,11 @@ #version 420 core +layout(std140, binding = 1) uniform LightData +{ + uint pointLightCount; + vec4 pointLightPos[10]; +} lightData; + in FragData { vec3 wsPosition; @@ -7,11 +13,13 @@ in FragData vec2 uv; } fragData; -vec3 lightPos = vec3(4.0, 5.0, 6.0); - void main() { - vec3 pointToLight = normalize(lightPos - fragData.wsPosition); - float test = max(dot(pointToLight, fragData.wsNormal), 0); + float test = 0.0; + for (int i = 0; i < lightData.pointLightCount; i++) + { + vec3 pointToLight = normalize(lightData.pointLightPos[i].xyz - fragData.wsPosition); + test += max(dot(pointToLight, fragData.wsNormal), 0); + } gl_FragColor = vec4(test, test, test, test); } diff --git a/external/DMath b/external/DMath index 0d9c06d..a17ca74 160000 --- a/external/DMath +++ b/external/DMath @@ -1 +1 @@ -Subproject commit 0d9c06d9e19a54a8747147a370d5e73dfe616220 +Subproject commit a17ca749764c26300ffaf2d8ffa13da38cc4d630 diff --git a/src/Engine/Application.cpp b/src/Engine/Application.cpp index 9663b05..72df58e 100644 --- a/src/Engine/Application.cpp +++ b/src/Engine/Application.cpp @@ -53,8 +53,8 @@ namespace Engine data = std::make_unique<Data>(); data->isRunning = true; - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); GLFWwindow* window = glfwCreateWindow(defaultWindowSize.width, defaultWindowSize.height, "My Title", NULL, NULL); if (!window) { @@ -133,6 +133,15 @@ Engine::Input::Raw::Button Engine::Application::Core::APIKeyToButton(int32_t api case GLFW_KEY_LEFT_CONTROL: return Button::LeftCtrl; + case GLFW_KEY_UP: + return Button::Up; + case GLFW_KEY_DOWN: + return Button::Down; + case GLFW_KEY_LEFT: + return Button::Left; + case GLFW_KEY_RIGHT: + return Button::Right; + case GLFW_KEY_A: return Button::A; case GLFW_KEY_B: diff --git a/src/Engine/Engine.cpp b/src/Engine/Engine.cpp index ac5b7a5..5b00171 100644 --- a/src/Engine/Engine.cpp +++ b/src/Engine/Engine.cpp @@ -69,8 +69,8 @@ void Engine::Core::Run() auto& sceneObject1 = scene1.NewSceneObject(); - auto& sprite1 = sceneObject1.AddComponent<Components::MeshRenderer>().first.get(); - sprite1.SetMesh(Asset::Mesh::Helmet); + auto& mesh1 = sceneObject1.AddComponent<Components::MeshRenderer>().first.get(); + mesh1.SetMesh(Asset::Mesh::Helmet); auto& mesh2 = sceneObject1.AddComponent<Components::MeshRenderer>().first.get(); mesh2.SetMesh(Asset::Mesh::Cube); @@ -80,9 +80,19 @@ void Engine::Core::Run() auto& camera = objCamera.AddComponent<Components::Camera>().first.get(); camera.positionOffset.z = 5.f; - auto& obj3 = scene1.NewSceneObject(); - obj3.transform.localPosition = { 5.f, 5.f, 10.f }; - Components::PointLight& light1 = obj3.AddComponent<Components::PointLight>().first.get(); + auto& lightObj = scene1.NewSceneObject(); + lightObj.transform.localPosition = { 2.5f, 2.5f, 2.5f }; + Components::PointLight& light1 = lightObj.AddComponent<Components::PointLight>().first.get(); + auto& mesh3 = lightObj.AddComponent<Components::MeshRenderer>().first.get(); + mesh3.SetMesh(Asset::Mesh::Cube); + mesh3.scale = { 0.1f, 0.1f, 0.1f }; + + auto& obj4 = scene1.NewSceneObject(); + obj4.transform.localPosition = { 0.f, -7.5f, -10.f }; + Components::PointLight& light3 = obj4.AddComponent<Components::PointLight>().first.get(); + auto& mesh4 = obj4.AddComponent<Components::MeshRenderer>().first.get(); + mesh4.SetMesh(Asset::Mesh::Cube); + mesh4.scale = { 0.1f, 0.1f, 0.1f }; Renderer::RenderGraph graph; @@ -109,6 +119,15 @@ void Engine::Core::Run() camera.positionOffset += Math::Vector3D::Down() * speed * scene1.GetTimeData().GetDeltaTime(); camera.LookAt({ 0, 0, 0 }); + if (Input::Raw::GetValue(Input::Raw::Button::Up)) + lightObj.transform.localPosition.z += speed * scene1.GetTimeData().GetDeltaTime(); + if (Input::Raw::GetValue(Input::Raw::Button::Down)) + lightObj.transform.localPosition.z -= speed * scene1.GetTimeData().GetDeltaTime(); + if (Input::Raw::GetValue(Input::Raw::Button::Left)) + lightObj.transform.localPosition.x -= speed * scene1.GetTimeData().GetDeltaTime(); + if (Input::Raw::GetValue(Input::Raw::Button::Right)) + lightObj.transform.localPosition.x += speed * scene1.GetTimeData().GetDeltaTime(); + if (Input::Raw::GetEventType(Input::Raw::Button::C) == Input::EventType::Pressed) { scene1.Clear(); diff --git a/src/Engine/Renderer/OpenGL.cpp b/src/Engine/Renderer/OpenGL.cpp index 5cd0661..065f8be 100644 --- a/src/Engine/Renderer/OpenGL.cpp +++ b/src/Engine/Renderer/OpenGL.cpp @@ -44,8 +44,11 @@ namespace Engine void Draw_SpritePass(const Data& data, const std::vector<SpriteID>& sprites, const std::vector<Math::Matrix4x4>& transforms); void Draw_MeshPass(const Data& data, const std::vector<MeshID>& meshes, const std::vector<Math::Matrix4x4>& transforms); + void CreateStandardUBOs(Data& data); void LoadSpriteShader(Data& data); void LoadMeshShader(Data& data); + + inline void PrintGLError(const char* string = ""); } } } @@ -58,7 +61,8 @@ struct Engine::Renderer::OpenGL::CameraDataUBO struct Engine::Renderer::OpenGL::LightDataUBO { uint32_t pointLightCount; - std::array<Math::Vector4D, 10> pointLights; + std::array<uint32_t, 3> padding; + std::array<Math::Vector4D, 10> pointLightPos; }; struct Engine::Renderer::OpenGL::VertexBufferObject @@ -96,6 +100,7 @@ struct Engine::Renderer::OpenGL::Data std::unordered_map<SpriteID, IBO> iboDatabase; GLuint cameraDataUBO; + GLuint lightDataUBO; GLuint samplerObject; GLuint spriteProgram; @@ -104,8 +109,6 @@ struct Engine::Renderer::OpenGL::Data GLuint meshProgram; GLint meshModelUniform; - - }; Engine::Renderer::OpenGL::Data& Engine::Renderer::OpenGL::GetData() { return std::any_cast<Data&>(Core::GetAPIData()); } @@ -232,7 +235,44 @@ void Engine::Renderer::OpenGL::LoadMeshShader(Engine::Renderer::OpenGL::Data &da // Grab uniforms data.meshModelUniform = glGetUniformLocation(data.meshProgram, "model"); - glUniformBlockBinding(data.meshProgram, 0, 0); + auto test = glGetUniformBlockIndex(data.meshProgram, "LightData"); + glUniformBlockBinding(data.meshProgram, 1, 1); +} + +inline void Engine::Renderer::OpenGL::PrintGLError(const char* string) +{ + if constexpr (enableDebug) + { + auto errorEnum = glGetError(); + if (errorEnum != 0) + { + auto errorString = glewGetErrorString(errorEnum); + std::cout << string << errorString << std::endl; + } + } +} + +void Engine::Renderer::OpenGL::CreateStandardUBOs(Data& data) +{ + std::array<GLuint, 2> buffers; + glGenBuffers(2, buffers.data()); + + PrintGLError("Making buffers for standard UBOs: "); + + data.cameraDataUBO = buffers[0]; + data.lightDataUBO = buffers[1]; + + // Make camera ubo + glBindBuffer(GL_UNIFORM_BUFFER, data.cameraDataUBO); + glNamedBufferData(data.cameraDataUBO, sizeof(CameraDataUBO), nullptr, GL_DYNAMIC_DRAW); + glBindBufferRange(GL_UNIFORM_BUFFER, 0, data.cameraDataUBO, 0, sizeof(CameraDataUBO)); + PrintGLError("Making Camera UBO: "); + + // Make light ubo + glBindBuffer(GL_UNIFORM_BUFFER, data.lightDataUBO); + glNamedBufferData(data.lightDataUBO, sizeof(LightDataUBO), nullptr, GL_DYNAMIC_DRAW); + glBindBufferRange(GL_UNIFORM_BUFFER, 1, data.lightDataUBO, 0, sizeof(LightDataUBO)); + PrintGLError("Making LightData UBO: "); } void Engine::Renderer::OpenGL::Initialize(std::any& apiData, CreateInfo&& createInfo) @@ -245,11 +285,7 @@ void Engine::Renderer::OpenGL::Initialize(std::any& apiData, CreateInfo&& create data.glSwapBuffers = std::move(createInfo.glSwapBuffers); - // Make camera ubo - glGenBuffers(1, &data.cameraDataUBO); - glBindBuffer(GL_UNIFORM_BUFFER, data.cameraDataUBO); - glBufferData(GL_UNIFORM_BUFFER, sizeof(CameraDataUBO), nullptr, GL_DYNAMIC_DRAW); - glBindBufferRange(GL_UNIFORM_BUFFER, 0, data.cameraDataUBO, 0, sizeof(CameraDataUBO)); + CreateStandardUBOs(data); // Gen sampler glGenSamplers(1, &data.samplerObject); @@ -265,22 +301,16 @@ void Engine::Renderer::OpenGL::Initialize(std::any& apiData, CreateInfo&& create else assert(false); - - glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glCullFace(GL_BACK); + //LoadSpriteShader(data); LoadMeshShader(data); - if constexpr (enableDebug) - { - auto errorEnum = glGetError(); - if (errorEnum != 0) - std::cout << glewGetErrorString(errorEnum) << std::endl; - } + PrintGLError("End of GL init: "); } void Engine::Renderer::OpenGL::Terminate(std::any& apiData) @@ -303,43 +333,56 @@ void Engine::Renderer::OpenGL::Terminate(std::any& apiData) void Engine::Renderer::OpenGL::PrepareRenderingEarly(const std::vector<SpriteID>& spriteLoadQueue, const std::vector<MeshID>& meshLoadQueue) { - UpdateIBODatabase(GetData(), spriteLoadQueue); - UpdateVBODatabase(GetData(), meshLoadQueue); -} + Data& data = GetData(); -void Engine::Renderer::OpenGL::PrepareRenderingLate() -{ - // Update lights positions + UpdateIBODatabase(data, spriteLoadQueue); + UpdateVBODatabase(data, meshLoadQueue); + + // Update light count + const auto& renderGraph = Core::GetRenderGraph(); + uint32_t pointLightCount = renderGraph.pointLights.size(); + glNamedBufferSubData(data.lightDataUBO, 0, sizeof(uint32_t), &pointLightCount); } -void Engine::Renderer::OpenGL::Draw() +void Engine::Renderer::OpenGL::PrepareRenderingLate() { Data& data = GetData(); - glClearColor(1.f, 0.f, 0.f, 1.f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + const auto& renderGraphTransform = Core::GetRenderGraphTransform(); - auto& viewport = Renderer::GetViewport(0); + // Update lights positions + const size_t elements = Math::Min(10, renderGraphTransform.pointLights.size()); + std::array<Math::Vector4D, 10> posData; + for (size_t i = 0; i < elements; i++) + posData[i] = renderGraphTransform.pointLights[i].AsVec4(); + size_t byteLength = sizeof(Math::Vector4D) * elements; + + glNamedBufferSubData(data.lightDataUBO, sizeof(uint32_t) * 4, byteLength, posData.data()); + auto& viewport = Renderer::GetViewport(0); auto& cameraInfo = Renderer::Core::GetCameraInfo(); auto viewMatrix = cameraInfo.GetModel(viewport.GetDimensions().GetAspectRatio()); glNamedBufferSubData(data.cameraDataUBO, 0, sizeof(CameraDataUBO::viewProjection), viewMatrix.data.data()); +} + +void Engine::Renderer::OpenGL::Draw() +{ + Data& data = GetData(); + + glClearColor(0.25f, 0.f, 0.f, 1.f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); const auto& renderGraph = Core::GetRenderGraph(); const auto& renderGraphTransform = Core::GetRenderGraphTransform(); - Draw_SpritePass(data, renderGraph.sprites, renderGraphTransform.sprites); Draw_MeshPass(data, renderGraph.meshes, renderGraphTransform.meshes); - if constexpr (enableDebug) - { - auto errorEnum = glGetError(); - if (errorEnum != 0) - std::cout << glewGetErrorString(errorEnum) << std::endl; - } + PrintGLError("End of GL tick: "); + + auto& viewport = Renderer::GetViewport(0); data.glSwapBuffers(viewport.GetSurfaceHandle()); } diff --git a/src/Engine/Renderer/Renderer.cpp b/src/Engine/Renderer/Renderer.cpp index ce93f8a..97aef6c 100644 --- a/src/Engine/Renderer/Renderer.cpp +++ b/src/Engine/Renderer/Renderer.cpp @@ -109,20 +109,22 @@ void Engine::Renderer::Core::Terminate() void Engine::Renderer::Core::PrepareRenderingEarly(RenderGraph& renderGraphInput) { - auto& renderGraph = data->renderGraph; + Data& data = *Core::data; - UpdateAssetReferences(*data, renderGraph, &renderGraphInput); + auto& renderGraph = data.renderGraph; + + UpdateAssetReferences(data, renderGraph, &renderGraphInput); std::swap(renderGraph, renderGraphInput); - if (!data->loadSpriteQueue.empty() || !data->loadMeshQueue.empty()) + if (!data.loadSpriteQueue.empty() || !data.loadMeshQueue.empty()) std::cout << "Loading sprite/mesh resource(s)..." << std::endl; - data->PrepareRenderingEarly(data->loadSpriteQueue, data->loadMeshQueue); + data.PrepareRenderingEarly(data.loadSpriteQueue, data.loadMeshQueue); - data->loadSpriteQueue.clear(); - data->unloadSpriteQueue.clear(); - data->loadMeshQueue.clear(); - data->unloadMeshQueue.clear(); + data.loadSpriteQueue.clear(); + data.unloadSpriteQueue.clear(); + data.loadMeshQueue.clear(); + data.unloadMeshQueue.clear(); } void Engine::Renderer::Core::PrepareRenderingLate(RenderGraphTransform &input) @@ -133,6 +135,8 @@ void Engine::Renderer::Core::PrepareRenderingLate(RenderGraphTransform &input) assert(IsCompatible(renderGraph, input)); std::swap(renderGraphTransform, input); + + data->PrepareRenderingLate(); } void Engine::Renderer::Core::Draw() -- GitLab