#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::vector>& meshes) { if (shader != nullptr) delete(shader); shader = new Shader("textureViewer.vert", "textureViewer.frag"); shader->addUniform("tex", 0); for (auto mesh : meshes) mesh->shader = std::make_shared("DSGeometryPass.vert", "DSGeometryPass.frag"); scnctx.firstRedraw = false; } void Multipass::recomputeDeferredLights(SceneContext &scnctx) { if (scnctx.renderMode != DEFERRED_LIGHT) return; 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::vector>& 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->shader = std::make_shared("DSGeometryPass.vert", "DSGeometryPass.frag"); recomputeDeferredLights(scnctx); scnctx.firstRedraw = false; } 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); 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); 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::vector>& meshes) { if (shader != nullptr) delete(shader); shader = nullptr; for (auto mesh : meshes) { mesh->shader = std::make_shared("tex_base_light.vert", "tex_base_light.frag"); mesh->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); 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); }