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);
}