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