#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) { delete(shader); shader = new Shader("textureViewer.vert", "textureViewer.frag"); scnctx.firstRedraw = false; } void Multipass::deferredLightSetup(SceneContext &scnctx) { shader = new Shader("DSLightPass.vert", "DSLightPass.frag"); shader->addUniform("pos_tex", 0); shader->addUniform("normal_tex", 1); shader->addUniform("color_tex", 2); int i = 0; for (auto light : scnctx.lights) { shader->addUniform("lights[" + std::to_string(i) + "].Position", glm::vec3(light.second.location)); shader->addUniform("lights[" + std::to_string(i) + "].Color", light.second.intensity); i++; } shader->addUniform("NLights", (int)scnctx.lights.size()); 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::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]); shader->addUniform("tex", 0); 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); }