diff --git a/data/shader/flame_post.fsh b/data/shader/flame_post.fsh new file mode 100644 index 0000000..7a01fd9 --- /dev/null +++ b/data/shader/flame_post.fsh @@ -0,0 +1,11 @@ +#version 150 + +in vec2 vTexCoord; + +uniform sampler2D flame_fbo; + +out vec4 oColor; + +void main() { + oColor = texture(flame_fbo, vTexCoord).rgba; +} diff --git a/data/shader/flame_post.vsh b/data/shader/flame_post.vsh new file mode 100644 index 0000000..f3e6540 --- /dev/null +++ b/data/shader/flame_post.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 e526e4e..e957d23 100644 --- a/graphics.cc +++ b/graphics.cc @@ -35,6 +35,25 @@ void Graphics::init(Level* level) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); glEnable(GL_MULTISAMPLE); + + fullscreen_quad_ab = SharedArrayBuffer(new ArrayBuffer()); + fullscreen_quad_ab->defineAttribute("aPosition", GL_FLOAT, 2); + fullscreen_quad_ab->defineAttribute("aTexCoord", GL_FLOAT, 2); + + float quadData[] = { + -1.0f, 1.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f, 0.0f, + + 1.0f, -1.0f, 1.0f, 0.0f, + -1.0f, -1.0f, 0.0f, 0.0f, + -1.0f, 1.0f, 0.0f, 1.0f + }; + + fullscreen_quad_ab->setDataElements(6, quadData); + + fullscreen_quad = SharedVertexArrayObject(new VertexArrayObject); + fullscreen_quad->attachAllAttributes(fullscreen_quad_ab); // update lights on creation lastUpdate = -lightUpdateDelay; @@ -67,11 +86,14 @@ void Graphics::init(Level* level) { flameShader = ShaderProgramCreator("flame") .attributeLocations(flame_positions->getAttributeLocations()).create(); + flamePostShader = ShaderProgramCreator("flame_post") + .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 < 14) { - printf("You need at least 14 texture units to run this application. Exiting\n"); + if (number_of_texture_units < 16) { + printf("You need at least 16 texture units to run this application. Exiting\n"); exit(-1); } @@ -113,13 +135,32 @@ void Graphics::init(Level* level) { framebuffer_cube = SharedFrameBufferObject(new FrameBufferObject()); - if (level->getLights()->size() > 0) { for(unsigned int i = 0; isetTexture("shadowMap_cube" + std::to_string(i), depth_cubeMaps.at(i), i+4); } } + + 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); + flame_fbo_depth_texture = SharedTexture2D(new Texture2D(windowSize, GL_DEPTH_COMPONENT24)); + flame_fbo_depth_texture->setMinFilter(GL_NEAREST); + flame_fbo_depth_texture->setMagFilter(GL_NEAREST); + flame_fbo_depth_texture->setWrapS(GL_CLAMP_TO_BORDER); + flame_fbo_depth_texture->setWrapT(GL_CLAMP_TO_BORDER); + framebuffer_flames = SharedFrameBufferObject(new FrameBufferObject()); + framebuffer_flames->attachColorTexture("oColor", flame_fbo_color_texture); + framebuffer_flames->setDepthTexture(flame_fbo_depth_texture); + framebuffer_flames->setClearColor(glm::vec4(0.0f, 0.0f, 0.0f, 0.0f)); + framebuffer_flames->validate(); + + flamePostShader->use(); + flamePostShader->setTexture("flame_fbo", flame_fbo_color_texture, 15); + updateClosestLights(); } @@ -187,7 +228,7 @@ void Graphics::render(double time) } } - // final render pass + // lighting render pass glBindFramebuffer(GL_FRAMEBUFFER, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -239,6 +280,10 @@ void Graphics::render(double time) glCullFace(GL_BACK); // draw flames on top + + framebuffer_flames->bind(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + flameShader->use(); flameShader->setUniform("viewProjectionMatrix", lightingViewProjectionMatrix); flameShader->setUniform("time", (float) time); @@ -255,6 +300,12 @@ void Graphics::render(double time) flame_positions->render(); glDisable(GL_CULL_FACE); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + flamePostShader->use(); + fullscreen_quad->render(); } bool Graphics::compareLightDistances(Light a, Light b) { diff --git a/graphics.hh b/graphics.hh index ad15594..57605d5 100644 --- a/graphics.hh +++ b/graphics.hh @@ -8,6 +8,8 @@ #include "level.hh" +using namespace ACGL::OpenGL; + class Graphics { public: Graphics(glm::uvec2 windowSize, float nearPlane, float farPlane, int cube_size, unsigned int maxShadowRenderCount); @@ -28,16 +30,22 @@ class Graphics { float nearPlane; float farPlane; std::vector closestLights; - ACGL::OpenGL::SharedShaderProgram lightingShader; - ACGL::OpenGL::SharedShaderProgram depthCubeShader; - ACGL::OpenGL::SharedShaderProgram depthShader; - ACGL::OpenGL::SharedShaderProgram flameShader; - std::vector depth_directionalMaps; - std::vector framebuffer_directional; - std::vector depth_cubeMaps; - ACGL::OpenGL::SharedFrameBufferObject framebuffer_cube; - ACGL::OpenGL::SharedVertexArrayObject flame_positions; - ACGL::OpenGL::SharedArrayBuffer flame_positions_ab; + SharedShaderProgram lightingShader; + SharedShaderProgram depthCubeShader; + SharedShaderProgram depthShader; + SharedShaderProgram flameShader; + SharedShaderProgram flamePostShader; + std::vector depth_directionalMaps; + std::vector framebuffer_directional; + std::vector depth_cubeMaps; + SharedFrameBufferObject framebuffer_cube; + SharedFrameBufferObject framebuffer_flames; + SharedTexture2D flame_fbo_color_texture; + SharedTexture2D flame_fbo_depth_texture; + SharedVertexArrayObject flame_positions; + SharedArrayBuffer flame_positions_ab; + SharedVertexArrayObject fullscreen_quad; + SharedArrayBuffer fullscreen_quad_ab; int cube_size; unsigned int maxShadowRenderCount; Level* level;