274 lines
9.1 KiB
C++
274 lines
9.1 KiB
C++
#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::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::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();
|
|
|
|
Dataset moddata;
|
|
|
|
|
|
//Scene for GBuffer Testing
|
|
Mesh *mountain = new Mesh("mountain/mount.blend1.obj", "DSGeometryPass.vert", "DSGeometryPass.frag");
|
|
|
|
meshes.emplace("mountain", mountain);
|
|
|
|
scnctx.lights.emplace_back(glm::vec3(1, 1, 1), glm::vec4(0, 2, 0, 1));
|
|
|
|
|
|
//Scene for light testing
|
|
|
|
//moddata.simpleCube();
|
|
|
|
//Hardcoded seed for easy scene replication
|
|
//std::srand(18);
|
|
|
|
//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_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, 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).second->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).second->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).second->shader->addUniform("view_pos", scnctx.camPos);
|
|
int i = 0;
|
|
for (auto light : scnctx.lights)
|
|
{
|
|
(*it).second->shader->addUniform("lights[" + std::to_string(i) + "].Position", glm::vec3(light.location));
|
|
(*it).second->shader->addUniform("lights[" + std::to_string(i) + "].Color", light.intensity);
|
|
i++;
|
|
}
|
|
|
|
(*it).second->shader->addUniform("NLights", (int)scnctx.lights.size());
|
|
(*it).second->draw(scnctx);
|
|
}
|
|
|
|
}
|
|
|
|
void MyGlWindow::resize(int w, int h)
|
|
{
|
|
m_width = w;
|
|
m_height = h;
|
|
viewer.setAspectRatio(w / float(h));
|
|
}
|