diff --git a/frag.glsl b/frag.glsl index 63a0030..728ea2c 100644 --- a/frag.glsl +++ b/frag.glsl @@ -1,15 +1,29 @@ #version 330 core +in vec3 Normal; +in vec3 FragPos; + out vec4 FragColor; void main() { vec3 objectColor = vec3(1.0, 0.5, 0.2); - vec3 lightColor = vec3(1.0, 1.0, 1.0); + vec3 result; + + // Ambient lighting + vec3 ambientLightColor = vec3(1.0, 1.0, 1.0); float ambientStrength = 0.1; + vec3 ambient = ambientStrength * ambientLightColor; - vec3 ambient = ambientStrength * lightColor; - vec3 result = ambient * objectColor; + // Directional lighting + vec3 directionalLightColor = vec3(1.0, 1.0, 1.0); + vec3 lightPos = vec3(10.0, 7.0, -8.0); + vec3 normal = normalize(Normal); + vec3 lightDir = normalize(lightPos - FragPos); + float diff = max(dot(normal, lightDir), 0.0); + vec3 diffuse = diff * directionalLightColor; - FragColor = vec4(ambient, 1.0); + result = (ambient + diffuse) * objectColor; + + FragColor = vec4(result, 1.0); } diff --git a/src/hello.cpp b/src/hello.cpp index 45d5e23..648153b 100644 --- a/src/hello.cpp +++ b/src/hello.cpp @@ -60,6 +60,9 @@ int initGraphics(GLFWwindow** window) std::cerr << "Failed to initialize GLFW" << std::endl; return -1; } + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); *window = glfwCreateWindow(640, 480, "Hello Astro", NULL, NULL); if (!window) @@ -93,22 +96,37 @@ GLint getShaderUniformLocation(GLuint shaderProgram, const std::string& uniformN return location; } -void updateModelViewProjectionMatrix(GLuint shaderProgram, float time) +void updateProjectionMatrix(GLuint shaderProgram) { // Calculate matrices float left = -1.0, right = 1.0, bottom = -1.0, top = 1.0, near = -1.0, far = 1.0; glm::mat4 projection = glm::ortho(left, right, bottom, top, near, far); + GLint projectionLocation = getShaderUniformLocation(shaderProgram, "_Projection"); + glUniformMatrix4fv(projectionLocation, 1, GL_FALSE, &projection[0][0]); +} +void updateModelMatrix(GLuint shaderProgram, float time) +{ constexpr float angle = glm::radians(10.0); glm::vec3 axis = glm::vec3(0.0, 1.0, 0.0); glm::mat4 model = glm::rotate(glm::mat4(1.0), angle * time, axis); + GLint modelLocation = getShaderUniformLocation(shaderProgram, "_Model"); + glUniformMatrix4fv(modelLocation, 1, GL_FALSE, &model[0][0]); +} +void updateViewMatrix(GLuint shaderProgram) +{ glm::mat4 view = glm::mat4(1.0); + GLint viewLocation = getShaderUniformLocation(shaderProgram, "_View"); + glUniformMatrix4fv(viewLocation, 1, GL_FALSE, &view[0][0]); +} - glm::mat4 mvp = projection * model * view; - - GLint mvpLocation = getShaderUniformLocation(shaderProgram, "_ModelViewProjectionMatrix"); - glUniformMatrix4fv(mvpLocation, 1, GL_FALSE, &mvp[0][0]); +void updateModelViewProjectionMatrix(GLuint shaderProgram, float time) +{ + // Calculate matrices + updateProjectionMatrix(shaderProgram); + updateModelMatrix(shaderProgram, time); + updateViewMatrix(shaderProgram); } int main() diff --git a/src/icosphere.cpp b/src/icosphere.cpp index ce6e9c8..2270dfa 100644 --- a/src/icosphere.cpp +++ b/src/icosphere.cpp @@ -22,28 +22,43 @@ Icosphere::Icosphere(int subdivisions) glBindVertexArray(_vao); - for (const auto& v : vertices) - { - _vertices.push_back(v[0]); - _vertices.push_back(v[1]); - _vertices.push_back(v[2]); - } - glBindBuffer(GL_ARRAY_BUFFER, _vbo); - size_t vboBufferSize = _vertices.size() * sizeof(float); - glBufferData(GL_ARRAY_BUFFER, vboBufferSize, &_vertices[0], GL_STATIC_DRAW); - for (const auto& tri : triangles) { _indices.push_back(tri.vertex[0]); _indices.push_back(tri.vertex[1]); _indices.push_back(tri.vertex[2]); } - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo); - size_t egoBufferSize = _indices.size() * sizeof(unsigned int); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, egoBufferSize, &_indices[0], GL_STATIC_DRAW); + for (const auto& v : vertices) + { + // Vertex Data + _vertices.push_back(v[0]); + _vertices.push_back(v[1]); + _vertices.push_back(v[2]); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); + // Normal data + // The normal at each vertex is actually going to just be the vertex again, but + // normalised, because this is a sphere. + glm::vec3 normal = normalize(v); + _vertices.push_back(normal[0]); + _vertices.push_back(normal[1]); + _vertices.push_back(normal[2]); + } + + glBindBuffer(GL_ARRAY_BUFFER, _vbo); + size_t vboBufferSize = _vertices.size() * sizeof(float); + glBufferData(GL_ARRAY_BUFFER, vboBufferSize, &_vertices[0], GL_STATIC_DRAW); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo); + size_t eboBufferSize = _indices.size() * sizeof(unsigned int); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, eboBufferSize, &_indices[0], GL_STATIC_DRAW); + + // Vertex position attribute glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0); + + // Vertex normal attribute + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); @@ -116,4 +131,5 @@ Icosphere::~Icosphere() { glDeleteVertexArrays(1, &_vao); glDeleteBuffers(1, &_vbo); + glDeleteBuffers(1, &_ebo); } diff --git a/vert.glsl b/vert.glsl index 96316d1..af0bea9 100644 --- a/vert.glsl +++ b/vert.glsl @@ -1,12 +1,27 @@ #version 330 core layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; -uniform mat4x4 _ModelViewProjectionMatrix; +uniform mat4x4 _Model; +uniform mat4x4 _View; +uniform mat4x4 _Projection; + +out vec3 Normal; +out vec3 FragPos; void main() { - vec4 pos = vec4(aPos.x, aPos.y, aPos.z, 1.0); - gl_Position = _ModelViewProjectionMatrix * pos; -} + vec4 pos = vec4(aPos, 1.0); + mat4x4 mvp = _Projection * _Model * _View; + gl_Position = mvp * pos; + FragPos = vec3(_Model * pos); + + // Convert the normal from model to world space + mat3 normalMatrix = mat3(mvp); + normalMatrix = inverse(normalMatrix); + normalMatrix = transpose(normalMatrix); + Normal = normalize(normalMatrix * aNormal); + //Normal = normalize(_Model * aNormal); +}