From 7c602529040fa7df9fa5f9595c0e080b278d61ca Mon Sep 17 00:00:00 2001 From: mikael-lovqvists-claude-agent Date: Sun, 10 May 2026 19:49:46 +0000 Subject: [PATCH] Add grid color and opacity controls Edge shader now takes u_edge_color and u_edge_opacity uniforms. Grid section added to sidebar with a color picker and opacity slider. Blending enabled around edge draw call to support sub-1 opacity. Co-Authored-By: Claude Sonnet 4.6 --- standalone/goldberg-sphere/index.html | 13 ++++++ .../goldberg-sphere/playground_main.mjs | 42 +++++++++++++++++++ standalone/goldberg-sphere/shaders/edge.frag | 4 +- 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/standalone/goldberg-sphere/index.html b/standalone/goldberg-sphere/index.html index 307077d..e36b3b9 100644 --- a/standalone/goldberg-sphere/index.html +++ b/standalone/goldberg-sphere/index.html @@ -133,6 +133,19 @@ +
+

Grid

+
+ +
+
+
+ + + 1.00 +
+
+

Noise

diff --git a/standalone/goldberg-sphere/playground_main.mjs b/standalone/goldberg-sphere/playground_main.mjs index 1e974a0..763f62c 100644 --- a/standalone/goldberg-sphere/playground_main.mjs +++ b/standalone/goldberg-sphere/playground_main.mjs @@ -31,6 +31,7 @@ const spin = new Spin_State(); const paint = new Paint_State(); const undo_state = new Undo_State(); const env = new Env_State(); +const grid_state = { color: [0.05, 0.05, 0.05], opacity: 1.0 }; let current_geo = null; let current_palette = DEFAULT_PALETTE; let building = false; @@ -681,10 +682,15 @@ function render_frame(ts) { gl.disable(gl.POLYGON_OFFSET_FILL); gl.useProgram(edge_prog); gl.uniformMatrix4fv(gl.getUniformLocation(edge_prog, 'u_mvp'), false, mvp); + gl.uniform3fv(gl.getUniformLocation(edge_prog, 'u_edge_color'), grid_state.color); + gl.uniform1f(gl.getUniformLocation(edge_prog, 'u_edge_opacity'), grid_state.opacity); + gl.enable(gl.BLEND); + gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); const ep = gl.getAttribLocation(edge_prog, 'a_pos'); gl.bindBuffer(gl.ARRAY_BUFFER, edge_pos_buf); gl.enableVertexAttribArray(ep); gl.vertexAttribPointer(ep, 3, gl.FLOAT, false, 0, 0); gl.drawArrays(gl.LINES, 0, edge_verts); gl.disableVertexAttribArray(ep); + gl.disable(gl.BLEND); gl.enable(gl.POLYGON_OFFSET_FILL); @@ -1073,6 +1079,42 @@ function _hsl_to_rgb(h,s,l) { sync_env_ui(); } +// --------------------------------------------------------------------------- +// Grid UI wiring +// --------------------------------------------------------------------------- + +{ + const btn = document.getElementById('grid-color-btn'); + const opacity = document.getElementById('grid-opacity'); + const opacity_val = document.getElementById('grid-opacity-val'); + + const hex_from = c => { + const h = v => Math.round(Math.min(v, 1) * 255).toString(16).padStart(2, '0'); + return `#${h(c[0])}${h(c[1])}${h(c[2])}`; + }; + + btn.style.background = hex_from(grid_state.color); + btn.addEventListener('click', () => { + color_dialog_open({ + get: () => hex_from(grid_state.color), + set: hex => { + const r = parseInt(hex.slice(1, 3), 16) / 255; + const g = parseInt(hex.slice(3, 5), 16) / 255; + const b = parseInt(hex.slice(5, 7), 16) / 255; + grid_state.color = [r, g, b]; + btn.style.background = hex; + request_render(); + }, + }); + }); + + opacity.addEventListener('input', () => { + grid_state.opacity = parseFloat(opacity.value); + opacity_val.textContent = grid_state.opacity.toFixed(2); + request_render(); + }); +} + // --------------------------------------------------------------------------- // Keyboard shortcuts // --------------------------------------------------------------------------- diff --git a/standalone/goldberg-sphere/shaders/edge.frag b/standalone/goldberg-sphere/shaders/edge.frag index c9a8140..beadcb1 100644 --- a/standalone/goldberg-sphere/shaders/edge.frag +++ b/standalone/goldberg-sphere/shaders/edge.frag @@ -1,2 +1,4 @@ precision mediump float; -void main() { gl_FragColor = vec4(0.05, 0.05, 0.05, 1.0); } +uniform vec3 u_edge_color; +uniform float u_edge_opacity; +void main() { gl_FragColor = vec4(u_edge_color, u_edge_opacity); }