summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/COMPLETED.md15
-rw-r--r--src/tests/gpu/test_shader_assets.cc11
-rw-r--r--workspaces/main/shaders/circle_mask_compute.wgsl12
-rw-r--r--workspaces/main/shaders/circle_mask_render.wgsl11
-rw-r--r--workspaces/main/shaders/ellipse.wgsl10
-rw-r--r--workspaces/main/shaders/gaussian_blur.wgsl11
-rw-r--r--workspaces/test/shaders/circle_mask_compute.wgsl12
-rw-r--r--workspaces/test/shaders/circle_mask_render.wgsl11
-rw-r--r--workspaces/test/shaders/ellipse.wgsl10
-rw-r--r--workspaces/test/shaders/gaussian_blur.wgsl11
10 files changed, 33 insertions, 81 deletions
diff --git a/doc/COMPLETED.md b/doc/COMPLETED.md
index c7b2cae..dddcc3e 100644
--- a/doc/COMPLETED.md
+++ b/doc/COMPLETED.md
@@ -29,6 +29,21 @@ Detailed historical documents have been moved to `doc/archive/` for reference:
Use `read @doc/archive/FILENAME.md` to access archived documents.
+## Recently Completed (February 14, 2026)
+
+- [x] **Fullscreen Vertex Shader Modularization**
+ - **Goal**: Eliminate duplicate fullscreen triangle vertex shader code
+ - **Changes**:
+ - Replaced inline `vs_main()` with `#include "render/fullscreen_vs"` in 8 shaders
+ - Updated test_shader_assets.cc validation for ELLIPSE and GAUSSIAN_BLUR
+ - Modified shaders: circle_mask_compute, circle_mask_render, ellipse, gaussian_blur (main/test workspaces)
+ - **Impact**:
+ - ~60 lines eliminated across codebase
+ - Better maintainability: single source of truth for fullscreen vertex shader
+ - Consistent with existing pattern (solarize, distort, chroma_aberration, vignette)
+ - **Result**: 34/34 tests passing (100%)
+ - **Related**: Task #50 (WGSL Modularization)
+
## Recently Completed (February 11, 2026)
- [x] **Effect Render API Refactor**
diff --git a/src/tests/gpu/test_shader_assets.cc b/src/tests/gpu/test_shader_assets.cc
index 7f2811e..1736dc0 100644
--- a/src/tests/gpu/test_shader_assets.cc
+++ b/src/tests/gpu/test_shader_assets.cc
@@ -63,13 +63,14 @@ int main() {
all_passed &=
validate_shader(AssetId::ASSET_SHADER_PASSTHROUGH, "PASSTHROUGH",
{"@vertex", "vs_main", "@fragment", "fs_main"});
- all_passed &= validate_shader(AssetId::ASSET_SHADER_ELLIPSE, "ELLIPSE",
- {"@vertex", "vs_main", "@fragment", "fs_main"});
+ all_passed &= validate_shader(
+ AssetId::ASSET_SHADER_ELLIPSE, "ELLIPSE",
+ {"#include \"render/fullscreen_vs\"", "@fragment", "fs_main"});
all_passed &= validate_shader(AssetId::ASSET_SHADER_PARTICLE_SPRAY_COMPUTE,
"PARTICLE_SPRAY_COMPUTE", {"@compute", "main"});
- all_passed &=
- validate_shader(AssetId::ASSET_SHADER_GAUSSIAN_BLUR, "GAUSSIAN_BLUR",
- {"@vertex", "vs_main", "@fragment", "fs_main"});
+ all_passed &= validate_shader(
+ AssetId::ASSET_SHADER_GAUSSIAN_BLUR, "GAUSSIAN_BLUR",
+ {"#include \"render/fullscreen_vs\"", "@fragment", "fs_main"});
all_passed &= validate_shader(
AssetId::ASSET_SHADER_SOLARIZE, "SOLARIZE",
{"#include \"render/fullscreen_vs\"", "@fragment", "fs_main"});
diff --git a/workspaces/main/shaders/circle_mask_compute.wgsl b/workspaces/main/shaders/circle_mask_compute.wgsl
index 484d3dd..b167781 100644
--- a/workspaces/main/shaders/circle_mask_compute.wgsl
+++ b/workspaces/main/shaders/circle_mask_compute.wgsl
@@ -2,6 +2,8 @@
// Generates a circular mask (1.0 inside, 0.0 outside)
#include "common_uniforms"
+#include "render/fullscreen_vs"
+
struct CircleMaskParams {
radius: f32,
_pad0: f32,
@@ -12,16 +14,6 @@ struct CircleMaskParams {
@group(0) @binding(0) var<uniform> uniforms: CommonUniforms;
@group(0) @binding(1) var<uniform> params: CircleMaskParams;
-struct VSOutput {
- @builtin(position) position: vec4<f32>,
-};
-
-@vertex fn vs_main(@builtin(vertex_index) i: u32) -> VSOutput {
- var pos = array<vec2<f32>, 3>(
- vec2<f32>(-1, -1), vec2<f32>(3, -1), vec2<f32>(-1, 3));
- return VSOutput(vec4<f32>(pos[i], 0.0, 1.0));
-}
-
@fragment fn fs_main(@builtin(position) p: vec4<f32>) -> @location(0) vec4<f32> {
let uv = p.xy / uniforms.resolution;
let center = vec2<f32>(0.5, 0.5);
diff --git a/workspaces/main/shaders/circle_mask_render.wgsl b/workspaces/main/shaders/circle_mask_render.wgsl
index cfa002e..55620c1 100644
--- a/workspaces/main/shaders/circle_mask_render.wgsl
+++ b/workspaces/main/shaders/circle_mask_render.wgsl
@@ -5,19 +5,10 @@
@group(0) @binding(1) var mask_sampler: sampler;
#include "common_uniforms"
+#include "render/fullscreen_vs"
@group(0) @binding(2) var<uniform> uniforms: CommonUniforms;
-struct VSOutput {
- @builtin(position) position: vec4<f32>,
-};
-
-@vertex fn vs_main(@builtin(vertex_index) i: u32) -> VSOutput {
- var pos = array<vec2<f32>, 3>(
- vec2<f32>(-1, -1), vec2<f32>(3, -1), vec2<f32>(-1, 3));
- return VSOutput(vec4<f32>(pos[i], 0.0, 1.0));
-}
-
@fragment fn fs_main(@builtin(position) p: vec4<f32>) -> @location(0) vec4<f32> {
let uv = p.xy / uniforms.resolution;
let mask_value = textureSample(mask_tex, mask_sampler, uv).r;
diff --git a/workspaces/main/shaders/ellipse.wgsl b/workspaces/main/shaders/ellipse.wgsl
index 69b2712..07f0c9a 100644
--- a/workspaces/main/shaders/ellipse.wgsl
+++ b/workspaces/main/shaders/ellipse.wgsl
@@ -1,16 +1,8 @@
#include "common_uniforms"
+#include "render/fullscreen_vs"
@group(0) @binding(0) var<uniform> uniforms: CommonUniforms;
-@vertex fn vs_main(@builtin(vertex_index) i: u32) -> @builtin(position) vec4<f32> {
- var pos = array<vec2<f32>, 3>(
- vec2<f32>(-1.0, -1.0),
- vec2<f32>(3.0, -1.0),
- vec2<f32>(-1.0, 3.0)
- );
- return vec4<f32>(pos[i], 0.0, 1.0);
-}
-
fn sdEllipse(p: vec2<f32>, ab: vec2<f32>) -> f32 {
var p_abs = abs(p);
if (p_abs.x > p_abs.y) {
diff --git a/workspaces/main/shaders/gaussian_blur.wgsl b/workspaces/main/shaders/gaussian_blur.wgsl
index 02156f7..22e467f 100644
--- a/workspaces/main/shaders/gaussian_blur.wgsl
+++ b/workspaces/main/shaders/gaussian_blur.wgsl
@@ -2,6 +2,8 @@
@group(0) @binding(1) var txt: texture_2d<f32>;
#include "common_uniforms"
+#include "render/fullscreen_vs"
+
struct GaussianBlurParams {
strength: f32,
_pad: f32,
@@ -10,15 +12,6 @@ struct GaussianBlurParams {
@group(0) @binding(2) var<uniform> uniforms: CommonUniforms;
@group(0) @binding(3) var<uniform> params: GaussianBlurParams;
-@vertex fn vs_main(@builtin(vertex_index) i: u32) -> @builtin(position) vec4<f32> {
- var pos = array<vec2<f32>, 3>(
- vec2<f32>(-1, -1),
- vec2<f32>(3, -1),
- vec2<f32>(-1, 3)
- );
- return vec4<f32>(pos[i], 0.0, 1.0);
-}
-
@fragment fn fs_main(@builtin(position) p: vec4<f32>) -> @location(0) vec4<f32> {
let uv = p.xy / uniforms.resolution;
var res = vec4<f32>(0.0);
diff --git a/workspaces/test/shaders/circle_mask_compute.wgsl b/workspaces/test/shaders/circle_mask_compute.wgsl
index 484d3dd..b167781 100644
--- a/workspaces/test/shaders/circle_mask_compute.wgsl
+++ b/workspaces/test/shaders/circle_mask_compute.wgsl
@@ -2,6 +2,8 @@
// Generates a circular mask (1.0 inside, 0.0 outside)
#include "common_uniforms"
+#include "render/fullscreen_vs"
+
struct CircleMaskParams {
radius: f32,
_pad0: f32,
@@ -12,16 +14,6 @@ struct CircleMaskParams {
@group(0) @binding(0) var<uniform> uniforms: CommonUniforms;
@group(0) @binding(1) var<uniform> params: CircleMaskParams;
-struct VSOutput {
- @builtin(position) position: vec4<f32>,
-};
-
-@vertex fn vs_main(@builtin(vertex_index) i: u32) -> VSOutput {
- var pos = array<vec2<f32>, 3>(
- vec2<f32>(-1, -1), vec2<f32>(3, -1), vec2<f32>(-1, 3));
- return VSOutput(vec4<f32>(pos[i], 0.0, 1.0));
-}
-
@fragment fn fs_main(@builtin(position) p: vec4<f32>) -> @location(0) vec4<f32> {
let uv = p.xy / uniforms.resolution;
let center = vec2<f32>(0.5, 0.5);
diff --git a/workspaces/test/shaders/circle_mask_render.wgsl b/workspaces/test/shaders/circle_mask_render.wgsl
index cfa002e..55620c1 100644
--- a/workspaces/test/shaders/circle_mask_render.wgsl
+++ b/workspaces/test/shaders/circle_mask_render.wgsl
@@ -5,19 +5,10 @@
@group(0) @binding(1) var mask_sampler: sampler;
#include "common_uniforms"
+#include "render/fullscreen_vs"
@group(0) @binding(2) var<uniform> uniforms: CommonUniforms;
-struct VSOutput {
- @builtin(position) position: vec4<f32>,
-};
-
-@vertex fn vs_main(@builtin(vertex_index) i: u32) -> VSOutput {
- var pos = array<vec2<f32>, 3>(
- vec2<f32>(-1, -1), vec2<f32>(3, -1), vec2<f32>(-1, 3));
- return VSOutput(vec4<f32>(pos[i], 0.0, 1.0));
-}
-
@fragment fn fs_main(@builtin(position) p: vec4<f32>) -> @location(0) vec4<f32> {
let uv = p.xy / uniforms.resolution;
let mask_value = textureSample(mask_tex, mask_sampler, uv).r;
diff --git a/workspaces/test/shaders/ellipse.wgsl b/workspaces/test/shaders/ellipse.wgsl
index 69b2712..07f0c9a 100644
--- a/workspaces/test/shaders/ellipse.wgsl
+++ b/workspaces/test/shaders/ellipse.wgsl
@@ -1,16 +1,8 @@
#include "common_uniforms"
+#include "render/fullscreen_vs"
@group(0) @binding(0) var<uniform> uniforms: CommonUniforms;
-@vertex fn vs_main(@builtin(vertex_index) i: u32) -> @builtin(position) vec4<f32> {
- var pos = array<vec2<f32>, 3>(
- vec2<f32>(-1.0, -1.0),
- vec2<f32>(3.0, -1.0),
- vec2<f32>(-1.0, 3.0)
- );
- return vec4<f32>(pos[i], 0.0, 1.0);
-}
-
fn sdEllipse(p: vec2<f32>, ab: vec2<f32>) -> f32 {
var p_abs = abs(p);
if (p_abs.x > p_abs.y) {
diff --git a/workspaces/test/shaders/gaussian_blur.wgsl b/workspaces/test/shaders/gaussian_blur.wgsl
index 02156f7..22e467f 100644
--- a/workspaces/test/shaders/gaussian_blur.wgsl
+++ b/workspaces/test/shaders/gaussian_blur.wgsl
@@ -2,6 +2,8 @@
@group(0) @binding(1) var txt: texture_2d<f32>;
#include "common_uniforms"
+#include "render/fullscreen_vs"
+
struct GaussianBlurParams {
strength: f32,
_pad: f32,
@@ -10,15 +12,6 @@ struct GaussianBlurParams {
@group(0) @binding(2) var<uniform> uniforms: CommonUniforms;
@group(0) @binding(3) var<uniform> params: GaussianBlurParams;
-@vertex fn vs_main(@builtin(vertex_index) i: u32) -> @builtin(position) vec4<f32> {
- var pos = array<vec2<f32>, 3>(
- vec2<f32>(-1, -1),
- vec2<f32>(3, -1),
- vec2<f32>(-1, 3)
- );
- return vec4<f32>(pos[i], 0.0, 1.0);
-}
-
@fragment fn fs_main(@builtin(position) p: vec4<f32>) -> @location(0) vec4<f32> {
let uv = p.xy / uniforms.resolution;
var res = vec4<f32>(0.0);