From b3e82ca9df4b3beb73633ab057edd39f71c5c534 Mon Sep 17 00:00:00 2001
From: Robert <robert.trololo@gmail.com>
Date: Tue, 26 Jan 2021 15:34:35 +0100
Subject: [PATCH] Added point light prototype

---
 examples/movement/main.cpp                    | 102 +++++++++++++-----
 examples/movement/shaders/fragmentShader.frag |  14 ++-
 .../movement/shaders/lightSourceShader.frag   |  10 ++
 .../movement/shaders/lightSourceShader.vert   |  13 +++
 examples/movement/shaders/vertexShader.vert   |   6 ++
 include/vertexArray.hpp                       |   1 +
 src/vertexArray.cpp                           |  31 ++++--
 7 files changed, 144 insertions(+), 33 deletions(-)
 create mode 100644 examples/movement/shaders/lightSourceShader.frag
 create mode 100644 examples/movement/shaders/lightSourceShader.vert

diff --git a/examples/movement/main.cpp b/examples/movement/main.cpp
index 2f4a090..314ba7b 100644
--- a/examples/movement/main.cpp
+++ b/examples/movement/main.cpp
@@ -117,39 +117,72 @@ int main(int argc, char** argv)
 
 	// Create vertices for square
 	float vertices[] = {
-		 0.5f,  0.5f, 0.5f,		1.0f, 1.0f, // front top right
-		 0.5f, -0.5f, 0.5f,		1.0f, 0.0f,	// front bottom right
-		-0.5f, -0.5f, 0.5f,		0.0f, 0.0f, // front bottom left
-		-0.5f,  0.5f, 0.5f,		0.0f, 1.0f, // front top left 
+		 -0.5f, -0.5f, -0.5f,  0.0f, 0.0f, 0.0f, 0.0f, -1.0f,
+		 0.5f, -0.5f, -0.5f,  1.0f, 0.0f, 0.0f, 0.0f, -1.0f,
+		 0.5f,  0.5f, -0.5f,  1.0f, 1.0f, 0.0f, 0.0f, -1.0f,
+		 0.5f,  0.5f, -0.5f,  1.0f, 1.0f, 0.0f, 0.0f, -1.0f,
+		-0.5f,  0.5f, -0.5f,  0.0f, 1.0f, 0.0f, 0.0f, -1.0f,
+		-0.5f, -0.5f, -0.5f,  0.0f, 0.0f, 0.0f, 0.0f, -1.0f,
 
-		 0.5f,  0.5f, -0.5f,	0.0f, 1.0f, // back top right
-		 0.5f, -0.5f, -0.5f,	0.0f, 0.0f,	// back bottom right
-		-0.5f, -0.5f, -0.5f,	1.0f, 0.0f, // back bottom left
-		-0.5f,  0.5f, -0.5f,	1.0f, 1.0f  // back top left 
+		-0.5f, -0.5f,  0.5f,  0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
+		 0.5f, -0.5f,  0.5f,  1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
+		 0.5f,  0.5f,  0.5f,  1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
+		 0.5f,  0.5f,  0.5f,  1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
+		-0.5f,  0.5f,  0.5f,  0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
+		-0.5f, -0.5f,  0.5f,  0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
+
+		-0.5f,  0.5f,  0.5f,  1.0f, 0.0f, -1.0f, 0.0f, 0.0f,
+		-0.5f,  0.5f, -0.5f,  1.0f, 1.0f, -1.0f, 0.0f, 0.0f,
+		-0.5f, -0.5f, -0.5f,  0.0f, 1.0f, -1.0f, 0.0f, 0.0f,
+		-0.5f, -0.5f, -0.5f,  0.0f, 1.0f, -1.0f, 0.0f, 0.0f,
+		-0.5f, -0.5f,  0.5f,  0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
+		-0.5f,  0.5f,  0.5f,  1.0f, 0.0f, -1.0f, 0.0f, 0.0f,
+
+		 0.5f,  0.5f,  0.5f,  1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
+		 0.5f,  0.5f, -0.5f,  1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
+		 0.5f, -0.5f, -0.5f,  0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
+		 0.5f, -0.5f, -0.5f,  0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
+		 0.5f, -0.5f,  0.5f,  0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
+		 0.5f,  0.5f,  0.5f,  1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
+
+		-0.5f, -0.5f, -0.5f,  0.0f, 1.0f, 0.0f, -1.0f, 0.0f,
+		 0.5f, -0.5f, -0.5f,  1.0f, 1.0f, 0.0f, -1.0f, 0.0f,
+		 0.5f, -0.5f,  0.5f,  1.0f, 0.0f, 0.0f, -1.0f, 0.0f,
+		 0.5f, -0.5f,  0.5f,  1.0f, 0.0f, 0.0f, -1.0f, 0.0f,
+		-0.5f, -0.5f,  0.5f,  0.0f, 0.0f, 0.0f, -1.0f, 0.0f,
+		-0.5f, -0.5f, -0.5f,  0.0f, 1.0f, 0.0f, -1.0f, 0.0f,
+
+		-0.5f,  0.5f, -0.5f,  0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
+		 0.5f,  0.5f, -0.5f,  1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
+		 0.5f,  0.5f,  0.5f,  1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
+		 0.5f,  0.5f,  0.5f,  1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
+		-0.5f,  0.5f,  0.5f,  0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
+		-0.5f,  0.5f, -0.5f,  0.0f, 1.0f, 0.0f, 1.0f, 0.0f
 	};
 
-	unsigned int indices[] = {
-		0, 1, 3,	// front
-		1, 2, 3,
-		7, 4, 0,	// top
-		7, 0, 3,
-		0, 4, 5,	// right
-		0, 5, 1,
-		7, 3, 2,	// right
-		7, 2, 6,
-		2, 1, 6,	// bottom
-		1, 6, 5,
-		4, 7, 5,	// back
-		7, 6, 5
-	};
+	//unsigned int indices[] = {
+	//	0, 1, 3,	// front
+	//	1, 2, 3,
+	//	7, 4, 0,	// top
+	//	7, 0, 3,
+	//	0, 4, 5,	// right
+	//	0, 5, 1,
+	//	7, 3, 2,	// right
+	//	7, 2, 6,
+	//	2, 1, 6,	// bottom
+	//	1, 6, 5,
+	//	4, 7, 5,	// back
+	//	7, 6, 5
+	//};
 
 	oglu::VertexAttribute topology[] = {
-		{ 0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0 },
-		{ 1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)) }
+		{ 0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0 },
+		{ 1, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)) },
+		{ 2, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(5 * sizeof(float)) }
 	};
 
 	// Make a square
-	oglu::VertexArray cubeDefault = oglu::MakeVertexArray(vertices, sizeof(vertices), indices, sizeof(indices), topology, sizeof(topology));
+	oglu::VertexArray cubeDefault = oglu::MakeVertexArray(vertices, sizeof(vertices), nullptr, 0, topology, sizeof(topology));
 	oglu::Object cubes[10] = { 
 		oglu::Object(cubeDefault),
 		oglu::Object(cubeDefault),
@@ -185,11 +218,15 @@ int main(int argc, char** argv)
 	cubes[8].SetRotation(150.0f, 20.0f, -150.0f);
 	cubes[9].SetRotation(-130.0f, 10.0f, -150.0f);
 
+	oglu::Object lightSource(cubeDefault);
+	lightSource.SetScale(glm::vec3(0.1f));
+
 	// Create a shader
-	oglu::Shader shader;
+	oglu::Shader shader, lightSourceShader;
 	try
 	{
 		shader = oglu::MakeShader("shaders/vertexShader.vert", "shaders/fragmentShader.frag");
+		lightSourceShader = oglu::MakeShader("shaders/lightSourceShader.vert", "shaders/lightSourceShader.frag");
 	}
 	catch (const std::runtime_error& e)
 	{
@@ -213,6 +250,7 @@ int main(int argc, char** argv)
 	glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
 
 	oglu::Color bgColor = oglu::Color::Black;
+	lightSource.SetPosition(1.0f, 1.0f, -1.0f);
 	while (!glfwWindowShouldClose(window))
 	{
 		processInput(window);
@@ -225,16 +263,28 @@ int main(int argc, char** argv)
 		shader->Use();
 		shader->SetUniformTexture("texture1", crate, 0);
 		shader->SetUniformTexture("texture2", opengl, 1);
+
 		shader->SetUniform("ambientColor", "ambientStrength", ambient);
+		shader->SetUniform3fv("lightPos", 1, glm::value_ptr(lightSource.GetPosition()));
+		shader->SetUniform("lightColor", oglu::Color::White, true);
+
 		shader->SetUniformMatrix4fv("view", 1, GL_FALSE, glm::value_ptr(camera.GetMatrix()));
 		shader->SetUniformMatrix4fv("projection", 1, GL_FALSE, glm::value_ptr(camera.GetProjection()));
 
 		for (oglu::Object& cube : cubes)
 		{
 			shader->SetUniform("model", cube);
+			shader->SetUniformMatrix3fv("normal", 1, GL_FALSE, glm::value_ptr(glm::mat3(glm::transpose(glm::inverse(cube.GetMatrix())))));
 			cube.Render();
 		}
 
+		lightSourceShader->Use();
+		lightSourceShader->SetUniform("model", lightSource);
+		lightSourceShader->SetUniformMatrix4fv("view", 1, GL_FALSE, glm::value_ptr(camera.GetMatrix()));
+		lightSourceShader->SetUniformMatrix4fv("projection", 1, GL_FALSE, glm::value_ptr(camera.GetProjection()));
+		lightSourceShader->SetUniform("color", oglu::Color::White, true);
+		lightSource.Render();
+
 		ImGui::Begin("Test");
 
 		if(ImGui::CollapsingHeader("Scene"));
diff --git a/examples/movement/shaders/fragmentShader.frag b/examples/movement/shaders/fragmentShader.frag
index ee12187..36444af 100644
--- a/examples/movement/shaders/fragmentShader.frag
+++ b/examples/movement/shaders/fragmentShader.frag
@@ -1,5 +1,7 @@
 #version 330 core
 in vec2 oUV;
+in vec3 oNormal;
+in vec3 oFragPos;
 
 out vec4 FragColor;
 
@@ -9,9 +11,19 @@ uniform sampler2D texture2;
 uniform float ambientStrength;
 uniform vec3 ambientColor;
 
+uniform vec3 lightPos;
+uniform vec3 lightColor;
+
 void main()
 {
 	vec3 ambient = ambientColor * ambientStrength;
+	vec3 norm = normalize(oNormal);
+	vec3 lightDir = normalize(lightPos - oFragPos);
 
-	FragColor = mix(texture(texture1, oUV), texture(texture2, oUV), 0.2) * vec4(ambient, 1.0);
+	float diff = max(dot(norm, lightDir), 0.0);
+	vec3 diffuse = diff * lightColor;
+
+	vec4 objColor = mix(texture(texture1, oUV), texture(texture2, oUV), 0.2);
+
+	FragColor = vec4(ambient + diffuse, 1.0) * objColor;
 }
\ No newline at end of file
diff --git a/examples/movement/shaders/lightSourceShader.frag b/examples/movement/shaders/lightSourceShader.frag
new file mode 100644
index 0000000..492cafe
--- /dev/null
+++ b/examples/movement/shaders/lightSourceShader.frag
@@ -0,0 +1,10 @@
+#version 330 core
+
+uniform vec3 color;
+
+out vec4 FragColor;
+
+void main()
+{
+	FragColor = vec4(color, 1.0);
+}
\ No newline at end of file
diff --git a/examples/movement/shaders/lightSourceShader.vert b/examples/movement/shaders/lightSourceShader.vert
new file mode 100644
index 0000000..e0ff96b
--- /dev/null
+++ b/examples/movement/shaders/lightSourceShader.vert
@@ -0,0 +1,13 @@
+#version 330 core
+layout (location = 0) in vec3 aPos;
+layout (location = 1) in vec2 aUV;
+layout (location = 2) in vec3 aNormal;
+
+uniform mat4 model;
+uniform mat4 view;
+uniform mat4 projection;
+
+void main()
+{
+	gl_Position = projection * view * model * vec4(aPos, 1.0);
+}
\ No newline at end of file
diff --git a/examples/movement/shaders/vertexShader.vert b/examples/movement/shaders/vertexShader.vert
index 6a4bd79..4c526ea 100644
--- a/examples/movement/shaders/vertexShader.vert
+++ b/examples/movement/shaders/vertexShader.vert
@@ -1,15 +1,21 @@
 #version 330 core
 layout (location = 0) in vec3 aPos;
 layout (location = 1) in vec2 aUV;
+layout (location = 2) in vec3 aNormal;
 
 out vec2 oUV;
+out vec3 oNormal;
+out vec3 oFragPos;
 
 uniform mat4 model;
 uniform mat4 view;
 uniform mat4 projection;
+uniform mat3 normal;
 
 void main()
 {
 	oUV = aUV;
+	oNormal = normal * aNormal;
 	gl_Position = projection * view * model * vec4(aPos, 1.0);
+	oFragPos = vec3(model * vec4(aPos, 1.0));
 }
\ No newline at end of file
diff --git a/include/vertexArray.hpp b/include/vertexArray.hpp
index bab315c..91658a3 100644
--- a/include/vertexArray.hpp
+++ b/include/vertexArray.hpp
@@ -129,6 +129,7 @@ namespace oglu
 		GLuint VBO;		///< Handle to OpenGL VBO
 		GLuint EBO;		///< Handle to OpenGL EBO
 		GLsizei count;	///< Amount of indices
+		bool useIndices;
 	};
 
 	VertexArray OGLU_API MakeVertexArray(const GLfloat* vertices, size_t verticesSize, const GLuint* indices, size_t indicesSize, const VertexAttribute* topology, size_t topologySize);
diff --git a/src/vertexArray.cpp b/src/vertexArray.cpp
index 7b56be9..176103f 100644
--- a/src/vertexArray.cpp
+++ b/src/vertexArray.cpp
@@ -8,7 +8,7 @@
 namespace oglu
 {
 	AbstractVertexArray::AbstractVertexArray(const AbstractVertexArray& other) :
-		VAO(other.VAO), VBO(other.VBO), EBO(other.EBO), count(other.count)
+		VAO(other.VAO), VBO(other.VBO), EBO(other.EBO), count(other.count), useIndices(other.useIndices)
 	{
 	}
 
@@ -82,10 +82,13 @@ namespace oglu
 					const VertexAttribute* topology, size_t topologySize) :
 		VAO(0), VBO(0), EBO(0), count(0)
 	{
+		useIndices = (indices != nullptr);
+
 		topologySize /= sizeof(VertexAttribute);
 
 		glGenBuffers(1, &VBO);
-		glGenBuffers(1, &EBO);
+		if(useIndices)
+			glGenBuffers(1, &EBO);
 
 		glGenVertexArrays(1, &VAO);
 		glBindVertexArray(VAO);
@@ -93,8 +96,11 @@ namespace oglu
 		glBindBuffer(GL_ARRAY_BUFFER, VBO);
 		glBufferData(GL_ARRAY_BUFFER, verticesSize, vertices, GL_STATIC_DRAW);
 
-		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
-		glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesSize, indices, GL_STATIC_DRAW);
+		if (useIndices)
+		{
+			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
+			glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesSize, indices, GL_STATIC_DRAW);
+		}
 
 		for (int i = 0; i < topologySize; i++)
 		{
@@ -103,7 +109,12 @@ namespace oglu
 
 		glBindVertexArray(0);
 
-		count = (GLsizei)(indicesSize / sizeof(GLuint));
+		if (useIndices)
+			count = (GLsizei)(indicesSize / sizeof(GLuint));
+		else
+		{
+			count = (GLsizei)(verticesSize / sizeof(GLfloat)) / (topology[0].stride / sizeof(GLfloat));
+		}
 	}
 
 	void AbstractVertexArray::Bind()
@@ -124,7 +135,15 @@ namespace oglu
 	void AbstractVertexArray::BindAndDraw()
 	{
 		glBindVertexArray(VAO);
-		glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, (GLvoid*)0);
+		if (useIndices)
+		{
+			glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, (GLvoid*)0);
+		}
+		else
+		{
+			glDrawArrays(GL_TRIANGLES, 0, count);
+		}
+		
 		glBindVertexArray(0);
 	}