From de9bc553ed0e8bda42057ac441936c20a8185f60 Mon Sep 17 00:00:00 2001 From: skal Date: Sat, 21 Feb 2026 09:44:17 +0100 Subject: refactor(wgsl): Use vec*f alias for vector types Replaces all instances of `vec` with the more concise `vec*f` alias (e.g., `vec3f`) across all `.wgsl` shaders. This improves readability and aligns with common graphics programming conventions. Also adds a new coding style rule to `doc/CODING_STYLE.md` to enforce this standard going forward. Finally, this commit fixes a build error in `test_effect_base.cc` by replacing a call to the non-existent `wgpuDeviceTick` with `wgpuDevicePoll`, which resolves the test failure. --- cnn_v1/shaders/cnn_conv1x1.wgsl | 2 +- cnn_v1/shaders/cnn_conv3x3.wgsl | 2 +- cnn_v1/shaders/cnn_conv5x5.wgsl | 2 +- cnn_v1/shaders/cnn_layer.wgsl | 2 +- cnn_v2/shaders/cnn_v2_compute.wgsl | 2 +- common/shaders/camera_common.wgsl | 24 ++++++++--------- common/shaders/combined_postprocess.wgsl | 2 +- common/shaders/math/common_utils.wgsl | 6 ++--- common/shaders/render/raymarching.wgsl | 10 +++---- common/shaders/render/raymarching_id.wgsl | 12 ++++----- doc/CODING_STYLE.md | 18 +++++++++++++ src/tests/gpu/test_effect_base.cc | 2 +- workspaces/main/shaders/scene1.wgsl | 44 +++++++++++++++---------------- workspaces/main/shaders/sdf_test.wgsl | 16 +++++------ 14 files changed, 81 insertions(+), 63 deletions(-) diff --git a/cnn_v1/shaders/cnn_conv1x1.wgsl b/cnn_v1/shaders/cnn_conv1x1.wgsl index f77cfa8..a6fb84a 100644 --- a/cnn_v1/shaders/cnn_conv1x1.wgsl +++ b/cnn_v1/shaders/cnn_conv1x1.wgsl @@ -45,7 +45,7 @@ fn cnn_conv1x1_7to4_src( let step = 1.0 / resolution; var original = (textureSample(tex, samp, uv) - 0.5) * 2.0; - let gray = dot(original.rgb, vec3(0.2126, 0.7152, 0.0722)); + let gray = dot(original.rgb, vec3f(0.2126, 0.7152, 0.0722)); let uv_norm = (uv - 0.5) * 2.0; let in1 = vec4(uv_norm, gray, 1.0); diff --git a/cnn_v1/shaders/cnn_conv3x3.wgsl b/cnn_v1/shaders/cnn_conv3x3.wgsl index f7d11b1..4fddd24 100644 --- a/cnn_v1/shaders/cnn_conv3x3.wgsl +++ b/cnn_v1/shaders/cnn_conv3x3.wgsl @@ -45,7 +45,7 @@ fn cnn_conv3x3_7to4_src( let step = 1.0 / resolution; let original = (textureSample(tex, samp, uv) - 0.5) * 2.0; - let gray = dot(original.rgb, vec3(0.2126, 0.7152, 0.0722)); + let gray = dot(original.rgb, vec3f(0.2126, 0.7152, 0.0722)); let uv_norm = (uv - 0.5) * 2.0; let in1 = vec4(uv_norm, gray, 1.0); diff --git a/cnn_v1/shaders/cnn_conv5x5.wgsl b/cnn_v1/shaders/cnn_conv5x5.wgsl index 9328d75..415938e 100644 --- a/cnn_v1/shaders/cnn_conv5x5.wgsl +++ b/cnn_v1/shaders/cnn_conv5x5.wgsl @@ -77,7 +77,7 @@ fn cnn_conv5x5_7to4_src( let step = 1.0 / resolution; let original = (textureSample(tex, samp, uv) - 0.5) * 2.0; - let gray = dot(original.rgb, vec3(0.2126, 0.7152, 0.0722)); + let gray = dot(original.rgb, vec3f(0.2126, 0.7152, 0.0722)); let uv_norm = (uv - 0.5) * 2.0; let in1 = vec4(uv_norm, gray, 1.0); diff --git a/cnn_v1/shaders/cnn_layer.wgsl b/cnn_v1/shaders/cnn_layer.wgsl index cbd1686..c35cb39 100644 --- a/cnn_v1/shaders/cnn_layer.wgsl +++ b/cnn_v1/shaders/cnn_layer.wgsl @@ -33,7 +33,7 @@ struct CNNLayerParams { let uv = (p.xy - 0.5) / (uniforms.resolution - 1.0); let original_raw = textureSample(original_input, smplr, uv); let original = (original_raw - 0.5) * 2.0; // Normalize to [-1,1] - let gray = (dot(original_raw.rgb, vec3(0.2126, 0.7152, 0.0722)) - 0.5) * 2.0; + let gray = (dot(original_raw.rgb, vec3f(0.2126, 0.7152, 0.0722)) - 0.5) * 2.0; var result = vec4(0.0); // Layer 0: 7→4 (RGBD output, normalizes [0,1] input) diff --git a/cnn_v2/shaders/cnn_v2_compute.wgsl b/cnn_v2/shaders/cnn_v2_compute.wgsl index cdbfd74..c788f69 100644 --- a/cnn_v2/shaders/cnn_v2_compute.wgsl +++ b/cnn_v2/shaders/cnn_v2_compute.wgsl @@ -132,7 +132,7 @@ fn main(@builtin(global_invocation_id) id: vec3) { // Blend with original on final layer if (is_output) { let original = textureLoad(original_input, coord, 0).rgb; - let result_rgb = vec3(output.x, output.y, output.z); + let result_rgb = vec3f(output.x, output.y, output.z); let blended = mix(original, result_rgb, params.blend_amount); output.x = blended.r; output.y = blended.g; diff --git a/common/shaders/camera_common.wgsl b/common/shaders/camera_common.wgsl index bd29775..c7daebf 100644 --- a/common/shaders/camera_common.wgsl +++ b/common/shaders/camera_common.wgsl @@ -9,17 +9,17 @@ struct CameraParams { } struct Ray { - origin: vec3, - direction: vec3, + origin: vec3f, + direction: vec3f, } // Generate camera ray for given UV coordinates (-1 to 1) fn getCameraRay(cam: CameraParams, uv: vec2) -> Ray { - let cam_pos = vec3(cam.inv_view[3].x, cam.inv_view[3].y, cam.inv_view[3].z); + let cam_pos = vec3f(cam.inv_view[3].x, cam.inv_view[3].y, cam.inv_view[3].z); // Compute ray direction from FOV and aspect ratio let tan_fov = tan(cam.fov * 0.5); - let ndc = vec3(uv.x * cam.aspect_ratio * tan_fov, uv.y * tan_fov, -1.0); + let ndc = vec3f(uv.x * cam.aspect_ratio * tan_fov, uv.y * tan_fov, -1.0); // Transform direction by inverse view matrix (rotation only) let dir = normalize( @@ -32,21 +32,21 @@ fn getCameraRay(cam: CameraParams, uv: vec2) -> Ray { } // Extract camera position from inverse view matrix -fn getCameraPosition(cam: CameraParams) -> vec3 { - return vec3(cam.inv_view[3].x, cam.inv_view[3].y, cam.inv_view[3].z); +fn getCameraPosition(cam: CameraParams) -> vec3f { + return vec3f(cam.inv_view[3].x, cam.inv_view[3].y, cam.inv_view[3].z); } // Extract camera forward vector (view direction) -fn getCameraForward(cam: CameraParams) -> vec3 { - return -normalize(vec3(cam.inv_view[2].x, cam.inv_view[2].y, cam.inv_view[2].z)); +fn getCameraForward(cam: CameraParams) -> vec3f { + return -normalize(vec3f(cam.inv_view[2].x, cam.inv_view[2].y, cam.inv_view[2].z)); } // Extract camera up vector -fn getCameraUp(cam: CameraParams) -> vec3 { - return normalize(vec3(cam.inv_view[1].x, cam.inv_view[1].y, cam.inv_view[1].z)); +fn getCameraUp(cam: CameraParams) -> vec3f { + return normalize(vec3f(cam.inv_view[1].x, cam.inv_view[1].y, cam.inv_view[1].z)); } // Extract camera right vector -fn getCameraRight(cam: CameraParams) -> vec3 { - return normalize(vec3(cam.inv_view[0].x, cam.inv_view[0].y, cam.inv_view[0].z)); +fn getCameraRight(cam: CameraParams) -> vec3f { + return normalize(vec3f(cam.inv_view[0].x, cam.inv_view[0].y, cam.inv_view[0].z)); } diff --git a/common/shaders/combined_postprocess.wgsl b/common/shaders/combined_postprocess.wgsl index ea65761..d56386e 100644 --- a/common/shaders/combined_postprocess.wgsl +++ b/common/shaders/combined_postprocess.wgsl @@ -28,7 +28,7 @@ struct VertexOutput { // Apply effects in sequence (customize as needed) // color = apply_solarize(color, 0.4, 0.4, uniforms.time); - // color = apply_theme(color, vec3(1.0, 0.8, 0.6), 0.3); + // color = apply_theme(color, vec3f(1.0, 0.8, 0.6), 0.3); color = apply_vignette(color, in.uv, 0.6, 0.1, uniforms.audio_intensity); // color = apply_flash(color, uniforms.beat_phase * 0.2); diff --git a/common/shaders/math/common_utils.wgsl b/common/shaders/math/common_utils.wgsl index 49aaead..b8446b4 100644 --- a/common/shaders/math/common_utils.wgsl +++ b/common/shaders/math/common_utils.wgsl @@ -6,21 +6,21 @@ const PI: f32 = 3.14159265359; const TAU: f32 = 6.28318530718; // Transform normal from local to world space using inverse model matrix -fn transform_normal(inv_model: mat4x4, normal_local: vec3) -> vec3 { +fn transform_normal(inv_model: mat4x4, normal_local: vec3f) -> vec3f { let normal_matrix = mat3x3(inv_model[0].xyz, inv_model[1].xyz, inv_model[2].xyz); return normalize(normal_matrix * normal_local); } // Spherical UV mapping (sphere or any radial surface) // Returns UV in [0,1] range -fn spherical_uv(p: vec3) -> vec2 { +fn spherical_uv(p: vec3f) -> vec2 { let u = atan2(p.x, p.z) / TAU + 0.5; let v = acos(clamp(p.y / length(p), -1.0, 1.0)) / PI; return vec2(u, v); } // Spherical UV from direction vector (for skybox, etc.) -fn spherical_uv_from_dir(dir: vec3) -> vec2 { +fn spherical_uv_from_dir(dir: vec3f) -> vec2 { let u = atan2(dir.z, dir.x) / TAU + 0.5; let v = asin(clamp(dir.y, -1.0, 1.0)) / PI + 0.5; return vec2(u, v); diff --git a/common/shaders/render/raymarching.wgsl b/common/shaders/render/raymarching.wgsl index fb96348..4e0327b 100644 --- a/common/shaders/render/raymarching.wgsl +++ b/common/shaders/render/raymarching.wgsl @@ -1,7 +1,7 @@ // Common functions for Signed Distance Field (SDF) raymarching. // // Required user-defined functions: -// - df(vec3) -> f32 +// - df(vec3f) -> f32 // Distance field for single-pass rendering (rayMarch, normal, shadow) // // For two-pass rendering with object IDs, see raymarching_id.wgsl @@ -15,9 +15,9 @@ const MAX_RAY_MARCHES: i32 = 80; const NORM_OFF: f32 = 0.005; // Computes the surface normal of the distance field at a point `pos`. -fn normal(pos: vec3) -> vec3 { +fn normal(pos: vec3f) -> vec3f { let eps = vec2(NORM_OFF, 0.0); - var nor: vec3; + var nor: vec3f; nor.x = df(pos + eps.xyy) - df(pos - eps.xyy); nor.y = df(pos + eps.yxy) - df(pos - eps.yxy); nor.z = df(pos + eps.yyx) - df(pos - eps.yyx); @@ -26,7 +26,7 @@ fn normal(pos: vec3) -> vec3 { // Performs the raymarching operation. // Returns the distance along the ray to the surface, or MAX_RAY_LENGTH if no surface is hit. -fn rayMarch(ro: vec3, rd: vec3, tmin: f32) -> f32 { +fn rayMarch(ro: vec3f, rd: vec3f, tmin: f32) -> f32 { var t = tmin; for (var i = 0; i < MAX_RAY_MARCHES; i++) { if (t > MAX_RAY_LENGTH) { @@ -43,7 +43,7 @@ fn rayMarch(ro: vec3, rd: vec3, tmin: f32) -> f32 { } // Computes a soft shadow for a given point. -fn shadow(lp: vec3, ld: vec3, mint: f32, maxt: f32) -> f32 { +fn shadow(lp: vec3f, ld: vec3f, mint: f32, maxt: f32) -> f32 { let ds = 1.0 - 0.4; var t = mint; var nd = 1e6; diff --git a/common/shaders/render/raymarching_id.wgsl b/common/shaders/render/raymarching_id.wgsl index d16445e..42be02d 100644 --- a/common/shaders/render/raymarching_id.wgsl +++ b/common/shaders/render/raymarching_id.wgsl @@ -1,7 +1,7 @@ // Common functions for Signed Distance Field (SDF) raymarching with object ID. // // Required user-defined functions: -// - dfWithID(vec3) -> RayMarchResult +// - dfWithID(vec3f) -> RayMarchResult // // Requires constants from raymarching.wgsl: // TOLERANCE, MAX_RAY_LENGTH, MAX_RAY_MARCHES, NORM_OFF @@ -21,7 +21,7 @@ struct RayMarchResult { } // Raymarch with object ID tracking. -fn rayMarchWithID(ro: vec3, rd: vec3, init: RayMarchResult) -> RayMarchResult { +fn rayMarchWithID(ro: vec3f, rd: vec3f, init: RayMarchResult) -> RayMarchResult { var t = init.distance; var result = init; @@ -45,14 +45,14 @@ fn rayMarchWithID(ro: vec3, rd: vec3, init: RayMarchResult) -> RayMarc } // Reconstruct world position from stored result. -fn reconstructPosition(ray: Ray, result: RayMarchResult) -> vec3 { +fn reconstructPosition(ray: Ray, result: RayMarchResult) -> vec3f { return ray.origin + ray.direction * result.distance; } // Normal calculation using dfWithID. -fn normalWithID(pos: vec3) -> vec3 { +fn normalWithID(pos: vec3f) -> vec3f { let eps = vec2(NORM_OFF, 0.0); - var nor: vec3; + var nor: vec3f; nor.x = dfWithID(pos + eps.xyy).distance - dfWithID(pos - eps.xyy).distance; nor.y = dfWithID(pos + eps.yxy).distance - dfWithID(pos - eps.yxy).distance; nor.z = dfWithID(pos + eps.yyx).distance - dfWithID(pos - eps.yyx).distance; @@ -60,7 +60,7 @@ fn normalWithID(pos: vec3) -> vec3 { } // Shadow using stored intersection distance. -fn shadowWithStoredDistance(lp: vec3, ld: vec3, stored_dist: f32) -> f32 { +fn shadowWithStoredDistance(lp: vec3f, ld: vec3f, stored_dist: f32) -> f32 { let ds = 1.0 - 0.4; var t = 0.01; var nd = 1e6; diff --git a/doc/CODING_STYLE.md b/doc/CODING_STYLE.md index b688d6b..57d4478 100644 --- a/doc/CODING_STYLE.md +++ b/doc/CODING_STYLE.md @@ -170,6 +170,24 @@ fn rayMarchWithID(ro: vec3, rd: vec3, result: ptr` adds complexity with no performance gain for small types +### Vector and Matrix Type Aliases + +**Rule:** Use concise aliases for vector and matrix types (`vec3f`, `mat4x4f`) instead of the verbose generic form (`vec3`, `mat4x4`). + +```wgsl +// Correct +var p: vec3f; +var m: mat4x4f; + +// Wrong +var p: vec3; +var m: mat4x4; +``` + +**Rationale:** +- Improves readability and reduces visual noise. +- Aligns with common graphics programming conventions. + --- ## WGPU Object Initialization diff --git a/src/tests/gpu/test_effect_base.cc b/src/tests/gpu/test_effect_base.cc index e55b254..68aabe3 100644 --- a/src/tests/gpu/test_effect_base.cc +++ b/src/tests/gpu/test_effect_base.cc @@ -166,7 +166,7 @@ static void test_sequence_render() { wgpuCommandBufferRelease(commands); // Wait for the GPU to complete rendering to avoid race conditions on exit. - wgpuDeviceTick(fixture.device()); + wgpuDevicePoll(fixture.device(), true, nullptr); fprintf(stdout, " ✓ Sequence rendered without error\n"); } diff --git a/workspaces/main/shaders/scene1.wgsl b/workspaces/main/shaders/scene1.wgsl index 87949fa..8cc36cd 100644 --- a/workspaces/main/shaders/scene1.wgsl +++ b/workspaces/main/shaders/scene1.wgsl @@ -12,23 +12,23 @@ @group(0) @binding(2) var uniforms: UniformsSequenceParams; @group(0) @binding(3) var camera: CameraParams; -const skyCol = vec3(0.176, 0.235, 0.25); -const skylineCol = vec3(0.5, 0.125, 0.025); -const sunCol = vec3(0.5, 0.163, 0.025); -const diffCol1 = vec3(0.4, 1.0, 1.0); -const diffCol2 = vec3(0.325, 1.0, 0.975); +const skyCol = vec3f(0.176, 0.235, 0.25); +const skylineCol = vec3f(0.5, 0.125, 0.025); +const sunCol = vec3f(0.5, 0.163, 0.025); +const diffCol1 = vec3f(0.4, 1.0, 1.0); +const diffCol2 = vec3f(0.325, 1.0, 0.975); // Lighting (normalized manually) -const sunDir1 = vec3(0.0, 0.04997, -0.99875); // normalize(0, 0.05, -1) -const lightPos1 = vec3(10.0, 10.0, 10.0); -const lightPos2 = vec3(-10.0, 10.0, -10.0); +const sunDir1 = vec3f(0.0, 0.04997, -0.99875); // normalize(0, 0.05, -1) +const lightPos1 = vec3f(10.0, 10.0, 10.0); +const lightPos2 = vec3f(-10.0, 10.0, -10.0); fn rayPlane(ray: Ray, plane: vec4) -> f32 { return (dot(ray.origin, plane.xyz) - plane.w) / dot(ray.direction, plane.xyz); } -fn render0(ray: Ray) -> vec3 { - var col = vec3(0.0); +fn render0(ray: Ray) -> vec3f { + var col = vec3f(0.0); let y = abs(ray.direction.y); let sf = 1.0001 - max(dot(sunDir1, ray.direction), 0.0); col += skyCol * pow(y, 8.0); @@ -41,11 +41,11 @@ fn render0(ray: Ray) -> vec3 { let pos = ray.origin + tp1 * ray.direction; let pp = pos.xz; let db = sdBox2D(pp, vec2(5.0, 9.0)) - 3.0; - col += vec3(4.0) * skyCol * y * y * smoothstep(0.25, 0.0, db); - col += vec3(0.8) * skyCol * exp(-0.5 * max(db, 0.0)); + col += vec3f(4.0) * skyCol * y * y * smoothstep(0.25, 0.0, db); + col += vec3f(0.8) * skyCol * exp(-0.5 * max(db, 0.0)); } */ - return clamp(col, vec3(0.0), vec3(10.0)); + return clamp(col, vec3f(0.0), vec3f(10.0)); } const OBJ_BACKGROUND: f32 = 0.0; @@ -54,17 +54,17 @@ const OBJ_SPHERE: f32 = 2.0; const OBJ_PLANE: f32 = 3.0; // TODO: remove! (issue with #include macros) -fn df(p: vec3) -> f32 { +fn df(p: vec3f) -> f32 { return 0.; } -fn dfWithID(p: vec3) -> RayMarchResult { +fn dfWithID(p: vec3f) -> RayMarchResult { // Cube - var pc = p - vec3(-1.9, 0.0, 0.0); - let dCube = sdBox(pc, vec3(1.6)); + var pc = p - vec3f(-1.9, 0.0, 0.0); + let dCube = sdBox(pc, vec3f(1.6)); // Sphere - var ps = p - vec3(1.3, 0.0, 0.0); + var ps = p - vec3f(1.3, 0.0, 0.0); let dSphere = sdSphere(ps, 1.2); // Ground plane @@ -89,7 +89,7 @@ fn dfWithID(p: vec3) -> RayMarchResult { return result; } -fn boxCol(col: vec3, nsp: vec3, rd: vec3, nnor: vec3, nrcol: vec3, nshd1: f32, nshd2: f32) -> vec3 { +fn boxCol(col: vec3f, nsp: vec3f, rd: vec3f, nnor: vec3f, nrcol: vec3f, nshd1: f32, nshd2: f32) -> vec3f { var nfre = 1.0 + dot(rd, nnor); nfre *= nfre; @@ -102,17 +102,17 @@ fn boxCol(col: vec3, nsp: vec3, rd: vec3, nnor: vec3, nrcol: var ndif2 = max(dot(nld2, nnor), 0.0); ndif2 *= ndif2; - var scol = vec3(0.0); + var scol = vec3f(0.0); let rf = smoothstep(1.0, 0.9, nfre); scol += diffCol1 * ndif1 * nshd1; scol += diffCol2 * ndif2 * nshd2; scol += 0.1 * (skyCol + skylineCol); - scol += nrcol * 0.75 * mix(vec3(0.25), vec3(0.5, 0.5, 1.0), nfre); + scol += nrcol * 0.75 * mix(vec3f(0.25), vec3f(0.5, 0.5, 1.0), nfre); return mix(col, scol, rf * smoothstep(90.0, 20.0, dot(nsp, nsp))); } -fn render1(ray: Ray) -> vec3 { +fn render1(ray: Ray) -> vec3f { let skyCol_local = render0(ray); var col = skyCol_local; diff --git a/workspaces/main/shaders/sdf_test.wgsl b/workspaces/main/shaders/sdf_test.wgsl index 3c97613..3b63fef 100644 --- a/workspaces/main/shaders/sdf_test.wgsl +++ b/workspaces/main/shaders/sdf_test.wgsl @@ -10,27 +10,27 @@ @group(0) @binding(1) var camera: CameraParams; // Scene distance function -fn df(p: vec3) -> f32 { +fn df(p: vec3f) -> f32 { // Animated sphere - let sphere_pos = vec3(sin(uniforms.beat_time * 0.5) * 2.0, 0.0, 0.0); + let sphere_pos = vec3f(sin(uniforms.beat_time * 0.5) * 2.0, 0.0, 0.0); let d_sphere = sdSphere(p - sphere_pos, 1.0); // Static box - let box_pos = vec3(0.0, -2.0, 0.0); - let d_box = sdBox(p - box_pos, vec3(3.0, 0.5, 3.0)); + let box_pos = vec3f(0.0, -2.0, 0.0); + let d_box = sdBox(p - box_pos, vec3f(3.0, 0.5, 3.0)); return min(d_sphere, d_box); } // Simple lighting -fn shade(pos: vec3, rd: vec3) -> vec3 { +fn shade(pos: vec3f, rd: vec3f) -> vec3f { let n = normal(pos); - let light_dir = normalize(vec3(1.0, 1.0, -1.0)); + let light_dir = normalize(vec3f(1.0, 1.0, -1.0)); let diff = max(dot(n, light_dir), 0.0); let amb = 0.2; // Color based on position - let col = mix(vec3(0.2, 0.6, 0.9), vec3(0.9, 0.3, 0.2), + let col = mix(vec3f(0.2, 0.6, 0.9), vec3f(0.9, 0.3, 0.2), smoothstep(-2.0, 2.0, pos.x)); return col * (diff + amb); @@ -56,7 +56,7 @@ fn fs_main(@builtin(position) pos: vec4) -> @location(0) vec4 { let t = rayMarch(ray.origin, ray.direction, 0.0); // Background color - var col = vec3(0.1, 0.1, 0.15); + var col = vec3f(0.1, 0.1, 0.15); // Shade hit point if (t < MAX_RAY_LENGTH) { -- cgit v1.2.3