From 40f45d7b7e35dd4937abe6b5ce16b6256b4f1eeb Mon Sep 17 00:00:00 2001 From: shan Date: Thu, 29 Sep 2022 10:52:58 -0700 Subject: Adds linear gradient support to 2D meshes in the canvas widget. --- wgpu/src/shader/triangle_gradient.wgsl | 83 ++++++++++++++++++++++++++++++++++ wgpu/src/shader/triangle_solid.wgsl | 18 ++++++++ 2 files changed, 101 insertions(+) create mode 100644 wgpu/src/shader/triangle_gradient.wgsl create mode 100644 wgpu/src/shader/triangle_solid.wgsl (limited to 'wgpu/src/shader') diff --git a/wgpu/src/shader/triangle_gradient.wgsl b/wgpu/src/shader/triangle_gradient.wgsl new file mode 100644 index 00000000..cb35b61c --- /dev/null +++ b/wgpu/src/shader/triangle_gradient.wgsl @@ -0,0 +1,83 @@ +// uniforms +struct GradientUniforms { + transform: mat4x4, + @size(16) start: vec2, + @size(16) end: vec2, + @size(16) start_stop: i32, + @size(16) end_stop: i32, +} + +struct Stop { + color: vec4, + offset: f32, +}; + +@group(0) @binding(0) +var gradient_uniforms: GradientUniforms; + +@group(0) @binding(1) +var color_stops: array; + +struct VertexOutput { + @builtin(position) position: vec4, + @location(0) raw_position: vec2 +} + +@vertex +fn vs_main(@location(0) input: vec2) -> VertexOutput { + var output: VertexOutput; + output.position = gradient_uniforms.transform * vec4(input.xy, 0.0, 1.0); + output.raw_position = input; + + return output; +} + +@fragment +fn fs_gradient(input: VertexOutput) -> @location(0) vec4 { + let v1 = gradient_uniforms.end - gradient_uniforms.start; + let v2 = input.raw_position.xy - gradient_uniforms.start; + let unit = normalize(v1); + let offset = dot(unit, v2) / length(v1); + + let min_stop = color_stops[gradient_uniforms.start_stop]; + let max_stop = color_stops[gradient_uniforms.end_stop]; + + var color: vec4; + + if (offset <= min_stop.offset) { + color = min_stop.color; + } else if (offset >= max_stop.offset) { + color = max_stop.color; + } else { + var min = min_stop; + var max = max_stop; + var min_index = gradient_uniforms.start_stop; + var max_index = gradient_uniforms.end_stop; + + loop { + if (min_index >= max_index - 1) { + break; + } + + let index = min_index + (max_index - min_index) / 2; + + let stop = color_stops[index]; + + if (offset <= stop.offset) { + max = stop; + max_index = index; + } else { + min = stop; + min_index = index; + } + } + + color = mix(min.color, max.color, smoothstep( + min.offset, + max.offset, + offset + )); + } + + return color; +} \ No newline at end of file diff --git a/wgpu/src/shader/triangle_solid.wgsl b/wgpu/src/shader/triangle_solid.wgsl new file mode 100644 index 00000000..126eceaa --- /dev/null +++ b/wgpu/src/shader/triangle_solid.wgsl @@ -0,0 +1,18 @@ +// uniforms +struct SolidUniforms { + transform: mat4x4, + color: vec4 +} + +@group(0) @binding(0) +var solid_uniforms: SolidUniforms; + +@vertex +fn vs_main(@location(0) input: vec2) -> @builtin(position) vec4 { + return solid_uniforms.transform * vec4(input.xy, 0.0, 1.0); +} + +@fragment +fn fs_solid() -> @location(0) vec4 { + return solid_uniforms.color; +} \ No newline at end of file -- cgit