diff --git a/src/entities/Entity.h b/src/entities/Entity.h index 8355488..089091d 100644 --- a/src/entities/Entity.h +++ b/src/entities/Entity.h @@ -5,6 +5,10 @@ namespace entities { + /* + * This class represents a movable model in the game + */ + class Entity { private: diff --git a/src/entities/light.h b/src/entities/light.h new file mode 100644 index 0000000..7e6dfce --- /dev/null +++ b/src/entities/light.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +namespace entities +{ + /* + * This class represents a light in the game + */ + + class Light + { + private: + glm::vec3 position; + glm::vec3 color; + + public: + Light(const glm::vec3& position, const glm::vec3& color) : position(position), color(color) { } + + glm::vec3 GetPosition() const { return position; } + void setPosition(const glm::vec3& position) { this->position = position; } + glm::vec3 GetColor() const { return color; } + void setColor(const glm::vec3& color) { this->color = color; } + }; +} diff --git a/src/main.cpp b/src/main.cpp index 5ed166a..3d7e14a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -48,8 +48,12 @@ int main(void) models::RawModel raw_model = LoadObjModel("res/Tree.obj"); models::ModelTexture texture = { render_engine::loader::LoadTexture("res/TreeTexture.png") }; + texture.shine_damper = 10; + texture.reflectivity = 1; models::TexturedModel model = { raw_model, texture }; - entities::Entity entity(model, glm::vec3(0, -5, -20), glm::vec3(0, 0, 0), 1); + entities::Entity entity(model, glm::vec3(0, -25, -50), glm::vec3(0, 0, 0), 1); + + entities::Light light(glm::vec3(0, 0, -30), glm::vec3(1, 1, 1)); shaders::StaticShader shader; shader.Init(); @@ -68,6 +72,7 @@ int main(void) // Render render_engine::renderer::Prepare(); shader.Start(); + shader.LoadLight(light); shader.LoadViewMatrix(camera); render_engine::renderer::Render(entity, shader); diff --git a/src/models/Model.h b/src/models/Model.h index 5bc8bf3..9c88855 100644 --- a/src/models/Model.h +++ b/src/models/Model.h @@ -19,10 +19,15 @@ namespace models /* Structure for storing a texture (texture_id) to apply to a RawModel. + + shine_damper = A damper for the angle the model needs to be look at to see reflections + reflectivity = The amount of light the model reflects */ struct ModelTexture { GLuint texture_id; + float shine_damper = 1; + float reflectivity = 0; }; /* diff --git a/src/renderEngine/Loader.cpp b/src/renderEngine/Loader.cpp index 9b66503..79f84bb 100644 --- a/src/renderEngine/Loader.cpp +++ b/src/renderEngine/Loader.cpp @@ -17,12 +17,13 @@ namespace render_engine /* This function will generate a Model from vertex positions, textureCoordinates and indices. */ - struct models::RawModel LoadToVAO(std::vector& positions, std::vector& texture_coords, std::vector& indices) + models::RawModel LoadToVAO(std::vector& positions, std::vector& texture_coords, std::vector& normals, std::vector& indices) { GLuint vao_id = CreateVao(); BindIndicesBuffer(indices); StoreDataInAttributeList(0, 3, positions); StoreDataInAttributeList(1, 2, texture_coords); + StoreDataInAttributeList(2, 3, normals); glBindVertexArray(0); return { vao_id, static_cast(indices.size()) }; } diff --git a/src/renderEngine/Loader.h b/src/renderEngine/Loader.h index e1baf76..c5fa8e9 100644 --- a/src/renderEngine/Loader.h +++ b/src/renderEngine/Loader.h @@ -11,7 +11,7 @@ namespace render_engine /* This function generates a model from model data. */ - struct models::RawModel LoadToVAO(std::vector& positions, std::vector& texture_coords, std::vector& indices); + models::RawModel LoadToVAO(std::vector& positions, std::vector& texture_coords, std::vector& normals, std::vector& indices); /* Loads a texture from a file into openGL using stb_image.h diff --git a/src/renderEngine/Renderer.cpp b/src/renderEngine/Renderer.cpp index b1d2564..93dc0a6 100644 --- a/src/renderEngine/Renderer.cpp +++ b/src/renderEngine/Renderer.cpp @@ -17,9 +17,14 @@ namespace render_engine */ void Init(shaders::StaticShader& shader) { + // Faces which are not facing the camera are not rendered + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + const glm::mat4 projectionMatrix = glm::perspective(glm::radians(FOV), (WINDOW_WIDTH / WINDOW_HEIGT), NEAR_PLANE, FAR_PLANE); - + + // Load the projectionmatrix into the shader shader.Start(); shader.LoadProjectionMatrix(projectionMatrix); shader.Stop(); @@ -41,26 +46,31 @@ namespace render_engine void Render(entities::Entity& entity, shaders::StaticShader& shader) { const models::TexturedModel model = entity.GetModel(); - const models::RawModel rawModel = model.raw_model; + const models::RawModel raw_model = model.raw_model; + const models::ModelTexture texture = model.texture; // Enable the model - glBindVertexArray(rawModel.vao_id); + glBindVertexArray(raw_model.vao_id); - // Enable the inputs for the vertexShader + // Enable the VBO's from the model (VAO) glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); + glEnableVertexAttribArray(2); // Load the transformation of the model into the shader const glm::mat4 modelMatrix = toolbox::CreateModelMatrix(entity.GetPosition(), entity.GetRotation(), entity.GetScale()); shader.LoadModelMatrix(modelMatrix); + shader.LoadShineVariables(texture.shine_damper, texture.reflectivity); // Draw the model glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, model.texture.texture_id); - glDrawElements(GL_TRIANGLES, rawModel.vertex_count, GL_UNSIGNED_INT, 0); - + glDrawElements(GL_TRIANGLES, raw_model.vertex_count, GL_UNSIGNED_INT, 0); + + // Disable the VBO's and model glDisableVertexAttribArray(0); glDisableVertexAttribArray(1); + glDisableVertexAttribArray(2); glBindVertexArray(0); } } diff --git a/src/renderEngine/obj_loader.cpp b/src/renderEngine/obj_loader.cpp index 72bd549..5d66301 100644 --- a/src/renderEngine/obj_loader.cpp +++ b/src/renderEngine/obj_loader.cpp @@ -125,5 +125,5 @@ models::RawModel LoadObjModel(std::string file_name) vertex_array[p++] = vertex.z; } - return render_engine::loader::LoadToVAO( vertex_array, texture_array, indices); + return render_engine::loader::LoadToVAO( vertex_array, texture_array, normal_array, indices); } \ No newline at end of file diff --git a/src/shaders/static_shader.cpp b/src/shaders/static_shader.cpp index b256b09..28994c0 100644 --- a/src/shaders/static_shader.cpp +++ b/src/shaders/static_shader.cpp @@ -12,21 +12,34 @@ namespace shaders in vec3 position; // Coordinates of the texture in vec2 texture_coords; + // The normal of the vertex + in vec3 normal; // Equal to the texture_coords out vec2 pass_texture_coords; + out vec3 surface_normal; + out vec3 to_light_vector; + out vec3 to_camera_vector; uniform mat4 model_matrix; uniform mat4 projection_matrix; uniform mat4 view_matrix; + uniform vec3 light_position; void main(void) { + // Calculate the real position of the vertex (after rotation and scaling) + vec4 world_position = model_matrix * vec4(position, 1.0); + // Tell OpenGL where to render the vertex - gl_Position = projection_matrix * view_matrix * model_matrix * vec4(position, 1.0); + gl_Position = projection_matrix * view_matrix * world_position; - // Pass the texture_coords directly to the fragment shader + // Pass the textureCoords directly to the fragment shader pass_texture_coords = texture_coords; + + surface_normal = (model_matrix * vec4(normal, 0.0)).xyz; + to_light_vector = light_position - world_position.xyz; + to_camera_vector = (inverse(view_matrix) * vec4(0.0, 0.0, 0.0, 1.0)).xyz - world_position.xyz; } )"; @@ -39,15 +52,40 @@ namespace shaders // Interpolated textureCoordinates of the vertex (relative to the distance to each vertex) in vec2 pass_texture_coords; + in vec3 surface_normal; + in vec3 to_light_vector; + in vec3 to_camera_vector; + // Final color of the pixel out vec4 out_color; // The texture of the model uniform sampler2D texture_sampler; + uniform vec3 light_color; + uniform float shine_damper; + uniform float reflectivity; + void main(void) { - out_color = texture(texture_sampler, pass_texture_coords); + vec3 unit_normal = normalize(surface_normal); + vec3 unit_light_vector = normalize(to_light_vector); + vec3 unit_camera_vector = normalize(to_camera_vector); + + // Calculate the diffuse lighting + float dot_diffuse = dot(unit_normal, unit_light_vector); + float brightness = max(dot_diffuse, 0.1); + vec3 diffuse = brightness * light_color; + + // Calculate the specular lighting + vec3 light_direction = -unit_light_vector; + vec3 reflected_light_direction = reflect(light_direction, unit_normal); + float dot_specular = dot(reflected_light_direction, unit_camera_vector); + dot_specular = max(dot_specular, 0.0); + float damped_specular = pow(dot_specular, shine_damper); + vec3 specular = damped_specular * reflectivity * light_color; + + out_color = vec4(diffuse, 1.0) * texture(texture_sampler, pass_texture_coords) + vec4(specular, 1.0); } )"; @@ -72,16 +110,35 @@ namespace shaders LoadMatrix(location_view_matrix, view_matrix); } + void StaticShader::LoadLight(entities::Light& light) const + { + LoadVector(location_light_position, light.GetPosition()); + LoadVector(location_light_color, light.GetColor()); + } + + void StaticShader::LoadShineVariables(float shine_damper, float reflectivity) const + { + LoadFloat(location_shine_damper, shine_damper); + LoadFloat(location_reflectivity, reflectivity); + } + void StaticShader::SetAttributes() const { + // Load the position VBO and textureCoords VBO from the VAO into the shader "in" variables SetAttribute(0, "position"); SetAttribute(1, "texture_coords"); + SetAttribute(2, "normal"); } void StaticShader::GetAllUniformLocations() { + // Get the locations from the uniform variables from the shaders location_model_matrix = GetUniformLocation("model_matrix"); location_projection_matrix = GetUniformLocation("projection_matrix"); location_view_matrix = GetUniformLocation("view_matrix"); + location_light_position = GetUniformLocation("light_position"); + location_light_color = GetUniformLocation("light_color"); + location_shine_damper = GetUniformLocation("shine_damper"); + location_reflectivity = GetUniformLocation("reflectivity"); } } diff --git a/src/shaders/static_shader.h b/src/shaders/static_shader.h index 8d24f4f..939da59 100644 --- a/src/shaders/static_shader.h +++ b/src/shaders/static_shader.h @@ -3,6 +3,7 @@ #include #include "shader_program.h" #include "../entities/camera.h" +#include "../entities/light.h" /* This class does represents the shaders for the models. @@ -16,6 +17,10 @@ namespace shaders GLuint location_model_matrix; GLuint location_projection_matrix; GLuint location_view_matrix; + GLuint location_light_position; + GLuint location_light_color; + GLuint location_shine_damper; + GLuint location_reflectivity; public: StaticShader(); @@ -23,6 +28,9 @@ namespace shaders void LoadModelMatrix(const glm::mat4& matrix) const; void LoadProjectionMatrix(const glm::mat4& projection) const; void LoadViewMatrix(entities::Camera& camera) const; + + void LoadLight(entities::Light& light) const; + void LoadShineVariables(float shine_damper, float reflectivity) const; protected: void SetAttributes() const override; diff --git a/wk2_fps.vcxproj b/wk2_fps.vcxproj index 5dd0806..4b8cc1e 100644 --- a/wk2_fps.vcxproj +++ b/wk2_fps.vcxproj @@ -32,6 +32,7 @@ + diff --git a/wk2_fps.vcxproj.filters b/wk2_fps.vcxproj.filters index d3370e0..e540659 100644 --- a/wk2_fps.vcxproj.filters +++ b/wk2_fps.vcxproj.filters @@ -74,5 +74,8 @@ Header Files + + Header Files + \ No newline at end of file