#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() { shaders.clear(); } void MyGlWindow::setBgColor(float bgColor[3]) { _scnctx.bg = glm::vec4(bgColor[0], bgColor[1], bgColor[2], 1); } 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::shaderSetup() { shaders["Simple"] = new Shader("simple.vert", "simple.frag"); shaders["Simple"]->uniformFlags = ShaderFlags::MVP_FLAG; shaders["BaseLight"] = new Shader("base_light.vert", "base_light.frag"); shaders["ShadowLight"] = new Shader("shadow_light.vert", "shadow_light.frag"); shaders["LightPOV"] = new Shader("light_pov.vert", "light_pov.frag"); shaders["LightPOV"]->uniformFlags = 0; shaders["Fog"] = new Shader("fog.vert", "fog.frag"); shaders["TexBaseLight"] = new Shader("tex_base_light.vert", "tex_base_light.frag"); shaders["TexNmapLight"] = new Shader("nmap.vert", "nmap.frag"); shaders["TexNmapLight"]->uniformFlags &= ~ShaderFlags::KD_FLAG; shaders["SpotLight"] = new Shader("spotlight.vert", "spotlight.frag"); shaders["SpotLight"]->light_type = Light::LightType::SPOT; shaders["TexSpotLight"] = new Shader("tex_spotlight.vert", "tex_spotlight.frag"); shaders["TexSpotLight"]->light_type = Light::LightType::SPOT; shaders["Silhouette"] = new Shader("silhouette.vert", "silhouette.frag"); shaders["Silhouette"]->uniformFlags = ShaderFlags::MVP_FLAG; shaders["Silhouette"]->addUniform("fColor", glm::vec3(237 / 255, 229 / 255, 194 / 255)); shaders["Silhouette"]->addUniform("sil_offset", 0.1f); shaders["Toon"] = new Shader("base_light.vert", "toon.frag"); //Removing useless specular component shaders["Toon"]->uniformFlags &= ~ShaderFlags::KS_FLAG; shaders["Toon"]->uniformFlags &= ~ShaderFlags::SHINE_FLAG; shaders["Skybox"] = new Shader("skybox.vert", "skybox.frag"); shaders["Skybox"]->uniformFlags = MVP_FLAG | MODEL_MATRIX_FLAG | SKYBOX_TEX_FLAG; shaders["Skybox"]->addUniform("RefractionIndex", glm::vec3(0.65, 0.67, 0.69)); shaders["DSGeometryPass"] = new Shader("DSGeometryPass.vert", "DSGeometryPass.frag"); shaders["DSGeometryPass"]->uniformFlags = MVP_FLAG | KA_FLAG | KD_FLAG | KS_FLAG | SHINE_FLAG; shaders["DSLightPass"] = new Shader("DSLightPass.vert", "DSLightPass.frag"); shaders["DSLightPass"]->uniformFlags = LIGHTS_FLAG; } void MyGlWindow::lightSetup() { //Showcase lights _scnctx.lights.emplace("Spotlight1", Light(glm::vec3(0.8f), glm::vec4(10, 10, 10, 1))); // 24, 12, 2, glm::vec4(0, 1, 0, 1))); //Party lights //_scnctx.lights.emplace("Light1", Light(glm::vec3(0.0f, 0.5f, 0.5f), glm::vec4(10, 10, 0, 1))); //_scnctx.lights.emplace("Light2", Light(glm::vec3(0.0f, 0.0f, 0.5f), glm::vec4(3.09, 10, 9.51, 1))); //_scnctx.lights.emplace("Light3", Light(glm::vec3(0.5f, 0.0f, 0.0f), glm::vec4(-8.09, 10, 5.87, 1))); //_scnctx.lights.emplace("Light4", Light(glm::vec3(0.0f, 0.5f, 0.0f), glm::vec4(-8.09, 10, -5.87, 1))); //_scnctx.lights.emplace("Light5", Light(glm::vec3(0.5f, 0.5f, 0.5f), glm::vec4(3.09, 10, -9.51, 1))); } void MyGlWindow::multipassSetup() { //_multipassManager.shader = shaders["ShadowLight"]; _multipassManager.addTexture("render_tex", GL_NEAREST, GL_RGB, GL_RGB, false, _scnctx); _multipassManager.bindToFrameBuffer(GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, "render_tex"); _multipassManager.addTexture("depth_tex", GL_LINEAR, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, true, _scnctx, 1024, 1024); _multipassManager.bindToFrameBuffer(GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, "depth_tex"); _multipassManager.setDrawBuffers(); _multipassManager.shader.addSubroutine(GL_FRAGMENT_SHADER, "depthing"); _multipassManager.shader.addSubroutine(GL_FRAGMENT_SHADER, "blurring"); _multipassManager.shader.addSubroutine(GL_FRAGMENT_SHADER, "sharpening"); _multipassManager.shader.addSubroutine(GL_FRAGMENT_SHADER, "sepia"); _multipassManager.shader.addSubroutine(GL_FRAGMENT_SHADER, "grayscale"); _multipassManager.shader.addSubroutine(GL_FRAGMENT_SHADER, "sobel_filter"); _multipassManager.shader.addSubroutine(GL_FRAGMENT_SHADER, "absolutely_no_postprocess"); } void MyGlWindow::setup() { glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_BUFFER); glEnable(GL_TEXTURE_2D); textureSetup(); shaderSetup(); skybox.initialize("Models/Skybox/", shaders["Skybox"]); skybox.scale = 10; _scnctx.skybox_tex = skybox.getTexID(); lightSetup(); multipassSetup(); Dataset moddata; moddata.checkeredFloor(100, 100, glm::vec3(0.1, 0.1, 0.1), glm::vec3(0.7, 0.7, 0.7)); //TODO : replace by specific light shader that supports color channel (and not just materials) meshes.emplace("Floor", new Mesh(moddata, shaders["BaseLight"])); moddata.simpleCube(); //Hardcoded seed for easy scene replication std::srand(18); int zob = std::rand(); for (int i = 0; i < 100; i++) { std::string cube_name = "Cube" + std::to_string(i); meshes.emplace(cube_name, new Mesh(moddata, shaders["Simple"])); meshes[cube_name]->addStartTranslation(glm::vec4(0, 1, 0, 0)); meshes[cube_name]->addStartTranslation(glm::vec4(std::rand() % 100 - 50, 0, 0, 0)); meshes[cube_name]->addStartTranslation(glm::vec4(0, 0, std::rand() % 100 - 50, 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)); } //meshes.emplace("Ogre", new Mesh("ogre/ogre.obj", shaders["TexNmapLight"])); //meshes["Ogre"]->addTranslation(glm::vec4(-0.5, 1, 0, 0)); //meshes["Ogre"]->assignTexture(_scnctx.textures["OgreTex"]); //meshes["Ogre"]->assignTexture(_scnctx.textures["OgreNmap"]); //meshes.emplace("Cube", new Mesh("cube/cube.obj", shaders["TexNmapLight"])); //meshes["Cube"]->addTranslation(glm::vec4(0.5, 1, 0, 0)); //meshes["Cube"]->assignTexture(_scnctx.textures["CubeTex"]); //meshes["Cube"]->assignTexture(_scnctx.textures["CubeNmap"]); //meshes["Buddha"]->addScaling(glm::vec4(4, 4, 4, 0)); //meshes["Buddha"]->addRotation(glm::vec4(0, 1, 0, 180)); //meshes.emplace("Buddha", new Mesh("buddha.obj", shaders["BaseLight"])); //meshes["Buddha"]->addTranslation(glm::vec4(-4, 3, -4, 0)); //meshes["Buddha"]->addScaling(glm::vec4(4, 4, 4, 0)); //meshes["Buddha"]->addRotation(glm::vec4(0, 1, 0, 180)); Dataset moddata; //moddata.simpleCube(); //meshes.emplace("Cube", new Mesh(moddata, shaders["TexBaseLight"])); //meshes["Cube"]->assignTexture(_scnctx.textures["BrickTex"]); //meshes["Cube"]->assignTexture(_scnctx.textures["MossTex"]); //meshes["Cube"]->addTranslation(glm::vec4(4, 3, -4, 0)); //meshes.emplace("Mountain", new Mesh("mountain/mount.blend1.obj", shaders["TexBaseLight"])); //meshes.emplace("Sponza", new Mesh("sponza/sponza.obj", shaders["TexBaseLight"])); //meshes["Sponza"]->addTranslation(glm::vec4(0, -200, 0, 1)); moddata.checkeredFloor(20, 20, glm::vec3(0.1, 0.1, 0.1), glm::vec3(0.7, 0.7, 0.7)); meshes.emplace("Floor", new Mesh(moddata, shaders["LightPOV"])); meshes["Floor"]->addTranslation(glm::vec4(0, -0.05, 0, 1)); meshes["Floor"]->cullMode = BACK; //moddata.simpleCube(); //meshes.emplace("Cube", new Mesh(moddata, shaders["BrickBaseLight"])); //meshes["Cube"]->addTranslation(glm::vec4(0, 1, 0, 1)); //moddata.sphere(1, 100, 100); //meshes.emplace("Sphere", new Mesh(moddata, shaders["TexBaseLight"])); //meshes["Sphere"]->assignTexture(_scnctx.textures["EarthTex"]); //meshes["Sphere"]->addTranslation(glm::vec4(-5, 1, -3, 1)); //meshes.emplace("TeapotSilhouette", new Mesh("teapot.obj", shaders["Silhouette"])); //meshes["TeapotSilhouette"]->addTranslation(glm::vec4(5, 0 ,3, 1)); //meshes["TeapotSilhouette"]->cullMode = FRONT; meshes.emplace("Teapot", new Mesh("teapot.obj", shaders["LightPOV"])); meshes["Teapot"]->addTranslation(glm::vec4(5, 0, 3, 1)); meshes["Teapot"]->cullMode = BACK; //meshes.emplace("Teapot", new Mesh("teapot.obj", shaders["Skybox"])); } void MyGlWindow::draw() { _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, 40.0f); _scnctx.viewMatrix = view; _scnctx.projectionMatrix = projection; // Light POV matrixes glm::mat4 lightMVP = glm::ortho(-25.0f, 25.0f, -25.0f, 25.0f, 0.1f, 40.0f) * lookAt(glm::vec3(_scnctx.lights["Spotlight1"].location), glm::vec3(0) , glm::vec3(0, 1, 0)) * glm::mat4(1.0); shaders["LightPOV"]->addUniform("lightmvp", lightMVP); _multipassManager.enableFrameBufferTexture("depth_tex"); 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); _multipassManager.drawResultToScreen(_scnctx); } void MyGlWindow::resize(int w, int h) { m_width = w; m_height = h; viewer.setAspectRatio(w / float(h)); }