#include "MyGlWindow.h" //Getting the projection matrix glm::mat4x4 perspective(float fovy, float aspect, float near, float far) { float fovy2 = glm::tan(fovy / 2); glm::mat4x4 pmat{ { 1 / (aspect * fovy2), 0, 0, 0}, { 0, 1 / fovy2, 0, 0}, { 0, 0, -((far + near) / (far - near)), -1}, { 0, 0, -((2 * far * near) / (far - near)), 0} }; return pmat; } // Getting the view matrix glm::mat4x4 lookAt(glm::vec3 campos, glm::vec3 look, glm::vec3 up) { glm::vec3 ZCam(glm::normalize(campos - look)); glm::vec3 XCam(glm::normalize(glm::cross(up, ZCam))); glm::vec3 YCam(glm::normalize(glm::cross(ZCam, XCam))); glm::mat4x4 cam_mat{ {XCam.x, YCam.x, ZCam.x, 0}, {XCam.y, YCam.y, ZCam.y, 0}, {XCam.z, YCam.z, ZCam.z, 0}, {0, 0, 0 ,1} }; glm::mat4x4 norm_mat{ {1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {-campos.x, -campos.y, -campos.z, 1} }; return cam_mat * norm_mat; } MyGlWindow::MyGlWindow(int w, int h) : viewer(glm::vec3(5, 5, 5), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0), 45.0f, (w / (float)h)) { m_width = w; m_height = h; scnctx.height = m_height; scnctx.width = m_width; setup(); } MyGlWindow::~MyGlWindow() { } void MyGlWindow::draw() { if (scnctx.renderMode == GBUF_DEBUG) drawDebugGBuffer(); 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); } void MyGlWindow::orbitLights(float timePassed, float speed) { float angle = timePassed * speed; for (auto &&light : scnctx.lights) { glm::mat4 rotate = glm::rotate(glm::mat4(1.0f), glm::radians(angle), glm::vec3(0, 1, 0)); light.location = rotate * light.location; } if (scnctx.renderMode == DEFERRED_LIGHT) multipassManager.recomputeDeferredLights(scnctx); } void MyGlWindow::loadScene(SceneChoice scene) { meshes.clear(); scnctx.lights.clear(); float pos_x = -20; float pos_z = -20; Dataset moddata; switch (scene) { case MOUNTAIN: meshes.emplace_back(std::make_shared("mountain/mount.blend1.obj", "DSGeometryPass.vert", "DSGeometryPass.frag")); scnctx.lights.emplace_back(glm::vec3(1, 1, 1), glm::vec4(0, 2, 2, 1)); break; case CUBES: moddata.simpleCube(); std::srand(18); for (int i = 1; i < 401; i++) { meshes.emplace_back(std::make_shared(moddata, "DSGeometryPass.vert", "DSGeometryPass.frag")); meshes[meshes.size() - 1]->textures["0"] = scnctx.textures["BrickTex"]; meshes[meshes.size() - 1]->addStartRotation(glm::vec4(1, -1, 1, 90)); meshes[meshes.size() - 1]->addStartTranslation(glm::vec4(0, 1, 0, 0)); meshes[meshes.size() - 1]->addStartTranslation(glm::vec4(pos_x, 0, 0, 0)); meshes[meshes.size() - 1]->addStartTranslation(glm::vec4(0, 0, pos_z, 0)); pos_x += 2; if (i % 20 == 0) { pos_x = -20; pos_z += 2; } } for (int i = 0; i < 64; i++) { float light_r = (std::rand() % 10) / 100.f; float light_g = (std::rand() % 10) / 100.f; float light_b = (std::rand() % 10) / 100.f; scnctx.lights.emplace_back(glm::vec3(light_r, light_g, light_b), glm::vec4(std::rand() % 40 - 20, std::rand() % 3 + 3, std::rand() % 40 - 20, 1)); } break; default: break; } this->scene = scene; scnctx.firstRedraw = true; } void MyGlWindow::textureSetup() { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 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; } 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.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(); } void MyGlWindow::setup() { glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_BUFFER); glEnable(GL_TEXTURE_2D); scnctx.bg = glm::vec4(0.7, 0.7, 0.9, 1); textureSetup(); multipassSetup(); loadScene(MOUNTAIN); } void MyGlWindow::drawDeferredLight() { if (scnctx.firstRedraw) multipassManager.deferredLightSetup(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); multipassManager.enableFrameBufferTexture(scnctx.fboDisplayName); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); for (auto it = meshes.begin(); it != meshes.end(); it++) (*it)->draw(scnctx); multipassManager.drawDeferredLightToScreen(scnctx); } void MyGlWindow::drawDebugGBuffer() { if (scnctx.firstRedraw) multipassManager.gBufferSetup(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); multipassManager.enableFrameBufferTexture(scnctx.fboDisplayName); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); for (auto it = meshes.begin(); it != meshes.end(); it++) (*it)->draw(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)->shader->addUniform("view_pos", scnctx.camPos); int i = 0; for (auto light : scnctx.lights) { (*it)->shader->addUniform("lights[" + std::to_string(i) + "].Position", glm::vec3(light.location)); (*it)->shader->addUniform("lights[" + std::to_string(i) + "].Color", light.intensity); i++; } (*it)->shader->addUniform("NLights", (int)scnctx.lights.size()); (*it)->draw(scnctx); } } void MyGlWindow::resize(int w, int h) { m_width = w; m_height = h; viewer.setAspectRatio(w / float(h)); }