From cde747667c938124441113a2b91d0ad3161e1b57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20=E2=80=98Touky=E2=80=99=20Huet?= Date: Tue, 12 Mar 2013 11:22:04 +0000 Subject: [PATCH] 12_voronoi : Added GPU Voronoi test. --- build/vs2010/Lol.sln | 21 ++ tutorial/12_distance.lolfx | 94 +++++++ tutorial/12_texture_to_screen.lolfx | 78 ++++++ tutorial/12_voronoi.cpp | 368 ++++++++++++++++++++++++++++ tutorial/12_voronoi.lolfx | 93 +++++++ tutorial/12_voronoi.vcxproj | 75 ++++++ tutorial/12_voronoi_distance.lolfx | 94 +++++++ tutorial/12_voronoi_setup.lolfx | 70 ++++++ tutorial/Makefile.am | 9 +- 9 files changed, 901 insertions(+), 1 deletion(-) create mode 100644 tutorial/12_distance.lolfx create mode 100644 tutorial/12_texture_to_screen.lolfx create mode 100644 tutorial/12_voronoi.cpp create mode 100644 tutorial/12_voronoi.lolfx create mode 100644 tutorial/12_voronoi.vcxproj create mode 100644 tutorial/12_voronoi_distance.lolfx create mode 100644 tutorial/12_voronoi_setup.lolfx diff --git a/build/vs2010/Lol.sln b/build/vs2010/Lol.sln index a92fb774..a34f6de9 100644 --- a/build/vs2010/Lol.sln +++ b/build/vs2010/Lol.sln @@ -142,6 +142,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "meshviewer", "..\..\test\me EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tactics", "..\..\people\touky\private\tactics\tactics.vcxproj", "{25493FC8-75AC-4703-AD58-AB0C4A0FB79C}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "12_Voronoi", "..\..\tutorial\12_Voronoi.vcxproj", "{6BF81B39-EDC2-4227-9982-C2D8ABEA95AF}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -765,6 +767,24 @@ Global {25493FC8-75AC-4703-AD58-AB0C4A0FB79C}.Release|x64.ActiveCfg = Release|x64 {25493FC8-75AC-4703-AD58-AB0C4A0FB79C}.Release|x64.Build.0 = Release|x64 {25493FC8-75AC-4703-AD58-AB0C4A0FB79C}.Release|Xbox 360.ActiveCfg = Release|x64 + {6BF81B39-EDC2-4227-9982-C2D8ABEA95AF}.Debug|Any CPU.ActiveCfg = Debug|x64 + {6BF81B39-EDC2-4227-9982-C2D8ABEA95AF}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {6BF81B39-EDC2-4227-9982-C2D8ABEA95AF}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {6BF81B39-EDC2-4227-9982-C2D8ABEA95AF}.Debug|PS3.ActiveCfg = Debug|x64 + {6BF81B39-EDC2-4227-9982-C2D8ABEA95AF}.Debug|Win32.ActiveCfg = Debug|Win32 + {6BF81B39-EDC2-4227-9982-C2D8ABEA95AF}.Debug|Win32.Build.0 = Debug|Win32 + {6BF81B39-EDC2-4227-9982-C2D8ABEA95AF}.Debug|x64.ActiveCfg = Debug|x64 + {6BF81B39-EDC2-4227-9982-C2D8ABEA95AF}.Debug|x64.Build.0 = Debug|x64 + {6BF81B39-EDC2-4227-9982-C2D8ABEA95AF}.Debug|Xbox 360.ActiveCfg = Debug|x64 + {6BF81B39-EDC2-4227-9982-C2D8ABEA95AF}.Release|Any CPU.ActiveCfg = Release|x64 + {6BF81B39-EDC2-4227-9982-C2D8ABEA95AF}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {6BF81B39-EDC2-4227-9982-C2D8ABEA95AF}.Release|Mixed Platforms.Build.0 = Release|Win32 + {6BF81B39-EDC2-4227-9982-C2D8ABEA95AF}.Release|PS3.ActiveCfg = Release|x64 + {6BF81B39-EDC2-4227-9982-C2D8ABEA95AF}.Release|Win32.ActiveCfg = Release|Win32 + {6BF81B39-EDC2-4227-9982-C2D8ABEA95AF}.Release|Win32.Build.0 = Release|Win32 + {6BF81B39-EDC2-4227-9982-C2D8ABEA95AF}.Release|x64.ActiveCfg = Release|x64 + {6BF81B39-EDC2-4227-9982-C2D8ABEA95AF}.Release|x64.Build.0 = Release|x64 + {6BF81B39-EDC2-4227-9982-C2D8ABEA95AF}.Release|Xbox 360.ActiveCfg = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -796,6 +816,7 @@ Global {BCEE0132-8E24-49BE-AFEB-96DAD14396BA} = {E74CF679-CA2A-47E9-B1F4-3779D6AC6B04} {B0A53D75-CBB4-4FDF-93AC-2D12A79ADA0E} = {E74CF679-CA2A-47E9-B1F4-3779D6AC6B04} {834852DB-EDB6-4FD0-BCF9-45CD01126962} = {E74CF679-CA2A-47E9-B1F4-3779D6AC6B04} + {6BF81B39-EDC2-4227-9982-C2D8ABEA95AF} = {E74CF679-CA2A-47E9-B1F4-3779D6AC6B04} {32F3F8CF-D22E-45E4-BEB8-AD909E8C5515} = {33704AA4-F2B5-4138-A40D-E3E77F89ED46} {EE203B88-44CF-4859-9D42-7A5F40FECB52} = {8C77EAA8-1077-4EF7-AE53-97C6C60A3601} {B357514A-7881-422D-8358-161B689E7620} = {3D341D8A-E400-4B1D-BC05-B5C35487D9B5} diff --git a/tutorial/12_distance.lolfx b/tutorial/12_distance.lolfx new file mode 100644 index 00000000..d47db363 --- /dev/null +++ b/tutorial/12_distance.lolfx @@ -0,0 +1,94 @@ +[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 in_Texture; +uniform float in_Flag; +uniform vec3 in_Point; +uniform vec3 in_Color; + +varying vec2 pass_Position; + +void main(void) +{ + if (in_Flag == 0.0) + { + float tc = 0.0, ta = 0.0; + { + float s = 3.0 + 2.0 * in_Point.z; + vec2 p = pass_Position - in_Point.xy * 0.9; + float t = clamp(1.2 - dot(s * p, s * p), 0.0, 1.0); + float u = t * t * t * t; + tc += 3.0 * t * t - 2.0 * t * t * t; + ta += 3.0 * u * u - 2.0 * u * u * u; + } + + gl_FragColor = vec4(tc * in_Color, ta + 0.1); + } + else + { + vec2 texcoords = pass_Position * 0.5 + vec2(0.5, 0.5); + gl_FragColor = vec4(texture2D(in_Texture, texcoords).xyz, 1.0); + } +} + +[vert.hlsl] + +void main(float2 in_Position : POSITION, + out float2 pass_Position : TEXCOORD0, + out float4 out_Position : POSITION) +{ + pass_Position = in_Position; + out_Position = float4(in_Position, 0.0, 1.0); +} + +[frag.hlsl] + +void main(in float2 pass_Position : TEXCOORD0, + uniform sampler2D in_Texture, + uniform float in_Flag, + uniform float3 in_Point, + uniform float3 in_Color, + out float4 out_FragColor : COLOR) +{ + if (in_Flag == 0.0) + { + float tc = 0.0, ta = 0.0; + { + float s = 3.0 + 2.0 * in_Point.z; + float2 p = pass_Position - in_Point.xy * 0.9; + float t = clamp(1.2 - dot(s * p, s * p), 0.0, 1.0); + float u = t * t * t * t; + tc += 3.0 * t * t - 2.0 * t * t * t; + ta += 3.0 * u * u - 2.0 * u * u * u; + } + + out_FragColor = float4(tc * in_Color, ta + 0.1); + } + else + { + float2 texcoords = pass_Position * float2(0.5, -0.5) + float2(0.5, 0.5); + /* FIXME: this should be passed as a uniform or something */ + texcoords += float2(0.5 / 800.0, 0.5 / 600.0); + out_FragColor = float4(tex2D(in_Texture, texcoords).xyz, 1.0); + } +} + diff --git a/tutorial/12_texture_to_screen.lolfx b/tutorial/12_texture_to_screen.lolfx new file mode 100644 index 00000000..a4d29779 --- /dev/null +++ b/tutorial/12_texture_to_screen.lolfx @@ -0,0 +1,78 @@ +[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 in_texture; +varying vec2 pass_position; + +void main(void) +{ + vec2 texcoords = pass_position * 0.5 + vec2(0.5, 0.5); + vec4 src_color = texture2D(in_texture, texcoords); + float newg = src_color.z; + float newb = 0.0; + if (newg > 0.0) + newb = 1.0; + gl_FragColor = vec4(0.0, newg, 0.0, 1.0); +} + +[vert.hlsl] + +void main(float2 in_Position : POSITION, + out float2 pass_Position : TEXCOORD0, + out float4 out_Position : POSITION) +{ + pass_Position = in_Position; + out_Position = float4(in_Position, 0.0, 1.0); +} + +[frag.hlsl] + +void main(in float2 pass_Position : TEXCOORD0, + uniform sampler2D in_Texture, + uniform float in_Flag, + uniform float3 in_Point, + uniform float3 in_Color, + out float4 out_FragColor : COLOR) +{ + if (in_Flag == 0.0) + { + float tc = 0.0, ta = 0.0; + { + float s = 3.0 + 2.0 * in_Point.z; + float2 p = pass_Position - in_Point.xy * 0.9; + float t = clamp(1.2 - dot(s * p, s * p), 0.0, 1.0); + float u = t * t * t * t; + tc += 3.0 * t * t - 2.0 * t * t * t; + ta += 3.0 * u * u - 2.0 * u * u * u; + } + + out_FragColor = float4(tc * in_Color, ta + 0.1); + } + else + { + float2 texcoords = pass_Position * float2(0.5, -0.5) + float2(0.5, 0.5); + /* FIXME: this should be passed as a uniform or something */ + texcoords += float2(0.5 / 800.0, 0.5 / 600.0); + out_FragColor = float4(tex2D(in_Texture, texcoords).xyz, 1.0); + } +} + diff --git a/tutorial/12_voronoi.cpp b/tutorial/12_voronoi.cpp new file mode 100644 index 00000000..53acefd5 --- /dev/null +++ b/tutorial/12_voronoi.cpp @@ -0,0 +1,368 @@ +// +// Lol Engine - Framebuffer Object tutorial +// +// Copyright: (c) 2012-2013 Sam Hocevar +// This program is free software; you can redistribute it and/or +// modify it under the terms of the Do What The Fuck You Want To +// Public License, Version 2, as published by Sam Hocevar. See +// http://www.wtfpl.net/ for more details. +// + +#if defined HAVE_CONFIG_H +# include "config.h" +#endif + +#include "core.h" +#include "loldebug.h" + +using namespace std; +using namespace lol; + +LOLFX_RESOURCE_DECLARE(12_voronoi); +LOLFX_RESOURCE_DECLARE(12_voronoi_setup); +LOLFX_RESOURCE_DECLARE(12_voronoi_distance); +LOLFX_RESOURCE_DECLARE(12_distance); +LOLFX_RESOURCE_DECLARE(12_texture_to_screen); + +enum FboType +{ + src_voronoi, + voronoi, + distance_voronoi, + distance, + + MAX +}; + +class Voronoi : public WorldEntity +{ +public: + Voronoi() + { + 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); + m_ready = false; + m_cur_fbo = 0; + m_timer = -1.0f; + } + + virtual void TickGame(float seconds) + { + WorldEntity::TickGame(seconds); + + { + //Shutdown logic + if (Input::WasReleased(Key::Escape)) + Ticker::Shutdown(); + } + + m_time += seconds; + m_hotspot = 0.4f * vec3(lol::sin(m_time * 4.f) + lol::cos(m_time * 5.3f), + lol::sin(m_time * 5.7f) + lol::cos(m_time * 4.4f), + lol::sin(m_time * 5.f)); + m_color = 0.25f * vec3(1.1f + lol::sin(m_time * 2.5f + 1.f), + 1.1f + lol::sin(m_time * 2.8f + 1.3f), + 1.1f + lol::sin(m_time * 2.7f)); + /* Saturate dot color */ + float x = std::max(m_color.x, std::max(m_color.y, m_color.z)); + m_color /= x; + } + + virtual void TickDraw(float seconds) + { + WorldEntity::TickDraw(seconds); + + if (!m_ready) + { + m_vdecl = new VertexDeclaration(VertexStream(VertexUsage::Position)); + + m_vbo = new VertexBuffer(m_vertices.Bytes()); + void *vertices = m_vbo->Lock(0, 0); + memcpy(vertices, &m_vertices[0], m_vertices.Bytes()); + m_vbo->Unlock(); + + m_screen_shader = Shader::Create(LOLFX_RESOURCE_NAME(12_texture_to_screen)); + m_screen_coord = m_screen_shader->GetAttribLocation("in_position", VertexUsage::Position, 0); + m_screen_texture = m_screen_shader->GetUniformLocation("in_texture"); + + for (int i = 0; i < FboType::MAX; ++i) + { + m_fbos.Push(new FrameBuffer(Video::GetSize()), 0, Array(), Array() ); + + if (i == src_voronoi) + { + m_fbos[i].m2 = Shader::Create(LOLFX_RESOURCE_NAME(12_voronoi_setup)); + m_fbos[i].m3 << m_fbos[i].m2->GetUniformLocation("in_texture"); + m_fbos[i].m3 << m_fbos[i].m2->GetUniformLocation("in_source_point"); + m_fbos[i].m3 << m_fbos[i].m2->GetUniformLocation("in_screen_res"); + m_fbos[i].m4 << m_fbos[i].m2->GetAttribLocation("in_position", VertexUsage::Position, 0); + } + else if (i == voronoi) + { + m_fbos[i].m2 = Shader::Create(LOLFX_RESOURCE_NAME(12_voronoi)); + m_fbos[i].m3 << m_fbos[i].m2->GetUniformLocation("in_texture"); + m_fbos[i].m3 << m_fbos[i].m2->GetUniformLocation("in_step"); + m_fbos[i].m3 << m_fbos[i].m2->GetUniformLocation("in_screen_res"); + m_fbos[i].m4 << m_fbos[i].m2->GetAttribLocation("in_position", VertexUsage::Position, 0); + } + else if (i == distance_voronoi) + { + m_fbos[i].m2 = Shader::Create(LOLFX_RESOURCE_NAME(12_voronoi_distance)); + } + else if (i == FboType::distance) + { + m_fbos[i].m2 = Shader::Create(LOLFX_RESOURCE_NAME(12_distance)); + } + + m_fbos.Last().m1->Bind(); + Video::SetClearColor(vec4(0.f, 0.f, 0.f, 1.f)); + Video::SetClearDepth(1.f); + Video::Clear(ClearMask::Color | ClearMask::Depth); + m_fbos.Last().m1->Unbind(); + } + + temp_buffer = new FrameBuffer(Video::GetSize()); + temp_buffer->Bind(); + Video::SetClearColor(vec4(0.f, 0.f, 0.f, 1.f)); + Video::SetClearDepth(1.f); + Video::Clear(ClearMask::Color | ClearMask::Depth); + temp_buffer->Unbind(); + + m_ready = true; + /* FIXME: this object never cleans up */ + + //SRC SETUP + int i = 4; + while (i-- > 0) + { + voronoi_points.Push(vec3(rand(512.f), rand(512.f), .0f), + vec2(64.f + rand(64.f), 64.f + rand(64.f))); + } + + //voronoi_points.Push(vec3(511.f, 511.f, .0f), vec2(-128.f)); + //voronoi_points.Push(vec3(256.f, 256.f, .0f), vec2( 128.f)); + //voronoi_points.Push(vec3(128.f, 128.f, .0f), vec2(-128.f)); + //voronoi_points.Push(vec3(128.f, 400.f, .0f), vec2( 128.f)); + //voronoi_points.Push(vec3(400.f, 24.f, .0f), vec2(-128.f)); + + m_cur_fbo = voronoi; + } + + { + //Shutdown logic + if (Input::WasReleased(Key::O)) + voronoi_points.Pop(); + else if (Input::WasReleased(Key::P)) + voronoi_points.Push(vec3(rand(512.f), rand(512.f), .0f), + vec2(64.f + rand(64.f), 64.f + rand(64.f))); + else if (Input::WasReleased(Key::F1)) + m_cur_fbo = src_voronoi; + else if (Input::WasReleased(Key::F2)) + m_cur_fbo = voronoi; + } + + + temp_buffer->Bind(); + Video::SetClearColor(vec4(0.f, 0.f, 0.f, 1.f)); + Video::SetClearDepth(1.f); + Video::Clear(ClearMask::Color | ClearMask::Depth); + temp_buffer->Unbind(); + + { + vec2 limit(1.f, 511.f); + //SRC SETUP + for (int j = 0; j < voronoi_points.Count(); ++j) + { + voronoi_points[j].m1 = vec3(voronoi_points[j].m1.xy + voronoi_points[j].m2 * seconds, voronoi_points[j].m1.z); + if (voronoi_points[j].m1.x >= limit.y || voronoi_points[j].m1.x <= limit.x) + { + voronoi_points[j].m2.x *= -1.f; + voronoi_points[j].m1.x = clamp(voronoi_points[j].m1.x, limit.x, limit.y); + } + if (voronoi_points[j].m1.y >= limit.y || voronoi_points[j].m1.y <= limit.x) + { + voronoi_points[j].m2.y *= -1.f; + voronoi_points[j].m1.y = clamp(voronoi_points[j].m1.y, limit.x, limit.y); + } + voronoi_points[j].m1.z = ((float)j + 1) / ((float)voronoi_points.Count()); + } + + int f = src_voronoi; + + m_fbos[f].m1->Bind(); + Video::SetClearColor(vec4(0.f, 0.f, 0.f, 1.f)); + Video::SetClearDepth(1.f); + Video::Clear(ClearMask::Color | ClearMask::Depth); + m_fbos[f].m1->Unbind(); + + int buf = voronoi_points.Count() % 2; + for (int j = 0; j < voronoi_points.Count(); ++j) + { + FrameBuffer *dst_buf; + FrameBuffer *src_buf; + + if (buf) + { + dst_buf = m_fbos[f].m1; + src_buf = temp_buffer; + } + else + { + src_buf = m_fbos[f].m1; + dst_buf = temp_buffer; + } + + dst_buf->Bind(); + /* FIXME: we should just disable depth test in the shader */ + Video::Clear(ClearMask::Depth); + m_fbos[f].m2->Bind(); + + int i = 0; + m_fbos[f].m2->SetUniform(m_fbos[f].m3[i++], src_buf->GetTexture(), 0); //"in_texture" + m_fbos[f].m2->SetUniform(m_fbos[f].m3[i++], voronoi_points[j].m1); //"in_source_point" + m_fbos[f].m2->SetUniform(m_fbos[f].m3[i++], vec2(512.f, 512.f)); //"in_screen_res" + + m_vdecl->SetStream(m_vbo, m_fbos[f].m4.Last()); + m_vdecl->Bind(); + m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, 6); + m_vdecl->Unbind(); + m_fbos[f].m2->Unbind(); + dst_buf->Unbind(); + + buf = 1 - buf; + } + } + + Video::Clear(ClearMask::Color | ClearMask::Depth); + + //FRAME BUFFER DRAW + m_timer -= seconds; + if (m_timer < .0f && m_cur_fbo != src_voronoi) + { + //m_timer = 1.0f; + m_fbos[m_cur_fbo].m1->Bind(); + Video::SetClearColor(vec4(0.f, 0.f, 0.f, 1.f)); + Video::SetClearDepth(1.f); + Video::Clear(ClearMask::Color | ClearMask::Depth); + m_fbos[m_cur_fbo].m1->Unbind(); + + ivec2 curres = ivec2(512, 512) / 2; + int buf = 0; + while (1) + { + FrameBuffer *dst_buf; + FrameBuffer *src_buf; + Shader *shader; + + if (curres == ivec2(0)) + shader = m_screen_shader; + else + shader = m_fbos[m_cur_fbo].m2; + + if (curres.x == 256) + src_buf = m_fbos[src_voronoi].m1; + else if (buf) + src_buf = m_fbos[m_cur_fbo].m1; + else + src_buf = temp_buffer; + + if (buf) + dst_buf = temp_buffer; + else + dst_buf = m_fbos[m_cur_fbo].m1; + + dst_buf->Bind(); + /* FIXME: we should just disable depth test in the shader */ + Video::Clear(ClearMask::Depth); + shader->Bind(); + + //08_FBO ?? + #if _XBOX + /* FIXME: the Xbox enforces full EDRAM clears on each frame, so + * we cannot expect the render target contents to be preserved. + * This code snippet should be moved inside the FrameBuffer class. */ + //m_fbos[m_cur_fbo].m2->SetUniform(m_uni_flag, 1.f); + //m_fbos[m_cur_fbo].m2->SetUniform(m_uni_texture, m_fbo->GetTexture(), 0); + //m_vdecl->SetStream(m_vbo, m_fbos[m_cur_fbo].m4.Last()); + //m_vdecl->Bind(); + //m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, 6); + //m_vdecl->Unbind(); + #endif + + int i = 0; + if (curres == ivec2(0)) + m_screen_shader->SetUniform(m_screen_texture, src_buf->GetTexture(), 0); + else if (m_cur_fbo == voronoi) + { + shader->SetUniform(m_fbos[m_cur_fbo].m3[i++], src_buf->GetTexture(), 0); //"in_texture" + shader->SetUniform(m_fbos[m_cur_fbo].m3[i++], ((float)curres.x) / 512.f); //"in_step" + shader->SetUniform(m_fbos[m_cur_fbo].m3[i++], vec2(512.f, 512.f)); //"in_screen_res" + } + + m_vdecl->SetStream(m_vbo, m_fbos[m_cur_fbo].m4.Last()); + m_vdecl->Bind(); + m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, 6); + m_vdecl->Unbind(); + m_fbos[m_cur_fbo].m2->Unbind(); + dst_buf->Unbind(); + + if (curres == ivec2(0)) + break; + if (curres == ivec2(1)) + { + if (buf == 1) + curres = ivec2(0); + else + break; + } + buf = 1 - buf; + curres /= 2; + } + } + + //SCREEN DRAW + m_screen_shader->Bind(); + m_screen_shader->SetUniform(m_screen_texture, m_fbos[m_cur_fbo].m1->GetTexture(), 0); + m_vdecl->SetStream(m_vbo, m_screen_coord); + m_vdecl->Bind(); + m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, 6); + m_vdecl->Unbind(); + m_screen_shader->Unbind(); + } + +private: + Array voronoi_points; + Array m_vertices; + Shader *m_screen_shader; + ShaderAttrib m_screen_coord; + ShaderUniform m_screen_texture; + + VertexDeclaration *m_vdecl; + VertexBuffer *m_vbo; + + Array, Array > m_fbos; + FrameBuffer *temp_buffer; + + int m_cur_fbo; + double m_time; + vec3 m_hotspot, m_color; + bool m_ready; + float m_timer; +}; + +int main(int argc, char **argv) +{ + System::Init(argc, argv); + + Application app("Tutorial 12: Jump Flooding Algorithm & Voronoi", ivec2(512, 512), 60.0f); + + new Voronoi(); + + app.Run(); + return EXIT_SUCCESS; +} + diff --git a/tutorial/12_voronoi.lolfx b/tutorial/12_voronoi.lolfx new file mode 100644 index 00000000..8ae45a11 --- /dev/null +++ b/tutorial/12_voronoi.lolfx @@ -0,0 +1,93 @@ +//----------------------------------------------------------------------------- +//GLSL +//----------------------------------------------------------------------------- +[vert.glsl] + +#version 120 + +attribute vec2 in_position; + +uniform vec2 in_screen_res; + +uniform float in_step; +varying vec2 pass_pos; +varying vec2 pass_p[8]; + +void main() +{ + //JFA ALGO + pass_pos = ((vec2(1.0) + in_position) * 0.5); + + float k = in_step; + + vec2 p2 = pass_pos; + pass_p[0] = p2 + vec2(-k, -k); + pass_p[1] = p2 + vec2( 0, -k); + pass_p[2] = p2 + vec2( k, -k); + pass_p[3] = p2 + vec2(-k, 0); + pass_p[4] = p2 + vec2( k, 0); + pass_p[5] = p2 + vec2(-k, k); + pass_p[6] = p2 + vec2( 0, k); + pass_p[7] = p2 + vec2( k, k); + + gl_Position = vec4(in_position, 0.0, 1.0); +} + +[frag.glsl] + +#version 120 + +#if defined GL_ES +precision highp float; +#endif + +uniform sampler2D in_texture; + +varying vec2 pass_pos; +varying vec2 pass_p[8]; + +void main(void) +{ + vec4 src_color = texture2D(in_texture, pass_pos); + vec4 neigh_color; + + for (int i = 0; i < 8; ++i) + { + neigh_color = texture2D(in_texture, pass_p[i]); + + if (neigh_color.z > 0.0 && src_color.z == 0.0) + src_color = neigh_color; + else if (neigh_color.z > 0.0 && src_color.z > 0.0 && + length(neigh_color.xy - pass_pos) < length(src_color.xy - pass_pos)) + src_color = neigh_color; + + } + + gl_FragColor = src_color; +} + +//----------------------------------------------------------------------------- +//HLSL +//----------------------------------------------------------------------------- +[vert.hlsl] + +void main(float2 in_Position : POSITION, + out float2 pass_Position : TEXCOORD0, + out float4 out_Position : POSITION) +{ + pass_Position = in_Position; + out_Position = float4(in_Position, 0.0, 1.0); +} + +[frag.hlsl] + +void main(in float2 pass_Position : TEXCOORD0, + uniform sampler2D in_Texture, + uniform float in_Flag, + uniform float3 in_Point, + uniform float3 in_Color, + out float4 out_FragColor : COLOR) +{ + out_FragColor = float4(0.0); +} + diff --git a/tutorial/12_voronoi.vcxproj b/tutorial/12_voronoi.vcxproj new file mode 100644 index 00000000..734166de --- /dev/null +++ b/tutorial/12_voronoi.vcxproj @@ -0,0 +1,75 @@ + + + + + Debug + PS3 + + + Debug + Win32 + + + Debug + x64 + + + Debug + Xbox 360 + + + Release + PS3 + + + Release + Win32 + + + Release + x64 + + + Release + Xbox 360 + + + + + + + + + + + + + + + {9e62f2fe-3408-4eae-8238-fd84238ceeda} + + + {83d3b207-c601-4025-8f41-01dedc354661} + + + + {6bf81b39-edc2-4227-9982-c2d8abea95af} + Application + Win32Proj + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tutorial/12_voronoi_distance.lolfx b/tutorial/12_voronoi_distance.lolfx new file mode 100644 index 00000000..d47db363 --- /dev/null +++ b/tutorial/12_voronoi_distance.lolfx @@ -0,0 +1,94 @@ +[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 in_Texture; +uniform float in_Flag; +uniform vec3 in_Point; +uniform vec3 in_Color; + +varying vec2 pass_Position; + +void main(void) +{ + if (in_Flag == 0.0) + { + float tc = 0.0, ta = 0.0; + { + float s = 3.0 + 2.0 * in_Point.z; + vec2 p = pass_Position - in_Point.xy * 0.9; + float t = clamp(1.2 - dot(s * p, s * p), 0.0, 1.0); + float u = t * t * t * t; + tc += 3.0 * t * t - 2.0 * t * t * t; + ta += 3.0 * u * u - 2.0 * u * u * u; + } + + gl_FragColor = vec4(tc * in_Color, ta + 0.1); + } + else + { + vec2 texcoords = pass_Position * 0.5 + vec2(0.5, 0.5); + gl_FragColor = vec4(texture2D(in_Texture, texcoords).xyz, 1.0); + } +} + +[vert.hlsl] + +void main(float2 in_Position : POSITION, + out float2 pass_Position : TEXCOORD0, + out float4 out_Position : POSITION) +{ + pass_Position = in_Position; + out_Position = float4(in_Position, 0.0, 1.0); +} + +[frag.hlsl] + +void main(in float2 pass_Position : TEXCOORD0, + uniform sampler2D in_Texture, + uniform float in_Flag, + uniform float3 in_Point, + uniform float3 in_Color, + out float4 out_FragColor : COLOR) +{ + if (in_Flag == 0.0) + { + float tc = 0.0, ta = 0.0; + { + float s = 3.0 + 2.0 * in_Point.z; + float2 p = pass_Position - in_Point.xy * 0.9; + float t = clamp(1.2 - dot(s * p, s * p), 0.0, 1.0); + float u = t * t * t * t; + tc += 3.0 * t * t - 2.0 * t * t * t; + ta += 3.0 * u * u - 2.0 * u * u * u; + } + + out_FragColor = float4(tc * in_Color, ta + 0.1); + } + else + { + float2 texcoords = pass_Position * float2(0.5, -0.5) + float2(0.5, 0.5); + /* FIXME: this should be passed as a uniform or something */ + texcoords += float2(0.5 / 800.0, 0.5 / 600.0); + out_FragColor = float4(tex2D(in_Texture, texcoords).xyz, 1.0); + } +} + diff --git a/tutorial/12_voronoi_setup.lolfx b/tutorial/12_voronoi_setup.lolfx new file mode 100644 index 00000000..3712ace8 --- /dev/null +++ b/tutorial/12_voronoi_setup.lolfx @@ -0,0 +1,70 @@ +//----------------------------------------------------------------------------- +//GLSL +//----------------------------------------------------------------------------- +[vert.glsl] + +#version 120 + +attribute vec2 in_position; + +uniform vec2 in_screen_res; + +varying vec2 pass_position; + +void main() +{ + pass_position = ((vec2(1.0) + in_position) * 0.5 * in_screen_res); + gl_Position = vec4(in_position, 0.0, 1.0); +} + +[frag.glsl] + +#version 120 + +#if defined GL_ES +precision highp float; +#endif + +uniform sampler2D in_texture; +uniform vec3 in_source_point; +uniform vec2 in_screen_res; + +varying vec2 pass_position; + +void main(void) +{ + if (floor(in_source_point.xy) == floor(pass_position)) + gl_FragColor = vec4(in_source_point.xy / in_screen_res, in_source_point.z, 1.0); + else + { + vec4 src_color = texture2D(in_texture, pass_position / in_screen_res); + gl_FragColor = src_color;//vec4(0.0, 0.0, 0.0, 1.0); + } + //vec4(pass_position / in_screen_res, 0.0, 1.0); +} + +//----------------------------------------------------------------------------- +//HLSL +//----------------------------------------------------------------------------- +[vert.hlsl] + +void main(float2 in_Position : POSITION, + out float2 pass_Position : TEXCOORD0, + out float4 out_Position : POSITION) +{ + pass_Position = in_Position; + out_Position = float4(in_Position, 0.0, 1.0); +} + +[frag.hlsl] + +void main(in float2 pass_Position : TEXCOORD0, + uniform sampler2D in_Texture, + uniform float in_Flag, + uniform float3 in_Point, + uniform float3 in_Color, + out float4 out_FragColor : COLOR) +{ + out_FragColor = float4(0.0); +} + diff --git a/tutorial/Makefile.am b/tutorial/Makefile.am index 0ebe284b..a50f33be 100644 --- a/tutorial/Makefile.am +++ b/tutorial/Makefile.am @@ -2,7 +2,8 @@ include $(top_srcdir)/build/autotools/common.am noinst_PROGRAMS = 01_triangle 02_cube 03_noise 04_texture 05_easymesh \ - 08_fbo 11_fractal + 08_fbo 11_fractal \ + 12_fractal 01_triangle_SOURCES = 01_triangle.cpp 01_triangle.lolfx 01_triangle_CPPFLAGS = $(AM_CPPFLAGS) @@ -32,3 +33,9 @@ noinst_PROGRAMS = 01_triangle 02_cube 03_noise 04_texture 05_easymesh \ 11_fractal_CPPFLAGS = $(AM_CPPFLAGS) 11_fractal_DEPENDENCIES = @LOL_DEPS@ +12_voronoi_SOURCES = 12_voronoi.cpp 12_voronoi.lolfx \ + 12_voronoi_distance.lolfx 12_voronoi_setup.lolfx \ + 12_texture_to_screen.lolfx 12_distance.lolfx +12_voronoi_CPPFLAGS = $(AM_CPPFLAGS) +12_voronoi_DEPENDENCIES = @LOL_DEPS@ +