Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Fun64 : A 2d starfield running in a shader.
local wstr=require("wetgenes.string")
hardware,main=system.configurator({
mode="fun64", -- select the standard 320x240 screen using the swanky32 palette.
graphics=function() return graphics end,
update=function() update() end, -- called repeatedly to update+draw
})
-- debug text dump
local ls=function(t) print(require("wetgenes.string").dump(t)) end
-- define all graphics in this global, we will convert and upload to tiles at setup
-- although you can change tiles during a game, we try and only upload graphics
-- during initial setup so we have a nice looking sprite sheet to be edited by artists
graphics={
{0x0000,"_font",0x0340}, -- pre-allocate the 4x8 and 8x8 font area
}
-----------------------------------------------------------------------------
--[[#update
update()
Update and draw loop, called every frame.
]]
-----------------------------------------------------------------------------
update=function()
local ccopper=system.components.copper
local cmap=system.components.map
if not setup_done then
ccopper.shader_name="fun_copper_noise"
ccopper.shader_uniforms.scroll={0,0,0,0}
it={}
it.vx=0.25
it.vy=1
setup_done=true
end
local up=ups(0) -- get all connected controls, keyboard or gamepad
if up.button("up") then it.vy=it.vy-(1/16) end
if up.button("down") then it.vy=it.vy+(1/16) end
if up.button("left") then it.vx=it.vx+(1/16) end
if up.button("right") then it.vx=it.vx-(1/16) end
if up.button("fire_set") then it.vx=0 it.vy=0 end
ccopper.shader_uniforms.scroll[1]=ccopper.shader_uniforms.scroll[1]+it.vx
ccopper.shader_uniforms.scroll[2]=ccopper.shader_uniforms.scroll[2]+it.vy
local tx=wstr.trim([[
Use up/down/left/right to adjust the speed of the scrolling star field.
Hit fire to reset the momentum.
]])
local tl=wstr.smart_wrap(tx,cmap.text_hx-4)
for i=1,#tl do
local t=tl[i]
cmap.text_print(t,2,1+i,28,0)
end
cmap.dirty(true)
end
-- Include GLSL code inside a comment
-- The GLSL handler will pickup the #shader directive and use all the code following it until the next #shader directive.
--[=[
#shader "fun_copper_noise"
#ifdef VERTEX_SHADER
uniform mat4 modelview;
uniform mat4 projection;
uniform vec4 color;
attribute vec3 a_vertex;
attribute vec2 a_texcoord;
varying vec2 v_texcoord;
varying vec4 v_color;
void main()
{
gl_Position = projection * vec4(a_vertex, 1.0);
v_texcoord=a_texcoord;
v_color=color;
}
#endif
#ifdef FRAGMENT_SHADER
#if defined(GL_FRAGMENT_PRECISION_HIGH)
precision highp float; /* really need better numbers if possible */
#endif
varying vec2 v_texcoord;
varying vec4 v_color;
uniform vec4 scroll;
uniform vec3 iResolution; // viewport resolution (in pixels)
uniform float iGlobalTime; // shader playback time (in seconds)
void mainImage( out vec4 fragColor, in vec2 fragCoord );
void main(void)
{
vec2 uv=v_texcoord;
uv.y=iResolution.y-uv.y;
mainImage(gl_FragColor,uv);
}
// Cellular noise ("Worley noise") in 3D in GLSL.
// Copyright (c) Stefan Gustavson 2011-04-19. All rights reserved.
// This code is released under the conditions of the MIT license.
// See LICENSE file for details.
// https://github.com/stegu/webgl-noise
// Modulo 289 without a division (only multiplications)
vec3 mod289(vec3 x) {
return x - floor(x * (1.0 / 289.0)) * 289.0;
}
// Modulo 7 without a division
vec3 mod7(vec3 x) {
return x - floor(x * (1.0 / 7.0)) * 7.0;
}
// Permutation polynomial: (34x^2 + x) mod 289
vec3 permute(vec3 x) {
return mod289((34.0 * x + 1.0) * x);
}
// Cellular noise, returning F1 and F2 in a vec2.
// 3x3x3 search region for good F2 everywhere, but a lot
// slower than the 2x2x2 version.
// The code below is a bit scary even to its author,
// but it has at least half decent performance on a
// modern GPU. In any case, it beats any software
// implementation of Worley noise hands down.
vec2 cellular(vec3 P) {
#define K 0.142857142857 // 1/7
#define Ko 0.428571428571 // 1/2-K/2
#define K2 0.020408163265306 // 1/(7*7)
#define Kz 0.166666666667 // 1/6
#define Kzo 0.416666666667 // 1/2-1/6*2
#define jitter 1.0 // smaller jitter gives more regular pattern
vec3 Pi = mod289(floor(P));
vec3 Pf = fract(P) - 0.5;
vec3 Pfx = Pf.x + vec3(1.0, 0.0, -1.0);
vec3 Pfy = Pf.y + vec3(1.0, 0.0, -1.0);
vec3 Pfz = Pf.z + vec3(1.0, 0.0, -1.0);
vec3 p = permute(Pi.x + vec3(-1.0, 0.0, 1.0));
vec3 p1 = permute(p + Pi.y - 1.0);
vec3 p2 = permute(p + Pi.y);
vec3 p3 = permute(p + Pi.y + 1.0);
vec3 p11 = permute(p1 + Pi.z - 1.0);
vec3 p12 = permute(p1 + Pi.z);
vec3 p13 = permute(p1 + Pi.z + 1.0);
vec3 p21 = permute(p2 + Pi.z - 1.0);
vec3 p22 = permute(p2 + Pi.z);
vec3 p23 = permute(p2 + Pi.z + 1.0);
vec3 p31 = permute(p3 + Pi.z - 1.0);
vec3 p32 = permute(p3 + Pi.z);
vec3 p33 = permute(p3 + Pi.z + 1.0);
vec3 ox11 = fract(p11*K) - Ko;
vec3 oy11 = mod7(floor(p11*K))*K - Ko;
vec3 oz11 = floor(p11*K2)*Kz - Kzo; // p11 < 289 guaranteed
vec3 ox12 = fract(p12*K) - Ko;
vec3 oy12 = mod7(floor(p12*K))*K - Ko;
vec3 oz12 = floor(p12*K2)*Kz - Kzo;
vec3 ox13 = fract(p13*K) - Ko;
vec3 oy13 = mod7(floor(p13*K))*K - Ko;
vec3 oz13 = floor(p13*K2)*Kz - Kzo;
vec3 ox21 = fract(p21*K) - Ko;
vec3 oy21 = mod7(floor(p21*K))*K - Ko;
vec3 oz21 = floor(p21*K2)*Kz - Kzo;
vec3 ox22 = fract(p22*K) - Ko;
vec3 oy22 = mod7(floor(p22*K))*K - Ko;
vec3 oz22 = floor(p22*K2)*Kz - Kzo;
vec3 ox23 = fract(p23*K) - Ko;
vec3 oy23 = mod7(floor(p23*K))*K - Ko;
vec3 oz23 = floor(p23*K2)*Kz - Kzo;
vec3 ox31 = fract(p31*K) - Ko;
vec3 oy31 = mod7(floor(p31*K))*K - Ko;
vec3 oz31 = floor(p31*K2)*Kz - Kzo;
vec3 ox32 = fract(p32*K) - Ko;
vec3 oy32 = mod7(floor(p32*K))*K - Ko;
vec3 oz32 = floor(p32*K2)*Kz - Kzo;
vec3 ox33 = fract(p33*K) - Ko;
vec3 oy33 = mod7(floor(p33*K))*K - Ko;
vec3 oz33 = floor(p33*K2)*Kz - Kzo;
vec3 dx11 = Pfx + jitter*ox11;
vec3 dy11 = Pfy.x + jitter*oy11;
vec3 dz11 = Pfz.x + jitter*oz11;
vec3 dx12 = Pfx + jitter*ox12;
vec3 dy12 = Pfy.x + jitter*oy12;
vec3 dz12 = Pfz.y + jitter*oz12;
vec3 dx13 = Pfx + jitter*ox13;
vec3 dy13 = Pfy.x + jitter*oy13;
vec3 dz13 = Pfz.z + jitter*oz13;
vec3 dx21 = Pfx + jitter*ox21;
vec3 dy21 = Pfy.y + jitter*oy21;
vec3 dz21 = Pfz.x + jitter*oz21;
vec3 dx22 = Pfx + jitter*ox22;
vec3 dy22 = Pfy.y + jitter*oy22;
vec3 dz22 = Pfz.y + jitter*oz22;
vec3 dx23 = Pfx + jitter*ox23;
vec3 dy23 = Pfy.y + jitter*oy23;
vec3 dz23 = Pfz.z + jitter*oz23;
vec3 dx31 = Pfx + jitter*ox31;
vec3 dy31 = Pfy.z + jitter*oy31;
vec3 dz31 = Pfz.x + jitter*oz31;
vec3 dx32 = Pfx + jitter*ox32;
vec3 dy32 = Pfy.z + jitter*oy32;
vec3 dz32 = Pfz.y + jitter*oz32;
vec3 dx33 = Pfx + jitter*ox33;
vec3 dy33 = Pfy.z + jitter*oy33;
vec3 dz33 = Pfz.z + jitter*oz33;
vec3 d11 = dx11 * dx11 + dy11 * dy11 + dz11 * dz11;
vec3 d12 = dx12 * dx12 + dy12 * dy12 + dz12 * dz12;
vec3 d13 = dx13 * dx13 + dy13 * dy13 + dz13 * dz13;
vec3 d21 = dx21 * dx21 + dy21 * dy21 + dz21 * dz21;
vec3 d22 = dx22 * dx22 + dy22 * dy22 + dz22 * dz22;
vec3 d23 = dx23 * dx23 + dy23 * dy23 + dz23 * dz23;
vec3 d31 = dx31 * dx31 + dy31 * dy31 + dz31 * dz31;
vec3 d32 = dx32 * dx32 + dy32 * dy32 + dz32 * dz32;
vec3 d33 = dx33 * dx33 + dy33 * dy33 + dz33 * dz33;
// Cheat and sort out only F1
vec3 d1 = min(min(d11,d12), d13);
vec3 d2 = min(min(d21,d22), d23);
vec3 d3 = min(min(d31,d32), d33);
vec3 d = min(min(d1,d2), d3);
d.x = min(min(d.x,d.y),d.z);
return vec2(sqrt(d.x)); // F1 duplicated, no F2 computed
}
// main
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
// plasma background
float f=cellular( vec3(fragCoord+(scroll.xy/32.0),iGlobalTime*3.0)/16.0 ).x;
vec3 color=vec3(
(0.0+ f*f*2.0)/32.0 ,
(0.0+ f*f*2.0)/32.0 ,
(2.0+ f *2.0)/32.0 );
for(float i=1.0;i<=4.0;i+=1.0 )
{
float speed=i/8.0;
f=1.0-cellular( vec3(fragCoord+vec2(i*19.0,0.0)+(scroll.xy*speed),i*19.0)/32.0 ).x;
f=pow(f,8.0-i);
f=max(f-0.75,0.0)*4.0;
color+=vec3(f)*vec3(0.5,0.5,1.0);
}
fragColor = vec4( color , 1.0 );
}
#endif
#shader
//]=]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment