From a82ecad52f13380cfd125008ec36710e2a2cb8f2 Mon Sep 17 00:00:00 2001 From: Faerbit Date: Fri, 6 Mar 2015 09:16:29 +0100 Subject: [PATCH] Gave the flames it's own framebuffer to be able to manipulate it's color. --- data/shader/flame.fsh | 2 +- data/shader/merge.fsh | 18 ++++++++++++++++++ data/shader/merge.vsh | 11 +++++++++++ graphics.cc | 37 ++++++++++++++++++++++++++++++++----- graphics.hh | 3 +++ 5 files changed, 65 insertions(+), 6 deletions(-) create mode 100644 data/shader/merge.fsh create mode 100644 data/shader/merge.vsh diff --git a/data/shader/flame.fsh b/data/shader/flame.fsh index 7a4127d..dc893c8 100644 --- a/data/shader/flame.fsh +++ b/data/shader/flame.fsh @@ -9,7 +9,7 @@ uniform bool withColor; void main() { if (withColor) { - oColor = vec4(fColor, 0.6); + oColor = vec4(fColor, 1.0); } else { oColor = vec4(0.0, 0.0, 0.0, 0.0); diff --git a/data/shader/merge.fsh b/data/shader/merge.fsh new file mode 100644 index 0000000..3e1e44f --- /dev/null +++ b/data/shader/merge.fsh @@ -0,0 +1,18 @@ +#version 150 + +in vec2 vTexCoord; + +uniform sampler2D flame_fbo; +uniform sampler2D light_fbo; + +out vec4 oColor; + +void main() { + vec4 flameColor = texture(flame_fbo, vTexCoord); + if (flameColor == vec4(0.0, 0.0, 0.0, 1.0)) { + oColor = texture(light_fbo, vTexCoord); + } + else { + oColor = mix(flameColor, texture(light_fbo, vTexCoord), 0.4); + } +} diff --git a/data/shader/merge.vsh b/data/shader/merge.vsh new file mode 100644 index 0000000..f3e6540 --- /dev/null +++ b/data/shader/merge.vsh @@ -0,0 +1,11 @@ +#version 150 + +in vec2 aPosition; +in vec2 aTexCoord; + +out vec2 vTexCoord; + +void main() { + vTexCoord = aTexCoord; + gl_Position = vec4(aPosition, 0.0, 1.0); +} diff --git a/graphics.cc b/graphics.cc index 65dcead..ee660c3 100644 --- a/graphics.cc +++ b/graphics.cc @@ -32,6 +32,7 @@ void Graphics::init(Level* level) { glClearColor( 0.0, 0.0, 0.0, 1.0 ); glEnable( GL_DEPTH_TEST ); glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); //glEnable(GL_MULTISAMPLE); @@ -92,11 +93,14 @@ void Graphics::init(Level* level) { flamePostShader = ShaderProgramCreator("flame_post") .attributeLocations(fullscreen_quad->getAttributeLocations()).create(); + mergeShader = ShaderProgramCreator("merge") + .attributeLocations(fullscreen_quad->getAttributeLocations()).create(); + glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &number_of_texture_units); printf("Your graphics card supports %d texture units.\n", number_of_texture_units); // Exit if we need more texture units - if (number_of_texture_units < 16) { - printf("You need at least 16 texture units to run this application. Exiting\n"); + if (number_of_texture_units < 18) { + printf("You need at least 18 texture units to run this application. Exiting\n"); exit(-1); } @@ -169,6 +173,21 @@ void Graphics::init(Level* level) { skydomeShader->use(); skydomeShader->setTexture("nightTexture", level->getSkydome()->getNightTexture()->getReference(), 15); + flame_fbo_color_texture = SharedTexture2D(new Texture2D(windowSize, GL_RGBA8)); + flame_fbo_color_texture->setMinFilter(GL_NEAREST); + flame_fbo_color_texture->setMagFilter(GL_NEAREST); + flame_fbo_color_texture->setWrapS(GL_CLAMP_TO_BORDER); + flame_fbo_color_texture->setWrapT(GL_CLAMP_TO_BORDER); + framebuffer_flame = SharedFrameBufferObject(new FrameBufferObject()); + framebuffer_flame->attachColorTexture("oColor", flame_fbo_color_texture); + framebuffer_flame->setDepthTexture(light_fbo_depth_texture); + framebuffer_flame->setClearColor(glm::vec4(0.0f, 0.0f, 0.0f, 0.0f)); + framebuffer_flame->validate(); + + mergeShader->use(); + mergeShader->setTexture("flame_fbo", flame_fbo_color_texture, 16); + mergeShader->setTexture("light_fbo", light_fbo_color_texture, 17); + updateClosestLights(); } @@ -298,6 +317,8 @@ void Graphics::render(double time) // draw flames on top flameShader->use(); + framebuffer_flame->bind(); + glClear(GL_COLOR_BUFFER_BIT); // cull faces to get consistent color while using alpha glEnable(GL_CULL_FACE); glCullFace(GL_BACK); @@ -317,10 +338,18 @@ void Graphics::render(double time) flame_positions->render(); flameShader->setUniform("left", false); flame_positions->render(); + glDisable(GL_CULL_FACE); + framebuffer_light->bind(); glDepthMask(GL_FALSE); + mergeShader->use(); + glDisable(GL_DEPTH_TEST); + fullscreen_quad->render(); + glEnable(GL_DEPTH_TEST); + // draw slightly larger only for stencil buffer to blur edges + flameShader->use(); glEnable(GL_STENCIL_TEST); glStencilFunc(GL_ALWAYS, 1, 0xFF); //Set any stencil to 1 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); @@ -346,11 +375,9 @@ void Graphics::render(double time) glStencilFunc(GL_EQUAL, 1, 0xFF); //Pass test if stencil value is 1 glStencilMask(0x00);// don't write to stencil buffer - glDepthMask(GL_TRUE); - glDisable(GL_CULL_FACE); - flamePostShader->use(); fullscreen_quad->render(); + glDepthMask(GL_TRUE); glDisable(GL_STENCIL_TEST); diff --git a/graphics.hh b/graphics.hh index 3e5358a..999e157 100644 --- a/graphics.hh +++ b/graphics.hh @@ -36,11 +36,14 @@ class Graphics { SharedShaderProgram depthShader; SharedShaderProgram flameShader; SharedShaderProgram flamePostShader; + SharedShaderProgram mergeShader; std::vector depth_directionalMaps; std::vector framebuffer_directional; std::vector depth_cubeMaps; SharedFrameBufferObject framebuffer_cube; SharedFrameBufferObject framebuffer_light; + SharedFrameBufferObject framebuffer_flame; + SharedTexture2D flame_fbo_color_texture; SharedTexture2D light_fbo_color_texture; SharedTexture2D light_fbo_depth_texture; SharedVertexArrayObject flame_positions;