From 874aa42f44dd94adb80532591d08fab73e48ae8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20=E2=80=98Touky=E2=80=99=20Huet?= Date: Thu, 12 Sep 2013 16:46:22 +0000 Subject: [PATCH] removed added tutorial folders because of version mixup. --- tutorial/01_triangle.cpp | 83 ---- tutorial/01_triangle.lolfx | 48 --- tutorial/01_triangle.vcxproj | 79 ---- tutorial/02_cube.cpp | 156 -------- tutorial/02_cube.lolfx | 50 --- tutorial/02_cube.vcxproj | 79 ---- tutorial/03_noise.cpp | 93 ----- tutorial/03_noise.lolfx | 278 ------------- tutorial/03_noise.vcxproj | 79 ---- tutorial/04_texture.cpp | 127 ------ tutorial/04_texture.lolfx | 148 ------- tutorial/04_texture.vcxproj | 79 ---- tutorial/05_easymesh.cpp | 145 ------- tutorial/05_easymesh.vcxproj | 76 ---- tutorial/06_sprite.cpp | 106 ----- tutorial/06_sprite.png | Bin 155434 -> 0 bytes tutorial/06_sprite.vcxproj | 68 ---- tutorial/08_fbo.cpp | 154 -------- tutorial/08_fbo.lolfx | 94 ----- tutorial/08_fbo.vcxproj | 79 ---- tutorial/11_fractal.cpp | 579 ---------------------------- tutorial/11_fractal.lolfx | 192 --------- tutorial/11_fractal.vcxproj | 79 ---- tutorial/12_distance.lolfx | 94 ----- tutorial/12_texture_to_screen.lolfx | 92 ----- tutorial/12_voronoi.cpp | 405 ------------------- tutorial/12_voronoi.lolfx | 93 ----- tutorial/12_voronoi.vcxproj | 83 ---- tutorial/12_voronoi_distance.lolfx | 94 ----- tutorial/12_voronoi_setup.lolfx | 70 ---- tutorial/Makefile.am | 49 --- 31 files changed, 3851 deletions(-) delete mode 100644 tutorial/01_triangle.cpp delete mode 100644 tutorial/01_triangle.lolfx delete mode 100644 tutorial/01_triangle.vcxproj delete mode 100644 tutorial/02_cube.cpp delete mode 100644 tutorial/02_cube.lolfx delete mode 100644 tutorial/02_cube.vcxproj delete mode 100644 tutorial/03_noise.cpp delete mode 100644 tutorial/03_noise.lolfx delete mode 100644 tutorial/03_noise.vcxproj delete mode 100644 tutorial/04_texture.cpp delete mode 100644 tutorial/04_texture.lolfx delete mode 100644 tutorial/04_texture.vcxproj delete mode 100644 tutorial/05_easymesh.cpp delete mode 100644 tutorial/05_easymesh.vcxproj delete mode 100644 tutorial/06_sprite.cpp delete mode 100644 tutorial/06_sprite.png delete mode 100644 tutorial/06_sprite.vcxproj delete mode 100644 tutorial/08_fbo.cpp delete mode 100644 tutorial/08_fbo.lolfx delete mode 100644 tutorial/08_fbo.vcxproj delete mode 100644 tutorial/11_fractal.cpp delete mode 100644 tutorial/11_fractal.lolfx delete mode 100644 tutorial/11_fractal.vcxproj delete mode 100644 tutorial/12_distance.lolfx delete mode 100644 tutorial/12_texture_to_screen.lolfx delete mode 100644 tutorial/12_voronoi.cpp delete mode 100644 tutorial/12_voronoi.lolfx delete mode 100644 tutorial/12_voronoi.vcxproj delete mode 100644 tutorial/12_voronoi_distance.lolfx delete mode 100644 tutorial/12_voronoi_setup.lolfx delete mode 100644 tutorial/Makefile.am diff --git a/tutorial/01_triangle.cpp b/tutorial/01_triangle.cpp deleted file mode 100644 index 3b481f81..00000000 --- a/tutorial/01_triangle.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// -// Lol Engine - Triangle 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(01_triangle); - -class Triangle : public WorldEntity -{ -public: - Triangle() - { - m_vertices << vec2( 0.0, 0.8); - m_vertices << vec2(-0.8, -0.8); - m_vertices << vec2( 0.8, -0.8); - m_ready = false; - } - - virtual void TickDraw(float seconds) - { - WorldEntity::TickDraw(seconds); - - if (!m_ready) - { - m_shader = Shader::Create(LOLFX_RESOURCE_NAME(01_triangle)); - m_coord = m_shader->GetAttribLocation("in_Position", VertexUsage::Position, 0); - - 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_ready = true; - - /* FIXME: this object never cleans up */ - } - - m_shader->Bind(); - m_vdecl->SetStream(m_vbo, m_coord); - m_vdecl->Bind(); - m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, 3); - m_vdecl->Unbind(); - } - -private: - Array m_vertices; - Shader *m_shader; - ShaderAttrib m_coord; - VertexDeclaration *m_vdecl; - VertexBuffer *m_vbo; - bool m_ready; -}; - -int main(int argc, char **argv) -{ - System::Init(argc, argv); - - Application app("Tutorial 1: Triangle", ivec2(640, 480), 60.0f); - - new DebugFps(5, 5); - new Triangle(); - - app.Run(); - return EXIT_SUCCESS; -} - diff --git a/tutorial/01_triangle.lolfx b/tutorial/01_triangle.lolfx deleted file mode 100644 index 5f59871b..00000000 --- a/tutorial/01_triangle.lolfx +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Awesome triangle shader - */ - -technique FlatColor -{ - pass DefaultPass - { - vertexshader = vert; - pixelshader = frag; - } -} - -[vert.glsl] -#version 120 - -attribute vec2 in_Position; - -void main(void) -{ - gl_Position = vec4(in_Position, 0.0, 1.0); -} - -[frag.glsl] -#version 120 - -#if defined GL_ES -precision highp float; -#endif - -void main(void) -{ - gl_FragColor = vec4(0.7, 0.2, 0.5, 1.0); -} - -[vert.hlsl] -void main(float2 in_Position : POSITION, - out float4 out_Position : POSITION) -{ - out_Position = float4(in_Position, 0.0, 1.0); -} - -[frag.hlsl] -void main(out float4 out_FragColor : COLOR) -{ - out_FragColor = float4(0.7, 0.2, 0.5, 1.0); -} - diff --git a/tutorial/01_triangle.vcxproj b/tutorial/01_triangle.vcxproj deleted file mode 100644 index 57e317e6..00000000 --- a/tutorial/01_triangle.vcxproj +++ /dev/null @@ -1,79 +0,0 @@ - - - - - Debug - ORBIS - - - Debug - PS3 - - - Debug - Win32 - - - Debug - x64 - - - Debug - Xbox 360 - - - Release - ORBIS - - - Release - PS3 - - - Release - Win32 - - - Release - x64 - - - Release - Xbox 360 - - - - - - - - - - - {9e62f2fe-3408-4eae-8238-fd84238ceeda} - - - {83d3b207-c601-4025-8f41-01dedc354661} - - - - {b92abadc-45be-4cc5-b724-9426053123a1} - Application - Win32Proj - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tutorial/02_cube.cpp b/tutorial/02_cube.cpp deleted file mode 100644 index ebe746da..00000000 --- a/tutorial/02_cube.cpp +++ /dev/null @@ -1,156 +0,0 @@ -// -// Lol Engine - Cube tutorial -// -// Copyright: (c) 2011-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(02_cube); - -class Cube : public WorldEntity -{ -public: - Cube() - { - m_angle = 0; - - /* Front vertices/colors */ - m_mesh.Push(vec3(-1.0, -1.0, 1.0), vec3(1.0, 0.0, 1.0)); - m_mesh.Push(vec3( 1.0, -1.0, 1.0), vec3(0.0, 1.0, 0.0)); - m_mesh.Push(vec3( 1.0, 1.0, 1.0), vec3(1.0, 0.5, 0.0)); - m_mesh.Push(vec3(-1.0, 1.0, 1.0), vec3(1.0, 1.0, 0.0)); - /* Back */ - m_mesh.Push(vec3(-1.0, -1.0, -1.0), vec3(1.0, 0.0, 0.0)); - m_mesh.Push(vec3( 1.0, -1.0, -1.0), vec3(0.0, 0.5, 0.0)); - m_mesh.Push(vec3( 1.0, 1.0, -1.0), vec3(0.0, 0.5, 1.0)); - m_mesh.Push(vec3(-1.0, 1.0, -1.0), vec3(0.0, 0.0, 1.0)); - - m_faces_indices << 0 << 1 << 2 << 2 << 3 << 0; - m_faces_indices << 1 << 5 << 6 << 6 << 2 << 1; - m_faces_indices << 7 << 6 << 5 << 5 << 4 << 7; - m_faces_indices << 4 << 0 << 3 << 3 << 7 << 4; - m_faces_indices << 4 << 5 << 1 << 1 << 0 << 4; - m_faces_indices << 3 << 2 << 6 << 6 << 7 << 3; - - m_lines_indices << 0 << 1 << 1 << 2 << 2 << 3 << 3 << 0; - m_lines_indices << 4 << 5 << 5 << 6 << 6 << 7 << 7 << 4; - m_lines_indices << 0 << 4 << 1 << 5 << 2 << 6 << 3 << 7; - - m_ready = false; - } - - virtual void TickGame(float seconds) - { - WorldEntity::TickGame(seconds); - - m_angle += seconds * 45.0f; - - mat4 anim = mat4::rotate(m_angle, vec3(0, 1, 0)); - mat4 model = mat4::translate(vec3(0, 0, -4.5)); - mat4 view = mat4::lookat(vec3(0, 2, 0), vec3(0, 0, -4), vec3(0, 1, 0)); - mat4 proj = mat4::perspective(45.0f, 640.0f, 480.0f, 0.1f, 10.0f); - - m_matrix = proj * view * model * anim; - } - - virtual void TickDraw(float seconds) - { - WorldEntity::TickDraw(seconds); - - if (!m_ready) - { - m_shader = Shader::Create(LOLFX_RESOURCE_NAME(02_cube)); - - m_mvp = m_shader->GetUniformLocation("in_Matrix"); - m_coord = m_shader->GetAttribLocation("in_Vertex", - VertexUsage::Position, 0); - m_color = m_shader->GetAttribLocation("in_Color", - VertexUsage::Color, 0); - - m_vdecl = - new VertexDeclaration(VertexStream(VertexUsage::Position, - VertexUsage::Color)); - - m_vbo = new VertexBuffer(m_mesh.Bytes()); - void *mesh = m_vbo->Lock(0, 0); - memcpy(mesh, &m_mesh[0], m_mesh.Bytes()); - m_vbo->Unlock(); - - m_lines_ibo = new IndexBuffer(m_lines_indices.Bytes()); - void *indices = m_lines_ibo->Lock(0, 0); - memcpy(indices, &m_lines_indices[0], m_lines_indices.Bytes()); - m_lines_ibo->Unlock(); - - m_faces_ibo = new IndexBuffer(m_faces_indices.Bytes()); - indices = m_faces_ibo->Lock(0, 0); - memcpy(indices, &m_faces_indices[0], m_faces_indices.Bytes()); - m_faces_ibo->Unlock(); - - /* FIXME: this object never cleans up */ - m_ready = true; - } - - g_renderer->SetClearColor(vec4(0.0f, 0.0f, 0.0f, 1.0f)); - - m_shader->Bind(); - m_vdecl->SetStream(m_vbo, m_coord, m_color); - m_vdecl->Bind(); - - m_shader->SetUniform(m_mvp, m_matrix); - m_lines_ibo->Bind(); - m_vdecl->DrawIndexedElements(MeshPrimitive::Lines, 0, 0, - m_mesh.Count(), 0, m_lines_indices.Count()); - m_lines_ibo->Unbind(); - - m_shader->SetUniform(m_mvp, m_matrix * mat4::scale(0.5f)); - m_faces_ibo->Bind(); - m_vdecl->DrawIndexedElements(MeshPrimitive::Triangles, 0, 0, - m_mesh.Count(), 0, m_faces_indices.Count()); - m_faces_ibo->Unbind(); - - m_vdecl->Unbind(); - } - -private: - float m_angle; - mat4 m_matrix; - Array m_mesh; - Array m_lines_indices, m_faces_indices; - - Shader *m_shader; - ShaderAttrib m_coord, m_color; - ShaderUniform m_mvp; - VertexDeclaration *m_vdecl; - VertexBuffer *m_vbo; - IndexBuffer *m_lines_ibo, *m_faces_ibo; - - bool m_ready; -}; - -int main(int argc, char **argv) -{ - System::Init(argc, argv); - - Application app("Tutorial 2: Cube", ivec2(640, 480), 60.0f); - - new DebugFps(5, 5); - new Cube(); - - app.Run(); - - return EXIT_SUCCESS; -} - diff --git a/tutorial/02_cube.lolfx b/tutorial/02_cube.lolfx deleted file mode 100644 index 8e1ae04f..00000000 --- a/tutorial/02_cube.lolfx +++ /dev/null @@ -1,50 +0,0 @@ -[vert.glsl] - -#version 120 - -attribute vec3 in_Vertex; -attribute vec3 in_Color; -uniform mat4 in_Matrix; -varying vec3 pass_Color; - -void main(void) -{ - gl_Position = in_Matrix * vec4(in_Vertex, 1.0); - pass_Color = in_Color; -} - -[frag.glsl] - -#version 120 - -#if defined GL_ES -precision highp float; -#endif - -varying vec3 pass_Color; - -void main(void) -{ - gl_FragColor = vec4(pass_Color, 1.0); -} - -[vert.hlsl] - -void main(float3 in_Vertex : POSITION, - float3 in_Color : COLOR, - uniform float4x4 in_Matrix, - out float4 out_Position : POSITION, - out float3 pass_Color : COLOR) -{ - pass_Color = in_Color; - out_Position = mul(in_Matrix, float4(in_Vertex, 1.0)); -} - -[frag.hlsl] - -void main(float3 pass_Color : COLOR, - out float4 out_FragColor : COLOR) -{ - out_FragColor = float4(pass_Color, 1.0); -} - diff --git a/tutorial/02_cube.vcxproj b/tutorial/02_cube.vcxproj deleted file mode 100644 index f2b1d571..00000000 --- a/tutorial/02_cube.vcxproj +++ /dev/null @@ -1,79 +0,0 @@ - - - - - Debug - ORBIS - - - Debug - PS3 - - - Debug - Win32 - - - Debug - x64 - - - Debug - Xbox 360 - - - Release - ORBIS - - - Release - PS3 - - - Release - Win32 - - - Release - x64 - - - Release - Xbox 360 - - - - - - - - - - - {9e62f2fe-3408-4eae-8238-fd84238ceeda} - - - {83d3b207-c601-4025-8f41-01dedc354661} - - - - {7b083da2-fe08-4f6d-bfdd-195d5c2783eb} - Application - Win32Proj - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tutorial/03_noise.cpp b/tutorial/03_noise.cpp deleted file mode 100644 index 35531e19..00000000 --- a/tutorial/03_noise.cpp +++ /dev/null @@ -1,93 +0,0 @@ -// -// Lol Engine - Noise 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(03_noise); - -class NoiseDemo : public WorldEntity -{ -public: - NoiseDemo() : - m_time(0.0), - 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); - m_ready = false; - } - - virtual void TickDraw(float seconds) - { - WorldEntity::TickDraw(seconds); - - m_time += seconds; - - if (!m_ready) - { - m_shader = Shader::Create(LOLFX_RESOURCE_NAME(03_noise)); - m_coord = m_shader->GetAttribLocation("in_Position", VertexUsage::Position, 0); - m_time_uni = m_shader->GetUniformLocation("u_Time"); - - 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_ready = true; - - /* FIXME: this object never cleans up */ - } - - m_shader->Bind(); - m_shader->SetUniform(m_time_uni, m_time); - m_vdecl->SetStream(m_vbo, m_coord); - m_vdecl->Bind(); - m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, 6); - m_vdecl->Unbind(); - } - -private: - Array m_vertices; - Shader *m_shader; - ShaderAttrib m_coord; - ShaderUniform m_time_uni; - VertexDeclaration *m_vdecl; - VertexBuffer *m_vbo; - float m_time; - bool m_ready; -}; - -int main(int argc, char **argv) -{ - System::Init(argc, argv); - - Application app("Tutorial 3: Noise", ivec2(1280, 720), 60.0f); - - new NoiseDemo(); - - app.Run(); - return EXIT_SUCCESS; -} - diff --git a/tutorial/03_noise.lolfx b/tutorial/03_noise.lolfx deleted file mode 100644 index 184252a7..00000000 --- a/tutorial/03_noise.lolfx +++ /dev/null @@ -1,278 +0,0 @@ -[vert.glsl] - -#version 120 - -uniform float u_Time; - -attribute vec2 in_Position; - -varying vec4 pass_Position; -varying vec3 water[4]; -varying vec3 fire[4]; - -float mod289(float x) -{ - return x - floor(x * (1.0 / 289.0)) * 289.0; -} - -void main(void) -{ - mat3 r = mat3(0.36, 0.48, -0.8, -0.8, 0.60, 0.0, 0.48, 0.64, 0.60); - vec3 p_pos = r * vec3(in_Position * vec2(16.0, 9.0), 0.0); - vec3 p_time = r * vec3(0.0, 0.0, u_Time * 2.0); - - /* Noise sampling points for water */ - water[0] = p_pos / 2.0 + p_time; - water[1] = p_pos / 4.0 + p_time; - water[2] = p_pos / 8.0 + p_time; - water[3] = p_pos / 16.0 + p_time; - - /* Noise sampling points for fire */ - p_pos = 16.0 * p_pos - r * vec3(0.0, mod289(u_Time) * 128.0, 0.0); - fire[0] = p_pos / 2.0 + p_time * 2.0; - fire[1] = p_pos / 4.0 + p_time * 1.5; - fire[2] = p_pos / 8.0 + p_time; - fire[3] = p_pos / 16.0 + p_time; - - /* Pass rotated screen coordinates */ - pass_Position.xy = in_Position; - mat2 rot = mat2(cos(u_Time), sin(u_Time), -sin(u_Time), cos(u_Time)); - pass_Position.zw = rot * in_Position; - - gl_Position = vec4(in_Position, 0.0, 1.0); -} - -[frag.glsl] - -#version 120 - -#if defined GL_ES -precision highp float; -#endif - -uniform float u_Time; - -varying vec4 pass_Position; -varying vec3 water[4]; -varying vec3 fire[4]; - -vec4 mod289(vec4 x) -{ - return x - floor(x * (1.0 / 289.0)) * 289.0; -} - -vec4 perm(vec4 x) -{ - return mod289(((x * 34.0) + 1.0) * x); -} - -float noise3d(vec3 p) -{ - vec3 a = floor(p); - vec3 d = p - a; - d = d * d * (3.0 - 2.0 * d); - - vec4 b = a.xxyy + vec4(0.0, 1.0, 0.0, 1.0); - vec4 k1 = perm(b.xyxy); - vec4 k2 = perm(k1.xyxy + b.zzww); - - vec4 c = k2 + a.zzzz; - vec4 k3 = perm(c); - vec4 k4 = perm(c + 1.0); - - vec4 o1 = fract(k3 * (1.0 / 41.0)); - vec4 o2 = fract(k4 * (1.0 / 41.0)); - - vec4 o3 = o2 * d.z + o1 * (1.0 - d.z); - vec2 o4 = o3.yw * d.x + o3.xz * (1.0 - d.x); - - return o4.y * d.y + o4.x * (1.0 - d.y); -} - -void main(void) -{ - /* Dither the transition between water and fire */ - float test = pass_Position.z * pass_Position.w + 1.5 * sin(u_Time); - vec2 d = vec2(16.0, 9.0) * pass_Position.xy; - test += 0.5 * (length(fract(d) - 0.5) - length(fract(d + 0.5) - 0.5)); - - /* Compute 4 octaves of noise */ -#if defined GL_ES - vec4 n = vec4(noise3d((test > 0.0) ? fire[0] : water[0]), - noise3d((test > 0.0) ? fire[1] : water[1]), - noise3d((test > 0.0) ? fire[2] : water[2]), - noise3d((test > 0.0) ? fire[3] : water[3])); -#else - vec3 points[4] = (test > 0.0) ? fire : water; - vec4 n = vec4(noise3d(points[0]), - noise3d(points[1]), - noise3d(points[2]), - noise3d(points[3])); -#endif - - vec4 color; - - if (test > 0.0) - { - /* Use noise results for fire */ - float p = dot(n, vec4(0.125, 0.125, 0.25, 0.5)); - - /* Fade to black on top of screen */ - p -= pass_Position.y * 0.8 + 0.25; - p = max(p, 0.0); - p = min(p, 1.0); - - float q = p * p * (3.0 - 2.0 * p); - float r = q * q * (3.0 - 2.0 * q); - color = vec4(min(q * 2.0, 1.0), - max(r * 1.5 - 0.5, 0.0), - max(q * 8.0 - 7.3, 0.0), - 1.0); - } - else - { - /* Use noise results for water */ - float p = dot(abs(2.0 * n - 1.0), - vec4(0.5, 0.25, 0.125, 0.125)); - float q = sqrt(p); - - color = vec4(1.0 - q, - 1.0 - 0.5 * q, - 1.0, - 1.0); - } - - gl_FragColor = color; -} - -[vert.hlsl] - -float mod289(float x) -{ - return x - floor(x * (1.0 / 289.0)) * 289.0; -} - -void main(float2 in_Position : POSITION, - uniform float u_Time, - out float4 out_Position : POSITION, - out float4 pass_Position : TEXCOORD0, - out float3 water[4] : TEXCOORD1, - out float3 fire[4] : TEXCOORD5) -{ - float3x3 r = float3x3(0.36, 0.48, -0.8, -0.8, 0.60, 0.0, 0.48, 0.64, 0.60); - float3 p_pos = mul(r, float3(in_Position * float2(16.0, 9.0), 0.0)); - float3 p_time = mul(r, float3(0.0, 0.0, u_Time * 2.0)); - - /* Noise sampling points for water */ - water[0] = p_pos / 2.0 + p_time; - water[1] = p_pos / 4.0 + p_time; - water[2] = p_pos / 8.0 + p_time; - water[3] = p_pos / 16.0 + p_time; - - /* Noise sampling points for fire */ - p_pos = 16.0 * p_pos - mul(r, float3(0.0, mod289(u_Time) * 128.0, 0.0)); - fire[0] = p_pos / 2.0 + p_time * 2.0; - fire[1] = p_pos / 4.0 + p_time * 1.5; - fire[2] = p_pos / 8.0 + p_time; - fire[3] = p_pos / 16.0 + p_time; - - /* Pass rotated screen coordinates */ - pass_Position.xy = in_Position; - float2x2 rot = float2x2(cos(u_Time), sin(u_Time), -sin(u_Time), cos(u_Time)); - pass_Position.zw = mul(rot, in_Position); - - out_Position = float4(in_Position, 0.0, 1.0); -} - -[frag.hlsl] - -float4 mod289(float4 x) -{ - return x - floor(x * (1.0 / 289.0)) * 289.0; -} - -float4 perm(float4 x) -{ - return mod289(((x * 34.0) + 1.0) * x); -} - -float noise3d(float3 p) -{ - float3 a = floor(p); - float3 d = p - a; - d = d * d * (3.0 - 2.0 * d); - - float4 b = a.xxyy + float4(0.0, 1.0, 0.0, 1.0); - float4 k1 = perm(b.xyxy); - float4 k2 = perm(k1.xyxy + b.zzww); - - float4 c = k2 + a.zzzz; - float4 k3 = perm(c); - float4 k4 = perm(c + 1.0); - - float4 o1 = frac(k3 * (1.0 / 41.0)); - float4 o2 = frac(k4 * (1.0 / 41.0)); - - float4 o3 = o2 * d.z + o1 * (1.0 - d.z); - float2 o4 = o3.yw * d.x + o3.xz * (1.0 - d.x); - - return o4.y * d.y + o4.x * (1.0 - d.y); -} - -void main(in float4 pass_Position : TEXCOORD0, - in float3 water[4] : TEXCOORD1, - in float3 fire[4] : TEXCOORD5, - uniform float u_Time, - out float4 out_FragColor : COLOR) -{ - /* Dither the transition between water and fire */ - float test = pass_Position.z * pass_Position.w + 1.5 * sin(u_Time); - float2 d = float2(16.0, 9.0) * pass_Position.xy; - test += 0.5 * (length(frac(d) - 0.5) - length(frac(d + 0.5) - 0.5)); - - float3 points[4]; - points[0] = (test > 0.0) ? fire[0] : water[0]; - points[1] = (test > 0.0) ? fire[1] : water[1]; - points[2] = (test > 0.0) ? fire[2] : water[2]; - points[3] = (test > 0.0) ? fire[3] : water[3]; - - /* Compute 4 octaves of noise */ - float4 n = float4(noise3d(points[0]), - noise3d(points[1]), - noise3d(points[2]), - noise3d(points[3])); - - float4 color; - - if (test > 0.0) - { - /* Use noise results for fire */ - float p = dot(n, float4(0.125, 0.125, 0.25, 0.5)); - - /* Fade to black on top of screen */ - p -= pass_Position.y * 0.8 + 0.25; - p = max(p, 0.0); - p = min(p, 1.0); - - float q = p * p * (3.0 - 2.0 * p); - float r = q * q * (3.0 - 2.0 * q); - color = float4(min(q * 2.0, 1.0), - max(r * 1.5 - 0.5, 0.0), - max(q * 8.0 - 7.3, 0.0), - 1.0); - } - else - { - /* Use noise results for water */ - float p = dot(abs(2.0 * n - 1.0), - float4(0.5, 0.25, 0.125, 0.125)); - float q = sqrt(p); - - color = float4(1.0 - q, - 1.0 - 0.5 * q, - 1.0, - 1.0); - } - - out_FragColor = color; -} diff --git a/tutorial/03_noise.vcxproj b/tutorial/03_noise.vcxproj deleted file mode 100644 index c14bdbdb..00000000 --- a/tutorial/03_noise.vcxproj +++ /dev/null @@ -1,79 +0,0 @@ - - - - - Debug - ORBIS - - - Debug - PS3 - - - Debug - Win32 - - - Debug - x64 - - - Debug - Xbox 360 - - - Release - ORBIS - - - Release - PS3 - - - Release - Win32 - - - Release - x64 - - - Release - Xbox 360 - - - - - - - - - - - {9e62f2fe-3408-4eae-8238-fd84238ceeda} - - - {83d3b207-c601-4025-8f41-01dedc354661} - - - - {b0a53d75-cbb4-4fdf-93ac-2d12a79ada0e} - Application - Win32Proj - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tutorial/04_texture.cpp b/tutorial/04_texture.cpp deleted file mode 100644 index e0a1b0be..00000000 --- a/tutorial/04_texture.cpp +++ /dev/null @@ -1,127 +0,0 @@ -// -// Lol Engine - Graphing 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; - -static int const TEXTURE_WIDTH = 256; - -LOLFX_RESOURCE_DECLARE(04_texture); - -class TextureDemo : public WorldEntity -{ -public: - TextureDemo() : - m_frames(0), - 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); - - m_heightmap = new uint8_t[TEXTURE_WIDTH * 1]; - } - - virtual ~TextureDemo() - { - delete m_heightmap; - } - - virtual void TickGame(float seconds) - { - WorldEntity::TickGame(seconds); - - /* Generate a new heightmap at the beginning */ - if (m_frames == 0) - memset(m_heightmap, 255, TEXTURE_WIDTH); - - /* Scroll left */ - for (int i = 0; i < TEXTURE_WIDTH - 1; i++) - m_heightmap[i] = m_heightmap[i + 1]; - - int height = m_heightmap[TEXTURE_WIDTH - 1]; - height = (height + 127 + 40 * lol::sin(m_frames * 0.03) + rand() % 97 - 38) / 2; - height = std::max(15, std::min(height, 240)); - m_heightmap[TEXTURE_WIDTH - 1] = height; - - /* Update frame counter */ - ++m_frames; - } - - virtual void TickDraw(float seconds) - { - WorldEntity::TickDraw(seconds); - - /* Initialise GPU data */ - if (!m_ready) - { - m_texture = new Texture(ivec2(TEXTURE_WIDTH, 1), PixelFormat::Y_8); - - m_shader = Shader::Create(LOLFX_RESOURCE_NAME(04_texture)); - m_coord = m_shader->GetAttribLocation("in_Position", VertexUsage::Position, 0); - - 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_ready = true; - - /* FIXME: this object never cleans up */ - } - - /* Send new heightmap to GPU */ - m_texture->SetData(m_heightmap); - - m_shader->Bind(); - m_shader->SetUniform(m_texture_uni, m_texture->GetTexture(), 0); - m_vdecl->SetStream(m_vbo, m_coord); - m_vdecl->Bind(); - m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, 6); - m_vdecl->Unbind(); - } - -private: - Array m_vertices; - Texture *m_texture; - Shader *m_shader; - ShaderAttrib m_coord; - ShaderUniform m_texture_uni; - VertexDeclaration *m_vdecl; - VertexBuffer *m_vbo; - uint8_t *m_heightmap; - int m_frames; - bool m_ready; -}; - -int main(int argc, char **argv) -{ - System::Init(argc, argv); - - Application app("Tutorial 4: Texture", ivec2(1280, 720), 60.0f); - - new TextureDemo(); - - app.Run(); - return EXIT_SUCCESS; -} - diff --git a/tutorial/04_texture.lolfx b/tutorial/04_texture.lolfx deleted file mode 100644 index 6ee4804d..00000000 --- a/tutorial/04_texture.lolfx +++ /dev/null @@ -1,148 +0,0 @@ -[vert.glsl] - -#version 120 - -attribute vec2 in_Position; - -varying vec4 pass_Position; - -void main(void) -{ - pass_Position = vec4(0.5 * in_Position + 0.5, 0.0, 1.0); - gl_Position = vec4(in_Position, 0.5, 1.0); -} - -[frag.glsl] - -#version 120 - -#if defined GL_ES -precision highp float; -#endif - -uniform sampler2D u_Texture; - -varying vec4 pass_Position; - -float segdist(vec2 p1, vec2 p2, vec2 a) -{ - float d = max(1e-10, dot(p2 - p1, p2 - p1)); - float t = clamp(dot(a - p1, p2 - p1) / d, 0.0, 1.0); - return distance(a, mix(p1, p2, t)); -} - -void main(void) -{ - float width = 800.0; - float height = 600.0; - float texture_width = 256.0; - float line_width = 1.2; - float dot_size = 1.0; - vec4 delta = vec4(1.0 / texture_width, 0.0, - 2.0 / texture_width, 0.0); - - vec2 p = pass_Position.xy; - vec2 tc = vec2(floor(p.x * texture_width) / texture_width, p.y); - float t = p.x * texture_width - floor(p.x * texture_width); - vec4 c; - c[0] = texture2D(u_Texture, tc - delta.xy).x; - c[1] = texture2D(u_Texture, tc).x; - c[2] = texture2D(u_Texture, tc + delta.xy).x; - c[3] = texture2D(u_Texture, tc + delta.zw).x; - - /* Find the 4 closest points in screen space */ - vec2 p0 = vec2((tc.x - delta.x) * width, c[0] * height); - vec2 p1 = vec2((tc.x ) * width, c[1] * height); - vec2 p2 = vec2((tc.x + delta.x) * width, c[2] * height); - vec2 p3 = vec2((tc.x + delta.z) * width, c[3] * height); - vec2 a = vec2(p.x * width, p.y * height); - - /* Compute distance to segments */ - float d = segdist(p0, p1, a); - d = min(d, segdist(p1, p2, a)); - d = min(d, segdist(p2, p3, a)); - - /* Compute distance to dots */ - d = min(d, length(a - p0) - dot_size); - d = min(d, length(a - p1) - dot_size); - d = min(d, length(a - p2) - dot_size); - d = min(d, length(a - p3) - dot_size); - - /* Add line width */ - float lum = clamp(line_width - d, 0.0, 1.0); - - /* Compensate for sRGB */ - lum = pow(1.0 - lum, 1.0 / 2.4); - - /* Choose some funny colours */ - gl_FragColor = vec4(mix(p.x, 1.0, lum), lum, lum, 1.0); -} - -[vert.hlsl] - -void main(float2 in_Position : POSITION, - out float4 out_Position : POSITION, - out float4 pass_Position : TEXCOORD0) -{ - pass_Position = float4(0.5 * in_Position + 0.5, 0.0, 1.0); - out_Position = float4(in_Position, 0.5, 1.0); -} - -[frag.hlsl] - -float segdist(float2 p1, float2 p2, float2 a) -{ - float d = max(1e-10, dot(p2 - p1, p2 - p1)); - float t = clamp(dot(a - p1, p2 - p1) / d, 0.0, 1.0); - return distance(a, lerp(p1, p2, t)); -} - -void main(in float4 pass_Position : TEXCOORD0, - uniform sampler2D u_Texture, - out float4 out_FragColor : COLOR) -{ - float width = 800.0; - float height = 600.0; - float texture_width = 256.0; - float line_width = 1.2; - float dot_size = 1.0; - float4 delta = float4(1.0 / texture_width, 0.0, - 2.0 / texture_width, 0.0); - - float2 p = pass_Position.xy; - float2 tc = float2(floor(p.x * texture_width) / texture_width, p.y); - float t = p.x * texture_width - floor(p.x * texture_width); - float4 c; - c[0] = tex2D(u_Texture, tc - delta.xy).x; - c[1] = tex2D(u_Texture, tc).x; - c[2] = tex2D(u_Texture, tc + delta.xy).x; - c[3] = tex2D(u_Texture, tc + delta.zw).x; - - /* Find the 4 closest points in screen space */ - float2 p0 = float2((tc.x - delta.x) * width, c[0] * height); - float2 p1 = float2((tc.x ) * width, c[1] * height); - float2 p2 = float2((tc.x + delta.x) * width, c[2] * height); - float2 p3 = float2((tc.x + delta.z) * width, c[3] * height); - float2 a = float2(p.x * width, p.y * height); - - /* Compute distance to segments */ - float d = segdist(p0, p1, a); - d = min(d, segdist(p1, p2, a)); - d = min(d, segdist(p2, p3, a)); - - /* Compute distance to dots */ - d = min(d, length(a - p0) - dot_size); - d = min(d, length(a - p1) - dot_size); - d = min(d, length(a - p2) - dot_size); - d = min(d, length(a - p3) - dot_size); - - /* Add line width */ - float lum = clamp(line_width - d, 0.0, 1.0); - - /* Compensate for sRGB */ - lum = pow(1.0 - lum, 1.0 / 2.4); - - /* Choose some funny colours */ - out_FragColor = float4(lerp(p.x, 1.0, lum), lum, lum, 1.0); -} - diff --git a/tutorial/04_texture.vcxproj b/tutorial/04_texture.vcxproj deleted file mode 100644 index 4404cd30..00000000 --- a/tutorial/04_texture.vcxproj +++ /dev/null @@ -1,79 +0,0 @@ - - - - - Debug - ORBIS - - - Debug - PS3 - - - Debug - Win32 - - - Debug - x64 - - - Debug - Xbox 360 - - - Release - ORBIS - - - Release - PS3 - - - Release - Win32 - - - Release - x64 - - - Release - Xbox 360 - - - - - - - - - - - {9e62f2fe-3408-4eae-8238-fd84238ceeda} - - - {83d3b207-c601-4025-8f41-01dedc354661} - - - - {834852db-edb6-4fd0-bcf9-45cd01126962} - Application - Win32Proj - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tutorial/05_easymesh.cpp b/tutorial/05_easymesh.cpp deleted file mode 100644 index 8cf71187..00000000 --- a/tutorial/05_easymesh.cpp +++ /dev/null @@ -1,145 +0,0 @@ -// -// Lol Engine - EasyMesh tutorial -// -// Copyright: (c) 2011-2013 Sam Hocevar -// (c) 2012-2013 Benjamin "Touky" Huet -// 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" - -using namespace std; -using namespace lol; - -class EasyMeshTutorial : public WorldEntity -{ -public: - EasyMeshTutorial() - { - m_gears.Push(EasyMesh(), mat4(1.0f), 0.0f); - m_gears.Push(EasyMesh(), mat4(1.0f), 0.0f); - m_gears.Push(EasyMesh(), mat4(1.0f), 180.0f / 18); - m_gears.Push(EasyMesh(), mat4(1.0f), 180.0f / 18); - m_gears.Push(EasyMesh(), mat4(1.0f), 180.0f / 18); - - m_gears[0].m1.Compile("[sc#00f ab 8 1 8 ty -.25]" - "[sc#f9f scb#f9f acg 12 10 5 5 20 20 5 5 0.1 0 s .1 .1 .1 ty -.1 csgu]" - "[sc#fff scb#000 acg 12 10 10 10 20 20 5 5 0.1 0 s .05 .05 .05 tx -1.5 ty .3 csgu]" - "[sc#00f ab 5 3 9 tx 2.5 csgs]" - "[[ sc#fff ab 3 1.4 2 tx -2 tz -2 " - "[sc#fff ab 2.1 .7 1.1 ty .5 tx -1.4 tz -1.4 csgs] mz] csgu]"); - //m_gears[0].m1.Compile("[sc#f9f scb#f9f acg 12 10 5 5 20 20 5 5 0.1 0 s .1 .1 .1 [sc#00f ab 3 1 2 ty .25 tx 1 csgs]]"); - m_gears[1].m1.Compile("sc#ff9 scb#ff9 acg 54 10 95 95 90 90 -5 -5 0.1 0 s .1 .1 .1"); - //m_gears[2].m1.Compile("sc#9ff scb#9ff acg 18 10 5 5 30 30 5 5 0.1 0 s .1 .1 .1 [sc#00f scb#00f ab 2 2 2 tx 1.5]"); - //m_gears[3].m1.Compile("sc#9ff scb#9ff acg 18 10 5 5 30 30 5 5 0.1 0 s .1 .1 .1 [sc#00f scb#00f ab 2 2 2 tx 1.5]"); - //m_gears[4].m1.Compile("sc#9ff scb#9ff acg 18 10 5 5 30 30 5 5 0.1 0 s .1 .1 .1 [sc#00f scb#00f ab 2 2 2 tx 1.5]"); - m_gears[2].m1.Compile("[sc#0f0 ab 2 2 2 t .8 .8 .8 rx 20 ry 20 [sc#00f ab 2 2 2 tx 0 csgu]]"); - m_gears[3].m1.Compile("[sc#0f0 ab 2 2 2 t .8 .8 .8 rx 20 ry 20 [sc#00f ab 2 2 2 tx 0 csgs]]"); - m_gears[4].m1.Compile("[sc#0f0 ab 2 2 2 t .8 .8 .8 rx 20 ry 20 [sc#00f ab 2 2 2 tx 0 csga]]"); - - m_angle = 0; - - m_camera = new Camera(); - m_camera->SetProjection(mat4::perspective(30.f, 960.f, 600.f, .1f, 1000.f)); - m_camera->SetView(mat4::lookat(vec3(-15.f, 5.f, 0.f), - vec3(0.f, -1.f, 0.f), - vec3(0.f, 1.f, 0.f))); - g_scene->PushCamera(m_camera); - - /* Add a white directional light */ - m_light1 = new Light(); - m_light1->SetPosition(vec4(0.2f, 0.2f, 0.f, 0.f)); - m_light1->SetColor(vec4(0.5f, 0.5f, 0.5f, 1.f)); - Ticker::Ref(m_light1); - - /* Add an orangeish point light */ - m_light2 = new Light(); - m_light2->SetPosition(vec4(-15.f, 15.f, 15.f, 1.f)); - m_light2->SetColor(vec4(0.4f, 0.3f, 0.2f, 1.f)); - Ticker::Ref(m_light2); - - m_ready = false; - } - - ~EasyMeshTutorial() - { - g_scene->PopCamera(m_camera); - Ticker::Unref(m_light1); - Ticker::Unref(m_light2); - } - - virtual void TickGame(float seconds) - { - WorldEntity::TickGame(seconds); - - m_angle += seconds * 70.0f; - m_mat = mat4::rotate(10.0f, vec3(0, 0, 1)) - * mat4::rotate(100, vec3(0, 1, 0)); - // * mat4::rotate(m_angle, vec3(0, 1, 0)); - - m_gears[0].m3 += seconds * 20.0f; - m_gears[1].m3 += seconds * 20.0f * -2 / 9; - m_gears[2].m3 += seconds * 20.0f * -2 / 3; - m_gears[3].m3 += seconds * 20.0f * -2 / 3; - m_gears[4].m3 += seconds * 20.0f * -2 / 3; - - m_gears[0].m2 = mat4::translate(vec3(0, -1, 0)) - * mat4::rotate(m_gears[0].m3 - 130.0f, vec3(0, 1, 0)) - * mat4::rotate(40.0f, vec3(0, 0, 1)); - m_gears[1].m2 = mat4::translate(vec3(0, 0, 0)) - * mat4::rotate(m_gears[1].m3, vec3(0, 1, 0)); - m_gears[2].m2 = mat4::translate(vec3(0, 0, 5.5f)) - * mat4::rotate(m_gears[2].m3 - 40.0f, vec3(0, 1, 0)) - * mat4::rotate(90.0f, vec3(0, 0, 1)); - m_gears[3].m2 = mat4::translate(vec3(5.5f * lol::sqrt(3.f) * 0.5f, 0, -5.5f * 0.5f)) - * mat4::rotate(m_gears[3].m3 - 140.0f, vec3(0, 1, 0)) - * mat4::rotate(-70.0f, vec3(0, 0, 1)); - m_gears[4].m2 = mat4::translate(vec3(-5.5f * lol::sqrt(3.f) * 0.5f, 0, -5.5f * 0.5f)) - * mat4::rotate(m_gears[4].m3 - 80.0f, vec3(0, 1, 0)); - } - - virtual void TickDraw(float seconds) - { - WorldEntity::TickDraw(seconds); - - if (!m_ready) - { - g_renderer->SetClearColor(vec4(0.0f, 0.0f, 0.0f, 1.0f)); - - for (int i = 0; i < m_gears.Count(); i++) - m_gears[i].m1.MeshConvert(); - m_ready = true; - } - - for (int i = 0; i < m_gears.Count(); i++) - m_gears[i].m1.Render(m_mat * m_gears[i].m2); - } - -private: - Array m_gears; - float m_angle; - mat4 m_mat; - Camera *m_camera; - Light *m_light1, *m_light2; - - bool m_ready; -}; - -int main(int argc, char **argv) -{ - System::Init(argc, argv); - - Application app("Tutorial 5: EasyMesh", ivec2(960, 600), 60.0f); - new EasyMeshTutorial(); - app.Run(); - - return EXIT_SUCCESS; -} - diff --git a/tutorial/05_easymesh.vcxproj b/tutorial/05_easymesh.vcxproj deleted file mode 100644 index 5cefd62f..00000000 --- a/tutorial/05_easymesh.vcxproj +++ /dev/null @@ -1,76 +0,0 @@ - - - - - Debug - ORBIS - - - Debug - PS3 - - - Debug - Win32 - - - Debug - x64 - - - Debug - Xbox 360 - - - Release - ORBIS - - - Release - PS3 - - - Release - Win32 - - - Release - x64 - - - Release - Xbox 360 - - - - - - - - {9e62f2fe-3408-4eae-8238-fd84238ceeda} - - - {83d3b207-c601-4025-8f41-01dedc354661} - - - - {1c5b8702-290c-42da-aa9e-671348f5b747} - Application - Win32Proj - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tutorial/06_sprite.cpp b/tutorial/06_sprite.cpp deleted file mode 100644 index fa56caba..00000000 --- a/tutorial/06_sprite.cpp +++ /dev/null @@ -1,106 +0,0 @@ -// -// Lol Engine - Sprite tutorial -// -// Copyright: (c) 2011-2013 Sam Hocevar -// (c) 2012 Daniel Stephens (artwork) -// 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" - -using namespace std; -using namespace lol; - -class SpriteTutorial : public WorldEntity -{ -public: - SpriteTutorial() - { - m_camera = new Camera(); - m_camera->SetView(mat4(1.f)); - m_camera->SetProjection(mat4::ortho(0.f, 640.f, 0.f, 480.f, -100.f, 100.f)); - g_scene->PushCamera(m_camera); - Ticker::Ref(m_camera); - - m_tileset = Tiler::Register("06_sprite.png"); - for (int i = 0; i < FRAME_COUNT; ++i) - m_tileset->AddTile(ibox2(i * 24, 376, 24 + i * 24, 24 + 376)); - - for (int i = 0; i < SPRITE_COUNT; ++i) - { - m_sprites.Push(ivec3(rand(-96, 640), rand(-96, 480), 0), - rand(0.f, 1.f)); - } - - m_ready = false; - } - - ~SpriteTutorial() - { - Tiler::Deregister(m_tileset); - - g_scene->PopCamera(m_camera); - Ticker::Unref(m_camera); - } - - virtual void TickGame(float seconds) - { - for (int i = 0; i < SPRITE_COUNT; ++i) - { - m_sprites[i].m1.y += 50.f * seconds; - m_sprites[i].m2 = lol::fmod(m_sprites[i].m2 + seconds, 1.f); - if (m_sprites[i].m1.y > 480 + 48) - m_sprites[i].m1.y = rand(-96, -48); - } - - WorldEntity::TickGame(seconds); - } - - virtual void TickDraw(float seconds) - { - WorldEntity::TickDraw(seconds); - - if (!m_ready) - { - g_renderer->SetClearColor(vec4(0.0f, 0.0f, 0.0f, 1.0f)); - m_ready = true; - } - - for (int i = 0; i < SPRITE_COUNT; ++i) - { - int frame = (int)(m_sprites[i].m2 * FRAME_COUNT); -// m_sprites[i].m1.z = frame; - g_scene->AddTile(m_tileset, frame, - (ivec3)m_sprites[i].m1, 0, vec2(2.f)); - } - } - -private: - Camera *m_camera; - TileSet *m_tileset; - - static int const SPRITE_COUNT = 192; - static int const FRAME_COUNT = 16; - Array m_sprites; - - bool m_ready; -}; - -int main(int argc, char **argv) -{ - System::Init(argc, argv); - - Application app("Tutorial 6: Sprite", ivec2(640, 480), 60.0f); - new SpriteTutorial(); - app.Run(); - - return EXIT_SUCCESS; -} - diff --git a/tutorial/06_sprite.png b/tutorial/06_sprite.png deleted file mode 100644 index e0bdabbb6ff72bc24d7e19bc326b37f6a0a3526e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 155434 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%0DCKQB-4v}f0tmvCeyr9lBzlhnsr9&z^}be~a~ZCq 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

>QQ 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.KV6PWt}PRlrjFTN%6b&`Q1P5i`EQ4Nhl5$6BF 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 - - - - 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} - - - - {1c5b8702-290c-42da-aa9e-671348f5b747} - Application - Win32Proj - - - - - - - - - - - - - - - - - diff --git a/tutorial/08_fbo.cpp b/tutorial/08_fbo.cpp deleted file mode 100644 index 291021c7..00000000 --- a/tutorial/08_fbo.cpp +++ /dev/null @@ -1,154 +0,0 @@ -// -// 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(08_fbo); - -class FBO : public WorldEntity -{ -public: - FBO() - : 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) - { - WorldEntity::TickGame(seconds); - - 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_shader = Shader::Create(LOLFX_RESOURCE_NAME(08_fbo)); - m_coord = m_shader->GetAttribLocation("in_Position", VertexUsage::Position, 0); - m_uni_flag = m_shader->GetUniformLocation("in_Flag"); - m_uni_point = m_shader->GetUniformLocation("in_Point"); - m_uni_color = m_shader->GetUniformLocation("in_Color"); - m_uni_texture = m_shader->GetUniformLocation("in_Texture"); - - 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_fbo = new Framebuffer(Video::GetSize()); - m_fbo->Bind(); - - { - RenderContext rc; - rc.SetClearColor(vec4(0.f, 0.f, 0.f, 1.f)); - rc.SetClearDepth(1.f); - g_renderer->Clear(ClearMask::Color | ClearMask::Depth); - } - - m_fbo->Unbind(); - - m_ready = true; - - /* FIXME: this object never cleans up */ - } - - /* FIXME: we should just disable depth test in the shader */ - RenderContext rc; - rc.SetDepthFunc(DepthFunc::Disabled); - - m_fbo->Bind(); - m_shader->Bind(); - -#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_shader->SetUniform(m_uni_flag, 1.f); - m_shader->SetUniform(m_uni_texture, m_fbo->GetTexture(), 0); - m_vdecl->SetStream(m_vbo, m_coord); - m_vdecl->Bind(); - m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, 6); - m_vdecl->Unbind(); -#endif - - m_shader->SetUniform(m_uni_flag, 0.f); - m_shader->SetUniform(m_uni_point, m_hotspot); - m_shader->SetUniform(m_uni_color, m_color); - m_vdecl->SetStream(m_vbo, m_coord); - m_vdecl->Bind(); - m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, 6); - m_vdecl->Unbind(); - m_shader->Unbind(); - m_fbo->Unbind(); - - m_shader->Bind(); - m_shader->SetUniform(m_uni_flag, 1.f); - m_shader->SetUniform(m_uni_texture, m_fbo->GetTexture(), 0); - m_vdecl->SetStream(m_vbo, m_coord); - m_vdecl->Bind(); - m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, 6); - m_vdecl->Unbind(); - m_shader->Unbind(); - } - -private: - Array m_vertices; - Shader *m_shader; - ShaderAttrib m_coord; - ShaderUniform m_uni_flag, m_uni_point, m_uni_color, m_uni_texture; - VertexDeclaration *m_vdecl; - VertexBuffer *m_vbo; - Framebuffer *m_fbo; - double m_time; - vec3 m_hotspot, m_color; - bool m_ready; -}; - -int main(int argc, char **argv) -{ - System::Init(argc, argv); - - Application app("Tutorial 08: Framebuffer Object", ivec2(512, 512), 60.0f); - - new FBO(); - - app.Run(); - return EXIT_SUCCESS; -} - diff --git a/tutorial/08_fbo.lolfx b/tutorial/08_fbo.lolfx deleted file mode 100644 index d47db363..00000000 --- a/tutorial/08_fbo.lolfx +++ /dev/null @@ -1,94 +0,0 @@ -[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/08_fbo.vcxproj b/tutorial/08_fbo.vcxproj deleted file mode 100644 index 44e1500f..00000000 --- a/tutorial/08_fbo.vcxproj +++ /dev/null @@ -1,79 +0,0 @@ - - - - - Debug - ORBIS - - - Debug - PS3 - - - Debug - Win32 - - - Debug - x64 - - - Debug - Xbox 360 - - - Release - ORBIS - - - Release - PS3 - - - Release - Win32 - - - Release - x64 - - - Release - Xbox 360 - - - - - - - - - - - {9e62f2fe-3408-4eae-8238-fd84238ceeda} - - - {83d3b207-c601-4025-8f41-01dedc354661} - - - - {BCEE0132-8E24-49BE-AFEB-96DAD14396BA} - Application - Win32Proj - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tutorial/11_fractal.cpp b/tutorial/11_fractal.cpp deleted file mode 100644 index 0380e39b..00000000 --- a/tutorial/11_fractal.cpp +++ /dev/null @@ -1,579 +0,0 @@ -// -// Lol Engine - Fractal tutorial -// -// Copyright: (c) 2011-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 -#include - -#include "core.h" -#include "loldebug.h" - -using namespace lol; - -LOLFX_RESOURCE_DECLARE(11_fractal); - -class Fractal : public WorldEntity -{ -public: - Fractal(ivec2 const &size) - { - /* Ensure texture size is a multiple of 16 for better aligned - * data access. Store the dimensions of a texel for our shader, - * as well as the half-size of the screen. */ - m_size = size; - m_size.x = (m_size.x + 15) & ~15; - m_size.y = (m_size.y + 15) & ~15; - m_texel_settings = vec4(1.0, 1.0, 2.0, 2.0) / m_size.xyxy; - m_screen_settings = vec4(1.0, 1.0, 0.5, 0.5) * m_size.xyxy; - - /* Window size decides the world aspect ratio. For instance, 640×480 - * will be mapped to (-0.66,-0.5) - (0.66,0.5). */ -#if !defined __native_client__ - m_window_size = Video::GetSize(); -#else - /* FIXME: it's illegal to call this on the game thread! */ - m_window_size = ivec2(640, 480); -#endif - if (m_window_size.y < m_window_size.x) - m_window2world = 0.5 / m_window_size.y; - else - m_window2world = 0.5 / m_window_size.x; - m_texel2world = (dvec2)m_window_size / (dvec2)m_size * m_window2world; - - m_oldmouse = ivec2(0, 0); - - m_pixels.Resize(m_size.x * m_size.y); - m_frame = -1; - m_slices = 4; - for (int i = 0; i < 4; i++) - { - m_deltashift[i] = real("0"); - m_deltascale[i] = real("1"); - m_dirty[i] = 2; - } -#if defined __CELLOS_LV2__ || defined _XBOX - //m_center = rcmplx(-.22815528839841, -1.11514249704382); - //m_center = rcmplx(0.001643721971153, 0.822467633298876); - m_center = rcmplx("-0.65823419062254", "0.50221777363480"); - m_zoom_speed = -0.025; -#else - m_center = rcmplx(-0.75, 0.0); - m_zoom_speed = 0.0; -#endif - m_translate = rcmplx(0.0, 0.0); - m_radius = 5.0; - m_ready = false; - m_drag = false; - - for (int i = 0; i < (MAX_ITERATIONS + 1) * PALETTE_STEP; i++) - { - double f = (double)i / PALETTE_STEP; - - double r = 0.5 * lol::sin(f * 0.27 + 2.0) + 0.5; - double g = 0.5 * lol::sin(f * 0.17 - 1.8) + 0.5; - double b = 0.5 * lol::sin(f * 0.21 - 2.6) + 0.5; - - if (f < 7.0) - { - f = f < 1.0 ? 0.0 : (f - 1.0) / 6.0; - r *= f; - g *= f; - b *= f; - } - - uint8_t red = r * 255.99f; - uint8_t green = g * 255.99f; - uint8_t blue = b * 255.99f; -#if defined __CELLOS_LV2__ || defined _XBOX - m_palette.Push(u8vec4(255, red, green, blue)); -#elif defined __native_client__ - m_palette.Push(u8vec4(red, green, blue, 255)); -#else - m_palette.Push(u8vec4(blue, green, red, 255)); -#endif - } - -#if !defined __native_client__ - m_centertext = new Text(NULL, "data/font/ascii.png"); - m_centertext->SetPos(ivec3(5, m_window_size.y - 15, 1)); - Ticker::Ref(m_centertext); - - m_mousetext = new Text(NULL, "data/font/ascii.png"); - m_mousetext->SetPos(ivec3(5, m_window_size.y - 29, 1)); - Ticker::Ref(m_mousetext); - - m_zoomtext = new Text(NULL, "data/font/ascii.png"); - m_zoomtext->SetPos(ivec3(5, m_window_size.y - 43, 1)); - Ticker::Ref(m_zoomtext); -#endif - - m_position = ivec3(0, 0, 0); - m_bbox[0] = m_position; - m_bbox[1] = ivec3(m_window_size, 0); - Input::TrackMouse(this); - -#if LOL_FEATURE_THREADS - /* Spawn worker threads and wait for their readiness. */ - for (int i = 0; i < MAX_THREADS; i++) - m_threads[i] = new Thread(DoWorkHelper, this); - for (int i = 0; i < MAX_THREADS; i++) - m_spawnqueue.Pop(); -#endif - } - - ~Fractal() - { -#if LOL_FEATURE_THREADS - /* Signal worker threads for completion and wait for - * them to quit. */ - for (int i = 0; i < MAX_THREADS; i++) - m_jobqueue.Push(-1); - for (int i = 0; i < MAX_THREADS; i++) - m_donequeue.Pop(); -#endif - - Input::UntrackMouse(this); -#if !defined __native_client__ - Ticker::Unref(m_centertext); - Ticker::Unref(m_mousetext); - Ticker::Unref(m_zoomtext); -#endif - } - - inline dcmplx TexelToWorldOffset(vec2 texel) - { - double dx = (0.5 + texel.x - m_size.x / 2) * m_texel2world.x; - double dy = (0.5 + m_size.y / 2 - texel.y) * m_texel2world.y; - return m_radius * dcmplx(dx, dy); - } - - inline dcmplx ScreenToWorldOffset(vec2 pixel) - { - /* No 0.5 offset here, because we want to be able to position the - * mouse at (0,0) exactly. */ - double dx = pixel.x - m_window_size.x / 2; - double dy = m_window_size.y / 2 - pixel.y; - return m_radius * m_window2world * dcmplx(dx, dy); - } - - virtual void TickGame(float seconds) - { - WorldEntity::TickGame(seconds); - - int prev_frame = (m_frame + 4) % 4; - m_frame = (m_frame + 1) % 4; - - rcmplx worldmouse = m_center + rcmplx(ScreenToWorldOffset(m_mousepos)); - - uint32_t buttons = Input::GetMouseButtons(); -#if !defined __CELLOS_LV2__ && !defined _XBOX - if (buttons & 0x2) - { - if (!m_drag) - { - m_oldmouse = m_mousepos; - m_drag = true; - } - m_translate = ScreenToWorldOffset(m_oldmouse) - - ScreenToWorldOffset(m_mousepos); - /* XXX: the purpose of this hack is to avoid translating by - * an exact number of pixels. If this were to happen, the step() - * optimisation for i915 cards in our shader would behave - * incorrectly because a quarter of the pixels in the image - * would have tie rankings in the distance calculation. */ - m_translate *= real(1023.0 / 1024.0); - m_oldmouse = m_mousepos; - } - else - { - m_drag = false; - if (m_translate != rcmplx(0.0, 0.0)) - { - m_translate *= real(std::pow(2.0, -seconds * 5.0)); - if ((double)m_translate.norm() < m_radius * 1e-4) - m_translate = rcmplx(0.0, 0.0); - } - } - - if (buttons & 0x5 && m_mousepos.x != -1) - { - double zoom = (buttons & 0x1) ? -0.5 : 0.5; - m_zoom_speed += zoom * seconds; - if (m_zoom_speed / zoom > 5e-3f) - m_zoom_speed = zoom * 5e-3f; - } - else if (m_zoom_speed) - { - m_zoom_speed *= std::pow(2.0, -seconds * 5.0); - if (lol::abs(m_zoom_speed) < 1e-5 || m_drag) - m_zoom_speed = 0.0; - } -#endif - - if (m_zoom_speed || m_translate != rcmplx(0.0, 0.0)) - { - rcmplx oldcenter = m_center; - double oldradius = m_radius; - double zoom = std::pow(2.0, seconds * 1e3f * m_zoom_speed); - if (m_radius * zoom > 8.0) - { - m_zoom_speed *= -1.0; - zoom = 8.0 / m_radius; - } - else if (m_radius * zoom < 1e-14) - { - m_zoom_speed *= -1.0; - zoom = 1e-14 / m_radius; - } - m_radius *= zoom; -#if !defined __CELLOS_LV2__ && !defined _XBOX - m_center += m_translate; - m_center = (m_center - worldmouse) * real(zoom) + worldmouse; - worldmouse = m_center + rcmplx(ScreenToWorldOffset(m_mousepos)); -#endif - - /* Store the transformation properties to go from m_frame - 1 - * to m_frame. */ - m_deltashift[prev_frame] = (m_center - oldcenter) / real(oldradius); - m_deltashift[prev_frame].x /= m_size.x * m_texel2world.x; - m_deltashift[prev_frame].y /= m_size.y * m_texel2world.y; - m_deltascale[prev_frame] = m_radius / oldradius; - m_dirty[0] = m_dirty[1] = m_dirty[2] = m_dirty[3] = 2; - } - else - { - /* If settings didn't change, set transformation from previous - * frame to identity. */ - m_deltashift[prev_frame] = real::R_0(); - m_deltascale[prev_frame] = real::R_1(); - } - - /* Transformation from current frame to current frame is always - * identity. */ - m_zoom_settings[m_frame][0] = 0.0f; - m_zoom_settings[m_frame][1] = 0.0f; - m_zoom_settings[m_frame][2] = 1.0f; - - /* Compute transformation from other frames to current frame */ - for (int i = 0; i < 3; i++) - { - int prev_index = (m_frame + 4 - i) % 4; - int cur_index = (m_frame + 3 - i) % 4; - - m_zoom_settings[cur_index][0] = (real)m_zoom_settings[prev_index][0] * m_deltascale[cur_index] + m_deltashift[cur_index].x; - m_zoom_settings[cur_index][1] = (real)m_zoom_settings[prev_index][1] * m_deltascale[cur_index] + m_deltashift[cur_index].y; - m_zoom_settings[cur_index][2] = (real)m_zoom_settings[prev_index][2] * m_deltascale[cur_index]; - } - - /* Precompute texture offset change instead of doing it in GLSL */ - for (int i = 0; i < 4; i++) - { - m_zoom_settings[i][0] += 0.5 * (1.0 - m_zoom_settings[i][2]); - m_zoom_settings[i][1] -= 0.5 * (1.0 - m_zoom_settings[i][2]); - } - -#if !defined __native_client__ - char buf[256]; - std::sprintf(buf, "center: "); - m_center.x.sprintf(buf + strlen(buf), 30); - std::sprintf(buf + strlen(buf), " "); - m_center.y.sprintf(buf + strlen(buf), 30); - m_centertext->SetText(buf); - std::sprintf(buf, " mouse: "); - worldmouse.x.sprintf(buf + strlen(buf), 30); - std::sprintf(buf + strlen(buf), " "); - worldmouse.y.sprintf(buf + strlen(buf), 30); - m_mousetext->SetText(buf); - std::sprintf(buf, " zoom: %g", 1.0 / m_radius); - m_zoomtext->SetText(buf); -#endif - - if (m_dirty[m_frame]) - { - m_dirty[m_frame]--; - - for (int i = 0; i < m_size.y; i += MAX_LINES * 2) - { -#if LOL_FEATURE_THREADS - m_jobqueue.Push(i); -#else - DoWork(i); -#endif - } - } - } - -#if LOL_FEATURE_THREADS - static void *DoWorkHelper(void *data) - { - Fractal *that = (Fractal *)data; - that->m_spawnqueue.Push(0); - for ( ; ; ) - { - int line = that->m_jobqueue.Pop(); - if (line == -1) - break; - that->DoWork(line); - that->m_donequeue.Push(0); - } - that->m_donequeue.Push(0); - return NULL; - }; -#endif - - void DoWork(int line) - { - double const maxsqlen = 1024; - double const k1 = 1.0 / (1 << 10) / (std::log(maxsqlen) / std::log(2.0)); - - int jmin = ((m_frame + 1) % 4) / 2 + line; - int jmax = jmin + MAX_LINES * 2; - if (jmax > m_size.y) - jmax = m_size.y; - u8vec4 *m_pixelstart = &m_pixels[0] - + m_size.x * (m_size.y / 4 * m_frame + line / 4); - - dcmplx c = (dcmplx)m_center; - - for (int j = jmin; j < jmax; j += 2) - for (int i = m_frame % 2; i < m_size.x; i += 2) - { - double xr, yr, x0, y0, x1, y1, x2, y2, x3, y3; - dcmplx z0 = c + TexelToWorldOffset(ivec2(i, j)); - //dcmplx r0(0.28693186889504513, 0.014286693904085048); - //dcmplx r0(0.001643721971153, 0.822467633298876); - //dcmplx r0(-1.207205434596, 0.315432814901); - //dcmplx r0(-0.79192956889854, -0.14632423080102); - //dcmplx r0(0.3245046418497685, 0.04855101129280834); - dcmplx r0 = z0; - - x0 = z0.x; y0 = z0.y; - xr = r0.x; yr = r0.y; - - int iter = MAX_ITERATIONS - 4; - for (;;) - { - /* Unroll the loop: tests are more expensive to do at each - * iteration than the few extra multiplications. */ - x1 = x0 * x0 - y0 * y0 + xr; - y1 = x0 * y0 + x0 * y0 + yr; - x2 = x1 * x1 - y1 * y1 + xr; - y2 = x1 * y1 + x1 * y1 + yr; - x3 = x2 * x2 - y2 * y2 + xr; - y3 = x2 * y2 + x2 * y2 + yr; - x0 = x3 * x3 - y3 * y3 + xr; - y0 = x3 * y3 + x3 * y3 + yr; - - if (x0 * x0 + y0 * y0 >= maxsqlen) - break; - iter -= 4; - if (iter < 4) - break; - } - - if (iter) - { - double n = x0 * x0 + y0 * y0; - - if (x1 * x1 + y1 * y1 >= maxsqlen) - { - iter += 3; n = x1 * x1 + y1 * y1; - } - else if (x2 * x2 + y2 * y2 >= maxsqlen) - { - iter += 2; n = x2 * x2 + y2 * y2; - } - else if (x3 * x3 + y3 * y3 >= maxsqlen) - { - iter += 1; n = x3 * x3 + y3 * y3; - } - - if (n > maxsqlen * maxsqlen) - n = maxsqlen * maxsqlen; - - /* Approximate log(sqrt(n))/log(sqrt(maxsqlen)) */ - double f = iter; - union { double n; uint64_t x; } u = { n }; - double k = (u.x >> 42) - (((1 << 10) - 1) << 10); - k *= k1; - - /* Approximate log2(k) in [1,2]. */ - f += (- 0.344847817623168308695977510213252644185 * k - + 2.024664188044341212602376988171727038739) * k - - 1.674876738008591047163498125918330313237; - - *m_pixelstart++ = m_palette[(int)(f * PALETTE_STEP)]; - } - else - { -#if defined __CELLOS_LV2__ || defined _XBOX - *m_pixelstart++ = u8vec4(255, 0, 0, 0); -#else - *m_pixelstart++ = u8vec4(0, 0, 0, 255); -#endif - } - } - } - - virtual void TickDraw(float seconds) - { - WorldEntity::TickDraw(seconds); - - static float const vertices[] = - { - 1.0f, 1.0f, - -1.0f, 1.0f, - -1.0f, -1.0f, - -1.0f, -1.0f, - 1.0f, -1.0f, - 1.0f, 1.0f, - }; - - static float const texcoords[] = - { - 1.0f, 1.0f, - 0.0f, 1.0f, - 0.0f, 0.0f, - 0.0f, 0.0f, - 1.0f, 0.0f, - 1.0f, 1.0f, - }; - - if (!m_ready) - { - /* Create a texture of half the width and twice the height - * so that we can upload four different subimages each frame. */ - m_texture = new Texture(ivec2(m_size.x / 2, m_size.y * 2), - PixelFormat::ABGR_8); - - /* Ensure the texture data is complete at least once, otherwise - * uploading subimages will not work. */ - m_texture->SetData(&m_pixels[0]); - - m_shader = Shader::Create(LOLFX_RESOURCE_NAME(11_fractal)); - - m_vertexattrib = m_shader->GetAttribLocation("a_Vertex", VertexUsage::Position, 0); - m_texattrib = m_shader->GetAttribLocation("a_TexCoord", VertexUsage::TexCoord, 0); - m_texeluni = m_shader->GetUniformLocation("u_TexelSize"); - m_screenuni = m_shader->GetUniformLocation("u_ScreenSize"); - m_zoomuni = m_shader->GetUniformLocation("u_ZoomSettings"); - - m_vdecl = - new VertexDeclaration(VertexStream(VertexUsage::Position), - VertexStream(VertexUsage::TexCoord)); - m_vbo = new VertexBuffer(sizeof(vertices)); - m_tbo = new VertexBuffer(sizeof(texcoords)); - - void *tmp = m_vbo->Lock(0, 0); - memcpy(tmp, vertices, sizeof(vertices)); - m_vbo->Unlock(); - - tmp = m_tbo->Lock(0, 0); - memcpy(tmp, texcoords, sizeof(texcoords)); - m_tbo->Unlock(); - - /* FIXME: this object never cleans up */ - m_ready = true; - } - - m_texture->Bind(); - - if (m_dirty[m_frame]) - { -#if LOL_FEATURE_THREADS - for (int i = 0; i < m_size.y; i += MAX_LINES * 2) - m_donequeue.Pop(); -#endif - - m_dirty[m_frame]--; - -#if defined __CELLOS_LV2__ - /* glTexSubImage2D is extremely slow on the PS3, to the point - * that uploading the whole texture is 40 times faster. */ - m_texture->SetData(&m_pixels[0]); -#else - m_texture->SetSubData(ivec2(0, m_frame * m_size.y / 2), - m_size / 2, - &m_pixels[m_size.x * m_size.y / 4 * m_frame]); -#endif - } - - m_shader->Bind(); - m_shader->SetUniform(m_texeluni, m_texel_settings); - m_shader->SetUniform(m_screenuni, m_screen_settings); - m_shader->SetUniform(m_zoomuni, m_zoom_settings); - m_vdecl->Bind(); - m_vdecl->SetStream(m_vbo, m_vertexattrib); - m_vdecl->SetStream(m_tbo, m_texattrib); - m_texture->Bind(); - m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, 6); - m_vdecl->Unbind(); - } - -private: - static int const MAX_ITERATIONS = 340; - static int const PALETTE_STEP = 32; - static int const MAX_THREADS = 8; - static int const MAX_LINES = 8; - - ivec2 m_size, m_window_size, m_oldmouse; - double m_window2world; - dvec2 m_texel2world; - Array m_pixels, m_palette; - - Shader *m_shader; - ShaderAttrib m_vertexattrib, m_texattrib; - ShaderUniform m_texeluni, m_screenuni, m_zoomuni; - - VertexDeclaration *m_vdecl; - VertexBuffer *m_vbo, *m_tbo; - Texture *m_texture; - - int m_frame, m_slices, m_dirty[4]; - bool m_ready, m_drag; - - rcmplx m_deltashift[4], m_center, m_translate; - real m_deltascale[4]; - double m_zoom_speed, m_radius; - - vec4 m_texel_settings, m_screen_settings; - mat4 m_zoom_settings; - -#if LOL_FEATURE_THREADS - /* Worker threads */ - Thread *m_threads[MAX_THREADS]; - Queue m_spawnqueue, m_jobqueue, m_donequeue; -#endif - -#if !defined __native_client__ - /* Debug information */ - Text *m_centertext, *m_mousetext, *m_zoomtext; -#endif -}; - -int main(int argc, char **argv) -{ - ivec2 window_size(640, 480); - - System::Init(argc, argv); - Application app("Tutorial 3: Fractal", window_size, 60.0f); - - new DebugFps(5, 5); - new Fractal(window_size); - //new DebugRecord("fractalol.ogm", 60.0f); - - app.Run(); - - return EXIT_SUCCESS; -} - diff --git a/tutorial/11_fractal.lolfx b/tutorial/11_fractal.lolfx deleted file mode 100644 index 803e8021..00000000 --- a/tutorial/11_fractal.lolfx +++ /dev/null @@ -1,192 +0,0 @@ -[vert.glsl] - -#version 120 - -uniform mat4 u_ZoomSettings; -uniform vec4 u_TexelSize; -uniform vec4 u_ScreenSize; - -attribute vec2 a_TexCoord; -attribute vec2 a_Vertex; - -varying vec4 v_CenterX, v_CenterY, v_IndexX, v_IndexY; - -void main(void) -{ - gl_Position = vec4(a_Vertex, 0.0, 1.0); - /* Center point in [-.5,.5], apply zoom and translation - * transformation, and go back to texture coordinates - * in [0,1]. That's the ideal point we would like to - * compute the value for. Then add or remove half the - * size of a texel: the distance from this new point to - * the final point will be our error. */ - vec4 offsets = vec4(0.5, -0.5, 0.015625, -0.015625); - vec4 zoomscale = vec4(u_ZoomSettings[0][2], - u_ZoomSettings[1][2], - u_ZoomSettings[2][2], - u_ZoomSettings[3][2]); - vec4 zoomtx = vec4(u_ZoomSettings[0][0], - u_ZoomSettings[1][0], - u_ZoomSettings[2][0], - u_ZoomSettings[3][0]); - vec4 zoomty = vec4(u_ZoomSettings[0][1], - u_ZoomSettings[1][1], - u_ZoomSettings[2][1], - u_ZoomSettings[3][1]); - v_CenterX = zoomscale * a_TexCoord.x + zoomtx - + offsets.xyxy * u_TexelSize.x; - v_CenterY = zoomscale * a_TexCoord.y - zoomty - + offsets.xyyx * u_TexelSize.y; - /* Precompute the multiple of one texel where our ideal - * point lies. The fragment shader will call floor() on - * this value. We add or remove a slight offset to avoid - * rounding issues at the image's edges. */ - v_IndexX = v_CenterX * u_ScreenSize.z - offsets.zwzw; - v_IndexY = v_CenterY * u_ScreenSize.w - offsets.zwwz; -} - -[frag.glsl] - -#version 120 - -#if defined GL_ES -precision highp float; -#endif - -uniform vec4 u_TexelSize; -uniform sampler2D u_Texture; - -varying vec4 v_CenterX, v_CenterY, v_IndexX, v_IndexY; - -void main(void) -{ - vec4 v05 = vec4(0.5, 0.5, 0.5, 0.5); - vec4 rx, ry, t0, dx, dy, dd; - /* Get a pixel coordinate from each slice into rx & ry */ - rx = u_TexelSize.x + u_TexelSize.z * floor(v_IndexX); - ry = u_TexelSize.y + u_TexelSize.w * floor(v_IndexY); - /* Compute inverse distance to expected pixel in dd, - * and put zero if we fall outside the texture. */ - t0 = step(abs(rx - v05), v05) * step(abs(ry - v05), v05); - dx = rx - v_CenterX; - dy = ry - v_CenterY; -#if 0 - vec4 dd = t0 * (abs(dx) + abs(dy)); - vec4 dd = t0 / (0.001 + sqrt((dx * dx) + (dy * dy))); -#endif - dd = t0 / (0.000001 + (dx * dx) + (dy * dy)); - /* Modify Y coordinate to select proper quarter. */ - ry = ry * 0.25 + vec4(0.0, 0.25, 0.5, 0.75); - -#if 1 -# if 0 - /* XXX: disabled until we can autodetect i915 */ - /* t1.x <-- dd.x > dd.y */ - /* t1.y <-- dd.z > dd.w */ - vec2 t1 = step(dd.xz, dd.yw); - /* ret.x <-- max(rx.x, rx.y) wrt. t1.x */ - /* ret.y <-- max(rx.z, rx.w) wrt. t1.y */ - /* ret.z <-- max(ry.x, ry.y) wrt. t1.x */ - /* ret.w <-- max(ry.z, ry.w) wrt. t1.y */ - vec4 ret = mix(vec4(rx.xz, ry.xz), - vec4(rx.yw, ry.yw), t1.xyxy); - /* dd.x <-- max(dd.x, dd.y) */ - /* dd.z <-- max(dd.z, dd.w) */ - dd.xy = mix(dd.xz, dd.yw, t1); - /* t2 <-- dd.x > dd.z */ - float t2 = step(dd.x, dd.y); - /* ret.x <-- max(ret.x, ret.y); */ - /* ret.y <-- max(ret.z, ret.w); */ - ret.xy = mix(ret.xz, ret.yw, t2); -# else - /* Fallback for i915 cards -- the trick to reduce the - * number of operations is to compute both step(a,b) - * and step(b,a) and hope that their sum is 1. This is - * almost always the case, and when it isn't we can - * afford to have a few wrong pixels. However, a real - * problem is when panning the image, because half the - * screen is likely to flicker. To avoid this problem, - * we cheat a little (see m_translate comment above). */ - vec4 t1 = step(dd.xzyw, dd.ywxz); - vec4 ret = vec4(rx.xz, ry.xz) * t1.zwzw - + vec4(rx.yw, ry.yw) * t1.xyxy; - dd.xy = dd.xz * t1.zw + dd.yw * t1.xy; - vec2 t2 = step(dd.xy, dd.yx); - ret.xy = ret.xz * t2.yy + ret.yw * t2.xx; -# endif - /* Nearest neighbour */ - gl_FragColor = texture2D(u_Texture, ret.xy); -#else - /* Alternate version: some kind of linear interpolation */ - vec4 p0 = texture2D(u_Texture, vec2(rx.x, ry.x)); - vec4 p1 = texture2D(u_Texture, vec2(rx.y, ry.y)); - vec4 p2 = texture2D(u_Texture, vec2(rx.z, ry.z)); - vec4 p3 = texture2D(u_Texture, vec2(rx.w, ry.w)); - gl_FragColor = 1.0 / (dd.x + dd.y + dd.z + dd.w) - * (dd.x * p0 + dd.y * p1 + dd.z * p2 + dd.w * p3); -#endif -} - -[vert.hlsl] - -void main(float2 a_Vertex : POSITION, - float2 a_TexCoord : TEXCOORD0, - uniform float4x4 u_ZoomSettings, - uniform float4 u_TexelSize, - uniform float4 u_ScreenSize, - out float4 out_Position : POSITION0, - out float4 v_CenterX : TEXCOORD0, - out float4 v_CenterY : TEXCOORD1, - out float4 v_IndexX : TEXCOORD2, - out float4 v_IndexY : TEXCOORD3) -{ - out_Position = float4(a_Vertex, 0.0, 1.0); - float4 offsets = float4(0.5, -0.5, 0.015625, -0.015625); - float4 zoomscale = float4(u_ZoomSettings[2][0], - u_ZoomSettings[2][1], - u_ZoomSettings[2][2], - u_ZoomSettings[2][3]); - float4 zoomtx = float4(u_ZoomSettings[0][0], - u_ZoomSettings[0][1], - u_ZoomSettings[0][2], - u_ZoomSettings[0][3]); - float4 zoomty = float4(u_ZoomSettings[1][0], - u_ZoomSettings[1][1], - u_ZoomSettings[1][2], - u_ZoomSettings[1][3]); - v_CenterX = zoomscale * a_TexCoord.x + zoomtx - + offsets.xyxy * u_TexelSize.x; - v_CenterY = zoomscale * a_TexCoord.y - zoomty - + offsets.xyyx * u_TexelSize.y; - v_IndexX = v_CenterX * u_ScreenSize.z - offsets.zwzw; - v_IndexY = v_CenterY * u_ScreenSize.w - offsets.zwwz; -} - -[frag.hlsl] - -void main(in float4 v_CenterX : TEXCOORD0, - in float4 v_CenterY : TEXCOORD1, - in float4 v_IndexX : TEXCOORD2, - in float4 v_IndexY : TEXCOORD3, - uniform float4 u_TexelSize, - uniform sampler2D u_Texture, - out float4 out_FragColor : COLOR) -{ - float4 v05 = float4(0.5, 0.5, 0.5, 0.5); - float4 rx, ry, t0, dx, dy, dd; - rx = u_TexelSize.x + u_TexelSize.z * floor(v_IndexX); - ry = u_TexelSize.y + u_TexelSize.w * floor(v_IndexY); - t0 = step(abs(rx - v05), v05) * step(abs(ry - v05), v05); - dx = rx - v_CenterX; - dy = ry - v_CenterY; - dd = t0 / (0.000001 + (dx * dx) + (dy * dy)); - ry = ry * 0.25 + float4(0.0, 0.25, 0.5, 0.75); - float2 t1 = step(dd.xz, dd.yw); - float4 ret = lerp(float4(rx.xz, ry.xz), - float4(rx.yw, ry.yw), t1.xyxy); - dd.xy = lerp(dd.xz, dd.yw, t1); - float t2 = step(dd.x, dd.y); - ret.xy = lerp(ret.xz, ret.yw, t2); - out_FragColor = tex2D(u_Texture, ret.xy); -} - diff --git a/tutorial/11_fractal.vcxproj b/tutorial/11_fractal.vcxproj deleted file mode 100644 index 63370a0e..00000000 --- a/tutorial/11_fractal.vcxproj +++ /dev/null @@ -1,79 +0,0 @@ - - - - - Debug - ORBIS - - - Debug - PS3 - - - Debug - Win32 - - - Debug - x64 - - - Debug - Xbox 360 - - - Release - ORBIS - - - Release - PS3 - - - Release - Win32 - - - Release - x64 - - - Release - Xbox 360 - - - - - - - - - - - {9e62f2fe-3408-4eae-8238-fd84238ceeda} - - - {83d3b207-c601-4025-8f41-01dedc354661} - - - - {6bf81b39-edc2-4227-9992-c2d8abea95af} - Application - Win32Proj - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tutorial/12_distance.lolfx b/tutorial/12_distance.lolfx deleted file mode 100644 index d47db363..00000000 --- a/tutorial/12_distance.lolfx +++ /dev/null @@ -1,94 +0,0 @@ -[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 deleted file mode 100644 index 78ca4d6d..00000000 --- a/tutorial/12_texture_to_screen.lolfx +++ /dev/null @@ -1,92 +0,0 @@ -[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; - -vec3 rand_color(float t) -{ - return vec3(0.5 + 0.5 * sin(t * 19.0 + 17.0), - 0.5 + 0.5 * sin(t * 24.0 + 23.0), - 0.5 + 0.5 * sin(t * 37.0 + 12.0)); -} - -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(rand_color(newg), 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] - -float3 rand_color(float t) -{ - return float3(0.5 + 0.5 * sin(t * 9.0 + 3.0), - 0.5 + 0.5 * sin(t * 4.0 + 1.0), - 0.5 + 0.5 * sin(t * 7.0 + 2.0)); -} - -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 deleted file mode 100644 index 08548943..00000000 --- a/tutorial/12_voronoi.cpp +++ /dev/null @@ -1,405 +0,0 @@ -// -// Lol Engine - Framebuffer Object tutorial -// -// Copyright: (c) 2013-2013 Sam Hocevar -// (c) 2013-2013 Benjamin "Touky" Huet -// 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 -{ - SrcVoronoiFbo, - VoronoiFbo, - DistanceVoronoiFbo, - DistanceFbo, - - MaxFboType -}; - -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_time = .0f; - m_timer = -1.0f; - mode = 0; - } - - 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 < MaxFboType; ++i) - { - m_fbos.Push(new Framebuffer(Video::GetSize()), 0, Array(), Array() ); - - if (i == SrcVoronoiFbo) - { - 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 == VoronoiFbo) - { - 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 == DistanceVoronoiFbo) - { - m_fbos[i].m2 = Shader::Create(LOLFX_RESOURCE_NAME(12_voronoi_distance)); - } - else if (i == DistanceFbo) - { - m_fbos[i].m2 = Shader::Create(LOLFX_RESOURCE_NAME(12_distance)); - } - - m_fbos.Last().m1->Bind(); - { - RenderContext rc; - rc.SetClearColor(vec4(0.f, 0.f, 0.f, 1.f)); - rc.SetClearDepth(1.f); - g_renderer->Clear(ClearMask::Color | ClearMask::Depth); - } - m_fbos.Last().m1->Unbind(); - } - - temp_buffer = new Framebuffer(Video::GetSize()); - temp_buffer->Bind(); - { - RenderContext rc; - rc.SetClearColor(vec4(0.f, 0.f, 0.f, 1.f)); - rc.SetClearDepth(1.f); - g_renderer->Clear(ClearMask::Color | ClearMask::Depth); - } - temp_buffer->Unbind(); - - m_ready = true; - /* FIXME: this object never cleans up */ - - //SRC SETUP - m_cur_fbo = VoronoiFbo; - } - - { - //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 = SrcVoronoiFbo; - else if (Input::WasReleased(Key::F2)) - m_cur_fbo = VoronoiFbo; - else if (Input::WasReleased(Key::F3)) - { - voronoi_points.Empty(); - if (mode == 0) - { - 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)) - //vec2(0.f) - ); - mode = 1; - } - else - { - mode = 0; - } - } - } - - if (mode == 0) - { - voronoi_points.Empty(); - int maxi = 6; - for (int i = 0; i < maxi; ++i) - { - voronoi_points.Push(vec3(256.f) + 196.f * vec3(lol::cos(m_time + i * 2.f * F_PI / maxi), lol::sin(m_time + i * 2.f * F_PI / maxi), .0f), vec2(.0f)); - voronoi_points.Push(vec3(256.f) + 128.f * vec3(lol::cos(-m_time + i * 2.f * F_PI / maxi), lol::sin(-m_time + i * 2.f * F_PI / maxi), .0f), vec2(.0f)); - voronoi_points.Push(vec3(256.f) + 64.f * vec3(lol::cos(m_time + i * 2.f * F_PI / maxi), lol::sin(m_time + i * 2.f * F_PI / maxi), .0f), vec2(.0f)); - voronoi_points.Push(vec3(256.f) + 32.f * vec3(lol::cos(-m_time + i * 2.f * F_PI / maxi), lol::sin(-m_time + i * 2.f * F_PI / maxi), .0f), vec2(.0f)); - } - voronoi_points.Push(vec3(256.f), vec2(.0f)); - } - - temp_buffer->Bind(); - { - RenderContext rc; - rc.SetClearColor(vec4(0.f, 0.f, 0.f, 1.f)); - rc.SetClearDepth(1.f); - g_renderer->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 = SrcVoronoiFbo; - - m_fbos[f].m1->Bind(); - { - RenderContext rc; - rc.SetClearColor(vec4(0.f, 0.f, 0.f, 1.f)); - rc.SetClearDepth(1.f); - g_renderer->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 */ - g_renderer->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; - } - } - - g_renderer->Clear(ClearMask::Color | ClearMask::Depth); - - //FRAME BUFFER DRAW - m_timer -= seconds; - if (m_timer < .0f && m_cur_fbo != SrcVoronoiFbo) - { - //m_timer = 1.0f; - m_fbos[m_cur_fbo].m1->Bind(); - { - RenderContext rc; - rc.SetClearColor(vec4(0.f, 0.f, 0.f, 1.f)); - rc.SetClearDepth(1.f); - g_renderer->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[SrcVoronoiFbo].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 */ - g_renderer->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 == VoronoiFbo) - { - 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 mode; - 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 deleted file mode 100644 index 8ae45a11..00000000 --- a/tutorial/12_voronoi.lolfx +++ /dev/null @@ -1,93 +0,0 @@ -//----------------------------------------------------------------------------- -//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 deleted file mode 100644 index 19320898..00000000 --- a/tutorial/12_voronoi.vcxproj +++ /dev/null @@ -1,83 +0,0 @@ - - - - - Debug - ORBIS - - - Debug - PS3 - - - Debug - Win32 - - - Debug - x64 - - - Debug - Xbox 360 - - - Release - ORBIS - - - 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 deleted file mode 100644 index d47db363..00000000 --- a/tutorial/12_voronoi_distance.lolfx +++ /dev/null @@ -1,94 +0,0 @@ -[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 deleted file mode 100644 index 3712ace8..00000000 --- a/tutorial/12_voronoi_setup.lolfx +++ /dev/null @@ -1,70 +0,0 @@ -//----------------------------------------------------------------------------- -//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 deleted file mode 100644 index dfb0a477..00000000 --- a/tutorial/Makefile.am +++ /dev/null @@ -1,49 +0,0 @@ - -include $(top_srcdir)/build/autotools/common.am - -noinst_PROGRAMS = 01_triangle 02_cube 03_noise 04_texture 05_easymesh \ - 06_sprite 08_fbo 11_fractal \ - 12_voronoi - -01_triangle_SOURCES = 01_triangle.cpp 01_triangle.lolfx -01_triangle_CPPFLAGS = $(AM_CPPFLAGS) -01_triangle_DEPENDENCIES = @LOL_DEPS@ - -02_cube_SOURCES = 02_cube.cpp 02_cube.lolfx -02_cube_CPPFLAGS = $(AM_CPPFLAGS) -02_cube_DEPENDENCIES = @LOL_DEPS@ - -03_noise_SOURCES = 03_noise.cpp 03_noise.lolfx -03_noise_CPPFLAGS = $(AM_CPPFLAGS) -03_noise_DEPENDENCIES = @LOL_DEPS@ - -04_texture_SOURCES = 04_texture.cpp 04_texture.lolfx -04_texture_CPPFLAGS = $(AM_CPPFLAGS) -04_texture_DEPENDENCIES = @LOL_DEPS@ - -05_easymesh_SOURCES = 05_easymesh.cpp -05_easymesh_CPPFLAGS = $(AM_CPPFLAGS) -05_easymesh_DEPENDENCIES = @LOL_DEPS@ - -06_sprite_SOURCES = 06_sprite.cpp 06_sprite.png -06_sprite_CPPFLAGS = $(AM_CPPFLAGS) -06_sprite_DEPENDENCIES = @LOL_DEPS@ -06_sprite_LDFLAGS = $(AM_LDFLAGS) -if USE_EMSCRIPTEN -06_sprite_LDFLAGS += --preload-file 06_sprite.png -endif - -08_fbo_SOURCES = 08_fbo.cpp 08_fbo.lolfx -08_fbo_CPPFLAGS = $(AM_CPPFLAGS) -08_fbo_DEPENDENCIES = @LOL_DEPS@ - -11_fractal_SOURCES = 11_fractal.cpp 11_fractal.lolfx -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@ -