diff options
author | alaric <alaric@netmythos.org> | 2024-03-30 18:36:47 -0700 |
---|---|---|
committer | alaric <alaric@netmythos.org> | 2024-03-30 18:36:47 -0700 |
commit | 05e8fc7dd6f59402a92d001f34d13ccc7971b49b (patch) | |
tree | 3fe065659a06f48004073369d186dd28dddde92f | |
parent | 17223eee868dfcd8f12bb2fd3b75acc0b2d0529a (diff) | |
download | colordots-05e8fc7dd6f59402a92d001f34d13ccc7971b49b.tar.gz colordots-05e8fc7dd6f59402a92d001f34d13ccc7971b49b.zip |
Neat line fan
-rw-r--r-- | src/line_vertex.glsl | 34 | ||||
-rw-r--r-- | src/shell.html | 5 | ||||
-rw-r--r-- | src/vertex.glsl | 2 | ||||
-rw-r--r-- | src/wasm_ttd.zig | 256 | ||||
-rw-r--r-- | src/webgl.js | 1 | ||||
-rw-r--r-- | src/webgl.zig | 1 |
6 files changed, 209 insertions, 90 deletions
diff --git a/src/line_vertex.glsl b/src/line_vertex.glsl new file mode 100644 index 0000000..b3a8250 --- /dev/null +++ b/src/line_vertex.glsl @@ -0,0 +1,34 @@ +#version 300 es + +in vec4 in_pos; +in float color; + +uniform vec2 u_resolution; + +out vec2 v_texcoord; +out vec3 v_color; + +// Function from IƱigo Quiles +// https://www.shadertoy.com/view/MsS3Wc +vec3 hsb2rgb( in vec3 c ){ + vec3 rgb = clamp(abs(mod(c.x*6.0+vec3(0.0,4.0,2.0), + 6.0)-3.0)-1.0, + 0.0, + 1.0 ); + rgb = rgb*rgb*(3.0-2.0*rgb); + return c.z * mix(vec3(1.0), rgb, c.y); +} + +void main() { + vec2 pos; + if (gl_VertexID == 0) { + pos = in_pos.xy; + } else { + pos = in_pos.zw; + } + vec2 zeroToOne = pos / u_resolution; + vec2 zeroToTwo = zeroToOne * 2.0; + vec2 clipSpace = zeroToTwo - 1.0; + gl_Position = vec4(clipSpace, 0, 1); + v_color = hsb2rgb(vec3(color, 1.0, 1.0)); +} diff --git a/src/shell.html b/src/shell.html index e05b7e0..3013360 100644 --- a/src/shell.html +++ b/src/shell.html @@ -19,12 +19,7 @@ <body> <canvas id="ttd-canvas" width="1280" height="720" tabindex="0"></canvas> <script src="webgl.js"></script> - <script type="text/javascript" src="https://spectorcdn.babylonjs.com/spector.bundle.js"></script> <script> - var spector = new SPECTOR.Spector(); - spector.displayUI(); - spector.spyCanvases(); - let memory = null; let last_frame_time = Date.now(); diff --git a/src/vertex.glsl b/src/vertex.glsl index fcdcd5d..335331b 100644 --- a/src/vertex.glsl +++ b/src/vertex.glsl @@ -26,6 +26,6 @@ void main() { vec2 zeroToOne = position / u_resolution; vec2 zeroToTwo = zeroToOne * 2.0; vec2 clipSpace = zeroToTwo - 1.0; - gl_Position = vec4(clipSpace, 0, 1); + gl_Position = vec4(clipSpace, 0, 1.0 - (float(gl_InstanceID) / 90000.0)); v_color = hsb2rgb(vec3(color, 1.0, 1.0)); } diff --git a/src/wasm_ttd.zig b/src/wasm_ttd.zig index 78b65e7..0ee02a5 100644 --- a/src/wasm_ttd.zig +++ b/src/wasm_ttd.zig @@ -27,18 +27,6 @@ fn formatLog(comptime fmt: []const u8, args: anytype) void { const pi = 3.1415926535; -var prog: webgl.Program = undefined; -var pos_attr_location: i32 = undefined; -var col_attr_location: i32 = undefined; -var translation_attr_location: i32 = undefined; -var scale_attr_location: i32 = undefined; -var res_uniform_location: i32 = undefined; -var pos_buffer: webgl.Buffer = undefined; -var col_buffer: webgl.Buffer = undefined; -var translation_buffer: webgl.Buffer = undefined; -var scale_buffer: webgl.Buffer = undefined; -var vao: webgl.VertexArrayObject = undefined; - var timer: f32 = 0.0; var rects: [128]Rectangle = undefined; var cols: [128][3]f32 = undefined; @@ -141,12 +129,149 @@ var pdown: u32 = 0; const circle = circlePoints(32); +const LineProgram = struct { + prog: webgl.Program, + vao: webgl.VertexArrayObject, + + res_uniform_location: i32, + + pos_buffer: webgl.Buffer, + col_buffer: webgl.Buffer, + + fn init() !LineProgram { + const vert = loadShader(.vertex_shader, @embedFile("line_vertex.glsl")) catch return error.FailedToLoadVertexShader; + const frag = loadShader(.fragment_shader, fs_source) catch return error.FailedToLoadFragmentShader; + const prog = createGLProgram(vert, frag) catch return error.FailedToCreateProgram; + webgl.useProgram(prog); + + const attr_name = "in_pos"; + const pos_attr_location = webgl.getAttribLocation(prog, attr_name.ptr, attr_name.len); + + const col_attr = "color"; + const col_attr_location = webgl.getAttribLocation(prog, col_attr.ptr, col_attr.len); + + const res_uniform_location = getUniformLocation(prog, "u_resolution") catch unreachable; + + const pos_buffer = webgl.createBuffer(); + webgl.bindBuffer(.array_buffer, pos_buffer); + webgl.bufferData(.array_buffer, @ptrCast(&[_]f32{ 0, 0, 0, 0 }), 2, .static_draw); + + const vao = webgl.createVertexArray(); + webgl.bindVertexArray(vao); + webgl.enableVertexAttribArray(pos_attr_location); + webgl.vertexAttribPointer(@intCast(pos_attr_location), 2, .f32, .false, 0, 0); + webgl.vertexAttribDivisor(pos_attr_location, 1); + + const col_buffer = webgl.createBuffer(); + webgl.bindBuffer(.array_buffer, col_buffer); + webgl.enableVertexAttribArray(col_attr_location); + webgl.vertexAttribPointer(@intCast(col_attr_location), 1, .f32, .false, 0, 0); + webgl.vertexAttribDivisor(col_attr_location, 1); + + return .{ + .prog = prog, + .pos_buffer = pos_buffer, + .col_buffer = col_buffer, + .res_uniform_location = res_uniform_location, + .vao = vao, + }; + } +}; + +const CircleProgram = struct { + prog: webgl.Program, + vao: webgl.VertexArrayObject, + + res_uniform_location: i32, + + translation_buffer: webgl.Buffer, + scale_buffer: webgl.Buffer, + col_buffer: webgl.Buffer, + + fn init() !CircleProgram { + const vert = loadShader(.vertex_shader, @embedFile("vertex.glsl")) catch return error.FailedToLoadVertexShader; + const frag = loadShader(.fragment_shader, fs_source) catch return error.FailedToLoadFragmentShader; + const prog = createGLProgram(vert, frag) catch return error.FailedToCreateProgram; + webgl.useProgram(prog); + + const attr_name = "in_pos"; + const pos_attr_location = webgl.getAttribLocation(prog, attr_name.ptr, attr_name.len); + + const col_attr = "color"; + const col_attr_location = webgl.getAttribLocation(prog, col_attr.ptr, col_attr.len); + + const translation_attr = "translation"; + const translation_attr_location = webgl.getAttribLocation( + prog, + translation_attr.ptr, + translation_attr.len, + ); + + const scale_attr = "scale"; + const scale_attr_location = webgl.getAttribLocation( + prog, + scale_attr.ptr, + scale_attr.len, + ); + + const res_uniform_location = getUniformLocation(prog, "u_resolution") catch unreachable; + + const pos_buffer = webgl.createBuffer(); + webgl.bindBuffer(.array_buffer, pos_buffer); + webgl.bufferData(.array_buffer, @ptrCast(&circle), circle.len * 2, .static_draw); + + const vao = webgl.createVertexArray(); + webgl.bindVertexArray(vao); + webgl.enableVertexAttribArray(pos_attr_location); + webgl.vertexAttribPointer(@intCast(pos_attr_location), 2, .f32, .false, 0, 0); + + const col_buffer = webgl.createBuffer(); + webgl.bindBuffer(.array_buffer, col_buffer); + webgl.enableVertexAttribArray(col_attr_location); + webgl.vertexAttribPointer(@intCast(col_attr_location), 1, .f32, .false, 0, 0); + webgl.vertexAttribDivisor(col_attr_location, 1); + + const scale_buffer = webgl.createBuffer(); + webgl.bindBuffer(.array_buffer, scale_buffer); + webgl.enableVertexAttribArray(scale_attr_location); + webgl.vertexAttribPointer(@intCast(scale_attr_location), 1, .f32, .false, 0, 0); + webgl.vertexAttribDivisor(scale_attr_location, 1); + + const translation_buffer = webgl.createBuffer(); + webgl.bindBuffer(.array_buffer, translation_buffer); + webgl.enableVertexAttribArray(translation_attr_location); + webgl.vertexAttribPointer(@intCast(translation_attr_location), 2, .f32, .false, 0, 0); + webgl.vertexAttribDivisor(translation_attr_location, 1); + + return .{ + .prog = prog, + .translation_buffer = translation_buffer, + .col_buffer = col_buffer, + .scale_buffer = scale_buffer, + .res_uniform_location = res_uniform_location, + .vao = vao, + }; + } +}; + +var circle_program: CircleProgram = undefined; +var line_program: LineProgram = undefined; + export fn init() void { const f_seed = rand() * (pow(f32, 2, 16) + 1); const seed: u64 = @intFromFloat(f_seed); rng = LinearCongruentialGenerator.ZX81(seed); - const width = getScreenWidth(); + circle_program = CircleProgram.init() catch |err| { + formatLog("Failed to create CircleProgram. {}", .{err}); + return; + }; + + line_program = LineProgram.init() catch |err| { + formatLog("Failed to create CircleProgram. {}", .{err}); + return; + }; + const height = getScreenHeight(); for (&stars) |*s| { @@ -157,61 +282,6 @@ export fn init() void { s.hue = rng.randFloat(f32); } - const vert = loadShader(.vertex_shader, vs_source) catch return; - const frag = loadShader(.fragment_shader, fs_source) catch return; - prog = createGLProgram(vert, frag) catch return; - webgl.useProgram(prog); - - const attr_name = "in_pos"; - pos_attr_location = webgl.getAttribLocation(prog, attr_name.ptr, attr_name.len); - - const col_attr = "color"; - col_attr_location = webgl.getAttribLocation(prog, col_attr.ptr, col_attr.len); - - const translation_attr = "translation"; - translation_attr_location = webgl.getAttribLocation( - prog, - translation_attr.ptr, - translation_attr.len, - ); - - const scale_attr = "scale"; - scale_attr_location = webgl.getAttribLocation( - prog, - scale_attr.ptr, - scale_attr.len, - ); - - res_uniform_location = getUniformLocation(prog, "u_resolution") catch unreachable; - webgl.uniform2f(res_uniform_location, width, height); - - pos_buffer = webgl.createBuffer(); - webgl.bindBuffer(.array_buffer, pos_buffer); - webgl.bufferData(.array_buffer, @ptrCast(&circle), circle.len * 2, .static_draw); - - vao = webgl.createVertexArray(); - webgl.bindVertexArray(vao); - webgl.enableVertexAttribArray(pos_attr_location); - webgl.vertexAttribPointer(@intCast(pos_attr_location), 2, .f32, .false, 0, 0); - - col_buffer = webgl.createBuffer(); - webgl.bindBuffer(.array_buffer, col_buffer); - webgl.enableVertexAttribArray(col_attr_location); - webgl.vertexAttribPointer(@intCast(col_attr_location), 1, .f32, .false, 0, 0); - webgl.vertexAttribDivisor(col_attr_location, 1); - - scale_buffer = webgl.createBuffer(); - webgl.bindBuffer(.array_buffer, scale_buffer); - webgl.enableVertexAttribArray(scale_attr_location); - webgl.vertexAttribPointer(@intCast(scale_attr_location), 1, .f32, .false, 0, 0); - webgl.vertexAttribDivisor(scale_attr_location, 1); - - translation_buffer = webgl.createBuffer(); - webgl.bindBuffer(.array_buffer, translation_buffer); - webgl.enableVertexAttribArray(translation_attr_location); - webgl.vertexAttribPointer(@intCast(translation_attr_location), 2, .f32, .false, 0, 0); - webgl.vertexAttribDivisor(translation_attr_location, 1); - registerKey(.up, &up); registerKey(.right, &right); registerKey(.left, &left); @@ -245,6 +315,7 @@ var sub_count: u32 = star_count; const batch_capacity = 90000; var translation_data: [batch_capacity][2]f32 = undefined; +var line_data: [batch_capacity][2][2]f32 = undefined; var scale_data: [batch_capacity]f32 = undefined; var color_data: [batch_capacity]f32 = undefined; @@ -252,27 +323,45 @@ const DrawBatch = struct { translation: [][2]f32, scales: []f32, colors: []f32, + lines: [][2][2]f32, len: u32 = 0, - fn addInstance(self: *DrawBatch, translation: [2]f32, hue: f32, scale: f32) !void { - if (self.len == self.translation.len or self.len == self.colors.len or self.len == self.scales.len) return error.OutOfSpace; + fn addInstance(self: *DrawBatch, translation: [2]f32, past_translation: [2]f32, hue: f32, scale: f32) !void { + if (self.len == self.translation.len or self.len == self.colors.len or self.len == self.scales.len or self.len == self.lines.len) return error.OutOfSpace; self.translation[self.len] = translation; self.colors[self.len] = hue; self.scales[self.len] = scale; + self.lines[self.len] = .{ past_translation, translation }; self.len += 1; } fn draw(self: DrawBatch) void { - webgl.bindBuffer(.array_buffer, translation_buffer); + const width = getScreenWidth(); + const height = getScreenHeight(); + webgl.bindVertexArray(circle_program.vao); + webgl.useProgram(circle_program.prog); + webgl.uniform2f(circle_program.res_uniform_location, width, height); + webgl.bindBuffer(.array_buffer, circle_program.translation_buffer); webgl.bufferData(.array_buffer, @ptrCast(self.translation), self.len * 2, .dynamic_draw); - webgl.bindBuffer(.array_buffer, scale_buffer); + webgl.bindBuffer(.array_buffer, circle_program.scale_buffer); webgl.bufferData(.array_buffer, @ptrCast(self.scales), self.len, .dynamic_draw); - webgl.bindBuffer(.array_buffer, col_buffer); + webgl.bindBuffer(.array_buffer, circle_program.col_buffer); + webgl.bufferData(.array_buffer, @ptrCast(self.colors), self.len, .dynamic_draw); + //webgl.drawArraysInstanced(.triangles, 0, circle.len, @intCast(self.len)); + + webgl.bindVertexArray(line_program.vao); + webgl.useProgram(line_program.prog); + webgl.uniform2f(line_program.res_uniform_location, width, height); + + webgl.bindBuffer(.array_buffer, line_program.pos_buffer); + webgl.bufferData(.array_buffer, @ptrCast(self.lines), self.len * 2 * 2, .dynamic_draw); + + webgl.bindBuffer(.array_buffer, line_program.col_buffer); webgl.bufferData(.array_buffer, @ptrCast(self.colors), self.len, .dynamic_draw); - webgl.drawArraysInstanced(.triangles, 0, circle.len, @intCast(self.len)); + webgl.drawArraysInstanced(.lines, 0, 2, @intCast(self.len)); } }; @@ -318,17 +407,18 @@ export fn update(elapsed_time: f32) void { pdown = down; webgl.viewport(0, 0, 1280, 720); - webgl.useProgram(prog); - webgl.bindVertexArray(vao); - webgl.uniform2f(res_uniform_location, 1280, 720); + webgl.useProgram(circle_program.prog); + webgl.bindVertexArray(circle_program.vao); + webgl.uniform2f(circle_program.res_uniform_location, 1280, 720); webgl.clearColor(0.0, 0.0, 0.0, 1.0); - webgl.clear(webgl.color_buffer_bit); + webgl.clear(webgl.color_buffer_bit | webgl.depth_buffer_bit); var batch: DrawBatch = .{ .translation = &translation_data, .colors = &color_data, .scales = &scale_data, + .lines = &line_data, }; const width = getScreenWidth(); @@ -338,24 +428,22 @@ export fn update(elapsed_time: f32) void { s.dist -= speed; const plen = lerp(1000, s.initial_len, s.pdist / max_dist); const psx = (@cos(s.angle) * plen) + width * 0.5; - _ = psx; const psy = (@sin(s.angle) * plen) + height * 0.5; - _ = psy; const len = lerp(1000, s.initial_len, s.dist / max_dist); const sx = (@cos(s.angle) * len) + width * 0.5; const sy = (@sin(s.angle) * len) + height * 0.5; const scale = lerp(8, 0, s.dist / max_dist); - batch.addInstance(.{ sx, sy }, s.hue, scale) catch unreachable; + batch.addInstance(.{ sx, sy }, .{ psx, psy }, s.hue, scale) catch unreachable; if (batch.len == batch_capacity) { batch.draw(); batch.len = 0; } - if (sx < 0 or sx > 1280 or sy < 0 or sy > height) { - s.angle = lerp(0, 2 * pi, rng.randFloat(f32)); - s.initial_len = lerp(0, 360, rng.randFloat(f32)); + if (sx < 0 or sx > width or sy < 0 or sy > height + 32) { + s.angle = lerp(0, 8 * pi, rng.randFloat(f32)); + s.initial_len = lerp(0, height, rng.randFloat(f32)); s.dist = max_dist; s.pdist = max_dist; } diff --git a/src/webgl.js b/src/webgl.js index 7df5be8..5c55de0 100644 --- a/src/webgl.js +++ b/src/webgl.js @@ -5,6 +5,7 @@ if (gfx_ctx === null) { } gfx_ctx.enable(gfx_ctx.BLEND); +gfx_ctx.enable(gfx_ctx.DEPTH_TEST); gfx_ctx.blendFunc(gfx_ctx.SRC_ALPHA, gfx_ctx.ONE_MINUS_SRC_ALPHA); let next_id = 0; diff --git a/src/webgl.zig b/src/webgl.zig index 4a1658d..0343bff 100644 --- a/src/webgl.zig +++ b/src/webgl.zig @@ -31,6 +31,7 @@ pub const GLUsagePattern = enum(u32) { }; pub const color_buffer_bit = 0x00004000; +pub const depth_buffer_bit = 0x00000100; pub extern fn clearColor(r: f32, g: f32, b: f32, a: f32) void; pub extern fn clear(mask: u32) void; |