diff --git a/include/Ex10LightDraw.h b/include/Ex10LightDraw.h new file mode 100644 index 0000000..cf7c0b3 --- /dev/null +++ b/include/Ex10LightDraw.h @@ -0,0 +1,23 @@ +#pragma once +#include +#include +#include + +class Ex10LightDraw +{ +public: + Ex10LightDraw(); + ~Ex10LightDraw(); + void Update(float InDeltaTime); +private: + GLuint Vao; + GLuint Vbo; + GLuint LightVao; + GLuint LightVbo; + class OGLProgram* Program; + class OGLTexture* StormTexture; + class OGLProgram* LightProgram; + glm::mat4 View; + glm::mat4 Projection; + std::vector Vertices; +}; \ No newline at end of file diff --git a/resources/shaders/light_light.frag b/resources/shaders/light_light.frag new file mode 100644 index 0000000..871da30 --- /dev/null +++ b/resources/shaders/light_light.frag @@ -0,0 +1,9 @@ +#version 460 core + +out vec4 frag_color; + +uniform vec3 light_color; + +void main() { + frag_color = vec4(light_color, 1.0); +} diff --git a/resources/shaders/light_light.vert b/resources/shaders/light_light.vert new file mode 100644 index 0000000..6287d3f --- /dev/null +++ b/resources/shaders/light_light.vert @@ -0,0 +1,9 @@ +#version 460 core + +layout(location = 0) in vec3 vert_pos; + +uniform mat4 mvp; + +void main() { + gl_Position = mvp * vec4(vert_pos, 1.0); +} diff --git a/resources/shaders/light_scene.frag b/resources/shaders/light_scene.frag new file mode 100644 index 0000000..dd56c87 --- /dev/null +++ b/resources/shaders/light_scene.frag @@ -0,0 +1,47 @@ +#version 460 core + +out vec4 frag_color; + +layout (binding = 0) uniform sampler2D storm_tex; + +in vec2 vert_uv_out; +in vec3 vert_world_pos_out; +in vec3 vert_world_norm_out; + +uniform vec3 point_light_pos; +uniform vec3 camera_pos; + + +void main() +{ + //frag_color = texture(storm_tex, vert_uv_out); + + vec3 pixel_color = texture(storm_tex, vert_uv_out).xyz; + + //Ambient + float ambient_factor = 0.2f; + vec3 ambient = pixel_color * ambient_factor; + + //Diffuse + vec3 light_dir = normalize(point_light_pos - vert_world_pos_out); + float lambert = max(dot( normalize(vert_world_norm_out), light_dir), 0.f); + vec3 diffuse = pixel_color * lambert; + //vec3 diffuse = vec3(1, 0, 0) * lambert; + + //Specular + vec3 dir_to_eye = normalize(camera_pos - vert_world_pos_out); + vec3 reflected =reflect((-light_dir), normalize(vert_world_norm_out)); + float beta = max(dot(dir_to_eye, reflected), 0.0); + float specular_strength = 0.5; + float shininess = 50.0; + vec3 specular_color = vec3(1.0); + vec3 specular = specular_color * specular_strength * pow(beta, shininess); + + //Phong + vec3 phong = vec3(0, 0, 0); + phong += ambient; + phong += diffuse; + phong += specular; + + frag_color = vec4(phong, 1); +} diff --git a/resources/shaders/light_scene.vert b/resources/shaders/light_scene.vert new file mode 100644 index 0000000..5f88d0f --- /dev/null +++ b/resources/shaders/light_scene.vert @@ -0,0 +1,21 @@ +#version 460 core + +layout (location = 0) in vec3 vert_pos; +layout (location = 1) in vec2 vert_uv; +layout (location = 2) in vec3 vert_norm; + +uniform mat4 mvp; +uniform mat4 model; + +out vec2 vert_uv_out; +out vec3 vert_world_pos_out; +out vec3 vert_world_norm_out; + +void main() +{ + gl_Position = mvp * vec4(vert_pos, 1.f); + vert_uv_out = vert_uv; + + vert_world_pos_out = ( model * vec4(vert_pos, 1.f) ).xyz; + vert_world_norm_out = mat3(transpose(inverse(model))) * vert_norm; +} diff --git a/src/Ex10LightDraw.cpp b/src/Ex10LightDraw.cpp new file mode 100644 index 0000000..1e504ac --- /dev/null +++ b/src/Ex10LightDraw.cpp @@ -0,0 +1,221 @@ +#include "Ex10LightDraw.h" +#include +#include +#include +#include +#include "OGLProgram.h" +#include +#include "OGLTexture.h" +#include "ObjParser.h" +#include +#include + +Ex10LightDraw::Ex10LightDraw() +{ + Program = new OGLProgram("resources/shaders/light_scene.vert", "resources/shaders/light_scene.frag"); + + Obj obj; + ObjParser::TryParseObj("resources/models/stormtrooper.obj", obj); + + for(size_t i = 0; i < obj.triangles.size(); ++i) + { + auto& t = obj.triangles[i]; + + Vertices.push_back(t.v1.point.x); + Vertices.push_back(t.v1.point.y); + Vertices.push_back(t.v1.point.z); + Vertices.push_back(t.v1.uv.x); + Vertices.push_back(t.v1.uv.y); + Vertices.push_back(t.v1.normal.x); + Vertices.push_back(t.v1.normal.y); + Vertices.push_back(t.v1.normal.z); + + Vertices.push_back(t.v2.point.x); + Vertices.push_back(t.v2.point.y); + Vertices.push_back(t.v2.point.z); + Vertices.push_back(t.v2.uv.x); + Vertices.push_back(t.v2.uv.y); + Vertices.push_back(t.v2.normal.x); + Vertices.push_back(t.v2.normal.y); + Vertices.push_back(t.v2.normal.z); + + Vertices.push_back(t.v3.point.x); + Vertices.push_back(t.v3.point.y); + Vertices.push_back(t.v3.point.z); + Vertices.push_back(t.v3.uv.x); + Vertices.push_back(t.v3.uv.y); + Vertices.push_back(t.v3.normal.x); + Vertices.push_back(t.v3.normal.y); + Vertices.push_back(t.v3.normal.z); + } + + + // Create Model VAO + glGenVertexArrays(1, &Vao); + glBindVertexArray(Vao); + + // Crate Model VBO to load data + glGenBuffers(1, &Vbo); + glBindBuffer(GL_ARRAY_BUFFER, Vbo); + size_t DataSize = Vertices.size() * sizeof(float); + glBufferData(GL_ARRAY_BUFFER, DataSize, Vertices.data(), GL_STATIC_DRAW); + + // Link to Vertex Shader + GLuint Location_0 = 0; + glVertexAttribPointer(Location_0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0); + glEnableVertexAttribArray(Location_0); + + GLuint Location_1 = 1; + glVertexAttribPointer(Location_1, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float))); + glEnableVertexAttribArray(Location_1); + + GLuint Location_2 = 2; + glVertexAttribPointer(Location_2, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(5 * sizeof(float))); + glEnableVertexAttribArray(Location_2); + + // Create Texture + StormTexture = new OGLTexture("resources/models/stormtrooper.png"); + + + // Setup light cube + LightProgram = new OGLProgram("resources/shaders/light_light.vert", "resources/shaders/light_light.frag"); + + std::vector LightVertices = { + //Position //Uvs + //FRONT FACE + -1, -1, 1, 0, 0, // bottom-left + 1, -1, 1, 1, 0, // bottom-right + 1, 1, 1, 1, 1, // top-right + -1, 1, 1, 0, 1, // top-left + -1, -1, 1, 0, 0, // bottom-left + 1, 1, 1, 1, 1, // top-right + + // BACK FACE + 1, -1, -1, 0, 0, // bottom-left + -1, -1, -1, 1, 0, // bottom-right + -1, 1, -1, 1, 1, // top-right + 1, 1, -1, 0, 1, // top-left + 1, -1, -1, 0, 0, // bottom-left + -1, 1, -1, 1, 1, // top-right + + //LEFT FACE + -1, -1,-1, 0, 0, //bottom-left + -1, -1, 1, 1, 0, //bottom-right + -1, 1, 1, 1, 1, //top-right + -1, 1,-1, 0, 1, //top-left + -1, -1,-1, 0, 0, //bottom-left + -1, 1, 1, 1, 1, //top-right + + //RIGHT FACE + 1, -1, 1, 0, 0, //bottom-left + 1, -1,-1, 1, 0, //bottom-right + 1, 1,-1, 1, 1, //top-right + 1, 1, 1, 0, 1, //top-left + 1, -1, 1, 0, 0, //bottom-left + 1, 1,-1, 1, 1, //top-right + + //TOP FACE + -1, 1, 1, 0, 0, //bottom-left + 1, 1, 1, 1, 0, //bottom-right + 1, 1,-1, 1, 1, //top-right + -1, 1,-1, 0, 1, //top-left + -1, 1, 1, 0, 0, //bottom-left + 1, 1,-1, 1, 1, //top-right + + //BOTTOM FACE + -1,-1,-1, 0, 0, //bottom-left + 1,-1,-1, 1, 0, //bottom-right + 1,-1, 1, 1, 1, //top-right + -1,-1, 1, 0, 1, //top-left + -1,-1,-1, 0, 0, //bottom-left + 1,-1, 1, 1, 1, //top-right + }; + + glGenVertexArrays(1, &LightVao); + glBindVertexArray(LightVao); + + glGenBuffers(1, &LightVbo); + glBindBuffer(GL_ARRAY_BUFFER, LightVbo); + glBufferData(GL_ARRAY_BUFFER, LightVertices.size() * sizeof(float), LightVertices.data(), GL_STATIC_DRAW); + + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); + glEnableVertexAttribArray(0); + + //GL States + glViewport(0, 0, 800, 600); + glClearColor(0.5f, 0.5f, 0.5f, 1.f); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + + + //Camera + glm::vec3 Position = glm::vec3(0, 0, 8); + glm::vec3 Direction = glm::vec3(0, 0, -1); + glm::vec3 Up = glm::vec3(0, 1, 0); + float FovY = 60.f; + float AspectRatio = 800.f / 600.f; + float ZNear = 0.01f; + float ZFar = 100.f; + + View = glm::lookAt(Position, Position + Direction, Up); + Projection = glm::perspective(glm::radians(FovY), AspectRatio, ZNear, ZFar); +} + +Ex10LightDraw::~Ex10LightDraw() +{ + glDeleteVertexArrays(1, &Vao); + glDeleteBuffers(1, &Vbo); + glDeleteVertexArrays(1, &LightVao); + glDeleteBuffers(1, &LightVbo); + delete Program; + delete LightProgram; + delete StormTexture; +} + +void Ex10LightDraw::Update(float InDeltaTime) +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + static float ElapsedTime = 0.f; + ElapsedTime += InDeltaTime; + + float Angle = 20.f * ElapsedTime; + + glm::mat4 LightModel = glm::mat4(1.f); + LightModel = glm::rotate(LightModel, glm::radians(Angle), glm::vec3(0, 1, 0)); + LightModel = glm::translate(LightModel, glm::vec3(4, 2, 0)); + + glm::vec3 LightPos = glm::vec3(LightModel * glm::vec4(0, 0, 0, 1)); + + // --- RENDER MODEL --- + Program->Bind(); + + Program->SetUniform("camera_pos", glm::vec3(0,0,8)); + Program->SetUniform("point_light_pos", LightPos); + + glm::mat4 Model = glm::mat4(1.f); + Model = glm::translate(Model, glm::vec3(0, -4, 0)); + Model = glm::scale(Model, glm::vec3(2.f)); + + glm::mat4 Mvp = Projection * View * Model; + + Program->SetUniform("mvp", Mvp); + Program->SetUniform("model", Model); + + StormTexture->Bind(GL_TEXTURE0); + + glBindVertexArray(Vao); + glDrawArrays(GL_TRIANGLES, 0, Vertices.size() / 8); + + // --- RENDER LIGHT CUBE --- + LightProgram->Bind(); + + glm::mat4 LightCubeModel = glm::scale(LightModel, glm::vec3(0.2f)); + glm::mat4 LightMvp = Projection * View * LightCubeModel; + + LightProgram->SetUniform("mvp", LightMvp); + LightProgram->SetUniform("light_color", glm::vec3(1.0f, 1.0f, 1.0f)); + + glBindVertexArray(LightVao); + glDrawArrays(GL_TRIANGLES, 0, 36); +} \ No newline at end of file