Proof that deferred shading is way better at handling a lot of lights
This commit is contained in:
parent
59c3fbd4f6
commit
3bbb233716
@ -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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -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());
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user