From 09a6bcfffc24f5abdc8709403bab7ae1e01563f1 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 2 May 2024 13:15:17 +0200 Subject: Add `Image` rotation support Co-authored-by: DKolter <68352124+DKolter@users.noreply.github.com> --- wgpu/src/shader/image.wgsl | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) (limited to 'wgpu/src/shader') diff --git a/wgpu/src/shader/image.wgsl b/wgpu/src/shader/image.wgsl index 7b2e5238..de962098 100644 --- a/wgpu/src/shader/image.wgsl +++ b/wgpu/src/shader/image.wgsl @@ -9,10 +9,13 @@ struct Globals { struct VertexInput { @builtin(vertex_index) vertex_index: u32, @location(0) pos: vec2, - @location(1) scale: vec2, - @location(2) atlas_pos: vec2, - @location(3) atlas_scale: vec2, - @location(4) layer: i32, + @location(1) center: vec2, + @location(2) image_size: vec2, + @location(3) rotation: f32, + @location(4) scale: vec2, + @location(5) atlas_pos: vec2, + @location(6) atlas_scale: vec2, + @location(7) layer: i32, } struct VertexOutput { @@ -25,24 +28,42 @@ struct VertexOutput { fn vs_main(input: VertexInput) -> VertexOutput { var out: VertexOutput; - let v_pos = vertex_position(input.vertex_index); + // Generate a vertex position in the range [0, 1] from the vertex index. + var v_pos = vertex_position(input.vertex_index); + // Map the vertex position to the atlas texture. out.uv = vec2(v_pos * input.atlas_scale + input.atlas_pos); out.layer = f32(input.layer); - var transform: mat4x4 = mat4x4( + // Calculate the vertex position and move the center to the origin + v_pos = input.pos + v_pos * input.image_size - input.center; + + // Apply the rotation around the center of the image + let cos_rot = cos(input.rotation); + let sin_rot = sin(input.rotation); + let rotate = mat4x4( + vec4(cos_rot, sin_rot, 0.0, 0.0), + vec4(-sin_rot, cos_rot, 0.0, 0.0), + vec4(0.0, 0.0, 1.0, 0.0), + vec4(0.0, 0.0, 0.0, 1.0) + ); + + // Scale the image and then translate to the final position by moving the center to the position + let scale_translate = mat4x4( vec4(input.scale.x, 0.0, 0.0, 0.0), vec4(0.0, input.scale.y, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), - vec4(input.pos, 0.0, 1.0) + vec4(input.center, 0.0, 1.0) ); - out.position = globals.transform * transform * vec4(v_pos, 0.0, 1.0); + // Calculate the final position of the vertex + out.position = globals.transform * scale_translate * rotate * vec4(v_pos, 0.0, 1.0); return out; } @fragment fn fs_main(input: VertexOutput) -> @location(0) vec4 { + // Sample the texture at the given UV coordinate and layer. return textureSample(u_texture, u_sampler, input.uv, i32(input.layer)); } -- cgit From a57313b23ecb9843856ca0ea08635b6121fcb2cb Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 2 May 2024 15:21:22 +0200 Subject: Simplify image rotation API and its internals --- wgpu/src/shader/image.wgsl | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) (limited to 'wgpu/src/shader') diff --git a/wgpu/src/shader/image.wgsl b/wgpu/src/shader/image.wgsl index de962098..71bf939c 100644 --- a/wgpu/src/shader/image.wgsl +++ b/wgpu/src/shader/image.wgsl @@ -10,12 +10,11 @@ struct VertexInput { @builtin(vertex_index) vertex_index: u32, @location(0) pos: vec2, @location(1) center: vec2, - @location(2) image_size: vec2, + @location(2) scale: vec2, @location(3) rotation: f32, - @location(4) scale: vec2, - @location(5) atlas_pos: vec2, - @location(6) atlas_scale: vec2, - @location(7) layer: i32, + @location(4) atlas_pos: vec2, + @location(5) atlas_scale: vec2, + @location(6) layer: i32, } struct VertexOutput { @@ -36,7 +35,7 @@ fn vs_main(input: VertexInput) -> VertexOutput { out.layer = f32(input.layer); // Calculate the vertex position and move the center to the origin - v_pos = input.pos + v_pos * input.image_size - input.center; + v_pos = input.pos + v_pos * input.scale - input.center; // Apply the rotation around the center of the image let cos_rot = cos(input.rotation); @@ -48,16 +47,8 @@ fn vs_main(input: VertexInput) -> VertexOutput { vec4(0.0, 0.0, 0.0, 1.0) ); - // Scale the image and then translate to the final position by moving the center to the position - let scale_translate = mat4x4( - vec4(input.scale.x, 0.0, 0.0, 0.0), - vec4(0.0, input.scale.y, 0.0, 0.0), - vec4(0.0, 0.0, 1.0, 0.0), - vec4(input.center, 0.0, 1.0) - ); - // Calculate the final position of the vertex - out.position = globals.transform * scale_translate * rotate * vec4(v_pos, 0.0, 1.0); + out.position = globals.transform * (vec4(input.center, 0.0, 0.0) + rotate * vec4(v_pos, 0.0, 1.0)); return out; } -- cgit From fa9e1d96ea1924b51749b775ea0e67e69bc8a305 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 3 May 2024 13:25:58 +0200 Subject: Introduce dynamic `opacity` support for `Image` and `Svg` --- wgpu/src/shader/image.wgsl | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'wgpu/src/shader') diff --git a/wgpu/src/shader/image.wgsl b/wgpu/src/shader/image.wgsl index 71bf939c..accefc17 100644 --- a/wgpu/src/shader/image.wgsl +++ b/wgpu/src/shader/image.wgsl @@ -12,15 +12,17 @@ struct VertexInput { @location(1) center: vec2, @location(2) scale: vec2, @location(3) rotation: f32, - @location(4) atlas_pos: vec2, - @location(5) atlas_scale: vec2, - @location(6) layer: i32, + @location(4) opacity: f32, + @location(5) atlas_pos: vec2, + @location(6) atlas_scale: vec2, + @location(7) layer: i32, } struct VertexOutput { @builtin(position) position: vec4, @location(0) uv: vec2, @location(1) layer: f32, // this should be an i32, but naga currently reads that as requiring interpolation. + @location(2) opacity: f32, } @vertex @@ -33,6 +35,7 @@ fn vs_main(input: VertexInput) -> VertexOutput { // Map the vertex position to the atlas texture. out.uv = vec2(v_pos * input.atlas_scale + input.atlas_pos); out.layer = f32(input.layer); + out.opacity = input.opacity; // Calculate the vertex position and move the center to the origin v_pos = input.pos + v_pos * input.scale - input.center; @@ -56,5 +59,5 @@ fn vs_main(input: VertexInput) -> VertexOutput { @fragment fn fs_main(input: VertexOutput) -> @location(0) vec4 { // Sample the texture at the given UV coordinate and layer. - return textureSample(u_texture, u_sampler, input.uv, i32(input.layer)); + return textureSample(u_texture, u_sampler, input.uv, i32(input.layer)) * vec4(1.0, 1.0, 1.0, input.opacity); } -- cgit