From 0e4dae6215a48cdfeef796010361bb36032edb0b Mon Sep 17 00:00:00 2001 From: Mark Date: Thu, 25 Jan 2024 21:24:37 -0800 Subject: [PATCH] Added animation to UI --- crates/render/shaders/ui.wgsl | 130 ++++++++++++++++++++++++++-------- 1 file changed, 99 insertions(+), 31 deletions(-) diff --git a/crates/render/shaders/ui.wgsl b/crates/render/shaders/ui.wgsl index 5c36d3e..3c2ccb9 100644 --- a/crates/render/shaders/ui.wgsl +++ b/crates/render/shaders/ui.wgsl @@ -18,11 +18,15 @@ struct VertexInput { struct VertexOutput { @builtin(position) position: vec4, - @location(0) texture_coords: vec2, - @location(1) texture_index: u32, - @location(2) mask_coords: vec2, - @location(3) mask_index: vec2, - @location(4) color_transform: vec4, + @location(0) tween: f32, + @location(1) texture_index_a: u32, + @location(2) texture_coords_a: vec2, + @location(3) texture_index_b: u32, + @location(4) texture_coords_b: vec2, + @location(5) color: vec4, + + @location(6) mask_coords: vec2, + @location(7) mask_index: vec2, } @group(0) @binding(0) @@ -80,31 +84,67 @@ fn vertex_main( vertex: VertexInput, instance: InstanceInput, ) -> VertexOutput { + var out: VertexOutput; // TODO: this will break if we try to use texture 0. // implement animations for ui sprites & fix that here. - let pos = transform_vertex( - instance, - vertex.position, - instance.texture_index.x, - ); - - var out: VertexOutput; - out.position = pos; - out.color_transform = instance.color_transform; - - - // TODO: function to get texture from sprite - // Pick texture frame - let t = global_atlas[instance.texture_index.x]; - out.texture_index = u32(t.atlas_texture); - out.texture_coords = vec2(t.xpos, t.ypos); - if vertex.texture_coords.x == 1.0 { - out.texture_coords = vec2(out.texture_coords.x + t.width, out.texture_coords.y); + // Pick texture size by the size of the visible texture + // (texture index 0 is special, it's the "hidden" texture) + if instance.texture_index.x == 0u && instance.texture_index.y == 0u { + out.position = vec4(0.0, 0.0, 0.0, 1.0); + } else if instance.texture_index.x == 0u { + out.position = transform_vertex( + instance, + vertex.position, + instance.texture_index.y, + ); + } else if instance.texture_index.y == 0u { + out.position = transform_vertex( + instance, + vertex.position, + instance.texture_index.x, + ); + } else { + out.position = transform_vertex( + instance, + vertex.position, + instance.texture_index.x, + ); } - if vertex.texture_coords.y == 1.0 { - out.texture_coords = vec2(out.texture_coords.x, out.texture_coords.y + t.height); + + out.color = instance.color_transform; + out.tween = instance.texture_fade; + + // Texture 0 is special, it's the empty texture + if instance.texture_index.x == 0u { + out.texture_index_a = 0u; + out.texture_coords_a = vec2(0.0, 0.0); + } else { + let t = global_atlas[instance.texture_index.x]; + out.texture_index_a = t.atlas_texture; + out.texture_coords_a = vec2(t.xpos, t.ypos); + if vertex.texture_coords.x == 1.0 { + out.texture_coords_a = out.texture_coords_a + vec2(t.width, 0.0); + } + if vertex.texture_coords.y == 1.0 { + out.texture_coords_a = out.texture_coords_a + vec2(0.0, t.height); + } + } + + if instance.texture_index.y == 0u { + out.texture_index_b = u32(0u); + out.texture_coords_b = vec2(0.0, 0.0); + } else { + let b = global_atlas[instance.texture_index.y]; + out.texture_index_b = u32(b.atlas_texture); + out.texture_coords_b = vec2(b.xpos, b.ypos); + if vertex.texture_coords.x == 1.0 { + out.texture_coords_b = out.texture_coords_b + vec2(b.width, 0.0); + } + if vertex.texture_coords.y == 1.0 { + out.texture_coords_b = out.texture_coords_b + vec2(0.0, b.height); + } } // Pick mask image if mask is enabled @@ -142,12 +182,40 @@ fn fragment_main(in: VertexOutput) -> @location(0) vec4 { ).a; } - var color: vec4 = textureSampleLevel( - texture_array[in.texture_index], - sampler_array[0], - in.texture_coords, - 0.0 - ).rgba * in.color_transform; + var texture_a: vec4 = vec4(0.0, 0.0, 0.0, 0.0); + if !( + (in.texture_index_a == 0u) && + (in.texture_coords_a.x == 0.0) && + (in.texture_coords_a.y == 0.0) + ) { + texture_a = textureSampleLevel( + texture_array[in.texture_index_a], + sampler_array[0], + in.texture_coords_a, + 0.0 + ).rgba; + } + + + var texture_b: vec4 = vec4(0.0, 0.0, 0.0, 0.0); + if !( + (in.texture_index_b == 0u) && + (in.texture_coords_b.x == 0.0) && + (in.texture_coords_b.y == 0.0) + ) { + texture_b = textureSampleLevel( + texture_array[in.texture_index_b], + sampler_array[0], + in.texture_coords_b, + 0.0 + ).rgba; + } + + var color: vec4 = mix( + texture_a, + texture_b, + in.tween + ) * in.color; // Apply mask and discard fully transparent pixels color = vec4(color.rgb, color.a *mask);