Proof that deferred shading is way better at handling a lot of lights

This commit is contained in:
Hurlu 2019-06-17 22:32:53 +09:00
parent 59c3fbd4f6
commit 3bbb233716
8 changed files with 149 additions and 96 deletions

View File

@ -20,7 +20,6 @@ public:
void glTranslate(float x, float y, float z)
{
glm::mat4 Trans = glm::translate(glm::mat4(1.0f), glm::vec3(x, y, z));
modelstack.top() = modelstack.top() * Trans;
}

View File

@ -66,14 +66,14 @@ void Multipass::enableFrameBufferTexture(const std::string tex_name)
glBindFramebuffer(GL_FRAMEBUFFER, _fboId);
}
void Multipass::gBufferSetup(SceneContext &scnctx, std::map<std::string, Mesh *> &meshes)
void Multipass::gBufferSetup(SceneContext &scnctx, std::vector<std::shared_ptr<Mesh>>& meshes)
{
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<Shader>("DSGeometryPass.vert", "DSGeometryPass.frag");
mesh->shader = std::make_shared<Shader>("DSGeometryPass.vert", "DSGeometryPass.frag");
scnctx.firstRedraw = false;
}
@ -93,7 +93,7 @@ void Multipass::recomputeDeferredLights(SceneContext &scnctx)
shader->addUniform("NLights", (int)scnctx.lights.size());
}
void Multipass::deferredLightSetup(SceneContext &scnctx, std::map<std::string, Mesh *> &meshes)
void Multipass::deferredLightSetup(SceneContext &scnctx, std::vector<std::shared_ptr<Mesh>>& meshes)
{
if (shader != nullptr)
delete(shader);
@ -104,7 +104,7 @@ void Multipass::deferredLightSetup(SceneContext &scnctx, std::map<std::string, M
shader->addUniform("color_tex", 2);
for (auto mesh : meshes)
mesh.second->shader = std::make_shared<Shader>("DSGeometryPass.vert", "DSGeometryPass.frag");
mesh->shader = std::make_shared<Shader>("DSGeometryPass.vert", "DSGeometryPass.frag");
recomputeDeferredLights(scnctx);
@ -114,6 +114,7 @@ void Multipass::deferredLightSetup(SceneContext &scnctx, std::map<std::string, M
void Multipass::drawDeferredLightToScreen(SceneContext &scnctx)
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
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);
@ -133,11 +134,6 @@ void Multipass::drawDeferredLightToScreen(SceneContext &scnctx)
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
static GLuint clearColor[4] = { 0, 0, 0, 0 };
glClearTexImage(_pass_textures["position_buffer"], 0, GL_BGRA, GL_UNSIGNED_BYTE, &clearColor);
glClearTexImage(_pass_textures["normal_buffer"], 0, GL_BGRA, GL_UNSIGNED_BYTE, &clearColor);
glClearTexImage(_pass_textures["color_buffer"], 0, GL_BGRA, GL_UNSIGNED_BYTE, &clearColor);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE1);
@ -151,15 +147,15 @@ void Multipass::drawDeferredLightToScreen(SceneContext &scnctx)
shader->disable();
}
void Multipass::forwardLightSetup(SceneContext &scnctx, std::map<std::string, Mesh *> &meshes)
void Multipass::forwardLightSetup(SceneContext &scnctx, std::vector<std::shared_ptr<Mesh>>& meshes)
{
if (shader != nullptr)
delete(shader);
shader = nullptr;
for (auto mesh : meshes)
{
mesh.second->shader = std::make_shared<Shader>("tex_base_light.vert", "tex_base_light.frag");
mesh.second->shader->addUniform("tex", 0);
mesh->shader = std::make_shared<Shader>("tex_base_light.vert", "tex_base_light.frag");
mesh->shader->addUniform("tex", 0);
}
scnctx.firstRedraw = false;
@ -181,11 +177,6 @@ void Multipass::drawGBufferToScreen(SceneContext & scnctx)
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
static GLuint clearColor[4] = { 0, 0, 0, 0 };
glClearTexImage(_pass_textures["position_buffer"], 0, GL_BGRA, GL_UNSIGNED_BYTE, &clearColor);
glClearTexImage(_pass_textures["normal_buffer"], 0, GL_BGRA, GL_UNSIGNED_BYTE, &clearColor);
glClearTexImage(_pass_textures["color_buffer"], 0, GL_BGRA, GL_UNSIGNED_BYTE, &clearColor);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindTexture(GL_TEXTURE_2D, 0);

View File

@ -22,13 +22,13 @@ public:
void enableFrameBufferTexture(const std::string tex_name);
void gBufferSetup(SceneContext &scnctx, std::map<std::string, Mesh *> &meshes);
void gBufferSetup(SceneContext &scnctx, std::vector<std::shared_ptr<Mesh>>& meshes);
void recomputeDeferredLights(SceneContext &scnctx);
void drawGBufferToScreen(SceneContext &scnctx);
void deferredLightSetup(SceneContext &scnctx, std::map<std::string, Mesh *> &meshes);
void deferredLightSetup(SceneContext &scnctx, std::vector<std::shared_ptr<Mesh>>& meshes);
void drawDeferredLightToScreen(SceneContext &scnctx);
void forwardLightSetup(SceneContext &scnctx, std::map<std::string, Mesh *> &meshes);
void forwardLightSetup(SceneContext &scnctx, std::vector<std::shared_ptr<Mesh>>& meshes);

View File

@ -49,7 +49,6 @@ MyGlWindow::MyGlWindow(int w, int h) :
MyGlWindow::~MyGlWindow()
{
shaders.clear();
}
void MyGlWindow::draw()
@ -67,6 +66,74 @@ 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<Mesh>("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<Mesh>(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);
@ -120,47 +187,7 @@ void MyGlWindow::setup()
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));
//}
loadScene(MOUNTAIN);
}
void MyGlWindow::drawDeferredLight()
@ -177,7 +204,6 @@ void MyGlWindow::drawDeferredLight()
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;
@ -189,7 +215,7 @@ void MyGlWindow::drawDeferredLight()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for (auto it = meshes.begin(); it != meshes.end(); it++)
(*it).second->draw(scnctx);
(*it)->draw(scnctx);
multipassManager.drawDeferredLightToScreen(scnctx);
}
@ -219,7 +245,7 @@ void MyGlWindow::drawDebugGBuffer()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for (auto it = meshes.begin(); it != meshes.end(); it++)
(*it).second->draw(scnctx);
(*it)->draw(scnctx);
multipassManager.drawGBufferToScreen(scnctx);
@ -250,17 +276,17 @@ void MyGlWindow::drawForwardLight()
for (auto it = meshes.begin(); it != meshes.end(); it++)
{
(*it).second->shader->addUniform("view_pos", scnctx.camPos);
(*it)->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);
(*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).second->shader->addUniform("NLights", (int)scnctx.lights.size());
(*it).second->draw(scnctx);
(*it)->shader->addUniform("NLights", (int)scnctx.lights.size());
(*it)->draw(scnctx);
}
}

View File

@ -13,6 +13,12 @@
#include "imgui/stb_image.h"
#include "Multipass.h"
enum SceneChoice
{
MOUNTAIN,
CUBES
};
struct vertexAttr {
GLfloat posX, posY, posZ;
GLfloat r, g, b;
@ -25,15 +31,17 @@ public:
void draw();
void setBgColor(float bgColor[3]);
void orbitLights(float timePassed, float speed);
void loadScene(SceneChoice scene);
std::map<std::string, Shader *> shaders;
std::map<std::string, Mesh *> meshes;
std::vector<std::shared_ptr<Mesh>> meshes;
void resize(int w, int h);
Viewer viewer;
SceneContext scnctx;
Multipass multipassManager;
SceneChoice scene;
private:
int m_width;
int m_height;

View File

@ -39,16 +39,4 @@ struct SceneContext
RenderMode renderMode;
bool firstRedraw;
void adjustSpots()
{
for (auto it : lights)
{
if (it.type == Light::SPOT)
{
it.location = it.location * viewMatrix;
it.direction = (viewMatrix * it.lookAt - it.location * viewMatrix);
}
}
}
};

View File

@ -18,6 +18,8 @@ double cx, cy;
int g_width;
int g_height;
bool reset = false;
void window_size_callback(GLFWwindow* window, int width, int height)
{
g_width = width;
@ -28,6 +30,8 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GLFW_TRUE);
if (key == GLFW_KEY_R && action == GLFW_PRESS)
reset = true;
}
static void cursor_pos_callback(GLFWwindow* window, double xpos, double ypos)
@ -160,7 +164,6 @@ 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.
@ -217,7 +220,7 @@ int loop(GLFWwindow *window)
glWin.scnctx.fboDisplayName = "position_buffer";
bool is_selected = false;
glWin.scnctx.renderMode = GBUF_DEBUG;
glWin.scnctx.renderMode = DEFERRED_LIGHT;
glWin.scnctx.firstRedraw = true;
std::vector<std::string> lights_strs;
@ -225,8 +228,17 @@ int loop(GLFWwindow *window)
int current_light = 0;
bool orbiting_lights = true;
float light_speed = 50.0f;
double prev_time = glfwGetTime();
double sinceLastFrame;
while (!glfwWindowShouldClose(window))
{
sinceLastFrame = glfwGetTime() - prev_time;
prev_time = glfwGetTime();
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
@ -269,10 +281,26 @@ int loop(GLFWwindow *window)
ImGui::EndCombo();
}
if (ImGui::BeginCombo("Scene Choice",
(glWin.scene == MOUNTAIN) ? "Mountain" : "Cubes"))
{
if (ImGui::Selectable("Mountain", &is_selected, 0, ImVec2(100, 10)))
glWin.loadScene(SceneChoice::MOUNTAIN);
if (ImGui::Selectable("Cubes", &is_selected, 0, ImVec2(100, 10)))
glWin.loadScene(SceneChoice::CUBES);
ImGui::EndCombo();
}
ImGui::SetWindowPos(ImVec2(20, 20));
}
ImGui::End();
if (reset)
{
glWin.loadScene(SceneChoice::MOUNTAIN);
reset = false;
}
if (ImGui::Begin("Light management"))
{
lights_strs.clear();
@ -297,7 +325,18 @@ int loop(GLFWwindow *window)
&& glWin.scnctx.renderMode == DEFERRED_LIGHT)
glWin.multipassManager.recomputeDeferredLights(glWin.scnctx);
if (ImGui::SliderFloat("Selected light R", &glWin.scnctx.lights[current_light].intensity.x, 0, 1)
&& glWin.scnctx.renderMode == DEFERRED_LIGHT)
glWin.multipassManager.recomputeDeferredLights(glWin.scnctx);
if (ImGui::SliderFloat("Selected light G", &glWin.scnctx.lights[current_light].intensity.y, 0, 1)
&& glWin.scnctx.renderMode == DEFERRED_LIGHT)
glWin.multipassManager.recomputeDeferredLights(glWin.scnctx);
if (ImGui::SliderFloat("Selected light B", &glWin.scnctx.lights[current_light].intensity.z, 0, 1)
&& glWin.scnctx.renderMode == DEFERRED_LIGHT)
glWin.multipassManager.recomputeDeferredLights(glWin.scnctx);
ImGui::Checkbox("Orbit Lights", &orbiting_lights);
ImGui::SliderFloat("Orbit degrees / second", &light_speed, 0, 360);
}
ImGui::End();
@ -305,6 +344,8 @@ int loop(GLFWwindow *window)
glfwSwapBuffers(window);
glWin.draw();
if (orbiting_lights)
glWin.orbitLights(sinceLastFrame, light_speed);
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

View File

@ -55,7 +55,7 @@ Collapsed=0
[Window][Scene settings]
Pos=20,20
Size=309,85
Size=314,106
Collapsed=0
[Window][FPSCounterOutline]
@ -84,7 +84,7 @@ Size=32,32
Collapsed=0
[Window][Light management]
Pos=12,120
Size=410,449
Pos=11,173
Size=443,328
Collapsed=0