From 3a975db66a3711f34e8b64bb27a8eaca79fdeca9 Mon Sep 17 00:00:00 2001 From: Alex Pickering Date: Sun, 1 Feb 2026 13:14:32 -0600 Subject: Initial commit --- src/shaders/lake.frag | 93 ++++++++++++ src/shaders/lake.moon | 29 ++++ src/shaders/lake.vert | 13 ++ src/shaders/land.frag | 100 +++++++++++++ src/shaders/land.vert | 26 ++++ src/shaders/palette.vert | 26 ++++ src/shaders/player.frag | 14 ++ src/shaders/player.vert | 23 +++ src/shaders/stars.frag | 5 + src/shaders/stars.lua | 75 ++++++++++ src/shaders/stars.vert | 30 ++++ src/shaders/world.frag | 29 ++++ src/shaders/world.frag.back | 20 +++ src/shaders/world.moon | 356 ++++++++++++++++++++++++++++++++++++++++++++ src/shaders/world.moon.back | 327 ++++++++++++++++++++++++++++++++++++++++ src/shaders/world.vert | 26 ++++ src/shaders/world.vert.back | 26 ++++ 17 files changed, 1218 insertions(+) create mode 100644 src/shaders/lake.frag create mode 100644 src/shaders/lake.moon create mode 100644 src/shaders/lake.vert create mode 100644 src/shaders/land.frag create mode 100644 src/shaders/land.vert create mode 100644 src/shaders/palette.vert create mode 100644 src/shaders/player.frag create mode 100644 src/shaders/player.vert create mode 100644 src/shaders/stars.frag create mode 100644 src/shaders/stars.lua create mode 100644 src/shaders/stars.vert create mode 100644 src/shaders/world.frag create mode 100644 src/shaders/world.frag.back create mode 100644 src/shaders/world.moon create mode 100644 src/shaders/world.moon.back create mode 100644 src/shaders/world.vert create mode 100644 src/shaders/world.vert.back (limited to 'src/shaders') diff --git a/src/shaders/lake.frag b/src/shaders/lake.frag new file mode 100644 index 0000000..c1c23f0 --- /dev/null +++ b/src/shaders/lake.frag @@ -0,0 +1,93 @@ +precision mediump float; +uniform vec4 black; +uniform vec4 outline; +uniform vec4 highlight; +uniform vec4 foreground; +uniform vec4 midground; +uniform vec4 shadow; +uniform vec4 background; +uniform vec4 lamp1; //vec3 position, float strength +uniform vec4 lamp2; +uniform vec4 lamp3; // max 3 lamps per shaded vertex +uniform vec4 lamp4; +uniform vec4 lamp5; +uniform vec4 lamp6; +uniform vec4 lamp7; +uniform vec4 lamp8; +uniform float streamer; // turn off the noise in the light +uniform float time; //used for noise +uniform sampler2D atlas; +uniform sampler2D previous; +uniform float nlamps; +varying vec2 worldxy; +varying vec2 norm; + +// Author @patriciogv - 2015 +float random (vec2 st) { + return fract( + sin( + dot(st.xy,vec2(12.9898,78.233)) + ) * + 43758.5453123 + ); +} + +// stolen from https://www.shadertoy.com/view/Msf3WH +float noise( in vec2 p ) +{ + const float K1 = 0.366025404; // (sqrt(3)-1)/2; + const float K2 = 0.211324865; // (3-sqrt(3))/6; + + vec2 i = floor( p + (p.x+p.y)*K1 ); + vec2 a = p - i + (i.x+i.y)*K2; + float m = step(a.y,a.x); + vec2 o = vec2(m,1.0-m); + vec2 b = a - o + K2; + vec2 c = a - 1.0 + 2.0*K2; + vec3 h = max( 0.5-vec3(dot(a,a), dot(b,b), dot(c,c) ), 0.0 ); + vec3 n = h*h*h*h*vec3( dot(a,random(i+0.0)), dot(b,random(i+o)), dot(c,random(i+1.0))); + return dot( n, vec3(70.0) ); +} + +void main() { + vec4 coord = gl_FragCoord + vec4(worldxy * 256., 0, 0); + /* + coord.x -= worldxy.x; + coord.y -= worldxy.y; + */ + //coord = coord / 1000.; + // calculate color at this pixel + vec4 normal = texture2D(atlas, norm); + float color = 0.; + vec4 lamp1_norm = lamp1 * 256.; + color += lamp1_norm.w - distance(lamp1_norm.xy - worldxy, coord.xy); + color = max(color,(lamp2.w * 256.) - distance((lamp2.xy * 256.) - worldxy, coord.xy)); + color = max(color,(lamp3.w * 256.) - distance((lamp3.xy * 256.) - worldxy, coord.xy)); + // divide to get a normalized color + //color /= (256. * max(max(lamp1.w, lamp2.w), lamp3.w)); + color /= 256. * 5.; + //color = sqrt(color / 2046.); + // Sett the normal texture under our lamplight + color = dot(vec4(color),normal) / 1.; + // make the colors fuzzy near the border (or don't if we're streaming) + float rng = random(vec2(coord.x, coord.y) + vec2(color, time)); + color -= (pow(rng / 1.3, 10. * color)) * streamer; + // add noise to the water + /* */ + if(color > 1.) + gl_FragColor = highlight * normal.a; + else if(color > 0.8) + gl_FragColor = foreground * normal.a; + else if(color > 0.6) + gl_FragColor = midground * normal.a; + else if(color > 0.4) + gl_FragColor = background * normal.a; + else if(color > 0.2) + gl_FragColor = shadow * normal.a; + else + gl_FragColor = black * normal.a; + /* + gl_FragColor = normal* vec4(color , color, color,1.); + */ + //gl_FragColor = normal* vec4(color , color / 10., color / 1024.,1.); +} diff --git a/src/shaders/lake.moon b/src/shaders/lake.moon new file mode 100644 index 0000000..bac2c42 --- /dev/null +++ b/src/shaders/lake.moon @@ -0,0 +1,29 @@ + +shader_shim = require("shader_shim") +win = require("window") +world = require("world") + +node = shader_shim.lake\append(am.bind({ + MV: mat4( + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + (-win.width / 2), (-win.height/2), 0, 1 + ), + P: mat4(1) + lake: am.vec3_array({}) + light1: am.vec4_array({}) + light2: am.vec4_array({}) + light3: am.vec4_array({}) + world_x: 0 + world_y: 0 + time: am.current_time() +}))\append(am.draw("triangles")) + +node\action((self) -> + self("bind").time = am.current_time! + self("bind").world_x = world.world_x + self("bind").world_y = world.world_y +) + +node diff --git a/src/shaders/lake.vert b/src/shaders/lake.vert new file mode 100644 index 0000000..2745cf9 --- /dev/null +++ b/src/shaders/lake.vert @@ -0,0 +1,13 @@ +precision highp float; +attribute vec3 lake; +attribute vec4 lamp1; //position, strength +attribute vec4 lamp2; +attribute vec4 lamp3; // max 3 lamps per shaded vertex +uniform float time; //used for noise +uniform float world_x; +uniform float world_y; +uniform mat4 MV; +uniform mat4 P; +void main() { + gl_Position = P * MV * vec4(lake.x - world_x, lake.y - world_y, 0., 1.0); +} diff --git a/src/shaders/land.frag b/src/shaders/land.frag new file mode 100644 index 0000000..1eb8d93 --- /dev/null +++ b/src/shaders/land.frag @@ -0,0 +1,100 @@ +precision mediump float; +uniform vec4 black; +uniform vec4 outline; +uniform vec4 highlight; +uniform vec4 foreground; +uniform vec4 midground; +uniform vec4 shadow; +uniform vec4 background; +uniform vec4 lamp1; //vec3 position, float strength +uniform vec4 lamp2; +uniform vec4 lamp3; // max 3 lamps per shaded vertex +uniform vec4 lamp4; +uniform vec4 lamp5; +uniform vec4 lamp6; +uniform vec4 lamp7; +uniform vec4 lamp8; +uniform float streamer; // turn off the noise in the light +uniform float time; //used for noise +uniform sampler2D atlas; +uniform float nlamps; +uniform float water; +varying vec2 worldxy; +varying vec2 norm; + +// Author @patriciogv - 2015 +float random (vec2 st) { + return fract( + sin( + dot(st.xy,vec2(12.9898,78.233)) + ) * + 43758.5453123 + ); +} + +// stolen from https://www.shadertoy.com/view/Msf3WH +vec2 hash( vec2 p ) // replace this by something better +{ + p = vec2( dot(p,vec2(127.1,311.7)), dot(p,vec2(269.5,183.3)) ); + return -1.0 + 2.0*fract(sin(p)*43758.5453123); +} +float noise( in vec2 p ) +{ + const float K1 = 0.366025404; // (sqrt(3)-1)/2; + const float K2 = 0.211324865; // (3-sqrt(3))/6; + + vec2 i = floor( p + (p.x+p.y)*K1 ); + vec2 a = p - i + (i.x+i.y)*K2; + float m = step(a.y,a.x); + vec2 o = vec2(m,1.0-m); + vec2 b = a - o + K2; + vec2 c = a - 1.0 + 2.0*K2; + vec3 h = max( 0.5-vec3(dot(a,a), dot(b,b), dot(c,c) ), 0.0 ); + vec3 n = h*h*h*h*vec3( dot(a,hash(i+0.0)), dot(b,hash(i+o)), dot(c,hash(i+1.0))); + return dot( n, vec3(70.0) ); +} + +void main() { + vec4 coord = gl_FragCoord + vec4(worldxy * 256., 0, 0); + /* + coord.x -= worldxy.x; + coord.y -= worldxy.y; + */ + //coord = coord / 1000.; + // calculate color at this pixel + vec4 normal = texture2D(atlas, norm); + float color = 0.; + vec4 lamp1_norm = lamp1 * 256.; + color += lamp1_norm.w - distance(lamp1_norm.xy - worldxy, coord.xy); + color = max(color,(lamp2.w * 256.) - distance((lamp2.xy * 256.) - worldxy, coord.xy)); + color = max(color,(lamp3.w * 256.) - distance((lamp3.xy * 256.) - worldxy, coord.xy)); + // divide to get a normalized color + //color /= (256. * max(max(lamp1.w, lamp2.w), lamp3.w)); + color /= 256. * 5.; + //color = sqrt(color / 2046.); + // see the normal texture under the color + color = dot(vec4(color),normal) / 1.; + // make the colors fuzzy near the border (or don't if we're streaming) + float rng = random(vec2(coord.x, coord.y) + vec2(color, time)); + color -= (pow(rng / 1.3, 10. * color)) * streamer; + // add noise to water + if(water > 1.) + color += (noise(coord.xy + vec2(time, time)) - 0.0) * 0.1; + /* */ + if(color > 1.) + gl_FragColor = highlight * normal.a; + else if(color > 0.8) + gl_FragColor = foreground * normal.a; + else if(color > 0.6) + gl_FragColor = midground * normal.a; + else if(color > 0.4) + gl_FragColor = background * normal.a; + else if(color > 0.2) + gl_FragColor = shadow * normal.a; + else + gl_FragColor = black * normal.a; + /* + gl_FragColor = normal* vec4(color , color, color,1.); + */ + //gl_FragColor = normal* vec4(color , color / 10., color / 1024.,1.); +} diff --git a/src/shaders/land.vert b/src/shaders/land.vert new file mode 100644 index 0000000..1c9b9f3 --- /dev/null +++ b/src/shaders/land.vert @@ -0,0 +1,26 @@ +precision highp float; +attribute vec3 land; +attribute vec2 landnormal; +uniform float rot; +uniform float world_x; +uniform float world_y; +uniform mat4 MV; +uniform mat4 P; +varying vec2 worldxy; +varying mat4 pre; +varying vec2 norm; +void main() { + norm = landnormal; + mat2 rotate = mat2( + cos(rot), -sin(rot), + sin(rot), cos(rot) + ); + worldxy = vec2(world_x, world_y); + pre = P * MV; + vec2 local = (land.xy - worldxy) * rotate; + float z_scale = 0.5; + // clamp so that everything becomes orthographic once we move away + float xoff = clamp(land.z * local.x * z_scale, -0.5, 0.5); + float yoff = clamp(land.z * local.y * z_scale, -0.5, 0.5); + gl_Position = P * MV * vec4(local.xy - vec2(xoff, yoff), land.z, 1.0); +} diff --git a/src/shaders/palette.vert b/src/shaders/palette.vert new file mode 100644 index 0000000..5937253 --- /dev/null +++ b/src/shaders/palette.vert @@ -0,0 +1,26 @@ +precision highp float; +attribute vec3 world; // position +attribute vec2 texuv; +attribute float r; // for round objects, 0 for non-round +varying vec2 textureuv; +varying float radius; +varying mat3 light1; +varying vec4 v_color; +uniform float world_x; +uniform float world_y; +uniform mat4 MV; +uniform mat4 P; +void main() { + v_color = vec4(world.xyz,1.); + vec2 vxy = vec2(world.x - world_x, world.y - world_y); + float z_scale = 0.5; + float max_parallax = 0.5; + float xoff = clamp(world.z * vxy.x * z_scale, -max_parallax, max_parallax); + float yoff = clamp(world.z * vxy.y * z_scale, -max_parallax, max_parallax); + textureuv=texuv; + //radius = r; + // if z > 0 then + // xoff = ceil(xoff, 0) + // add to the z coord so we don't intersect with the ui + gl_Position = P * MV * vec4(vxy.x + xoff, vxy.y + yoff, world.z, 1.0); +} diff --git a/src/shaders/player.frag b/src/shaders/player.frag new file mode 100644 index 0000000..5d329fa --- /dev/null +++ b/src/shaders/player.frag @@ -0,0 +1,14 @@ +precision mediump float; +varying vec2 textureuv; // uv +uniform sampler2D textures; +uniform sampler2D emissives; +uniform sampler2D normals; +varying mat3 light1; // position, color, intensity-fadetime-? +varying vec4 v_color; +void main() { + vec2 uv = textureuv; + //gl_FragColor = texture2D(textures,uv);// + vec4(uv.xy / 4.,0.,1.); + gl_FragColor = vec4(uv.xy / 1., 0., max(uv.x, uv.y)); + //gl_FragColor = texture2D(textures,screen_intersection.xy); + +} diff --git a/src/shaders/player.vert b/src/shaders/player.vert new file mode 100644 index 0000000..ce53bf5 --- /dev/null +++ b/src/shaders/player.vert @@ -0,0 +1,23 @@ +precision highp float; +attribute vec3 player; +attribute vec2 texuv; +varying vec2 textureuv; +attribute vec4 lamp1; //vec3 position, float strength +attribute vec4 lamp2; +attribute vec4 lamp3; // max 3 lamps per shaded player +uniform float time; //used for noise +uniform float world_x; +uniform float world_y; +uniform float dir; +uniform mat4 MV; +uniform mat4 P; +void main() { + textureuv=texuv; + mat2 rotate = mat2( + cos(dir), -sin(dir), + sin(dir), cos(dir) + ); + vec2 world = vec2(world_x, world_y); + vec2 local = (player.xy - world) * rotate; + gl_Position = P * MV * vec4(local.xy, -2, 1.0); +} diff --git a/src/shaders/stars.frag b/src/shaders/stars.frag new file mode 100644 index 0000000..d45917e --- /dev/null +++ b/src/shaders/stars.frag @@ -0,0 +1,5 @@ +precision mediump float; +uniform vec4 color; +void main() { + gl_FragColor = color; +} diff --git a/src/shaders/stars.lua b/src/shaders/stars.lua new file mode 100644 index 0000000..3e4138e --- /dev/null +++ b/src/shaders/stars.lua @@ -0,0 +1,75 @@ +local win = require("window") +local color = require("color") +local world = require("world") +local shim = require("shader_shim") +local numstars = 500 -- we might have as many as 4 over +local genned_stars = 0 +local period_x = 3 +local period_y = 3 +local stars = {} +local tries = 0 +aspect = win.width / win.height +while genned_stars < numstars and tries < 100000 do + local rngx = math.random() + local xpos = rngx * win.width --* (period_x - 1) + local rngy = math.random() + local ypos = rngy * win.height --* (period_y - 1) + local blinks = math.random() > 0.3 and (math.random() * 2 * math.pi) or 0 + --if math.distance(vec2(rngx,rngy), vec2(0.53,0.5)) > 0.5 then + local off = vec2(math.abs(rngx - 0.50) * aspect, math.abs(rngy-0.5)) + if math.length(off) > 0.5 then + stars[#stars+1] = vec3(xpos, ypos, blinks) + genned_stars = genned_stars + 1 + if xpos < win.width then + -- duplicate on the last screen + stars[#stars+1] = vec3(xpos + (win.width * (period_x-2)), ypos, blinks) + genned_stars = genned_stars + 1 + end + if ypos < win.height then + stars[#stars+1] = vec3(xpos, ypos + (win.height * (period_y-2)), blinks) + genned_stars = genned_stars + 1 + end + if xpos < win.width and ypos < win.height then + stars[#stars+1] = vec3(xpos + (win.width * (period_x-2)), ypos+(win.height * (period_y-2)),blinks) + genned_stars = genned_stars + 1 + end + end + tries = tries + 1 +end +assert(genned_stars == numstars, "Failed to generate stars") +local node = am.blend("premult") ^ shim.stars +^ am.bind({ + MV = mat4( + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + (-win.width / 2), (-win.height/2), 0, 1 + ), + color = color.am_color.highlight, + stars = am.vec3_array(stars), + world_x = am.current_time(), + world_x_period = (period_x - 2) * win.width, + world_y = am.current_time(), + world_y_period = (period_y - 2) * win.height, + time = am.current_time(), + lamp1 = vec3(0), + lamp2 = vec3(0), + lamp3 = vec3(0), + lamp4 = vec3(0), + lamp5 = vec3(0), + lamp6 = vec3(0), + lamp7 = vec3(0), + lamp8 = vec3(0) +}) +^ am.draw("points") +node:action(function(self) + self("bind").time = am.current_time() + self("bind").world_x = world.world_x + self("bind").world_y = world.world_y + local lamps = world.level.lamps_on_screen() + for i,v in pairs(lamps) do + print("Setting lamp", i, "to", v) + self("bind")["lamp" .. tostring(i)] = v + end +end) +return node diff --git a/src/shaders/stars.vert b/src/shaders/stars.vert new file mode 100644 index 0000000..8737482 --- /dev/null +++ b/src/shaders/stars.vert @@ -0,0 +1,30 @@ +precision highp float; +attribute vec3 stars; +uniform float time; +uniform float world_x; +uniform float world_y; +uniform float world_x_period; +uniform float world_y_period; +uniform vec4 lamp1; +uniform vec4 lamp2; +uniform vec4 lamp3; +uniform vec4 lamp4; +uniform vec4 lamp5; +uniform vec4 lamp6; +uniform vec4 lamp7; +uniform vec4 lamp8; +uniform mat4 MV; +uniform mat4 P; +void main() { + float world_x_off = mod(world_x, world_x_period); + float world_y_off = mod(world_y, world_y_period); + vec4 pos = P * MV * vec4(stars.x - world_x_off, stars.y - world_y_off, -0.1, 1.0); + gl_Position = pos; + float intensity = sin(stars.z + time) * cos(time) + 1.; + /* + if(distance(pos.xyz, lamp1.xyz) < 80.) + intensity = 0.; + */ + gl_PointSize = pow(intensity, 2.) * stars.z * 0.3; + //gl_PointSize = distance(pos.xyz, lamp1.xyz); +} diff --git a/src/shaders/world.frag b/src/shaders/world.frag new file mode 100644 index 0000000..9cc1bc9 --- /dev/null +++ b/src/shaders/world.frag @@ -0,0 +1,29 @@ +precision mediump float; +varying vec2 textureuv; // uv +varying float radius; +uniform sampler2D textures; +uniform sampler2D emissives; +uniform sampler2D normals; +varying mat3 light1; // position, color, intensity-fadetime-? +uniform float time; +varying vec4 v_color; +void main() { + + vec2 uv = textureuv; + //vec2 uv = gl_FragCoord.xy; + //vec3 view_origin = vec3(0., 0., -3.); + //vec3 view_direction = vec3(uv, 3); + //vec3 screen_intersection = vec3(uv.x, uv.y, 0.); + vec4 raw = texture2D(textures,uv); + gl_FragColor = raw; + //gl_FragColor = texture2D(textures,uv);// + vec4(uv.xy / 4.,0.,1.); + //if(raw.r == 1.0 && raw.g == 1.0 && raw.b == 1.0){ + //gl_FragColor = vec4(0.9058, 0.9215, 0.7725, 1); + //} else if(raw.r == 0.0 && raw.g == 0.0 && raw.b == 0.0){ + //gl_FragColor = vec4(0.298, 0.267, 0.216, 1); + //} else { + //gl_FragColor = raw; + //} +} + //gl_FragColor = vec4(gl_FragCoord.z, gl_FragCoord.z, gl_FragCoord.z, 1.); + //gl_FragColor = texture2D(textures,screen_intersection.xy); diff --git a/src/shaders/world.frag.back b/src/shaders/world.frag.back new file mode 100644 index 0000000..15d7b27 --- /dev/null +++ b/src/shaders/world.frag.back @@ -0,0 +1,20 @@ +precision mediump float; +varying vec2 textureuv; // uv +varying float radius; +uniform sampler2D textures; +uniform sampler2D emissives; +uniform sampler2D normals; +varying mat3 light1; // position, color, intensity-fadetime-? +uniform float time; +varying vec4 v_color; +void main() { + + vec2 uv = textureuv; + //vec2 uv = gl_FragCoord.xy; + //vec3 view_origin = vec3(0., 0., -3.); + //vec3 view_direction = vec3(uv, 3); + //vec3 screen_intersection = vec3(uv.x, uv.y, 0.); + gl_FragColor = texture2D(textures,uv);// + vec4(uv.xy / 4.,0.,1.); + //gl_FragColor = texture2D(textures,screen_intersection.xy); + +} diff --git a/src/shaders/world.moon b/src/shaders/world.moon new file mode 100644 index 0000000..87dba90 --- /dev/null +++ b/src/shaders/world.moon @@ -0,0 +1,356 @@ +win = require("window") +color = require("color") +world = require("world") +sprites = require("sprites") +shader_shim = require("shader_shim") +hc = require("party.hc.init") +log = require("log") +assert(world.world_x, "No world_x" .. debug.traceback()) +-- Process the world into buffers to send to the shader +view_angle = math.pi / 4 +near_plane = 0.01 +far_plane = 100 +aspect = win.width / win.height +-- 2.5D model-view matrix: scale down and offset camera +s_mv = mat4( + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, -2, 1 +) +p_mv = math.perspective(math.rad(85), aspect, near_plane, far_plane) + +sd = sprites.floor +w1 = sprites.wall + +-- Each point needs: +-- vec3 position (x,y,z) +-- vec2 (u,v) +up_down_hall = (x,y) -> + r = { + --floor + vec3(x,y,0), + vec3(x+1,y,0), + vec3(x+1,y-1,0), + vec3(x+1,y-1,0), + vec3(x,y-1,0), + vec3(x,y,0), + + -- Left wall + vec3(x,y,1), + vec3(x,y,0), + vec3(x,y-1,0), + vec3(x,y-1,0), + vec3(x,y-1,1), + vec3(x,y,1), + + --Right wall + vec3(x+1,y,0), + vec3(x+1,y,1), + vec3(x+1,y-1,1), + vec3(x+1,y-1,1), + vec3(x+1,y-1,0), + vec3(x+1,y,0), + } + r + +room = (x,y,w,h,left_holes,right_holes,top_holes,bottom_holes) -> + left_holes\sort() + right_holes\sort() + top_holes\sort() + bottom_holes\sort() + r = { + --floor + vec3(x,y,0) + vec3(x+w,y,0), + vec3(x+w,y-h,0), + vec3(x+w,y-h,0), + vec3(x,y-h,0), + vec3(x,y,0), + + --left wall + } + r + +barrel = (x,y,w,h) -> + tris = 18 + rad = (w/2) + l = x - (w/2) + j = x + (w/2) + t = h + b = 0 + f = y - (w/2) + n = y + (w/2) + r = { + --top + vec3(l,f,h), + vec3(l,n,h), + vec3(j,n,h), + vec3(j,n,h), + vec3(j,f,h), + vec3(l,f,h), + } + step = (2*math.pi)/tris + for i = 0,2*math.pi,step + r[#r+1] =vec3(x + math.cos(i)*rad,y + math.sin(i)*n,h) + r[#r+1] =vec3(x + math.cos(i+step)*rad,math.sin(i+step)*n,h) + r[#r+1] =vec3(x + math.cos(i+step)*rad,math.sin(i+step)*n,0) + r[#r+1] =vec3(x + math.cos(i+step)*rad,math.sin(i+step)*n,0) + r[#r+1] =vec3(x + math.cos(i)*rad,math.sin(i)*n,0) + r[#r+1] =vec3(x + math.cos(i)*rad,math.sin(i)*n,h) + r + +barrel_uv = (x,y,w,h) -> + tris = 18 + r = { + vec4(w1.s1,w1.t1,1,1), + vec4(w1.s1,w1.t2,1,1), + vec4(w1.s2,w1.t2,1,1), + vec4(w1.s2,w1.t2,1,1), + vec4(w1.s2,w1.t1,1,1), + vec4(w1.s1,w1.t1,1,1), + } + step = (2*math.pi)/tris + for i = 0,2*math.pi,step + perc = (i / (2*math.pi)) + nextperc = ((i+step) / (2*math.pi)) + srange = w1.s2 - w1.s1 + trange = w1.t2 - w1.t1 + sstart = w1.s1 + (srange * perc) + send = w1.s1 + (srange * nextperc) + tstart = w1.t1 + tend = w1.t2 + r[#r+1] = vec4(sstart ,tstart,1,1) + r[#r+1] = vec4(sstart ,tend,1,1) + r[#r+1] = vec4(send ,tend,1,1) + r[#r+1] = vec4(send ,tend,1,1) + r[#r+1] = vec4(send ,tstart,1,1) + r[#r+1] = vec4(sstart ,tstart,1,1) + r + +barrel_r = (x,y,w,h) -> + r = {-1,-1,1,1,1,-1,0,0,0,0,0,0} + r + + +-- uvs are s,t,smult, tmult +up_down_hall_uv = (x,y) -> + r = { + --floor + vec4(sd.s1,sd.t1,1,1), + vec4(sd.s2,sd.t1,1,1), + vec4(sd.s2,sd.t2,1,1), + vec4(sd.s2,sd.t2,1,1), + vec4(sd.s1,sd.t2,1,1), + vec4(sd.s1,sd.t1,1,1), + -- left wall + vec4(w1.s1,w1.t1,1,1), + vec4(w1.s1,w1.t2,1,1), + vec4(w1.s2,w1.t2,1,1), + vec4(w1.s2,w1.t2,1,1), + vec4(w1.s2,w1.t1,1,1), + vec4(w1.s1,w1.t1,1,1), + -- right wall + vec4(w1.s2,w1.t2,1,1), + vec4(w1.s2,w1.t1,1,1), + vec4(w1.s1,w1.t1,1,1), + vec4(w1.s1,w1.t1,1,1), + vec4(w1.s1,w1.t2,1,1), + vec4(w1.s2,w1.t2,1,1), + + } + r + +up_down_hall_r = (x,y) -> + r = { + 0,0,0,0,0,0 + 0,0,0,0,0,0 + 0,0,0,0,0,0 + 0,0,0,0,0,0 + 0,0,0,0,0,0 + 0,0,0,0,0,0 + } + r + +-- Barrel? + + +add_verts = (tbl, new) -> + for i = 1, #new + tbl[#tbl+1] = new[i] + +world_geom = {} +world_uv = {} +world_r = {} +add_verts(world_geom, up_down_hall(0,-1)) +add_verts(world_uv, up_down_hall_uv(0,0)) +add_verts(world_r, up_down_hall_r(0,0)) +add_verts(world_geom, up_down_hall(0,1)) +add_verts(world_uv, up_down_hall_uv(0,0)) +add_verts(world_r, up_down_hall_r(0,0)) +add_verts(world_geom, up_down_hall(0,0)) +add_verts(world_uv, up_down_hall_uv(0,0)) +add_verts(world_r, up_down_hall_r(0,0)) +add_verts(world_geom, barrel(-1,0,0.5,0.5)) +add_verts(world_uv, barrel_uv(-1,0,0.5,0.5)) +add_verts(world_r, barrel_r(-1,0,0.5,0.5)) +--add_verts(world_geom, barrel(0.5,0.5,0.5,0.5)) +--add_verts(world_uv, barrel_uv(0.5,0.5,0.5,0.5)) +--add_verts(world_r, barrel_r(0.5,0.5,0.5,0.5)) +--sprites["diffuse"].texture.wrap = "repeat" +--sprites["normals"].texture.wrap = "repeat" + +test_world = { + vec3(0,0,0), + vec3(1,0,0), + vec3(0,1,0) +} +test_uvs = { + vec4(sd.s1,sd.t1,1,1), + vec4(sd.s2,sd.t1,1,1), + vec4(sd.s2,sd.t2,1,1), +} +test_r = { + 0,0,0 +} + +-- How big should our buffer for the world be? +-- Let's call it at up to 100 players +--MAX_PLAYERS = 128 +MAX_PLAYERS = 8 +--MAX_LEVEL_TRIS = 1 * 1024 * 1024 -- 1M level triangles? +MAX_LEVEL_TRIS = 1024 -- testing? +buffer_tris = (MAX_PLAYERS * 2) + MAX_LEVEL_TRIS +geom_buffer = am.buffer(buffer_tris * 3 * 12) --am.vec3_array +uv_buffer = am.buffer(buffer_tris * 3 * 16) --am.vec2_array +geom_view = geom_buffer\view("vec3") +uv_view = uv_buffer\view("vec4") +for i = 1, #world_geom + geom_view[i] = world_geom[i] + +for i = 1, #world_uv + uv_view[i] = world_uv[i] + +world.geom_view = geom_view +world.uv_view = uv_view + +buf_cursor = #world_geom -- the vertex number +shimworld = shader_shim.world +depth_test = am.depth_test("less") +shimworld\append(depth_test) +--cull = am.cull_face("back") +--depth_test\append(cull) + +--{ + --MV: s_mv + --P: mat4(1) + --world_x: math.sin(am.current_time!) * 2 + --world_y: math.cos(am.current_time!) * 2 + ----world_x: 0, + ----world_y: 0, + --world: geom_view, + --texuv: uv_view, + ----world: am.vec3_array(world_geom) + ----texuv: am.vec4_array(world_uv) + ----r: am.float_array(world_r) + ----world:am.vec3_array(test_world) + ----texuv: am.vec4_array(test_uvs) + ----r: am.float_array(test_r) + --time: am.current_time(), + --textures: sprites.floor.texture +--} + +-- In the example we have +-- am.group (buildings_group) +-- ^ many am.bind(...) +-- ^ am.draw("triangles") + + +bind = am.group! +depth_test\append(bind) + +add = (n) -> + assert(n.tris) + assert(n.populate_buf) + assert(n.properties) + assert(n.properties.graphic) + --assert(buf_cursor + n_tris < buffer_tris, "Not enough tris! Had " .. buf_cursor .. " and wanted " .. n_tris .. " so we sould end up with " .. (buf_cursor + n_tris) .. " but we only have " .. buffer_tris) + n_tris = n\tris! + log.info(string.format("Adding %d tris to buffer at %d",n_tris, buf_cursor),{"graphics"}) + geom_buffer = am.buffer(n_tris * 3 * 12) --am.vec3_array + uv_buffer = am.buffer(n_tris * 3 * 16) --am.vec2_array + geom_view = geom_buffer\view("vec3") + uv_view = uv_buffer\view("vec4") + texture = n.properties.graphic.texture + n\populate_buf(geom_view, uv_view, 1) + tbind = am.bind({ + MV: s_mv + P: p_mv + world_x: math.sin(am.current_time!) * 2 + world_y: math.cos(am.current_time!) * 2 + world: geom_view, + texuv: uv_view, + time: am.current_time! + textures: texture + }) + tbind\append(am.draw("triangles")) + bind\append(tbind) + n.node = tbind + --buf_cursor += n_tris * 6 + +remove = (n) -> + bind\remove(n.node) + +clear = () -> + log.info("Clearing shader!") + geom_view\set(vec3(0,0,0),1,buf_cursor) + uv_view\set(vec4(0,0,0,0),1,buf_cursor) + buf_cursor = 1 + + +--draw = am.draw("triangles", 1, buf_cursor) +--bind\append(draw) + +--world.geom = binds.geom +--world.texuv = binds.texuv + +shimworld\action(() => + binds = bind\all("bind") + binds.time = am.current_time! + --bind.world_x = math.sin(am.current_time!) * 2 + --bind.world_y = math.cos(am.current_time!) * 2 + binds.world_x = world.world_x + binds.world_y = world.world_y +) +node = shimworld + +--node = shader_shim.world\append(am.depth_test("less")\append(am.cull_face("front")\append(am.bind({ -- should cull front + --MV: s_mv + --P: mat4(1) + --color: color.am_color.highlight, + --world_x: 0, + --world_y: 0, + --world: am.vec3_array(world_geom) + --texuv: am.vec4_array(world_uv) + --r: am.float_array(world_r) + ----world:am.vec3_array(test_world) + ----texuv: am.vec4_array(test_uvs) + ----r: am.float_array(test_r) + --time: am.current_time(), + --textures: sprites.floor1_diffuse.texture +--})\append(am.draw("triangles"))))) +--node\action(() => + --bind = self("bind") + --bind.time = am.current_time! + --bind.world_x = math.sin(am.current_time!) * 2 + --bind.world_y = math.cos(am.current_time!) * 2 + ----bind.world_x = world.world_x + ----bind.world_y = world.world_y +--) +{ + :add + :clear + :remove + node: node + bind: node("bind") +} diff --git a/src/shaders/world.moon.back b/src/shaders/world.moon.back new file mode 100644 index 0000000..7950f51 --- /dev/null +++ b/src/shaders/world.moon.back @@ -0,0 +1,327 @@ +win = require("window") +color = require("color") +world = require("world") +sprites = require("sprites") +shader_shim = require("shader_shim") +hc = require("party.hc.init") +log = require("log") +PlayerGraphicComponent = require("ecs.player_graphic") +assert(world.world_x, "No world_x" .. debug.traceback()) +-- Process the world into buffers to send to the shader + +view_angle = math.pi / 4 +near_plane = 1 +far_plane = 2 +aspect = win.width / win.height +s_mv = mat4( + 1, 0, 0, 0, + 0, aspect, 0, 0, + 0, 0, 1, 0, + -0.0, 0.5, 0, 4 + ) +p_mv = mat4( + 1 / ((win.width / win.height) * math.tan(view_angle / 2)), 0, 0, 0, + 0, 1/math.tan(view_angle/2), 0, 0, + 0, 0, far_plane / (far_plane - near_plane), 1, + 0, 0,(-far_plane * near_plane)/(far_plane - near_plane), 0 +) + +sd = sprites.floor +w1 = sprites.wall + +-- Each point needs: +-- vec3 position (x,y,z) +-- vec2 (u,v) +up_down_hall = (x,y) -> + r = { + --floor + vec3(x,y,0), + vec3(x+1,y,0), + vec3(x+1,y-1,0), + vec3(x+1,y-1,0), + vec3(x,y-1,0), + vec3(x,y,0), + + -- Left wall + vec3(x,y,1), + vec3(x,y,0), + vec3(x,y-1,0), + vec3(x,y-1,0), + vec3(x,y-1,1), + vec3(x,y,1), + + --Right wall + vec3(x+1,y,0), + vec3(x+1,y,1), + vec3(x+1,y-1,1), + vec3(x+1,y-1,1), + vec3(x+1,y-1,0), + vec3(x+1,y,0), + } + r + +room = (x,y,w,h,left_holes,right_holes,top_holes,bottom_holes) -> + left_holes\sort() + right_holes\sort() + top_holes\sort() + bottom_holes\sort() + r = { + --floor + vec3(x,y,0) + vec3(x+w,y,0), + vec3(x+w,y-h,0), + vec3(x+w,y-h,0), + vec3(x,y-h,0), + vec3(x,y,0), + + --left wall + } + r + +barrel = (x,y,w,h) -> + tris = 18 + rad = (w/2) + l = x - (w/2) + j = x + (w/2) + t = h + b = 0 + f = y - (w/2) + n = y + (w/2) + r = { + --top + vec3(l,f,h), + vec3(l,n,h), + vec3(j,n,h), + vec3(j,n,h), + vec3(j,f,h), + vec3(l,f,h), + } + step = (2*math.pi)/tris + for i = 0,2*math.pi,step + r[#r+1] =vec3(x + math.cos(i)*rad,y + math.sin(i)*n,h) + r[#r+1] =vec3(x + math.cos(i+step)*rad,math.sin(i+step)*n,h) + r[#r+1] =vec3(x + math.cos(i+step)*rad,math.sin(i+step)*n,0) + r[#r+1] =vec3(x + math.cos(i+step)*rad,math.sin(i+step)*n,0) + r[#r+1] =vec3(x + math.cos(i)*rad,math.sin(i)*n,0) + r[#r+1] =vec3(x + math.cos(i)*rad,math.sin(i)*n,h) + r + +barrel_uv = (x,y,w,h) -> + tris = 18 + r = { + vec4(w1.s1,w1.t1,1,1), + vec4(w1.s1,w1.t2,1,1), + vec4(w1.s2,w1.t2,1,1), + vec4(w1.s2,w1.t2,1,1), + vec4(w1.s2,w1.t1,1,1), + vec4(w1.s1,w1.t1,1,1), + } + step = (2*math.pi)/tris + for i = 0,2*math.pi,step + perc = (i / (2*math.pi)) + nextperc = ((i+step) / (2*math.pi)) + srange = w1.s2 - w1.s1 + trange = w1.t2 - w1.t1 + sstart = w1.s1 + (srange * perc) + send = w1.s1 + (srange * nextperc) + tstart = w1.t1 + tend = w1.t2 + r[#r+1] = vec4(sstart ,tstart,1,1) + r[#r+1] = vec4(sstart ,tend,1,1) + r[#r+1] = vec4(send ,tend,1,1) + r[#r+1] = vec4(send ,tend,1,1) + r[#r+1] = vec4(send ,tstart,1,1) + r[#r+1] = vec4(sstart ,tstart,1,1) + r + +barrel_r = (x,y,w,h) -> + r = {-1,-1,1,1,1,-1,0,0,0,0,0,0} + r + + +-- uvs are s,t,smult, tmult +up_down_hall_uv = (x,y) -> + r = { + --floor + vec4(sd.s1,sd.t1,1,1), + vec4(sd.s2,sd.t1,1,1), + vec4(sd.s2,sd.t2,1,1), + vec4(sd.s2,sd.t2,1,1), + vec4(sd.s1,sd.t2,1,1), + vec4(sd.s1,sd.t1,1,1), + -- left wall + vec4(w1.s1,w1.t1,1,1), + vec4(w1.s1,w1.t2,1,1), + vec4(w1.s2,w1.t2,1,1), + vec4(w1.s2,w1.t2,1,1), + vec4(w1.s2,w1.t1,1,1), + vec4(w1.s1,w1.t1,1,1), + -- right wall + vec4(w1.s2,w1.t2,1,1), + vec4(w1.s2,w1.t1,1,1), + vec4(w1.s1,w1.t1,1,1), + vec4(w1.s1,w1.t1,1,1), + vec4(w1.s1,w1.t2,1,1), + vec4(w1.s2,w1.t2,1,1), + + } + r + +up_down_hall_r = (x,y) -> + r = { + 0,0,0,0,0,0 + 0,0,0,0,0,0 + 0,0,0,0,0,0 + 0,0,0,0,0,0 + 0,0,0,0,0,0 + 0,0,0,0,0,0 + } + r + +-- Barrel? + + +add_verts = (tbl, new) -> + for i = 1, #new + tbl[#tbl+1] = new[i] + +world_geom = {} +world_uv = {} +world_r = {} +add_verts(world_geom, up_down_hall(0,-1)) +add_verts(world_uv, up_down_hall_uv(0,0)) +add_verts(world_r, up_down_hall_r(0,0)) +add_verts(world_geom, up_down_hall(0,1)) +add_verts(world_uv, up_down_hall_uv(0,0)) +add_verts(world_r, up_down_hall_r(0,0)) +add_verts(world_geom, up_down_hall(0,0)) +add_verts(world_uv, up_down_hall_uv(0,0)) +add_verts(world_r, up_down_hall_r(0,0)) +add_verts(world_geom, barrel(-1,0,0.5,0.5)) +add_verts(world_uv, barrel_uv(-1,0,0.5,0.5)) +add_verts(world_r, barrel_r(-1,0,0.5,0.5)) +--add_verts(world_geom, barrel(0.5,0.5,0.5,0.5)) +--add_verts(world_uv, barrel_uv(0.5,0.5,0.5,0.5)) +--add_verts(world_r, barrel_r(0.5,0.5,0.5,0.5)) +--sprites["diffuse"].texture.wrap = "repeat" +--sprites["normals"].texture.wrap = "repeat" + +test_world = { + vec3(0,0,0), + vec3(1,0,0), + vec3(0,1,0) +} +test_uvs = { + vec4(sd.s1,sd.t1,1,1), + vec4(sd.s2,sd.t1,1,1), + vec4(sd.s2,sd.t2,1,1), +} +test_r = { + 0,0,0 +} + +-- How big should our buffer for the world be? +-- Let's call it at up to 100 players +--MAX_PLAYERS = 128 +MAX_PLAYERS = 8 +--MAX_LEVEL_TRIS = 1 * 1024 * 1024 -- 1M level triangles? +MAX_LEVEL_TRIS = 1024 -- testing? +buffer_tris = (MAX_PLAYERS * PlayerGraphicComponent.tris!) + MAX_LEVEL_TRIS +geom_buffer = am.buffer(buffer_tris * 3 * 12) --am.vec3_array +uv_buffer = am.buffer(buffer_tris * 3 * 16) --am.vec2_array +geom_view = geom_buffer\view("vec3") +uv_view = uv_buffer\view("vec4") +for i = 1, #world_geom + geom_view[i] = world_geom[i] + +for i = 1, #world_uv + uv_view[i] = world_uv[i] + +world.geom_view = geom_view +world.uv_view = uv_view + +buf_cursor = #world_geom -- the vertex number +add = (n) -> + assert(n.tris) + assert(n.populate_buf) + n_tris = n\tris! + assert(buf_cursor + n_tris < buffer_tris, "Not enough tris! Had " .. buf_cursor .. " and wanted " .. n_tris .. " so we sould end up with " .. (buf_cursor + n_tris) .. " but we only have " .. buffer_tris) + log.info(string.format("Adding %d tris to buffer at %d",n_tris, buf_cursor),{"graphics"}) + n\populate_buf(geom_view, uv_view, buf_cursor) + buf_cursor += n_tris * 6 + +clear = () -> + log.info("Clearing shader!") + geom_view\set(vec3(0,0,0),1,buf_cursor) + uv_view\set(vec4(0,0,0,0),1,buf_cursor) + buf_cursor = 1 + +shimworld = shader_shim.world +depth_test = am.depth_test("less") +shimworld\append(depth_test) +cull = am.cull_face("front") +depth_test\append(cull) +binds = { + MV: s_mv + P: mat4(1) + color: color.am_color.highlight, + world_x: 0, + world_y: 0, + world: geom_view, + texuv: uv_view, + --world: am.vec3_array(world_geom) + --texuv: am.vec4_array(world_uv) + --r: am.float_array(world_r) + --world:am.vec3_array(test_world) + --texuv: am.vec4_array(test_uvs) + --r: am.float_array(test_r) + time: am.current_time(), + textures: sprites.floor.texture +} +bind = am.bind(binds) +cull\append(bind) +draw = am.draw("triangles", 1, buf_cursor) +bind\append(draw) + +world.geom = binds.geom +world.texuv = binds.texuv + +shimworld\action(() => + bind = self("bind") + bind.time = am.current_time! + --bind.world_x = math.sin(am.current_time!) * 2 + --bind.world_y = math.cos(am.current_time!) * 2 + bind.world_x = world.world_x + bind.world_y = world.world_y +) +node = shimworld + +--node = shader_shim.world\append(am.depth_test("less")\append(am.cull_face("front")\append(am.bind({ -- should cull front + --MV: s_mv + --P: mat4(1) + --color: color.am_color.highlight, + --world_x: 0, + --world_y: 0, + --world: am.vec3_array(world_geom) + --texuv: am.vec4_array(world_uv) + --r: am.float_array(world_r) + ----world:am.vec3_array(test_world) + ----texuv: am.vec4_array(test_uvs) + ----r: am.float_array(test_r) + --time: am.current_time(), + --textures: sprites.floor1_diffuse.texture +--})\append(am.draw("triangles"))))) +--node\action(() => + --bind = self("bind") + --bind.time = am.current_time! + --bind.world_x = math.sin(am.current_time!) * 2 + --bind.world_y = math.cos(am.current_time!) * 2 + ----bind.world_x = world.world_x + ----bind.world_y = world.world_y +--) +{ + :add + :clear + node: node + bind: node("bind") +} diff --git a/src/shaders/world.vert b/src/shaders/world.vert new file mode 100644 index 0000000..5937253 --- /dev/null +++ b/src/shaders/world.vert @@ -0,0 +1,26 @@ +precision highp float; +attribute vec3 world; // position +attribute vec2 texuv; +attribute float r; // for round objects, 0 for non-round +varying vec2 textureuv; +varying float radius; +varying mat3 light1; +varying vec4 v_color; +uniform float world_x; +uniform float world_y; +uniform mat4 MV; +uniform mat4 P; +void main() { + v_color = vec4(world.xyz,1.); + vec2 vxy = vec2(world.x - world_x, world.y - world_y); + float z_scale = 0.5; + float max_parallax = 0.5; + float xoff = clamp(world.z * vxy.x * z_scale, -max_parallax, max_parallax); + float yoff = clamp(world.z * vxy.y * z_scale, -max_parallax, max_parallax); + textureuv=texuv; + //radius = r; + // if z > 0 then + // xoff = ceil(xoff, 0) + // add to the z coord so we don't intersect with the ui + gl_Position = P * MV * vec4(vxy.x + xoff, vxy.y + yoff, world.z, 1.0); +} diff --git a/src/shaders/world.vert.back b/src/shaders/world.vert.back new file mode 100644 index 0000000..42276fe --- /dev/null +++ b/src/shaders/world.vert.back @@ -0,0 +1,26 @@ +precision highp float; +attribute vec3 world; // position +attribute vec2 texuv; +attribute float r; // for round objects, 0 for non-round +varying vec2 textureuv; +varying float radius; +varying mat3 light1; +uniform vec4 color; +varying vec4 v_color; +uniform float world_x; +uniform float world_y; +uniform mat4 MV; +uniform mat4 P; +void main() { + v_color = vec4(world.xyz,1.); + vec2 vxy = vec2(world.x - world_x, world.y - world_y); + float z_scale = 0.5; + float xoff = clamp(world.z * vxy.x * z_scale, -32., 32.); + float yoff = clamp(world.z * vxy.y * z_scale, -32., 32.); + textureuv=texuv; + //radius = r; + // if z > 0 then + // xoff = ceil(xoff, 0) + // add to the z coord so we don't intersect with the ui + gl_Position = P * MV * vec4(vxy.x + xoff, vxy.y + yoff, -world.z -1., 1.0); +} -- cgit v1.2.3-70-g09d2