Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GPU Backend: Add gradient rendering and transform-aware image rendering #307

Merged
merged 3 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1092,7 +1092,6 @@ export class NativeElementPool {
}

async imageLoad(patch: ImageLoadPatch, chassis: PaxChassisWeb) {

if (chassis.image_loaded(patch.path ?? "")) {
return
}
Expand Down
4 changes: 3 additions & 1 deletion pax-compiler/files/interfaces/web/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,9 @@ export function processMessages(messages: any[], chassis: PaxChassisWeb, objectM
let msg = unwrapped_msg["ImageLoad"];
let patch: ImageLoadPatch = objectManager.getFromPool(IMAGE_LOAD_PATCH);
patch.fromPatch(msg);
nativePool.imageLoad(patch, chassis)
queueMicrotask(async () => {
await nativePool.imageLoad(patch, chassis);
});
}else if(unwrapped_msg["ScrollerCreate"]) {
let msg = unwrapped_msg["ScrollerCreate"]
let patch: AnyCreatePatch = objectManager.getFromPool(ANY_CREATE_PATCH);
Expand Down
6 changes: 3 additions & 3 deletions pax-pixels/src/render_backend/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ pub(crate) struct GpuPrimitive {
pub fill_id: u16,
pub fill_type_flag: u16,
pub z_index: i32,
pub clipping_id: u32,
pub transform_id: u32, //not used atm
pub clipping_id: u32, //not used atm
pub transform_id: u32,
}

#[repr(C)]
Expand Down Expand Up @@ -54,7 +54,7 @@ pub(crate) struct GpuTransform {
impl Default for GpuTransform {
fn default() -> Self {
Self {
transform: Transform2D::scale(1000.0, 1000.0).to_arrays(),
transform: Transform2D::identity().to_arrays(),
_pad: 0,
_pad2: 0,
}
Expand Down
135 changes: 50 additions & 85 deletions pax-pixels/src/render_backend/geometry.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ struct Globals {
struct Primitive {
fill_id_and_type: u32,
z_index: i32,
clipping_id: u32,
transform_id: u32, //not used atm
clipping_id: u32, //not used atm
transform_id: u32,
};

struct Primitives {
Expand Down Expand Up @@ -57,7 +57,7 @@ struct Gradients {

@group(0) @binding(0) var<uniform> globals: Globals;
@group(0) @binding(1) var<uniform> u_primitives: Primitives;
@group(0) @binding(2) var<uniform> clipping: Transforms;
@group(0) @binding(2) var<uniform> transforms: Transforms;
@group(0) @binding(3) var<uniform> colors: Colors;
@group(0) @binding(4) var<uniform> gradients: Gradients;

Expand All @@ -77,7 +77,17 @@ fn vs_main(
model: GpuVertex,
) -> VertexOutput {
var out: VertexOutput;
var pos = model.position;
var p = model.position;

// apply transform
let primitive = u_primitives.primitives[model.prim_id];
let m = transforms.transforms[primitive.transform_id];

let t_p_x = p.x * m.xx + p.y * m.yx + m.zx;
let t_p_y = p.x * m.xy + p.y * m.yy + m.zy;

var pos = vec2<f32>(t_p_x, t_p_y);

pos /= globals.resolution;
pos *= 2.0;
pos -= 1.0;
Expand All @@ -87,22 +97,13 @@ fn vs_main(
out.clip_position = vec4<f32>(pos, 0.0, 1.0);
return out;
}

// Fragment shader
@fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {

let primitive = u_primitives.primitives[in.prim_id];

// let p = in.clip_position.xy;
// let m = clipping.transforms[primitive.clipping_id];
// let t_p_x = p.x * m.xx + p.y * m.yx + m.zx;
// let t_p_y = p.x * m.xy + p.y * m.yy + m.zy;
// if t_p_x > 1.0 || t_p_x < 0.0 || t_p_y > 1.0 || t_p_y < 0.0 {
// discard;
// }



//color/gradient
let fill_id_and_type = primitive.fill_id_and_type;
//clipping rectangle
Expand All @@ -119,85 +120,49 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
}



fn gradient(fill_id: u32, coord: vec2<f32>) -> vec4<f32> {

let gradient = gradients.gradients[fill_id];

//color space for linear gradient:
let g_p = gradient.position*f32(globals.dpr);
let g_a = gradient.main_axis*f32(globals.dpr);
// Calculate color space position
let g_p = gradient.position * f32(globals.dpr);
let g_a = gradient.main_axis * f32(globals.dpr);
let p_t = coord - g_p;
let m_a_l = length(g_a);
let n = g_a/m_a_l;
let t_m = dot(p_t, n); //this is the ammount that p_t points in the direction of n
let color_space = t_m/m_a_l; //This is 0.0..=1.0 and can be mapped to color space with coords
let n = g_a / m_a_l;
let color_space = dot(p_t, n);

//figure out surrounding stops in color space:
let s1 = gradient.stops_set1;
let s2 = gradient.stops_set2;
let stops = array<f32, 8>(s1[0], s1[1], s1[2], s1[3], s2[0], s2[1], s2[2], s2[3]);
let colors = gradient.colors;

//assumed to be 2 or larger
let len = gradient.stop_count;
var color: vec4<f32>;


// Find the appropriate stop segment
var left_idx = 0u;
var right_idx = 1u;

// Handle edge cases first
if color_space <= stops[0] {
return gradient.colors[0];
}
if color_space >= stops[gradient.stop_count - 1u] {
return gradient.colors[gradient.stop_count - 1u];
}

// This is horrible, but can't use dynamic indicies in loops in wgsl. One
// possible path forward would be to create 1d textures to sample from
// instead.
var left_stop: f32;
var right_stop: f32;
var left_col: vec4<f32>;
var right_col: vec4<f32>;
if stops[0] > color_space {
left_stop = stops[0] - 1.0;
right_stop = stops[0];
left_col = colors[0];
right_col = colors[0];
} else if stops[1] > color_space || len <= 1u {
left_stop = stops[0];
right_stop = stops[1];
left_col = colors[0];
right_col = colors[1];
} else if stops[2] > color_space || len <= 2u {
left_stop = stops[1];
right_stop = stops[2];
left_col = colors[1];
right_col = colors[2];
} else if stops[3] > color_space || len <= 3u {
left_stop = stops[2];
right_stop = stops[3];
left_col = colors[2];
right_col = colors[3];
} else if stops[4] > color_space || len <= 4u {
left_stop = stops[3];
right_stop = stops[4];
left_col = colors[3];
right_col = colors[4];
} else if stops[5] > color_space || len <= 5u {
left_stop = stops[4];
right_stop = stops[5];
left_col = colors[4];
right_col = colors[5];
} else if stops[6] > color_space || len <= 6u {
left_stop = stops[5];
right_stop = stops[6];
left_col = colors[5];
right_col = colors[6];
} else if stops[7] > color_space || len <= 7u {
left_stop = stops[6];
right_stop = stops[7];
left_col = colors[6];
right_col = colors[7];
} else {
left_stop = stops[7] - 1.0;
right_stop = stops[7];
left_col = colors[7];
right_col = colors[7];
// Find the segment using a fixed loop
for (var i = 0u; i < 7u; i++) {
if i >= gradient.stop_count - 1u { break; }
if stops[i + 1u] > color_space {
left_idx = i;
right_idx = i + 1u;
break;
}
}
let space = (color_space - left_stop)/(right_stop - left_stop);
color = left_col*(1.0 - space) + right_col*space;
return color;

let left_stop = stops[left_idx];
let right_stop = stops[right_idx];
let left_col = gradient.colors[left_idx];
let right_col = gradient.colors[right_idx];

let t = (color_space - left_stop) / (right_stop - left_stop);
return mix(left_col, right_col, t);
}

Loading
Loading