Adjusted gradient uniforms to be more tightly packed.

This commit is contained in:
shan 2022-10-05 11:32:59 -07:00
parent e540b7f642
commit f7ce7244d0
2 changed files with 37 additions and 31 deletions

View file

@ -1,10 +1,10 @@
// uniforms // uniforms
struct GradientUniforms { struct GradientUniforms {
transform: mat4x4<f32>, transform: mat4x4<f32>,
@size(16) start: vec2<f32>, //xy = start, wz = end
@size(16) end: vec2<f32>, position: vec4<f32>,
@size(16) start_stop: i32, //x = start, y = end, zw = padding
@size(16) end_stop: i32, stop_range: vec4<i32>,
} }
struct Stop { struct Stop {
@ -13,7 +13,7 @@ struct Stop {
}; };
@group(0) @binding(0) @group(0) @binding(0)
var<uniform> gradient_uniforms: GradientUniforms; var<uniform> uniforms: GradientUniforms;
@group(0) @binding(1) @group(0) @binding(1)
var<storage, read> color_stops: array<Stop>; var<storage, read> color_stops: array<Stop>;
@ -26,7 +26,7 @@ struct VertexOutput {
@vertex @vertex
fn vs_main(@location(0) input: vec2<f32>) -> VertexOutput { fn vs_main(@location(0) input: vec2<f32>) -> VertexOutput {
var output: VertexOutput; var output: VertexOutput;
output.position = gradient_uniforms.transform * vec4<f32>(input.xy, 0.0, 1.0); output.position = uniforms.transform * vec4<f32>(input.xy, 0.0, 1.0);
output.raw_position = input; output.raw_position = input;
return output; return output;
@ -34,13 +34,18 @@ fn vs_main(@location(0) input: vec2<f32>) -> VertexOutput {
@fragment @fragment
fn fs_gradient(input: VertexOutput) -> @location(0) vec4<f32> { fn fs_gradient(input: VertexOutput) -> @location(0) vec4<f32> {
let v1 = gradient_uniforms.end - gradient_uniforms.start; let start = uniforms.position.xy;
let v2 = input.raw_position.xy - gradient_uniforms.start; let end = uniforms.position.zw;
let start_stop = uniforms.stop_range.x;
let end_stop = uniforms.stop_range.y;
let v1 = end - start;
let v2 = input.raw_position.xy - start;
let unit = normalize(v1); let unit = normalize(v1);
let offset = dot(unit, v2) / length(v1); let offset = dot(unit, v2) / length(v1);
let min_stop = color_stops[gradient_uniforms.start_stop]; let min_stop = color_stops[start_stop];
let max_stop = color_stops[gradient_uniforms.end_stop]; let max_stop = color_stops[end_stop];
var color: vec4<f32>; var color: vec4<f32>;
@ -51,8 +56,8 @@ fn fs_gradient(input: VertexOutput) -> @location(0) vec4<f32> {
} else { } else {
var min = min_stop; var min = min_stop;
var max = max_stop; var max = max_stop;
var min_index = gradient_uniforms.start_stop; var min_index = start_stop;
var max_index = gradient_uniforms.end_stop; var max_index = end_stop;
loop { loop {
if (min_index >= max_index - 1) { if (min_index >= max_index - 1) {

View file

@ -5,7 +5,7 @@ use crate::triangle::{
default_triangle_primitive_state, vertex_buffer_layout, default_triangle_primitive_state, vertex_buffer_layout,
}; };
use encase::ShaderType; use encase::ShaderType;
use glam::{Vec2, Vec4}; use glam::{IVec4, Vec4};
use iced_graphics::gradient::Gradient; use iced_graphics::gradient::Gradient;
use iced_graphics::Transformation; use iced_graphics::Transformation;
@ -21,17 +21,13 @@ pub(super) struct GradientPipeline {
bind_group: wgpu::BindGroup, bind_group: wgpu::BindGroup,
} }
//TODO I can tightly pack this by rearranging/consolidating some fields
#[derive(Debug, ShaderType)] #[derive(Debug, ShaderType)]
pub(super) struct GradientUniforms { pub(super) struct GradientUniforms {
transform: glam::Mat4, transform: glam::Mat4,
start: Vec2, //xy = start, zw = end
#[align(16)] direction: Vec4,
end: Vec2, //x = start, y = end, zw = padding
#[align(16)] stop_range: IVec4,
start_stop: i32,
#[align(16)]
end_stop: i32,
} }
#[derive(Debug, ShaderType)] #[derive(Debug, ShaderType)]
@ -58,7 +54,7 @@ impl GradientPipeline {
"iced_wgpu::triangle [GRADIENT] uniforms", "iced_wgpu::triangle [GRADIENT] uniforms",
); );
//TODO: With a WASM target storage buffers are not supported. Will need to use UBOs & static //TODO: With a WASM target storage buffers are not supported. Will need to use UBOs & static
// sized array (64 on OpenGL side right now) to make gradients work // sized array (64 on OpenGL side right now) to make gradients work
let storage_buffer = DynamicBuffer::storage( let storage_buffer = DynamicBuffer::storage(
device, device,
@ -143,7 +139,9 @@ impl GradientPipeline {
uniform_buffer, uniform_buffer,
storage_buffer, storage_buffer,
color_stop_offset: 0, color_stop_offset: 0,
color_stops_pending_write: GradientStorage { color_stops: vec![] }, color_stops_pending_write: GradientStorage {
color_stops: vec![],
},
bind_group_layout, bind_group_layout,
bind_group, bind_group,
} }
@ -159,10 +157,13 @@ impl GradientPipeline {
self.uniform_buffer.push(&GradientUniforms { self.uniform_buffer.push(&GradientUniforms {
transform: transform.into(), transform: transform.into(),
start: Vec2::new(linear.start.x, linear.start.y), direction: Vec4::new(
end: Vec2::new(linear.end.x, linear.end.y), linear.start.x,
start_stop: start_offset, linear.start.y,
end_stop: end_offset, linear.end.x,
linear.end.y,
),
stop_range: IVec4::new(start_offset, end_offset, 0, 0),
}); });
self.color_stop_offset = end_offset + 1; self.color_stop_offset = end_offset + 1;
@ -202,13 +203,13 @@ impl GradientPipeline {
wgpu::BufferBinding { wgpu::BufferBinding {
buffer: uniform_buffer, buffer: uniform_buffer,
offset: 0, offset: 0,
size: Some(GradientUniforms::min_size()) size: Some(GradientUniforms::min_size()),
} },
) ),
}, },
wgpu::BindGroupEntry { wgpu::BindGroupEntry {
binding: 1, binding: 1,
resource: storage_buffer.as_entire_binding() resource: storage_buffer.as_entire_binding(),
}, },
], ],
}) })