From 2149187abd255a2b1733a0ab4911e1f9c58fabdf Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Sat, 8 Oct 2016 20:54:13 +0200 Subject: [PATCH] tutorial: fix tutorial 11 (fractal) Input was broken, as well as palette generation, and even texture upload. Should be all good now. --- doc/tutorial/11_fractal.cpp | 67 ++++++++++------- doc/tutorial/11_fractal.lolfx | 135 +++++++++------------------------- 2 files changed, 75 insertions(+), 127 deletions(-) diff --git a/doc/tutorial/11_fractal.cpp b/doc/tutorial/11_fractal.cpp index c8206f23..3c79b289 100644 --- a/doc/tutorial/11_fractal.cpp +++ b/doc/tutorial/11_fractal.cpp @@ -1,7 +1,7 @@ // // Lol Engine — Fractal tutorial // -// Copyright © 2011—2015 Sam Hocevar +// Copyright © 2011—2016 Sam Hocevar // // Lol Engine is free software. It comes without any warranty, to // the extent permitted by applicable law. You can redistribute it @@ -38,6 +38,13 @@ public: m_texel_settings = vec4(1.0, 1.0, 2.0, 2.0) / (vec4)m_size.xyxy; m_screen_settings = vec4(1.0, 1.0, 0.5, 0.5) * (vec4)m_size.xyxy; + m_controller = new Controller("Default"); + m_profile << InputProfile::MouseKey(0, "Left") + << InputProfile::MouseKey(1, "Right") + << InputProfile::MouseKey(2, "Middle"); + m_controller->Init(m_profile); + m_mouse = InputDevice::GetMouse(); + /* 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__ @@ -74,21 +81,19 @@ public: { 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; + vec3 hsv(lol::fmod(i * 0.002f, 1.f), + 0.4 * lol::sin(f * 0.27 + 2.0) + 0.4, + 0.4 * lol::sin(f * 0.21 - 2.6) + 0.4); + vec3 rgb = Color::HSVToRGB(hsv); if (f < 7.0) { - f = f < 1.0 ? 0.0 : (f - 1.0) / 6.0; - r *= f; - g *= f; - b *= f; + rgb *= f < 1.0 ? 0.0 : (f - 1.0) / 6.0; } - uint8_t red = (uint8_t)r * 256; - uint8_t green = (uint8_t)g * 256; - uint8_t blue = (uint8_t)b * 256; + uint8_t red = (uint8_t)(rgb.r * 256); + uint8_t green = (uint8_t)(rgb.g * 256); + uint8_t blue = (uint8_t)(rgb.b * 256); #if defined __native_client__ m_palette.push(u8vec4(red, green, blue, 255)); #else @@ -113,7 +118,6 @@ public: m_position = vec3::zero; m_aabb.aa = m_position; m_aabb.bb = vec3((vec2)m_window_size, 0); - //Input::TrackMouse(this); #if LOL_FEATURE_THREADS /* Spawn worker threads and wait for their readiness. */ @@ -163,7 +167,7 @@ public: { WorldEntity::TickGame(seconds); - ivec2 mousepos = ivec2::zero; /* FIXME: input */ + ivec2 mousepos = m_mouse->GetCursorPixel(0); int prev_frame = (m_frame + 4) % 4; m_frame = (m_frame + 1) % 4; @@ -171,9 +175,7 @@ public: rcmplx worldmouse = m_center + rcmplx(ScreenToWorldOffset((vec2)mousepos)); - uint32_t buttons = 0; - //uint32_t buttons = Input::GetMouseButtons(); - if (buttons & 0x2) + if (m_controller->IsKeyPressed(2)) { if (!m_drag) { @@ -201,9 +203,11 @@ public: } } - if (buttons & 0x5 && mousepos.x != -1) + bool hold_right = m_controller->IsKeyPressed(0); + bool hold_left = m_controller->IsKeyPressed(1); + if ((hold_right || hold_left) && mousepos.x != -1) { - double zoom = (buttons & 0x1) ? -0.5 : 0.5; + double zoom = hold_right ? -0.5 : 0.5; m_zoom_speed += zoom * seconds; if (m_zoom_speed / zoom > 5e-3f) m_zoom_speed = zoom * 5e-3f; @@ -308,7 +312,7 @@ public: } #if LOL_FEATURE_THREADS - void DoWorkHelper(thread *inst) + void DoWorkHelper(thread *) { m_spawnqueue.push(0); for ( ; ; ) @@ -332,8 +336,8 @@ public: 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); + u8vec4 *pixelstart = &m_pixels[0] + + m_size.x * (m_size.y / 4 * m_frame + line / 4); dcmplx c = (dcmplx)m_center; @@ -404,11 +408,11 @@ public: + 2.024664188044341212602376988171727038739) * k - 1.674876738008591047163498125918330313237; - *m_pixelstart++ = m_palette[(int)(f * PALETTE_STEP)]; + *pixelstart++ = m_palette[(int)(f * PALETTE_STEP)]; } else { - *m_pixelstart++ = u8vec4(0, 0, 0, 255); + *pixelstart++ = u8vec4(0, 0, 0, 255); } } } @@ -452,9 +456,10 @@ public: m_vertexattrib = m_shader->GetAttribLocation(VertexUsage::Position, 0); m_texattrib = m_shader->GetAttribLocation(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_texuni = m_shader->GetUniformLocation("u_texture"); + m_texeluni = m_shader->GetUniformLocation("u_texel_size"); + m_screenuni = m_shader->GetUniformLocation("u_screen_size"); + m_zoomuni = m_shader->GetUniformLocation("u_zoom_settings"); m_vdecl = new VertexDeclaration(VertexStream(VertexUsage::Position), @@ -491,6 +496,7 @@ public: } m_shader->Bind(); + m_shader->SetUniform(m_texuni, m_texture->GetTextureUniform(), 0); m_shader->SetUniform(m_texeluni, m_texel_settings); m_shader->SetUniform(m_screenuni, m_screen_settings); m_shader->SetUniform(m_zoomuni, m_zoom_settings); @@ -515,7 +521,7 @@ private: Shader *m_shader; ShaderAttrib m_vertexattrib, m_texattrib; - ShaderUniform m_texeluni, m_screenuni, m_zoomuni; + ShaderUniform m_texuni, m_texeluni, m_screenuni, m_zoomuni; VertexDeclaration *m_vdecl; VertexBuffer *m_vbo, *m_tbo; @@ -531,6 +537,11 @@ private: vec4 m_texel_settings, m_screen_settings; mat4 m_zoom_settings; + // Input support + InputDevice *m_mouse; + Controller *m_controller; + InputProfile m_profile; + #if LOL_FEATURE_THREADS /* Worker threads */ thread *m_threads[MAX_THREADS]; @@ -548,7 +559,7 @@ int main(int argc, char **argv) ivec2 window_size(640, 480); sys::init(argc, argv); - Application app("Tutorial 3: Fractal", window_size, 60.0f); + Application app("Tutorial 11: Fractal", window_size, 60.0f); new DebugFps(5, 5); new Fractal(window_size); diff --git a/doc/tutorial/11_fractal.lolfx b/doc/tutorial/11_fractal.lolfx index 4e869841..f707109b 100644 --- a/doc/tutorial/11_fractal.lolfx +++ b/doc/tutorial/11_fractal.lolfx @@ -1,15 +1,15 @@ [vert.glsl] -#version 120 +#version 130 -uniform mat4 u_ZoomSettings; -uniform vec4 u_TexelSize; -uniform vec4 u_ScreenSize; +uniform mat4 u_zoom_settings; +uniform vec4 u_texel_size; +uniform vec4 u_screen_size; attribute vec2 in_TexCoord; attribute vec2 in_Position; -varying vec4 v_CenterX, v_CenterY, v_IndexX, v_IndexY; +out vec4 v_center_x, v_center_y, v_index_x, v_index_y; void main(void) { @@ -21,55 +21,55 @@ void main(void) * 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 * in_TexCoord.x + zoomtx - + offsets.xyxy * u_TexelSize.x; - v_CenterY = zoomscale * in_TexCoord.y - zoomty - + offsets.xyyx * u_TexelSize.y; + vec4 zoomscale = vec4(u_zoom_settings[0][2], + u_zoom_settings[1][2], + u_zoom_settings[2][2], + u_zoom_settings[3][2]); + vec4 zoomtx = vec4(u_zoom_settings[0][0], + u_zoom_settings[1][0], + u_zoom_settings[2][0], + u_zoom_settings[3][0]); + vec4 zoomty = vec4(u_zoom_settings[0][1], + u_zoom_settings[1][1], + u_zoom_settings[2][1], + u_zoom_settings[3][1]); + v_center_x = zoomscale * in_TexCoord.x + zoomtx + + offsets.xyxy * u_texel_size.x; + v_center_y = zoomscale * in_TexCoord.y - zoomty + + offsets.xyyx * u_texel_size.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; + v_index_x = v_center_x * u_screen_size.z - offsets.zwzw; + v_index_y = v_center_y * u_screen_size.w - offsets.zwwz; } [frag.glsl] -#version 120 +#version 130 #if defined GL_ES precision highp float; #endif -uniform vec4 u_TexelSize; -uniform sampler2D u_Texture; +uniform vec4 u_texel_size; +uniform sampler2D u_texture; -varying vec4 v_CenterX, v_CenterY, v_IndexX, v_IndexY; +in vec4 v_center_x, v_center_y, v_index_x, v_index_y; 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); + rx = u_texel_size.x + u_texel_size.z * floor(v_index_x); + ry = u_texel_size.y + u_texel_size.w * floor(v_index_y); /* 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; + dx = rx - v_center_x; + dy = ry - v_center_y; #if 0 vec4 dd = t0 * (abs(dx) + abs(dy)); vec4 dd = t0 / (0.001 + sqrt((dx * dx) + (dy * dy))); @@ -115,78 +115,15 @@ void main(void) ret.xy = ret.xz * t2.yy + ret.yw * t2.xx; # endif /* Nearest neighbour */ - gl_FragColor = texture2D(u_Texture, ret.xy); + 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)); + 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); -} -