From 4c0d737678f149a403a2d070e76a40bb6c1063b2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nils=20Petter=20Sk=C3=A5lerud?= <np_skalerud@hotmail.com>
Date: Sat, 23 Mar 2019 16:42:10 +0100
Subject: [PATCH] Made progress on lighting Updated submodule DMath to latest
 version Updated Mesh shader to use Phong lighting (only diffuse and
 specularity atm). Changed default window size to be slightly larger yet fit
 on 1080p. Added GetModel functions to Camera component. Updated test scene in
 Engine.cpp Fixed Camera world-space position calculation bug. Renamed
 Renderer::CameraInfo::ProjectMode to ProjectionMode.
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      | 29 ++++++++++++++++++++++++++---
 Data/Shaders/Mesh/Mesh.vert      | 15 ++++++++-------
 external/DMath                   |  2 +-
 src/Engine/Application.hpp       |  2 +-
 src/Engine/Components/Camera.cpp | 21 ++++++++++++++++++---
 src/Engine/Components/Camera.hpp |  4 +++-
 src/Engine/Engine.cpp            | 19 +++++++++++--------
 src/Engine/Renderer/OpenGL.cpp   | 23 ++++++++++++++++-------
 src/Engine/Renderer/Renderer.cpp |  4 ++--
 src/Engine/Renderer/Renderer.hpp |  5 +++--
 10 files changed, 89 insertions(+), 35 deletions(-)

diff --git a/Data/Shaders/Mesh/Mesh.frag b/Data/Shaders/Mesh/Mesh.frag
index 72a9dae..9adfd48 100644
--- a/Data/Shaders/Mesh/Mesh.frag
+++ b/Data/Shaders/Mesh/Mesh.frag
@@ -1,5 +1,11 @@
 #version 420 core
 
+layout(std140, binding = 0) uniform CameraData
+{
+	vec4 wsPosition;
+	mat4 viewProjection;
+} cameraData;
+
 layout(std140, binding = 1) uniform LightData
 {
 	uint pointLightCount;
@@ -13,13 +19,30 @@ in FragData
 	vec2 uv;
 } fragData;
 
+layout(location = 0) out vec4 frag_color;
+
 void main()
 {
+	vec3 pointToCamera = cameraData.wsPosition.xyz - fragData.wsPosition;
+	vec3 pointToCameraDir = normalize(pointToCamera);
+
 	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);
+		vec3 pointToLight = lightData.pointLightPos[i].xyz - fragData.wsPosition;
+		vec3 pointToLightDir = normalize(pointToLight);
+		
+		float diff = max(0, dot(pointToLightDir, fragData.wsNormal));
+		test += diff;
+		
+		vec3 lightToPointDir = -pointToLightDir;
+		
+		vec3 reflectDir = reflect(lightToPointDir, fragData.wsNormal);
+		
+		float spec = pow(max(dot(pointToCameraDir, reflectDir), 0.0), 50);
+		
+		test += spec;
+		
 	}
-	gl_FragColor = vec4(test, test, test, test);
+	frag_color = vec4(test);
 }
diff --git a/Data/Shaders/Mesh/Mesh.vert b/Data/Shaders/Mesh/Mesh.vert
index aaee841..af8162a 100644
--- a/Data/Shaders/Mesh/Mesh.vert
+++ b/Data/Shaders/Mesh/Mesh.vert
@@ -1,11 +1,12 @@
 #version 420 core
 
-layout(location = 0) in vec3 position;
-layout(location = 1) in vec2 texCoord;
-layout(location = 2) in vec3 normal;
+layout(location = 0) in vec3 vtxPosition;
+layout(location = 1) in vec2 vtxUV;
+layout(location = 2) in vec3 vtxNormal;
 
 layout(std140, binding = 0) uniform CameraData
 {
+	vec4 wsPosition;
 	mat4 viewProjection;
 } cameraData;
 
@@ -20,9 +21,9 @@ out FragData
 
 void main()
 {
-	gl_Position = cameraData.viewProjection * model * vec4(position, 1.0);
+	gl_Position = cameraData.viewProjection * model * vec4(vtxPosition, 1.0);
 	
-	fragData.wsPosition = vec4(model * vec4(position, 1.0)).xyz;
-	fragData.wsNormal = vec4(model * vec4(normal, 0.0)).xyz;
-	fragData.uv = texCoord;
+	fragData.wsPosition = vec3(model * vec4(vtxPosition, 1.0));
+	fragData.wsNormal = mat3(transpose(inverse(model))) * vtxNormal;
+	fragData.uv = vtxUV;
 }
diff --git a/external/DMath b/external/DMath
index a17ca74..62afefe 160000
--- a/external/DMath
+++ b/external/DMath
@@ -1 +1 @@
-Subproject commit a17ca749764c26300ffaf2d8ffa13da38cc4d630
+Subproject commit 62afefe2fcf6db2471846d3b42800a0ae44f0f8e
diff --git a/src/Engine/Application.hpp b/src/Engine/Application.hpp
index e4cd30e..fe15414 100644
--- a/src/Engine/Application.hpp
+++ b/src/Engine/Application.hpp
@@ -10,7 +10,7 @@ namespace Engine
 {
 	namespace Application
 	{
-		constexpr Utility::ImgDim defaultWindowSize = { 1280, 720 };
+		constexpr Utility::ImgDim defaultWindowSize = { 1800, 900 };
 		constexpr Utility::ImgDim minimumWindowSize = { 800, 600 };
 		constexpr float narrowestAspectRatio = minimumWindowSize.GetAspectRatio();
 		constexpr std::string_view defaultApplicationName = "VulkanProject1";
diff --git a/src/Engine/Components/Camera.cpp b/src/Engine/Components/Camera.cpp
index 04d7824..af2e012 100644
--- a/src/Engine/Components/Camera.cpp
+++ b/src/Engine/Components/Camera.cpp
@@ -1,5 +1,7 @@
 #include "Camera.hpp"
 
+#include "../SceneObject.hpp"
+
 #include "DMath/LinearTransform3D.hpp"
 
 #include "../Renderer/Renderer.hpp"
@@ -30,7 +32,17 @@ namespace Engine
 			forward = (newTarget - positionOffset).GetNormalized();
 		}
 
-		Renderer::CameraInfo Camera::GetCameraInfo() const
+		Math::Matrix<4, 3, float> Camera::GetModel_Reduced(Space space) const
+		{
+			using namespace Math::LinTran3D;
+			const auto& localModel = Translate_Reduced(positionOffset);
+			if (space == Space::Local)
+				return localModel;
+			else
+				return Multiply(GetSceneObject().transform.GetModel_Reduced(Space::World), localModel);
+		}
+
+		Renderer::CameraInfo Camera::GetRendererCameraInfo() const
 		{
 			Renderer::CameraInfo cameraInfo;
 
@@ -40,12 +52,15 @@ namespace Engine
 			cameraInfo.zFar = zFar;
 
 			if (projectionMode == ProjectionMode::Perspective)
-				cameraInfo.projectMode = Renderer::CameraInfo::ProjectMode::Perspective;
+				cameraInfo.projectMode = Renderer::CameraInfo::ProjectionMode::Perspective;
 			else if (projectionMode == ProjectionMode::Orthgraphic)
-				cameraInfo.projectMode = Renderer::CameraInfo::ProjectMode::Orthographic;
+				cameraInfo.projectMode = Renderer::CameraInfo::ProjectionMode::Orthographic;
 
 			cameraInfo.transform = Math::LinTran3D::LookAt_RH(positionOffset, positionOffset + forward, up);
 
+			auto test = GetModel_Reduced(Space::World);
+			cameraInfo.worldSpacePos = Math::LinTran3D::GetTranslation(test);
+
 			return cameraInfo;
 		}
 	}
diff --git a/src/Engine/Components/Camera.hpp b/src/Engine/Components/Camera.hpp
index 0226c36..de12d6b 100644
--- a/src/Engine/Components/Camera.hpp
+++ b/src/Engine/Components/Camera.hpp
@@ -1,6 +1,7 @@
 #pragma once
 
 #include "Components.hpp"
+#include "../Enum.hpp"
 
 #include "DMath/Vector/Vector.hpp"
 
@@ -42,7 +43,8 @@ namespace Engine
 
 			void LookAt(const Math::Vector3D& newTarget);
 
-			Renderer::CameraInfo GetCameraInfo() const;
+			[[nodiscard]] Math::Matrix<4, 3, float> GetModel_Reduced(Space space) const;
+			Renderer::CameraInfo GetRendererCameraInfo() const;
 		};
 	}
 }
\ No newline at end of file
diff --git a/src/Engine/Engine.cpp b/src/Engine/Engine.cpp
index 5b00171..a89788a 100644
--- a/src/Engine/Engine.cpp
+++ b/src/Engine/Engine.cpp
@@ -68,13 +68,19 @@ void Engine::Core::Run()
 	Renderer::GetViewport(0).SetSceneRef(&scene1);
 
 
+
+
 	auto& sceneObject1 = scene1.NewSceneObject();
 	auto& mesh1 = sceneObject1.AddComponent<Components::MeshRenderer>().first.get();
 	mesh1.SetMesh(Asset::Mesh::Helmet);
 
+	auto& meshTest = sceneObject1.AddComponent<Components::MeshRenderer>().first.get();
+	meshTest.SetMesh(Asset::Mesh::Helmet);
+	meshTest.positionOffset.x = -3.f;
+
 	auto& mesh2 = sceneObject1.AddComponent<Components::MeshRenderer>().first.get();
 	mesh2.SetMesh(Asset::Mesh::Cube);
-	mesh2.positionOffset.x = 2.5f;
+	mesh2.positionOffset.x = 2.f;
 
 	auto& objCamera = scene1.NewSceneObject();
 	auto& camera = objCamera.AddComponent<Components::Camera>().first.get();
@@ -117,12 +123,12 @@ void Engine::Core::Run()
 			camera.positionOffset += Math::Vector3D::Up() * speed * scene1.GetTimeData().GetDeltaTime();
 		if (Input::Raw::GetValue(Input::Raw::Button::LeftCtrl))
 			camera.positionOffset += Math::Vector3D::Down() * speed * scene1.GetTimeData().GetDeltaTime();
-		camera.LookAt({ 0, 0, 0 });
+		camera.LookAt({ -1.f, 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::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))
@@ -140,14 +146,11 @@ void Engine::Core::Run()
 		RenderSystem::BuildRenderGraph(scene1, graph);
 		Renderer::Core::PrepareRenderingEarly(graph);
 
-
+		Renderer::Core::SetCameraInfo(camera.GetRendererCameraInfo());
 		RenderSystem::BuildRenderGraphTransform(scene1, graphTransform);
 		Renderer::Core::PrepareRenderingLate(graphTransform);
 
 
-		Renderer::Core::SetCameraInfo(camera.GetCameraInfo());
-
-
 		Renderer::Core::Draw();
 
 
diff --git a/src/Engine/Renderer/OpenGL.cpp b/src/Engine/Renderer/OpenGL.cpp
index 065f8be..8648cc9 100644
--- a/src/Engine/Renderer/OpenGL.cpp
+++ b/src/Engine/Renderer/OpenGL.cpp
@@ -55,13 +55,14 @@ namespace Engine
 
 struct Engine::Renderer::OpenGL::CameraDataUBO
 {
+	Math::Vector4D wsPosition;
 	Math::Matrix<4, 4, float> viewProjection;
 };
 
 struct Engine::Renderer::OpenGL::LightDataUBO
 {
 	uint32_t pointLightCount;
-	std::array<uint32_t, 3> padding;
+	std::array<uint32_t, 3> padding1;
 	std::array<Math::Vector4D, 10> pointLightPos;
 };
 
@@ -235,7 +236,6 @@ void Engine::Renderer::OpenGL::LoadMeshShader(Engine::Renderer::OpenGL::Data &da
 	// Grab uniforms
 	data.meshModelUniform = glGetUniformLocation(data.meshProgram, "model");
 
-	auto test = glGetUniformBlockIndex(data.meshProgram, "LightData");
 	glUniformBlockBinding(data.meshProgram, 1, 1);
 }
 
@@ -340,10 +340,12 @@ void Engine::Renderer::OpenGL::PrepareRenderingEarly(const std::vector<SpriteID>
 
 	// Update light count
 	const auto& renderGraph = Core::GetRenderGraph();
-	uint32_t pointLightCount = renderGraph.pointLights.size();
-	glNamedBufferSubData(data.lightDataUBO, 0, sizeof(uint32_t), &pointLightCount);
+	auto pointLightCount = static_cast<uint32_t>(renderGraph.pointLights.size());
+	constexpr GLintptr pointLightCountDataOffset = offsetof(LightDataUBO, LightDataUBO::pointLightCount);
+	glNamedBufferSubData(data.lightDataUBO, pointLightCountDataOffset, sizeof(pointLightCount), &pointLightCount);
 }
 
+bool testing = false;
 void Engine::Renderer::OpenGL::PrepareRenderingLate()
 {
 	Data& data = GetData();
@@ -356,14 +358,21 @@ void Engine::Renderer::OpenGL::PrepareRenderingLate()
 	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());
+	constexpr GLintptr pointLightPosDataOffset = offsetof(LightDataUBO, LightDataUBO::pointLightPos);
+	glNamedBufferSubData(data.lightDataUBO, pointLightPosDataOffset, byteLength, posData.data());
 
 	auto& viewport = Renderer::GetViewport(0);
 
+	// Update camera UBO
 	auto& cameraInfo = Renderer::Core::GetCameraInfo();
+	const Math::Vector4D& cameraWSPosition = cameraInfo.worldSpacePos.AsVec4();
+	constexpr GLintptr cameraWSPositionDataOffset = offsetof(CameraDataUBO, CameraDataUBO::wsPosition);
+	glBindBuffer(GL_UNIFORM_BUFFER, data.cameraDataUBO);
+	glBufferSubData(GL_UNIFORM_BUFFER, cameraWSPositionDataOffset, sizeof(cameraWSPosition), cameraWSPosition.Data());
+
 	auto viewMatrix = cameraInfo.GetModel(viewport.GetDimensions().GetAspectRatio());
-	glNamedBufferSubData(data.cameraDataUBO, 0, sizeof(CameraDataUBO::viewProjection), viewMatrix.data.data());
+	constexpr GLintptr cameraViewProjectionDataOffset = offsetof(CameraDataUBO, CameraDataUBO::viewProjection);
+	glBufferSubData(GL_UNIFORM_BUFFER, cameraViewProjectionDataOffset, sizeof(viewMatrix), viewMatrix.Data());
 }
 
 void Engine::Renderer::OpenGL::Draw()
diff --git a/src/Engine/Renderer/Renderer.cpp b/src/Engine/Renderer/Renderer.cpp
index 97aef6c..d2fc6ef 100644
--- a/src/Engine/Renderer/Renderer.cpp
+++ b/src/Engine/Renderer/Renderer.cpp
@@ -254,7 +254,7 @@ void Engine::Renderer::Core::UpdateAssetReferences(Data& data, const RenderGraph
 Math::Matrix4x4 Engine::Renderer::CameraInfo::GetModel(float aspectRatio) const
 {
 	using namespace Math::LinTran3D;
-	if (projectMode == ProjectMode::Perspective)
+	if (projectMode == ProjectionMode::Perspective)
 	{
 		switch (GetActiveAPI())
 		{
@@ -267,7 +267,7 @@ Math::Matrix4x4 Engine::Renderer::CameraInfo::GetModel(float aspectRatio) const
 				return {};
 		}
 	}
-	else if (projectMode == ProjectMode::Orthographic)
+	else if (projectMode == ProjectionMode::Orthographic)
 	{
 		const float& right = orthoWidth / 2;
 		const float& left = -right;
diff --git a/src/Engine/Renderer/Renderer.hpp b/src/Engine/Renderer/Renderer.hpp
index ad5a549..22d9a53 100644
--- a/src/Engine/Renderer/Renderer.hpp
+++ b/src/Engine/Renderer/Renderer.hpp
@@ -93,14 +93,15 @@ namespace Engine
 
 	struct Renderer::CameraInfo
 	{
-		enum class ProjectMode
+		enum class ProjectionMode
 		{
 			Perspective,
 			Orthographic
 		};
 
 		Math::Matrix4x4 transform;
-		ProjectMode projectMode;
+		Math::Vector3D worldSpacePos;
+		ProjectionMode projectMode;
 		float fovY;
 		float zNear;
 		float zFar;
-- 
GitLab