summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralaric <alaric@netmythos.org>2024-03-30 18:36:47 -0700
committeralaric <alaric@netmythos.org>2024-03-30 18:36:47 -0700
commit05e8fc7dd6f59402a92d001f34d13ccc7971b49b (patch)
tree3fe065659a06f48004073369d186dd28dddde92f
parent17223eee868dfcd8f12bb2fd3b75acc0b2d0529a (diff)
downloadcolordots-05e8fc7dd6f59402a92d001f34d13ccc7971b49b.tar.gz
colordots-05e8fc7dd6f59402a92d001f34d13ccc7971b49b.zip
Neat line fan
-rw-r--r--src/line_vertex.glsl34
-rw-r--r--src/shell.html5
-rw-r--r--src/vertex.glsl2
-rw-r--r--src/wasm_ttd.zig256
-rw-r--r--src/webgl.js1
-rw-r--r--src/webgl.zig1
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;