From f1873abed7427f52a50313fc2b7c3e9d8ab426ad Mon Sep 17 00:00:00 2001 From: yaw-man Date: Sat, 14 Jan 2023 16:03:57 -0400 Subject: [PATCH] Render wave via shader. --- conf.lua | 2 +- main.lua | 18 -------------- wave.lua | 72 ++++++++++++++++++++++++++++++++++++++++++++------------ 3 files changed, 58 insertions(+), 34 deletions(-) diff --git a/conf.lua b/conf.lua index 5428891..5c93839 100644 --- a/conf.lua +++ b/conf.lua @@ -4,7 +4,7 @@ function love.conf( t ) t.modules.touch = false t.modules.video = false - t.window.title = "By Your Own Beat" + t.window.title = "Your Own Drum" t.window.width = 600 t.window.height = 600 t.window.resizable = true diff --git a/main.lua b/main.lua index 9965a30..9039522 100644 --- a/main.lua +++ b/main.lua @@ -29,24 +29,6 @@ state = { currentBeat = 1, startTime = 0.0, - wave = { - x = { 1.0, 0.0, -0.5, 0.2, 0.4, 0.8, 0.3, 0.9, -0.4, 0.8, 0.5, 0.1, -0.9 }, - dx = { 1.0, 0.0, -0.5, 0.2, 0.4, 0.8, 0.3, 0.9, -0.4, 0.8, 0.5, 0.1, -0.9 }, - ddx = { 1.0, 0.0, -0.5, 0.2, 0.4, 0.8, 0.3, 0.9, -0.4, 0.8, 0.5, 0.1, -0.9 }, - X = function(th) end, - DX = function(th) end, - DDX = function(th) end, - Draw = function() end, - AddImpulse = function( th, size ) end, - - ImpactPoint = function( xi, yi, xf, yf ) - local impact = { r = 0, th = 0, t = 0, x = 0, y = 0, dx = 0, dy = 0 } - return impact - end, - - Update = function( dt ) end, - }, - beat = { t = nil, mu = nil, diff --git a/wave.lua b/wave.lua index 51349e6..d493deb 100644 --- a/wave.lua +++ b/wave.lua @@ -1,6 +1,6 @@ --Render and simulate 1D wave equation. local love = love -local N = 15 +local N = 33 local SOUNDSPEED = 0.5 local IMPULSESIZE = 20 local DAMPING = 0.01 @@ -16,6 +16,41 @@ local Derivative local SecondDerivative local DFT +local shader = love.graphics.newShader([[ + + uniform float re[33]; + uniform float im[33]; + + //Slow IDFT + float r( float x ) +{ + float r = re[0]; + + for( int k = 1; k < 17; k++ ) + { + float c = cos( x * float( k ) ); + float s = sin( x * float( k ) ); + r += + + c * re[k] + - s * im[k] + + c * re[33 - k] + + s * im[33 - k]; + } + + return r; +} + + vec4 effect(vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords) +{ + vec2 p = (3.0 * screen_coords - 1.5 * love_ScreenSize.xy ) / love_ScreenSize.y; + p.y = -p.y; + + float r = r( atan(p.y, p.x) ) - length( p ); + + return vec4(color.x, color.y, color.z, (r > -0.01)) ; +} + ]]) + --Calculate discrete fourier transform of radius function. do @@ -112,7 +147,7 @@ end --Apply bandlimited impulse to wave. local function OnImpact( impact ) - + local r = cur.radii local theta = impact.th local magnitude = IMPULSESIZE * impact.speed @@ -120,7 +155,7 @@ local function OnImpact( impact ) for i = 0, N - 1 do r[ i + 1 ] = r[ i + 1 ] + dt * magnitude * AliasedSinc( theta, 2.0 * math.pi * i / N ) end - + --We've updated the positions, now we need to take a DFT --in order to get the bandlimited second spatial derivative. cur:DFT() @@ -161,10 +196,16 @@ local function Draw() -- Blue circle. love.graphics.setColor( 91 / 255, 206 / 255, 250 / 255 ) - love.graphics.circle("fill", 0, 0, 1) + + shader:send( "re", unpack( cur.dftre ) ) + shader:send( "im", unpack( cur.dftim ) ) + love.graphics.setShader( shader ) + love.graphics.circle("fill", 0, 0, 1.5) local t = love.timer.getTime() + love.graphics.setShader( ) -- Debug dots. + --[[ for i = 1, N do local th = ( i - 1 ) * 2.0 * math.pi / N @@ -172,9 +213,9 @@ local function Draw() love.graphics.setCanvas() love.graphics.setColor( 0, 0, 0, 0.5 ) love.graphics.circle( "fill", cx, cy, 0.02 ) - - + + for k = 0.1, 1.0, 0.1 do --Interpolant. love.graphics.setColor( 1.0, 0, 0, 0.7 ) @@ -183,9 +224,9 @@ local function Draw() local x, y = r * math.cos( th ), r * math.sin( th ) love.graphics.circle( "fill", x, y, 0.01 ) --love.graphics.circle( "fill", th / math.pi - 1.0 , r, 0.01) - + --First derivative. - --[[love.graphics.setColor( 0, 1.0, 0, 0.7 ) + --love.graphics.setColor( 0, 1.0, 0, 0.7 ) r = cur:Derivative( th ) x, y = r * math.cos( th ), r * math.sin( th ) --love.graphics.circle( "fill", x, y, 0.01 ) @@ -199,15 +240,16 @@ local function Draw() love.graphics.circle( "fill", th / math.pi - 1.0, r, 0.01) love.graphics.setColor( 1.0, 1.0, 1.0, 0.2 ) - love.graphics.circle( "fill", 2.0 * ( i + k ) / N - 1.2, 0, 0.02 )]] - + love.graphics.circle( "fill", 2.0 * ( i + k ) / N - 1.2, 0, 0.02 ) + end end love.graphics.setColor( 1, 1, 1, 0.5 ) local r = cur:Interpolate( t ) local x, y = r * math.cos( t ), r * math.sin( t ) - love.graphics.circle( "fill", x, y, 0.02 ) + love.graphics.circle( "fill", x, y, 0.02 )]] + end @@ -219,7 +261,7 @@ local function Update() old[name][i] = t[i] end end - + --Deep copy of new state to current state. for name, t in pairs( new ) do for i = 1, N do @@ -229,16 +271,16 @@ local function Update() end Integrate = function( step ) - + for i = 1, N do local rxx = cur:SecondDerivative( math.pi * 2.0 * ( i - 1 ) / N ) local r = ( 1.0 - DAMPING ) * ( 2.0 * cur.radii[i] - old.radii[i] + step * step * SOUNDSPEED * rxx ) --Verlet - + DAMPING --Damping: oscillate toward 1. + + DAMPING --Damping: oscillate toward 1. if r > 1.5 then r = 1.5 end if r < 0.5 then r = 0.5 end new.radii[i] = r end - + new:DFT( ) end