From 3a9076661489005cb1d1a69fbc82675e11fa877b Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Sat, 27 Aug 2016 23:05:45 +0000 Subject: [PATCH] scene: start working on a postprocess mechanism. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not all programs support this feature for now, but that’s because they don’t support the scene framework either, and will need patching. Also the default postprocess is deliberately exaggerated for now. --- doc/tutorial/08_fbo.cpp | 14 +++++----- src/Makefile.am | 1 + src/engine/ticker.cpp | 4 +-- src/gpu/framebuffer.cpp | 2 +- src/gpu/postprocess.lolfx | 34 ++++++++++++++++++++++ src/lolcore.vcxproj | 1 + src/scene.cpp | 59 +++++++++++++++++++++++++++++++++++++-- src/scene.h | 9 ++++-- 8 files changed, 107 insertions(+), 17 deletions(-) create mode 100644 src/gpu/postprocess.lolfx diff --git a/doc/tutorial/08_fbo.cpp b/doc/tutorial/08_fbo.cpp index 8d83a80c..75fd45f0 100644 --- a/doc/tutorial/08_fbo.cpp +++ b/doc/tutorial/08_fbo.cpp @@ -24,15 +24,15 @@ class FBO : public WorldEntity { public: FBO() - : m_time(0.f), + : m_vertices { vec2( 1.0, 1.0), + vec2(-1.0, -1.0), + vec2( 1.0, -1.0), + vec2(-1.0, -1.0), + vec2( 1.0, 1.0), + vec2(-1.0, 1.0), }, + m_time(0.f), m_ready(false) { - m_vertices << vec2( 1.0, 1.0); - m_vertices << vec2(-1.0, -1.0); - m_vertices << vec2( 1.0, -1.0); - m_vertices << vec2(-1.0, -1.0); - m_vertices << vec2( 1.0, 1.0); - m_vertices << vec2(-1.0, 1.0); } virtual void TickGame(float seconds) diff --git a/src/Makefile.am b/src/Makefile.am index 4d4f5768..1ed61609 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -101,6 +101,7 @@ liblolcore_sources = \ gpu/tile.lolfx gpu/palette.lolfx gpu/line.lolfx \ gpu/emptymaterial.lolfx \ gpu/testmaterial.lolfx \ + gpu/postprocess.lolfx \ \ gpu/lolfx.cpp \ \ diff --git a/src/engine/ticker.cpp b/src/engine/ticker.cpp index 147e4a30..ffe29ef7 100644 --- a/src/engine/ticker.cpp +++ b/src/engine/ticker.cpp @@ -468,9 +468,7 @@ void TickerData::DrawThreadTick() } /* Do the render step */ - scene.RenderPrimitives(); - scene.RenderTiles(); - scene.RenderLines(data->deltatime); + scene.render(data->deltatime); /* Disable display */ scene.DisableDisplay(); diff --git a/src/gpu/framebuffer.cpp b/src/gpu/framebuffer.cpp index a85002c5..23097efc 100644 --- a/src/gpu/framebuffer.cpp +++ b/src/gpu/framebuffer.cpp @@ -303,7 +303,7 @@ Framebuffer::Framebuffer(ivec2 size, FramebufferFormat fbo_format) GLenum format = fbo_format.GetFormat(); # endif GLenum wrapmode = GL_CLAMP_TO_EDGE; - GLenum filtering = GL_NEAREST; + GLenum filtering = GL_LINEAR; # if GL_VERSION_1_1 || GL_ES_VERSION_2_0 glGenFramebuffers(1, &m_data->m_fbo); diff --git a/src/gpu/postprocess.lolfx b/src/gpu/postprocess.lolfx new file mode 100644 index 00000000..c3efbd60 --- /dev/null +++ b/src/gpu/postprocess.lolfx @@ -0,0 +1,34 @@ +[vert.glsl] + +#version 120 + +attribute vec2 in_Position; + +varying vec2 pass_Position; + +void main() +{ + pass_Position = in_Position; + gl_Position = vec4(in_Position, 0.0, 1.0); +} + +[frag.glsl] + +#version 120 + +#if defined GL_ES +precision highp float; +#endif + +uniform sampler2D u_texture; + +varying vec2 pass_Position; + +void main(void) +{ + vec2 texcoords = pass_Position * 0.5 + vec2(0.5, 0.5); + texcoords += 0.02 * sin(0.05 * gl_FragCoord.xy); + vec4 color = vec4(texture2D(u_texture, texcoords).rgb, 1.0); + gl_FragColor = color; +} + diff --git a/src/lolcore.vcxproj b/src/lolcore.vcxproj index 96d8d1cc..69969fa1 100644 --- a/src/lolcore.vcxproj +++ b/src/lolcore.vcxproj @@ -370,6 +370,7 @@ + diff --git a/src/scene.cpp b/src/scene.cpp index 376b6769..bee56f48 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -26,6 +26,7 @@ LOLFX_RESOURCE_DECLARE(tile); LOLFX_RESOURCE_DECLARE(palette); LOLFX_RESOURCE_DECLARE(line); +LOLFX_RESOURCE_DECLARE(postprocess); namespace lol { @@ -127,6 +128,14 @@ private: * the default one created by the app will be used */ SceneDisplay* m_display = nullptr; + /** Back buffer: where to render to. */ + Framebuffer *m_backbuffer = nullptr; + Shader *m_pp_shader = nullptr; + VertexDeclaration *m_pp_vdecl; + ShaderUniform m_pp_texture; + ShaderAttrib m_pp_coord; + VertexBuffer *m_pp_vbo; + /* Sources are shared by all scenes. * Renderers are scene-dependent. They get the primitive in the identical * slot to render with the given scene. @@ -179,6 +188,20 @@ mutex SceneData::m_prim_mutex; Scene::Scene(ivec2 size) : data(new SceneData()) { + data->m_backbuffer = new Framebuffer(size); + data->m_pp_shader = Shader::Create(LOLFX_RESOURCE_NAME(postprocess)); + data->m_pp_coord = data->m_pp_shader->GetAttribLocation(VertexUsage::Position, 0); + data->m_pp_vdecl = new VertexDeclaration(VertexStream(VertexUsage::Position)); + data->m_pp_texture = data->m_pp_shader->GetUniformLocation("u_texture"); + + array quad { vec2( 1.0, 1.0), vec2(-1.0, -1.0), vec2( 1.0, -1.0), + vec2(-1.0, -1.0), vec2( 1.0, 1.0), vec2(-1.0, 1.0), }; + + data->m_pp_vbo = new VertexBuffer(quad.bytes()); + void *vertices = data->m_pp_vbo->Lock(0, 0); + memcpy(vertices, &quad[0], quad.bytes()); + data->m_pp_vbo->Unlock(); + /* Create a default orthographic camera, in case the user doesn’t. */ data->m_default_cam = new Camera(); mat4 proj = mat4::ortho(0.f, (float)size.x, 0.f, (float)size.y, -1000.f, 1000.f); @@ -576,8 +599,36 @@ void Scene::DisableDisplay() data->m_display->Disable(); } +/* Render everything that the scene contains */ +void Scene::render(float seconds) +{ + /* First render into the offline buffer */ + data->m_backbuffer->Bind(); + { + RenderContext rc; + rc.SetClearColor(vec4(0.f, 0.f, 0.f, 1.f)); + rc.SetClearDepth(1.f); + Renderer::Get()->Clear(ClearMask::Color | ClearMask::Depth); + + // FIXME: get rid of the delta time argument + render_primitives(); + render_tiles(); + render_lines(seconds); + } + data->m_backbuffer->Unbind(); + + /* Now blit the offline buffer */ + data->m_pp_shader->Bind(); + data->m_pp_shader->SetUniform(data->m_pp_texture, data->m_backbuffer->GetTextureUniform(), 0); + data->m_pp_vdecl->SetStream(data->m_pp_vbo, data->m_pp_coord); + data->m_pp_vdecl->Bind(); + data->m_pp_vdecl->DrawElements(MeshPrimitive::Triangles, 0, 6); + data->m_pp_vdecl->Unbind(); + data->m_pp_shader->Unbind(); +} + //----------------------------------------------------------------------------- -void Scene::RenderPrimitives() +void Scene::render_primitives() { ASSERT(!!data, "Trying to access a non-ready scene"); @@ -599,7 +650,7 @@ void Scene::RenderPrimitives() } //----------------------------------------------------------------------------- -void Scene::RenderTiles() // XXX: rename to Blit() +void Scene::render_tiles() // XXX: rename to Blit() { ASSERT(!!data, "Trying to access a non-ready scene"); @@ -723,7 +774,9 @@ void Scene::RenderTiles() // XXX: rename to Blit() } //----------------------------------------------------------------------------- -void Scene::RenderLines(float seconds) // XXX: rename to Blit() +// FIXME: get rid of the delta time argument +// XXX: rename to Blit() +void Scene::render_lines(float seconds) { ASSERT(!!data, "Trying to access a non-ready scene"); diff --git a/src/scene.h b/src/scene.h index ad4c234d..6a3aa57e 100644 --- a/src/scene.h +++ b/src/scene.h @@ -178,6 +178,7 @@ public: private: int HasPrimitiveRenderer(uintptr_t key); + void AddPrimitiveRenderer(uintptr_t key, class PrimitiveRenderer* renderer); void SetPrimitiveRenderer(int index, uintptr_t key, class PrimitiveRenderer* renderer); void ReleasePrimitiveRenderer(int index, uintptr_t key); @@ -250,11 +251,13 @@ public: void EnableDisplay(); void DisableDisplay(); - void RenderPrimitives(); - void RenderTiles(); - void RenderLines(float seconds); + void render(float seconds); private: + void render_primitives(); + void render_tiles(); + void render_lines(float seconds); + SceneData *data; };