242 lines
7.0 KiB
C++
242 lines
7.0 KiB
C++
#include "Multipass.h"
|
|
|
|
Multipass::Multipass()
|
|
{
|
|
shader = new Shader("textureViewer.vert", "textureViewer.frag");
|
|
_draw_buffers_size = 0;
|
|
glGenFramebuffers(1, &_fboId);
|
|
glBindFramebuffer(GL_FRAMEBUFFER, _fboId);
|
|
_createQuad();
|
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
}
|
|
|
|
void Multipass::setDrawBuffers()
|
|
{
|
|
glBindFramebuffer(GL_FRAMEBUFFER, _fboId);
|
|
glDrawBuffers(_draw_buffers_size, _draw_buffers);
|
|
int framebuffer_status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
|
if (framebuffer_status != GL_FRAMEBUFFER_COMPLETE)
|
|
throw std::runtime_error("Error during framebuffer initialisation");
|
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
}
|
|
|
|
void Multipass::bindToFrameBuffer(GLenum type, GLenum texture, std::string texName)
|
|
{
|
|
glBindFramebuffer(GL_FRAMEBUFFER, _fboId);
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, type, texture, _pass_textures[texName], 0);
|
|
if (type != GL_DEPTH_ATTACHMENT) {
|
|
_draw_buffers[_draw_buffers_size] = type;
|
|
_draw_buffers_size++;
|
|
}
|
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
}
|
|
|
|
Multipass::~Multipass()
|
|
{
|
|
glDeleteFramebuffers(1, &_fboId);
|
|
}
|
|
|
|
void Multipass::addTexture(const std::string & tex_name, GLuint filter, GLuint type, GLuint type_2, GLuint type_3,
|
|
bool depth, SceneContext &scnctx, GLuint height, GLuint width)
|
|
{
|
|
height = (height == 0) ? scnctx.height : height;
|
|
width = (width == 0) ? scnctx.width : width;
|
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, _fboId);
|
|
glGenTextures(1, &_pass_textures[tex_name]);;
|
|
glBindTexture(GL_TEXTURE_2D, _pass_textures[tex_name]);
|
|
glTexImage2D(GL_TEXTURE_2D, 0, type, width, height, 0, type_2, type_3, 0);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
|
|
if (depth)
|
|
{
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
|
|
}
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
}
|
|
|
|
void Multipass::enableFrameBufferTexture(const std::string tex_name)
|
|
{
|
|
_current_tex = tex_name;
|
|
glBindFramebuffer(GL_FRAMEBUFFER, _fboId);
|
|
}
|
|
|
|
void Multipass::gBufferSetup(SceneContext &scnctx, std::map<std::string, 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");
|
|
scnctx.firstRedraw = false;
|
|
}
|
|
|
|
void Multipass::recomputeDeferredLights(SceneContext &scnctx)
|
|
{
|
|
int i = 0;
|
|
for (auto light : scnctx.lights)
|
|
{
|
|
shader->addUniform("lights[" + std::to_string(i) + "].Position", glm::vec3(light.location));
|
|
shader->addUniform("lights[" + std::to_string(i) + "].Color", light.intensity);
|
|
i++;
|
|
}
|
|
|
|
shader->addUniform("NLights", (int)scnctx.lights.size());
|
|
}
|
|
|
|
void Multipass::deferredLightSetup(SceneContext &scnctx, std::map<std::string, Mesh *> &meshes)
|
|
{
|
|
if (shader != nullptr)
|
|
delete(shader);
|
|
shader = new Shader("DSLightPass.vert", "DSLightPass.frag");
|
|
|
|
shader->addUniform("pos_tex", 0);
|
|
shader->addUniform("normal_tex", 1);
|
|
shader->addUniform("color_tex", 2);
|
|
|
|
for (auto mesh : meshes)
|
|
mesh.second->shader = std::make_shared<Shader>("DSGeometryPass.vert", "DSGeometryPass.frag");
|
|
|
|
recomputeDeferredLights(scnctx);
|
|
|
|
scnctx.firstRedraw = false;
|
|
}
|
|
|
|
void Multipass::drawDeferredLightToScreen(SceneContext &scnctx)
|
|
{
|
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
glViewport(0, 0, scnctx.width, scnctx.height);
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
glActiveTexture(GL_TEXTURE0);
|
|
glBindTexture(GL_TEXTURE_2D, _pass_textures["position_buffer"]);
|
|
glActiveTexture(GL_TEXTURE1);
|
|
glBindTexture(GL_TEXTURE_2D, _pass_textures["normal_buffer"]);
|
|
glActiveTexture(GL_TEXTURE2);
|
|
glBindTexture(GL_TEXTURE_2D, _pass_textures["color_buffer"]);
|
|
|
|
shader->enable();
|
|
|
|
shader->addUniform("view_pos", scnctx.camPos);
|
|
|
|
glBindVertexArray(_quad_vao);
|
|
glBindBuffer(GL_ARRAY_BUFFER, _quad_vbo);
|
|
|
|
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);
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
glActiveTexture(GL_TEXTURE2);
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
glBindVertexArray(0);
|
|
|
|
shader->disable();
|
|
}
|
|
|
|
void Multipass::forwardLightSetup(SceneContext &scnctx, std::map<std::string, 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);
|
|
}
|
|
|
|
scnctx.firstRedraw = false;
|
|
}
|
|
|
|
void Multipass::drawGBufferToScreen(SceneContext & scnctx)
|
|
{
|
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
glViewport(0, 0, scnctx.width, scnctx.height);
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
shader->enable();
|
|
|
|
glActiveTexture(GL_TEXTURE0);
|
|
glBindTexture(GL_TEXTURE_2D, _pass_textures[_current_tex]);
|
|
|
|
glBindVertexArray(_quad_vao);
|
|
glBindBuffer(GL_ARRAY_BUFFER, _quad_vbo);
|
|
|
|
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);
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
glBindVertexArray(0);
|
|
shader->disable();
|
|
}
|
|
|
|
GLuint Multipass::getCurrentTexture()
|
|
{
|
|
return _pass_textures[_current_tex];
|
|
}
|
|
|
|
void Multipass::_createQuad()
|
|
{
|
|
float pos[] = {
|
|
-1.0, 1.0,
|
|
1.0, 1.0,
|
|
-1.0, -1.0,
|
|
1.0, -1.0
|
|
};
|
|
|
|
float uv[] = {
|
|
0.0, 1.0,
|
|
1.0, 1.0,
|
|
0.0, 0.0,
|
|
1.0, 0.0
|
|
};
|
|
|
|
//Generate VAO
|
|
glGenVertexArrays(1, &_quad_vao);
|
|
//Bind VAO
|
|
glBindVertexArray(_quad_vao);
|
|
|
|
//Generate VBO
|
|
glGenBuffers(1, &_quad_vbo);
|
|
//Bind VBO
|
|
glBindBuffer(GL_ARRAY_BUFFER, _quad_vbo);
|
|
//Alocate buffer
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(pos) + sizeof(uv), NULL, GL_STATIC_DRAW);
|
|
//Fill VBO
|
|
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(pos), pos);
|
|
glBufferSubData(GL_ARRAY_BUFFER, 8 * sizeof(float), sizeof(uv), uv);
|
|
|
|
//Fill attributes and uniforms
|
|
glEnableVertexAttribArray(0);
|
|
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, (sizeof(float) * 2), (void*)0);
|
|
|
|
glEnableVertexAttribArray(1);
|
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, (sizeof(float) * 2), (GLvoid*)(sizeof(float) * 8));
|
|
|
|
//unbind buffer
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
|
|
glBindVertexArray(0);
|
|
}
|