diff --git a/BaseGLProject/DSLightPass.frag b/BaseGLProject/DSLightPass.frag index d058b88..dbe8c31 100644 --- a/BaseGLProject/DSLightPass.frag +++ b/BaseGLProject/DSLightPass.frag @@ -29,10 +29,14 @@ void main() vec3 viewDir = normalize(view_pos - FragPos); for (int i = 0; i < NLights; ++i) { - // diffuse - vec3 lightDir = normalize(lights[i].Position - FragPos); - vec3 diffuse = max(dot(Normal, lightDir), 0.0) * Albedo * lights[i].Color; - lighting += diffuse; +// diffuse + vec3 lightDir = normalize(lights[i].Position - FragPos); + vec3 diffuse = max(dot(Normal, lightDir), 0.0) * Albedo * lights[i].Color; + // specular + vec3 halfwayDir = normalize(lightDir + viewDir); + float spec = pow(max(dot(Normal, halfwayDir), 0.0), 16.0); + vec3 specular = lights[i].Color * spec * Specular; + lighting += diffuse + specular; } FragColor = vec4(lighting, 1.0); diff --git a/BaseGLProject/Light.cpp b/BaseGLProject/Light.cpp index e57e2c1..2d03f99 100644 --- a/BaseGLProject/Light.cpp +++ b/BaseGLProject/Light.cpp @@ -21,3 +21,10 @@ Light::Light() : location(glm::vec4(0)), intensity(glm::vec3(1)) Light::~Light() { } + +std::string Light::toString() +{ + return "(" + std::to_string(location.x) + ", " + + std::to_string(location.y) + ", " + + std::to_string(location.z) + ")"; +} \ No newline at end of file diff --git a/BaseGLProject/Light.h b/BaseGLProject/Light.h index dd67c37..b449dfd 100644 --- a/BaseGLProject/Light.h +++ b/BaseGLProject/Light.h @@ -2,6 +2,7 @@ #include "glm/vec3.hpp" #include "glm/vec4.hpp" +#include class Light { @@ -18,6 +19,8 @@ public: float spot_exponent, glm::vec4 lookAt); ~Light(); + std::string toString(); + bool activated = true; LightType type; glm::vec3 intensity; diff --git a/BaseGLProject/Loader.h b/BaseGLProject/Loader.h index a618f4c..9628e8e 100644 --- a/BaseGLProject/Loader.h +++ b/BaseGLProject/Loader.h @@ -377,7 +377,7 @@ public: // Check to ensure that the shader contains a uniform with this name if (uniformMap[uniformName] == -1) - { + { int error = glGetError(); throw std::runtime_error("Could not add uniform: " + uniformName + " - location returned -1."); } diff --git a/BaseGLProject/Models/Mesh.cpp b/BaseGLProject/Models/Mesh.cpp index 2199355..8bfe5b7 100644 --- a/BaseGLProject/Models/Mesh.cpp +++ b/BaseGLProject/Models/Mesh.cpp @@ -297,8 +297,9 @@ void Mesh::MeshEntry::render(SceneContext &ctx, Shader &shd) { /** * Mesh constructor, loads the specified filename if supported by Assimp **/ -Mesh::Mesh(const char *filename, std::string vert_shd, std::string frag_shd) : shader(vert_shd, frag_shd) +Mesh::Mesh(const char *filename, std::string vert_shd, std::string frag_shd) { + shader = std::make_shared(vert_shd, frag_shd); std::string fullname; fullname = std::string("./Models/")+ std::string(filename); directory = fullname; @@ -336,8 +337,9 @@ Mesh::Mesh(const char *filename, std::string vert_shd, std::string frag_shd) : s } } -Mesh::Mesh(Dataset &set, std::string vert_shd, std::string frag_shd) : shader(vert_shd, frag_shd) +Mesh::Mesh(Dataset &set, std::string vert_shd, std::string frag_shd) { + shader = std::make_shared(vert_shd, frag_shd); meshEntries.push_back(new Mesh::MeshEntry(set, this)); } @@ -355,7 +357,7 @@ Mesh::~Mesh(void) void Mesh::draw(SceneContext &ctx) { - shader.enable(); + shader->enable(); for (unsigned int i = 0; i < meshEntries.size(); ++i) { MeshEntry * m = meshEntries[i]; @@ -371,21 +373,24 @@ void Mesh::draw(SceneContext &ctx) { ctx.modelViewMatrix = ctx.viewMatrix * ctx.modelMatrix; ctx.normalMatrix = glm::transpose(glm::inverse(glm::mat3(ctx.modelMatrix))); - shader.addUniform("mvp", ctx.mvpMatrix); - shader.addUniform("NormalMatrix", ctx.normalMatrix); - shader.addUniform("ModelMatrix", ctx.modelMatrix); + shader->addUniform("mvp", ctx.mvpMatrix); + shader->addUniform("NormalMatrix", ctx.normalMatrix); + if (ctx.renderMode == FORWARD_LIGHT) + shader->addUniform("ModelViewMatrix", ctx.modelViewMatrix); + else + shader->addUniform("ModelMatrix", ctx.modelMatrix); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, textures["0"].tex_ref); - meshEntries.at(i)->render(ctx, shader); + meshEntries.at(i)->render(ctx, *shader); glBindTexture(GL_TEXTURE_2D, 0); model.glPopMatrix(); } - shader.disable(); + shader->disable(); } void Mesh::effectTransformations() diff --git a/BaseGLProject/Models/Mesh.h b/BaseGLProject/Models/Mesh.h index f8334fc..b217039 100644 --- a/BaseGLProject/Models/Mesh.h +++ b/BaseGLProject/Models/Mesh.h @@ -61,9 +61,7 @@ public: ~MeshEntry(); Mesh * parent; void render(SceneContext &ctx, Shader &shd); - private: - void textureBinding(Shader *shd); - void textureUnbinding(); + }; public: @@ -77,10 +75,6 @@ public: private: std::vector> _transformations; - void enableCulling(); - void textureBinding(Shader *shd); - void textureUnbinding(); - void disableCulling(); public: Model model; CullFace cullMode = NONE; @@ -97,8 +91,7 @@ public: void removeLastTransformations(int n); glm::vec3 getPosition(); - Shader shader; + std::shared_ptr shader; void draw(SceneContext &ctx); - void assignTexture(Texture &texture); }; \ No newline at end of file diff --git a/BaseGLProject/Multipass.cpp b/BaseGLProject/Multipass.cpp index c1eefed..c32afcd 100644 --- a/BaseGLProject/Multipass.cpp +++ b/BaseGLProject/Multipass.cpp @@ -66,30 +66,45 @@ void Multipass::enableFrameBufferTexture(const std::string tex_name) glBindFramebuffer(GL_FRAMEBUFFER, _fboId); } -void Multipass::gBufferSetup(SceneContext &scnctx) +void Multipass::gBufferSetup(SceneContext &scnctx, std::map &meshes) { - delete(shader); + if (shader != nullptr) + delete(shader); shader = new Shader("textureViewer.vert", "textureViewer.frag"); + shader->addUniform("tex", 0); + for (auto mesh : meshes) + mesh.second->shader = std::make_shared("DSGeometryPass.vert", "DSGeometryPass.frag"); scnctx.firstRedraw = false; } -void Multipass::deferredLightSetup(SceneContext &scnctx) +void Multipass::recomputeDeferredLights(SceneContext &scnctx) +{ + int i = 0; + for (auto light : scnctx.lights) + { + shader->addUniform("lights[" + std::to_string(i) + "].Position", glm::vec3(light.location)); + shader->addUniform("lights[" + std::to_string(i) + "].Color", light.intensity); + i++; + } + + shader->addUniform("NLights", (int)scnctx.lights.size()); +} + +void Multipass::deferredLightSetup(SceneContext &scnctx, std::map &meshes) { - shader = new Shader("DSLightPass.vert", "DSLightPass.frag"); + if (shader != nullptr) + delete(shader); + shader = new Shader("DSLightPass.vert", "DSLightPass.frag"); shader->addUniform("pos_tex", 0); shader->addUniform("normal_tex", 1); shader->addUniform("color_tex", 2); - int i = 0; - for (auto light : scnctx.lights) - { - shader->addUniform("lights[" + std::to_string(i) + "].Position", glm::vec3(light.second.location)); - shader->addUniform("lights[" + std::to_string(i) + "].Color", light.second.intensity); - i++; - } + for (auto mesh : meshes) + mesh.second->shader = std::make_shared("DSGeometryPass.vert", "DSGeometryPass.frag"); + + recomputeDeferredLights(scnctx); - shader->addUniform("NLights", (int)scnctx.lights.size()); scnctx.firstRedraw = false; } @@ -133,6 +148,20 @@ void Multipass::drawDeferredLightToScreen(SceneContext &scnctx) shader->disable(); } +void Multipass::forwardLightSetup(SceneContext &scnctx, std::map &meshes) +{ + if (shader != nullptr) + delete(shader); + shader = nullptr; + for (auto mesh : meshes) + { + mesh.second->shader = std::make_shared("tex_base_light.vert", "tex_base_light.frag"); + mesh.second->shader->addUniform("tex", 0); + } + + scnctx.firstRedraw = false; +} + void Multipass::drawGBufferToScreen(SceneContext & scnctx) { glBindFramebuffer(GL_FRAMEBUFFER, 0); @@ -143,8 +172,7 @@ void Multipass::drawGBufferToScreen(SceneContext & scnctx) glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, _pass_textures[_current_tex]); - - shader->addUniform("tex", 0); + glBindVertexArray(_quad_vao); glBindBuffer(GL_ARRAY_BUFFER, _quad_vbo); diff --git a/BaseGLProject/Multipass.h b/BaseGLProject/Multipass.h index 5ff8a13..c9721e3 100644 --- a/BaseGLProject/Multipass.h +++ b/BaseGLProject/Multipass.h @@ -3,6 +3,7 @@ #include #include #include "Shader.h" +#include "Models/Mesh.h" #include "SceneContext.h" class Multipass @@ -21,11 +22,13 @@ public: void enableFrameBufferTexture(const std::string tex_name); - void gBufferSetup(SceneContext & scnctx); + void gBufferSetup(SceneContext &scnctx, std::map &meshes); + void recomputeDeferredLights(SceneContext &scnctx); void drawGBufferToScreen(SceneContext &scnctx); - void deferredLightSetup(SceneContext &scnctx); + void deferredLightSetup(SceneContext &scnctx, std::map &meshes); void drawDeferredLightToScreen(SceneContext &scnctx); + void forwardLightSetup(SceneContext &scnctx, std::map &meshes); diff --git a/BaseGLProject/MyGLWindow.cpp b/BaseGLProject/MyGLWindow.cpp index 24601b9..b002325 100644 --- a/BaseGLProject/MyGLWindow.cpp +++ b/BaseGLProject/MyGLWindow.cpp @@ -41,8 +41,8 @@ MyGlWindow::MyGlWindow(int w, int h) : m_width = w; m_height = h; - _scnctx.height = m_height; - _scnctx.width = m_width; + scnctx.height = m_height; + scnctx.width = m_width; setup(); } @@ -54,15 +54,17 @@ MyGlWindow::~MyGlWindow() void MyGlWindow::draw() { - if (_scnctx.renderMode == GBUF_DEBUG) + if (scnctx.renderMode == GBUF_DEBUG) drawDebugGBuffer(); - else if (_scnctx.renderMode == DEFERRED_LIGHT) + else if (scnctx.renderMode == DEFERRED_LIGHT) drawDeferredLight(); + else if (scnctx.renderMode == FORWARD_LIGHT) + drawForwardLight(); } void MyGlWindow::setBgColor(float bgColor[3]) { - _scnctx.bg = glm::vec4(bgColor[0], bgColor[1], bgColor[2], 1); + scnctx.bg = glm::vec4(bgColor[0], bgColor[1], bgColor[2], 1); } void MyGlWindow::textureSetup() @@ -72,39 +74,39 @@ void MyGlWindow::textureSetup() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); - _scnctx.textures.emplace("BrickTex", Texture("brick1.jpg")); - _scnctx.textures.emplace("MossTex", Texture("moss.png")); - _scnctx.textures.emplace("EarthTex", Texture("earth.jpg")); - _scnctx.textures.emplace("OgreTex", Texture("Models/ogre/ogre_diffuse.png")); - _scnctx.textures["OgreTex"].mat.shininess = 3.0f; - _scnctx.textures["OgreTex"].mat.ks = glm::vec3(0.1f, 0.1f, 0.1f); - _scnctx.textures["OgreTex"].mat.ka = glm::vec3(0.3f, 0.3f, 0.3f); - _scnctx.textures["OgreTex"].mat.enabled = true; - _scnctx.textures.emplace("OgreNmap", Texture("Models/ogre/ogre_normalmap.png")); - _scnctx.textures["OgreNmap"].isNmap = true; - _scnctx.textures.emplace("CubeTex", Texture("Models/cube/color_map.jpg")); - _scnctx.textures["CubeTex"].mat.shininess = 3.0f; - _scnctx.textures["CubeTex"].mat.ks = glm::vec3(0.1f, 0.1f, 0.1f); - _scnctx.textures["CubeTex"].mat.ka = glm::vec3(0.3f, 0.3f, 0.3f); - _scnctx.textures["CubeTex"].mat.enabled = true; - _scnctx.textures.emplace("CubeNmap", Texture("Models/cube/normal_map.jpg")); - _scnctx.textures["CubeNmap"].isNmap = true; + scnctx.textures.emplace("BrickTex", Texture("brick1.jpg")); + scnctx.textures.emplace("MossTex", Texture("moss.png")); + scnctx.textures.emplace("EarthTex", Texture("earth.jpg")); + scnctx.textures.emplace("OgreTex", Texture("Models/ogre/ogre_diffuse.png")); + scnctx.textures["OgreTex"].mat.shininess = 3.0f; + scnctx.textures["OgreTex"].mat.ks = glm::vec3(0.1f, 0.1f, 0.1f); + scnctx.textures["OgreTex"].mat.ka = glm::vec3(0.3f, 0.3f, 0.3f); + scnctx.textures["OgreTex"].mat.enabled = true; + scnctx.textures.emplace("OgreNmap", Texture("Models/ogre/ogre_normalmap.png")); + scnctx.textures["OgreNmap"].isNmap = true; + scnctx.textures.emplace("CubeTex", Texture("Models/cube/color_map.jpg")); + scnctx.textures["CubeTex"].mat.shininess = 3.0f; + scnctx.textures["CubeTex"].mat.ks = glm::vec3(0.1f, 0.1f, 0.1f); + scnctx.textures["CubeTex"].mat.ka = glm::vec3(0.3f, 0.3f, 0.3f); + scnctx.textures["CubeTex"].mat.enabled = true; + scnctx.textures.emplace("CubeNmap", Texture("Models/cube/normal_map.jpg")); + scnctx.textures["CubeNmap"].isNmap = true; } void MyGlWindow::multipassSetup() { - _multipassManager.addTexture("position_buffer", GL_NEAREST, GL_RGB16F, GL_RGB, GL_FLOAT, false, _scnctx); - _multipassManager.addTexture("normal_buffer", GL_NEAREST, GL_RGB16F, GL_RGB, GL_UNSIGNED_BYTE, false, _scnctx); - _multipassManager.addTexture("color_buffer", GL_NEAREST, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, false, _scnctx); - _multipassManager.addTexture("depth_tex", GL_LINEAR, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_FLOAT, true, _scnctx); + multipassManager.addTexture("position_buffer", GL_NEAREST, GL_RGB16F, GL_RGB, GL_FLOAT, false, scnctx); + multipassManager.addTexture("normal_buffer", GL_NEAREST, GL_RGB16F, GL_RGB, GL_UNSIGNED_BYTE, false, scnctx); + multipassManager.addTexture("color_buffer", GL_NEAREST, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, false, scnctx); + multipassManager.addTexture("depth_tex", GL_LINEAR, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_FLOAT, true, scnctx); - _multipassManager.bindToFrameBuffer(GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, "position_buffer"); - _multipassManager.bindToFrameBuffer(GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, "normal_buffer"); - _multipassManager.bindToFrameBuffer(GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, "color_buffer"); - _multipassManager.bindToFrameBuffer(GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, "depth_tex"); + multipassManager.bindToFrameBuffer(GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, "position_buffer"); + multipassManager.bindToFrameBuffer(GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, "normal_buffer"); + multipassManager.bindToFrameBuffer(GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, "color_buffer"); + multipassManager.bindToFrameBuffer(GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, "depth_tex"); - _multipassManager.setDrawBuffers(); + multipassManager.setDrawBuffers(); } void MyGlWindow::setup() @@ -113,7 +115,7 @@ void MyGlWindow::setup() glEnable(GL_DEPTH_BUFFER); glEnable(GL_TEXTURE_2D); - _scnctx.bg = glm::vec4(0.7, 0.7, 0.9, 1); + scnctx.bg = glm::vec4(0.7, 0.7, 0.9, 1); textureSetup(); multipassSetup(); @@ -126,105 +128,131 @@ void MyGlWindow::setup() meshes.emplace("mountain", mountain); - _scnctx.lights.emplace("RandLight", - Light(glm::vec3(1, 1, 1), glm::vec4(0, 2, 0, 1))); + scnctx.lights.emplace_back(glm::vec3(1, 1, 1), glm::vec4(0, 2, 0, 1)); //Scene for light testing - moddata.simpleCube(); + //moddata.simpleCube(); //Hardcoded seed for easy scene replication - /*std::srand(18); + //std::srand(18); - int zob = std::rand(); - for (int i = 0; i < 64; i++) - { - std::string cube_name = "Cube" + std::to_string(i); - meshes.emplace(cube_name, new Mesh(moddata, "DSGeometryPass.vert", "DSGeometryPass.frag")); - meshes[cube_name]->textures["0"] = _scnctx.textures["BrickTex"]; - - float pos_x = std::rand() % 100 - 50; - float pos_z = std::rand() % 100 - 50; + //int zob = std::rand(); + //for (int i = 0; i < 20; i++) + //{ + // //std::string cube_name = "Cube" + std::to_string(i); + // //meshes.emplace(cube_name, new Mesh(moddata, "DSGeometryPass.vert", "DSGeometryPass.frag")); + // //meshes[cube_name]->textures["0"] = _scnctx.textures["BrickTex"]; + // // + // float pos_x = std::rand() % 100 - 50; + // float pos_z = std::rand() % 100 - 50; - meshes[cube_name]->addStartTranslation(glm::vec4(0, 1, 0, 0)); - meshes[cube_name]->addStartTranslation(glm::vec4(pos_x, 0, 0, 0)); - meshes[cube_name]->addStartTranslation(glm::vec4(0, 0, pos_z, 0)); - meshes[cube_name]->addStartRotation(glm::vec4(1, 0, 0, std::rand() % 360)); - meshes[cube_name]->addStartRotation(glm::vec4(0, 1, 0, std::rand() % 360)); - meshes[cube_name]->addStartRotation(glm::vec4(0, 0, 1, std::rand() % 360)); - - float light_r = (40 + std::rand() % 60) / 100.f; - float light_g = (40 + std::rand() % 60) / 100.f; - float light_b = (40 + std::rand() % 60) / 100.f; - - _scnctx.lights.emplace("RandLight" + i, - Light(glm::vec3(light_r, light_g, light_b), glm::vec4(pos_x, 2, pos_z, 1))); - }*/ + // //meshes[cube_name]->addStartTranslation(glm::vec4(0, 1, 0, 0)); + // //meshes[cube_name]->addStartTranslation(glm::vec4(pos_x, 0, 0, 0)); + // //meshes[cube_name]->addStartTranslation(glm::vec4(0, 0, pos_z, 0)); + // //meshes[cube_name]->addStartRotation(glm::vec4(1, 0, 0, std::rand() % 360)); + // //meshes[cube_name]->addStartRotation(glm::vec4(0, 1, 0, std::rand() % 360)); + // //meshes[cube_name]->addStartRotation(glm::vec4(0, 0, 1, std::rand() % 360)); + // + // float light_r = (40 + std::rand() % 60) / 100.f; + // float light_g = (40 + std::rand() % 60) / 100.f; + // float light_b = (40 + std::rand() % 60) / 100.f; + // + // scnctx.lights.emplace_back(glm::vec3(light_r, light_g, light_b), glm::vec4(pos_x, 2, pos_z, 1)); + //} } void MyGlWindow::drawDeferredLight() { - if (_scnctx.firstRedraw) - _multipassManager.deferredLightSetup(_scnctx); + if (scnctx.firstRedraw) + multipassManager.deferredLightSetup(scnctx, meshes); - _scnctx.height = m_height; - _scnctx.width = m_width; + scnctx.height = m_height; + scnctx.width = m_width; glm::vec3 eye(viewer.getViewPoint().x, viewer.getViewPoint().y, viewer.getViewPoint().z); glm::vec3 look(viewer.getViewCenter().x, viewer.getViewCenter().y, viewer.getViewCenter().z); glm::vec3 up(viewer.getUpVector().x, viewer.getUpVector().y, viewer.getUpVector().z); glm::mat4 view = lookAt(eye, look, up); //Calculate view matrix from parameters of m_viewer - glm::mat4 projection = perspective(45.0f, (float)_scnctx.width / (float)_scnctx.height, 0.1f, 1000.0f); + glm::mat4 projection = perspective(45.0f, (float)scnctx.width / (float)scnctx.height, 0.1f, 1000.0f); - _scnctx.camPos = eye; - _scnctx.viewMatrix = view; - _scnctx.projectionMatrix = projection; + scnctx.camPos = eye; + scnctx.viewMatrix = view; + scnctx.projectionMatrix = projection; - glClearColor(_scnctx.bg.r, _scnctx.bg.g, _scnctx.bg.b, _scnctx.bg.a); - glViewport(0, 0, _scnctx.width, _scnctx.height); + glClearColor(scnctx.bg.r, scnctx.bg.g, scnctx.bg.b, scnctx.bg.a); + glViewport(0, 0, scnctx.width, scnctx.height); - _multipassManager.enableFrameBufferTexture(_scnctx.fboDisplayName); + multipassManager.enableFrameBufferTexture(scnctx.fboDisplayName); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); for (auto it = meshes.begin(); it != meshes.end(); it++) - (*it).second->draw(_scnctx); + (*it).second->draw(scnctx); - _multipassManager.drawDeferredLightToScreen(_scnctx); + multipassManager.drawDeferredLightToScreen(scnctx); } void MyGlWindow::drawDebugGBuffer() { - if (_scnctx.firstRedraw) - _multipassManager.gBufferSetup(_scnctx); + if (scnctx.firstRedraw) + multipassManager.gBufferSetup(scnctx, meshes); - _scnctx.height = m_height; - _scnctx.width = m_width; + scnctx.height = m_height; + scnctx.width = m_width; glm::vec3 eye(viewer.getViewPoint().x, viewer.getViewPoint().y, viewer.getViewPoint().z); glm::vec3 look(viewer.getViewCenter().x, viewer.getViewCenter().y, viewer.getViewCenter().z); glm::vec3 up(viewer.getUpVector().x, viewer.getUpVector().y, viewer.getUpVector().z); glm::mat4 view = lookAt(eye, look, up); //Calculate view matrix from parameters of m_viewer - glm::mat4 projection = perspective(45.0f, (float)_scnctx.width / (float)_scnctx.height, 0.1f, 1000.0f); + glm::mat4 projection = perspective(45.0f, (float)scnctx.width / (float)scnctx.height, 0.1f, 1000.0f); - _scnctx.camPos = eye; - _scnctx.viewMatrix = view; - _scnctx.projectionMatrix = projection; + scnctx.camPos = eye; + scnctx.viewMatrix = view; + scnctx.projectionMatrix = projection; - glClearColor(_scnctx.bg.r, _scnctx.bg.g, _scnctx.bg.b, _scnctx.bg.a); - glViewport(0, 0, _scnctx.width, _scnctx.height); + glClearColor(scnctx.bg.r, scnctx.bg.g, scnctx.bg.b, scnctx.bg.a); + glViewport(0, 0, scnctx.width, scnctx.height); - _multipassManager.enableFrameBufferTexture(_scnctx.fboDisplayName); + multipassManager.enableFrameBufferTexture(scnctx.fboDisplayName); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); for (auto it = meshes.begin(); it != meshes.end(); it++) - (*it).second->draw(_scnctx); + (*it).second->draw(scnctx); - _multipassManager.drawGBufferToScreen(_scnctx); + multipassManager.drawGBufferToScreen(scnctx); } +void MyGlWindow::drawForwardLight() +{ + if (scnctx.firstRedraw) + multipassManager.forwardLightSetup(scnctx, meshes); + + scnctx.height = m_height; + scnctx.width = m_width; + + glm::vec3 eye(viewer.getViewPoint().x, viewer.getViewPoint().y, viewer.getViewPoint().z); + glm::vec3 look(viewer.getViewCenter().x, viewer.getViewCenter().y, viewer.getViewCenter().z); + glm::vec3 up(viewer.getUpVector().x, viewer.getUpVector().y, viewer.getUpVector().z); + glm::mat4 view = lookAt(eye, look, up); //Calculate view matrix from parameters of m_viewer + glm::mat4 projection = perspective(45.0f, (float)scnctx.width / (float)scnctx.height, 0.1f, 1000.0f); + + scnctx.camPos = eye; + scnctx.viewMatrix = view; + scnctx.projectionMatrix = projection; + + glClearColor(scnctx.bg.r, scnctx.bg.g, scnctx.bg.b, scnctx.bg.a); + glViewport(0, 0, scnctx.width, scnctx.height); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + for (auto it = meshes.begin(); it != meshes.end(); it++) + (*it).second->draw(scnctx); + +} + void MyGlWindow::resize(int w, int h) { m_width = w; diff --git a/BaseGLProject/MyGLWindow.h b/BaseGLProject/MyGLWindow.h index e8d981f..7a298c7 100644 --- a/BaseGLProject/MyGLWindow.h +++ b/BaseGLProject/MyGLWindow.h @@ -32,19 +32,21 @@ public: void resize(int w, int h); Viewer viewer; - SceneContext _scnctx; + SceneContext scnctx; + Multipass multipassManager; private: int m_width; int m_height; float _bgColor[3]; - Multipass _multipassManager; + GLuint _vaoHandle; GLuint _iboHandle; void drawDebugGBuffer(); + void drawForwardLight(); void drawDeferredLight(); void textureSetup(); void multipassSetup(); diff --git a/BaseGLProject/SceneContext.h b/BaseGLProject/SceneContext.h index c637e45..17d2ec5 100644 --- a/BaseGLProject/SceneContext.h +++ b/BaseGLProject/SceneContext.h @@ -9,12 +9,13 @@ enum RenderMode { GBUF_DEBUG, - DEFERRED_LIGHT + DEFERRED_LIGHT, + FORWARD_LIGHT }; struct SceneContext { - std::map lights; + std::vector lights; std::map floatValues; glm::mat4x4 viewMatrix; @@ -43,10 +44,10 @@ struct SceneContext { for (auto it : lights) { - if (it.second.type == Light::SPOT) + if (it.type == Light::SPOT) { - it.second.location = it.second.location * viewMatrix; - it.second.direction = (viewMatrix * it.second.lookAt - it.second.location * viewMatrix); + it.location = it.location * viewMatrix; + it.direction = (viewMatrix * it.lookAt - it.location * viewMatrix); } } } diff --git a/BaseGLProject/Source.cpp b/BaseGLProject/Source.cpp index 24d9a22..a416f8a 100644 --- a/BaseGLProject/Source.cpp +++ b/BaseGLProject/Source.cpp @@ -155,6 +155,55 @@ bool createWindow(GLFWwindow **window) return true; } +void FPSDisplay(int width) +{ + static int frameCount = 0; + static int fps = 60; + static double previousTime = glfwGetTime(); + + double currentTime = glfwGetTime(); + frameCount++; + // If a second has passed. + if (currentTime - previousTime >= 1.0) + { + fps = frameCount; + frameCount = 0; + previousTime = currentTime; + } + + if (ImGui::Begin("FPSCounterOutline1", false, + ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoFocusOnAppearing)) + ImGui::TextColored(ImVec4(0, 0, 0, 1), std::to_string(fps).c_str()); + ImGui::End(); + + if (ImGui::Begin("FPSCounterOutline2", false, + ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoFocusOnAppearing)) + ImGui::TextColored(ImVec4(0, 0, 0, 1), std::to_string(fps).c_str()); + ImGui::End(); + + if (ImGui::Begin("FPSCounterOutline3", false, + ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoFocusOnAppearing)) + ImGui::TextColored(ImVec4(0, 0, 0, 1), std::to_string(fps).c_str()); + ImGui::End(); + + if (ImGui::Begin("FPSCounterOutline4", false, + ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoFocusOnAppearing)) + ImGui::TextColored(ImVec4(0, 0, 0, 1), std::to_string(fps).c_str()); + ImGui::End(); + + if (ImGui::Begin("FPSCounter", false, + ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoFocusOnAppearing)) + ImGui::TextColored(ImVec4(1, 1, 1, 1), std::to_string(fps).c_str()); + ImGui::End(); + + ImGui::SetWindowPos("FPSCounterOutline1", ImVec2(width - 49.f, 20.f), ImGuiCond_Once); + ImGui::SetWindowPos("FPSCounterOutline2", ImVec2(width - 51.f, 20.f), ImGuiCond_Once); + ImGui::SetWindowPos("FPSCounterOutline3", ImVec2(width - 50.f, 19.f), ImGuiCond_Once); + ImGui::SetWindowPos("FPSCounterOutline4", ImVec2(width - 50.f, 21.f), ImGuiCond_Once); + + ImGui::SetWindowPos("FPSCounter", ImVec2(width - 50.f, 20.f), ImGuiCond_Once); +} + int loop(GLFWwindow *window) { std::printf("OpenGL %s, GLSL %s\n", glGetString(GL_VERSION), glGetString(GL_SHADING_LANGUAGE_VERSION)); @@ -165,15 +214,16 @@ int loop(GLFWwindow *window) glfwGetWindowSize(window, &width, &heigth); MyGlWindow glWin(width, heigth); - int frameCount = 0; - int fps = 60; - double previousTime = glfwGetTime(); - - glWin._scnctx.fboDisplayName = "position_buffer"; + glWin.scnctx.fboDisplayName = "position_buffer"; bool is_selected = false; - glWin._scnctx.renderMode = GBUF_DEBUG; - glWin._scnctx.firstRedraw = true; + glWin.scnctx.renderMode = GBUF_DEBUG; + glWin.scnctx.firstRedraw = true; + + std::vector lights_strs; + char const **strings = nullptr; + + int current_light = 0; while (!glfwWindowShouldClose(window)) { @@ -183,30 +233,37 @@ int loop(GLFWwindow *window) if (ImGui::Begin("Scene settings")) { - if (ImGui::BeginCombo("Debug Buffer", glWin._scnctx.fboDisplayName.c_str())) + if (ImGui::BeginCombo("Debug Buffer", glWin.scnctx.fboDisplayName.c_str())) { if (ImGui::Selectable("Position buffer", &is_selected, 0, ImVec2(120, 10))) - glWin._scnctx.fboDisplayName = "position_buffer"; + glWin.scnctx.fboDisplayName = "position_buffer"; if (ImGui::Selectable("Normal buffer", &is_selected, 0, ImVec2(120, 10))) - glWin._scnctx.fboDisplayName = "normal_buffer"; + glWin.scnctx.fboDisplayName = "normal_buffer"; if (ImGui::Selectable("Color buffer", &is_selected, 0, ImVec2(120, 10))) - glWin._scnctx.fboDisplayName = "color_buffer"; + glWin.scnctx.fboDisplayName = "color_buffer"; ImGui::EndCombo(); } if (ImGui::BeginCombo("Render Mode", - (glWin._scnctx.renderMode == DEFERRED_LIGHT)? "Deferred Lights" : "Debug GBuffers")) + (glWin.scnctx.renderMode == DEFERRED_LIGHT) ? "Deferred Lights" : ( + (glWin.scnctx.renderMode == FORWARD_LIGHT) ? "Forward Lights" : "Debug GBuffers"))) { if (ImGui::Selectable("Draw Debug GBuffers", &is_selected, 0, ImVec2(120, 10))) { - glWin._scnctx.renderMode = GBUF_DEBUG; - glWin._scnctx.firstRedraw = true; + glWin.scnctx.renderMode = GBUF_DEBUG; + glWin.scnctx.firstRedraw = true; } if (ImGui::Selectable("Draw with Deferred Lights", &is_selected, 0, ImVec2(120, 10))) { - glWin._scnctx.renderMode = DEFERRED_LIGHT; - glWin._scnctx.firstRedraw = true; + glWin.scnctx.renderMode = DEFERRED_LIGHT; + glWin.scnctx.firstRedraw = true; + } + + if (ImGui::Selectable("Draw with Forward Lights", &is_selected, 0, ImVec2(120, 10))) + { + glWin.scnctx.renderMode = FORWARD_LIGHT; + glWin.scnctx.firstRedraw = true; } ImGui::EndCombo(); @@ -216,25 +273,35 @@ int loop(GLFWwindow *window) } ImGui::End(); + if (ImGui::Begin("Light management")) + { + lights_strs.clear(); + for (auto light : glWin.scnctx.lights) + lights_strs.push_back(light.toString()); + + std::free(strings); + strings = (char const **)std::malloc(sizeof(char *) * (lights_strs.size() + 1)); + std::memset((void *)strings, 0, sizeof(char *) * (lights_strs.size() + 1)); + + for (int i = 0; i < lights_strs.size(); i++) + strings[i] = lights_strs[i].c_str(); + + ImGui::ListBox("Lights", ¤t_light, strings, lights_strs.size()); + if (ImGui::SliderFloat("Selected light X", &glWin.scnctx.lights[current_light].location.x, -10, 10) + && glWin.scnctx.renderMode != GBUF_DEBUG) + glWin.multipassManager.recomputeDeferredLights(glWin.scnctx); + if (ImGui::SliderFloat("Selected light Y", &glWin.scnctx.lights[current_light].location.y, -10, 10) + && glWin.scnctx.renderMode != GBUF_DEBUG) + glWin.multipassManager.recomputeDeferredLights(glWin.scnctx); + if (ImGui::SliderFloat("Selected light Z", &glWin.scnctx.lights[current_light].location.z, -10, 10) + && glWin.scnctx.renderMode != GBUF_DEBUG) + glWin.multipassManager.recomputeDeferredLights(glWin.scnctx); - double currentTime = glfwGetTime(); - frameCount++; - // If a second has passed. - if (currentTime - previousTime >= 1.0) - { - fps = frameCount; - frameCount = 0; - previousTime = currentTime; } - - - if (ImGui::Begin("FPSCounter", false, - ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoFocusOnAppearing)) - ImGui::TextColored(ImVec4(1, 1, 0, 1), std::to_string(fps).c_str()); ImGui::End(); - ImGui::SetWindowPos("FPSCounter", ImVec2(width - 50, 20), ImGuiCond_Once); + FPSDisplay(width); glfwSwapBuffers(window); glWin.draw(); diff --git a/BaseGLProject/imgui.ini b/BaseGLProject/imgui.ini index 6ceff39..aff7282 100644 --- a/BaseGLProject/imgui.ini +++ b/BaseGLProject/imgui.ini @@ -58,3 +58,33 @@ Pos=20,20 Size=309,85 Collapsed=0 +[Window][FPSCounterOutline] +Pos=1031,21 +Size=32,32 +Collapsed=0 + +[Window][FPSCounterOutline4] +Pos=1030,21 +Size=32,32 +Collapsed=0 + +[Window][FPSCounterOutline3] +Pos=1030,19 +Size=32,32 +Collapsed=0 + +[Window][FPSCounterOutline2] +Pos=1029,20 +Size=32,32 +Collapsed=0 + +[Window][FPSCounterOutline1] +Pos=1031,20 +Size=32,32 +Collapsed=0 + +[Window][Light management] +Pos=12,120 +Size=410,449 +Collapsed=0 + diff --git a/BaseGLProject/tex_base_light.frag b/BaseGLProject/tex_base_light.frag index f2e0eff..c0c826b 100644 --- a/BaseGLProject/tex_base_light.frag +++ b/BaseGLProject/tex_base_light.frag @@ -8,52 +8,43 @@ uniform vec3 Ka; uniform vec3 Ks; uniform float Shininess; -struct LightInfo { +struct Light { vec4 Position; - vec3 Intensity; + vec3 Color; }; -uniform LightInfo Light[64]; -uniform int LightCount; +uniform Light lights[64]; +uniform int NLights; in vec3 fNormal; in vec3 pos; in vec2 texCoord; -uniform int TexCount; -uniform sampler2D tex[32]; +uniform sampler2D tex; void main() { - vec3 finalColor; vec3 diffuse_sum; vec3 specular_sum; vec3 ambient; - ambient = Ka * Light[0].Intensity; - for (int i=0; i