Skip to content

Commit

Permalink
Merge pull request #42 from Senryoku/renderer/packed-color
Browse files Browse the repository at this point in the history
[renderer] Use PackedColors
  • Loading branch information
Senryoku authored Jul 19, 2024
2 parents f2d154d + f3d8d0b commit 0349143
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 114 deletions.
82 changes: 37 additions & 45 deletions src/Renderer.zig
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,10 @@ const Vertex = packed struct {
y: f32,
z: f32,
primitive_index: u32,
base_color: fRGBA,
offset_color: fRGBA = .{},
area1_base_color: fRGBA = .{},
area1_offset_color: fRGBA = .{},
base_color: PackedColor,
offset_color: PackedColor = .{},
area1_base_color: PackedColor = .{},
area1_offset_color: PackedColor = .{},
u: f32 = 0.0,
v: f32 = 0.0,
area1_u: f32 = 0.0,
Expand All @@ -131,8 +131,8 @@ const StripMetadata = packed struct {

const wgsl_vs = @embedFile("./shaders/uniforms.wgsl") ++ @embedFile("./shaders/vs.wgsl");
const wgsl_fs = @embedFile("./shaders/uniforms.wgsl") ++ @embedFile("./shaders/fragment_color.wgsl") ++ @embedFile("./shaders/fs.wgsl");
const wgsl_translucent_fs = @embedFile("./shaders/uniforms.wgsl") ++ @embedFile("./shaders/fragment_color.wgsl") ++ @embedFile("./shaders/oit_draw_fs.wgsl");
const wgsl_blend_cs = @embedFile("./shaders/oit_blend_cs.wgsl");
const wgsl_translucent_fs = @embedFile("./shaders/uniforms.wgsl") ++ @embedFile("./shaders/oit_structs.wgsl") ++ @embedFile("./shaders/fragment_color.wgsl") ++ @embedFile("./shaders/oit_draw_fs.wgsl");
const wgsl_blend_cs = @embedFile("./shaders/oit_structs.wgsl") ++ @embedFile("./shaders/oit_blend_cs.wgsl");
const wgsl_modifier_volume_vs = @embedFile("./shaders/modifier_volume_vs.wgsl");
const wgsl_modifier_volume_fs = @embedFile("./shaders/modifier_volume_fs.wgsl");
const wgsl_modifier_volume_apply_fs = @embedFile("./shaders/modifier_volume_apply_fs.wgsl");
Expand Down Expand Up @@ -357,10 +357,10 @@ fn gen_sprite_vertices(sprite: HollyModule.VertexParameter) [4]Vertex {
const vertex_attributes = [_]wgpu.VertexAttribute{
.{ .format = .float32x3, .offset = 0, .shader_location = 0 },
.{ .format = .uint32, .offset = @offsetOf(Vertex, "primitive_index"), .shader_location = 1 },
.{ .format = .float32x4, .offset = @offsetOf(Vertex, "base_color"), .shader_location = 2 },
.{ .format = .float32x4, .offset = @offsetOf(Vertex, "offset_color"), .shader_location = 3 },
.{ .format = .float32x4, .offset = @offsetOf(Vertex, "area1_base_color"), .shader_location = 4 },
.{ .format = .float32x4, .offset = @offsetOf(Vertex, "area1_offset_color"), .shader_location = 5 },
.{ .format = .uint32, .offset = @offsetOf(Vertex, "base_color"), .shader_location = 2 },
.{ .format = .uint32, .offset = @offsetOf(Vertex, "offset_color"), .shader_location = 3 },
.{ .format = .uint32, .offset = @offsetOf(Vertex, "area1_base_color"), .shader_location = 4 },
.{ .format = .uint32, .offset = @offsetOf(Vertex, "area1_offset_color"), .shader_location = 5 },
.{ .format = .float32x2, .offset = @offsetOf(Vertex, "u"), .shader_location = 6 },
.{ .format = .float32x2, .offset = @offsetOf(Vertex, "area1_u"), .shader_location = 7 },
};
Expand Down Expand Up @@ -1675,23 +1675,15 @@ pub const Renderer = struct {
offset_color = @bitCast(vp[6]);
}
}
if (!use_alpha) base_color.a = 255;

vertices[i] = Vertex{
.primitive_index = @intCast(self.strips_metadata.items.len),
.x = @bitCast(vp[0]),
.y = @bitCast(vp[1]),
.z = @bitCast(vp[2]),
.base_color = .{
.r = @as(f32, @floatFromInt(base_color.r)) / 255.0,
.g = @as(f32, @floatFromInt(base_color.g)) / 255.0,
.b = @as(f32, @floatFromInt(base_color.b)) / 255.0,
.a = if (use_alpha) @as(f32, @floatFromInt(base_color.a)) / 255.0 else 1.0,
},
.offset_color = .{
.r = @as(f32, @floatFromInt(offset_color.r)) / 255.0,
.g = @as(f32, @floatFromInt(offset_color.g)) / 255.0,
.b = @as(f32, @floatFromInt(offset_color.b)) / 255.0,
.a = if (use_alpha) @as(f32, @floatFromInt(offset_color.a)) / 255.0 else 1.0,
},
.base_color = base_color,
.offset_color = offset_color,
.u = u,
.v = v,
};
Expand Down Expand Up @@ -1969,7 +1961,7 @@ pub const Renderer = struct {
.x = v.x,
.y = v.y,
.z = v.z,
.base_color = fRGBA.from_packed(v.base_color, use_alpha),
.base_color = v.base_color.with_alpha(use_alpha),
});
},
// Non-Textured, Floating Color
Expand All @@ -1985,8 +1977,8 @@ pub const Renderer = struct {
.r = v.r,
.g = v.g,
.b = v.b,
.a = if (use_alpha) v.a else 1.0,
}).clamped(),
.a = v.a,
}).to_packed(use_alpha),
});
},
// Non-Textured, Intensity
Expand All @@ -1997,7 +1989,7 @@ pub const Renderer = struct {
.x = v.x,
.y = v.y,
.z = v.z,
.base_color = face_color.apply_intensity(v.base_intensity, use_alpha),
.base_color = face_color.apply_intensity(v.base_intensity, use_alpha).to_packed(use_alpha),
});
},
// Packed Color, Textured 32bit UV
Expand All @@ -2009,8 +2001,8 @@ pub const Renderer = struct {
.x = v.x,
.y = v.y,
.z = v.z,
.base_color = fRGBA.from_packed(v.base_color, use_alpha),
.offset_color = if (use_offset) fRGBA.from_packed(v.offset_color, true) else .{},
.base_color = v.base_color.with_alpha(use_alpha),
.offset_color = if (use_offset) v.offset_color.with_alpha(true) else .{},
.u = v.u,
.v = v.v,
});
Expand All @@ -2022,8 +2014,8 @@ pub const Renderer = struct {
.x = v.x,
.y = v.y,
.z = v.z,
.base_color = fRGBA.from_packed(v.base_color, use_alpha),
.offset_color = if (use_offset) fRGBA.from_packed(v.offset_color, true) else .{},
.base_color = v.base_color.with_alpha(use_alpha),
.offset_color = if (use_offset) v.offset_color.with_alpha(true) else .{},
.u = @bitCast(@as(u32, v.uv.u) << 16),
.v = @bitCast(@as(u32, v.uv.v) << 16),
});
Expand All @@ -2039,14 +2031,14 @@ pub const Renderer = struct {
.r = v.base_r,
.g = v.base_g,
.b = v.base_b,
.a = if (use_alpha) v.base_a else 1.0,
}).clamped(),
.a = v.base_a,
}).to_packed(use_alpha),
.offset_color = if (use_offset) (fRGBA{
.r = v.offset_r,
.g = v.offset_g,
.b = v.offset_b,
.a = v.offset_a,
}).clamped() else .{},
}).to_packed(true) else .{},
.u = v.u,
.v = v.v,
});
Expand All @@ -2062,14 +2054,14 @@ pub const Renderer = struct {
.r = v.base_r,
.g = v.base_g,
.b = v.base_b,
.a = if (use_alpha) v.base_a else 1.0,
}).clamped(),
.a = v.base_a,
}).to_packed(use_alpha),
.offset_color = if (use_offset) (fRGBA{
.r = v.offset_r,
.g = v.offset_g,
.b = v.offset_b,
.a = v.offset_a,
}).clamped() else .{},
}).to_packed(true) else .{},
.u = @bitCast(@as(u32, v.uv.u) << 16),
.v = @bitCast(@as(u32, v.uv.v) << 16),
});
Expand All @@ -2083,8 +2075,8 @@ pub const Renderer = struct {
.x = v.x,
.y = v.y,
.z = v.z,
.base_color = face_color.apply_intensity(v.base_intensity, use_alpha),
.offset_color = if (use_offset) face_offset_color.apply_intensity(v.offset_intensity, true) else .{},
.base_color = face_color.apply_intensity(v.base_intensity, use_alpha).to_packed(use_alpha),
.offset_color = if (use_offset) face_offset_color.apply_intensity(v.offset_intensity, true).to_packed(true) else .{},
.u = v.u,
.v = v.v,
});
Expand All @@ -2098,8 +2090,8 @@ pub const Renderer = struct {
.x = v.x,
.y = v.y,
.z = v.z,
.base_color = face_color.apply_intensity(v.base_intensity, use_alpha),
.offset_color = if (use_offset) face_offset_color.apply_intensity(v.offset_intensity, true) else .{},
.base_color = face_color.apply_intensity(v.base_intensity, use_alpha).to_packed(use_alpha),
.offset_color = if (use_offset) face_offset_color.apply_intensity(v.offset_intensity, true).to_packed(true) else .{},
.u = @bitCast(@as(u32, v.uv.u) << 16),
.v = @bitCast(@as(u32, v.uv.v) << 16),
});
Expand All @@ -2115,12 +2107,12 @@ pub const Renderer = struct {
.x = v.x,
.y = v.y,
.z = v.z,
.base_color = fRGBA.from_packed(v.offset_color_0, use_alpha),
.offset_color = if (use_offset) fRGBA.from_packed(v.offset_color_0, true) else .{},
.base_color = v.offset_color_0.with_alpha(use_alpha),
.offset_color = if (use_offset) v.offset_color_0.with_alpha(true) else .{},
.u = v.u0,
.v = v.v0,
.area1_base_color = fRGBA.from_packed(v.offset_color_1, use_alpha),
.area1_offset_color = if (use_offset) fRGBA.from_packed(v.offset_color_1, true) else .{},
.area1_base_color = v.offset_color_1.with_alpha(use_alpha),
.area1_offset_color = if (use_offset) v.offset_color_1.with_alpha(true) else .{},
.area1_u = v.u1,
.area1_v = v.v1,
});
Expand All @@ -2129,7 +2121,7 @@ pub const Renderer = struct {
var vs = gen_sprite_vertices(vertex);
for (&vs) |*v| {
v.primitive_index = primitive_index;
v.base_color = fRGBA.from_packed(sprite_base_color, use_alpha);
v.base_color = sprite_base_color.with_alpha(use_alpha);
// FIXME: This is wrong.
//if (use_offset)
// v.offset_color = .{
Expand Down
21 changes: 17 additions & 4 deletions src/colors.zig
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,14 @@ pub const RGBA = packed struct(u32) {
};

pub const PackedColor = packed struct(u32) {
b: u8,
g: u8,
r: u8,
a: u8,
b: u8 = 0,
g: u8 = 0,
r: u8 = 0,
a: u8 = 0,

pub fn with_alpha(self: @This(), use_alpha: bool) @This() {
return .{ .r = self.r, .g = self.g, .b = self.b, .a = if (use_alpha) self.a else 255 };
}
};

pub const fRGBA = packed struct {
Expand All @@ -58,6 +62,15 @@ pub const fRGBA = packed struct {
};
}

pub fn to_packed(self: @This(), use_alpha: bool) PackedColor {
return .{
.r = @intFromFloat(std.math.clamp(self.r * 255.0, 0.0, 255.0)),
.g = @intFromFloat(std.math.clamp(self.g * 255.0, 0.0, 255.0)),
.b = @intFromFloat(std.math.clamp(self.b * 255.0, 0.0, 255.0)),
.a = if (use_alpha) @intFromFloat(std.math.clamp(self.a * 255.0, 0.0, 255.0)) else 255,
};
}

pub fn apply_intensity(self: @This(), intensity: f32, use_alpha: bool) @This() {
// "Convert the Face Color alpha values specified in the Global
// Parameters into 8-bit integers (0 to 255). Multiply the RGB
Expand Down
16 changes: 8 additions & 8 deletions src/shaders/fs.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ fn main(
@location(1) offset_color: vec4<f32>,
@location(2) area1_base_color: vec4<f32>,
@location(3) area1_offset_color: vec4<f32>,
@location(4) @interpolate(flat) flat_base_color: vec4<f32>,
@location(5) @interpolate(flat) flat_offset_color: vec4<f32>,
@location(6) @interpolate(flat) area1_flat_base_color: vec4<f32>,
@location(7) @interpolate(flat) area1_flat_offset_color: vec4<f32>,
@location(4) @interpolate(flat) flat_base_color: u32,
@location(5) @interpolate(flat) flat_offset_color: u32,
@location(6) @interpolate(flat) area1_flat_base_color: u32,
@location(7) @interpolate(flat) area1_flat_offset_color: u32,
@location(8) @interpolate(flat) tex_idx_shading_instr: vec2<u32>,
@location(9) @interpolate(flat) area1_tex_idx_shading_instr: vec2<u32>,
@location(10) uv: vec2<f32>,
Expand All @@ -23,12 +23,12 @@ fn main(
let gouraud = ((tex_idx_shading_instr[1] >> 23) & 1) == 1;

var final_color = fragment_color(
select(flat_base_color, base_color / inv_w, gouraud),
select(flat_offset_color, offset_color / inv_w, gouraud),
select(unpack4x8unorm(flat_base_color).zyxw, base_color / inv_w, gouraud),
select(unpack4x8unorm(flat_offset_color).zyxw, offset_color / inv_w, gouraud),
uv / inv_w,
tex_idx_shading_instr,
select(area1_flat_base_color, area1_base_color / inv_w, gouraud),
select(area1_flat_offset_color, area1_offset_color / inv_w, gouraud),
select(unpack4x8unorm(area1_flat_base_color).zyxw, area1_base_color / inv_w, gouraud),
select(unpack4x8unorm(area1_flat_offset_color).zyxw, area1_offset_color / inv_w, gouraud),
area1_uv / inv_w,
area1_tex_idx_shading_instr,
inv_w,
Expand Down
21 changes: 2 additions & 19 deletions src/shaders/oit_blend_cs.wgsl
Original file line number Diff line number Diff line change
@@ -1,27 +1,10 @@
// Modified from https://webgpu.github.io/webgpu-samples/samples/A-buffer - BSD-3-Clause license

struct OITUniforms {
max_fragments: u32,
target_width: u32,
start_y: u32,
};

struct Heads {
fragment_count: u32, // No concurency here, no need for atomics.
fragment_count: u32, // No concurency here, no need for atomics. Although I'm not sure this has any impact :)
data: array<u32>
};

struct LinkedListElement {
color: vec4<f32>,
depth: f32,
index_and_blend_mode: u32,
next: u32,
};

struct LinkedList {
data: array<LinkedListElement>
};

@group(0) @binding(0) var<uniform> oit_uniforms: OITUniforms;
@group(0) @binding(1) var<storage, read_write> heads: Heads;
@group(0) @binding(2) var<storage, read_write> linked_list: LinkedList;
Expand Down Expand Up @@ -106,7 +89,7 @@ fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {

// Blend the translucent fragments
for (var i = 0u; i < layer_count; i++) {
let src = layers[i].color;
let src = unpack4x8unorm(layers[i].color);
let dst = color;
let blend_mode = layers[i].index_and_blend_mode & 0x3F;
color = src * get_src_factor(blend_mode & 7, src, dst) + dst * get_dst_factor((blend_mode >> 3) & 7, src, dst);
Expand Down
35 changes: 9 additions & 26 deletions src/shaders/oit_draw_fs.wgsl
Original file line number Diff line number Diff line change
@@ -1,27 +1,10 @@
// Modified from https://webgpu.github.io/webgpu-samples/samples/A-buffer - BSD-3-Clause license

struct OITUniforms {
max_fragments: u32,
target_width: u32,
start_y: u32,
};

struct Heads {
fragment_count: atomic<u32>,
data: array<atomic<u32>>
};

struct LinkedListElement {
color: vec4<f32>,
depth: f32,
index_and_blend_mode: u32,
next: u32,
};

struct LinkedList {
data: array<LinkedListElement>
};

@group(2) @binding(0) var<uniform> oit_uniforms: OITUniforms;
@group(2) @binding(1) var<storage, read_write> heads: Heads;
@group(2) @binding(2) var<storage, read_write> linked_list: LinkedList;
Expand All @@ -34,10 +17,10 @@ fn main(
@location(1) offset_color: vec4<f32>,
@location(2) area1_base_color: vec4<f32>,
@location(3) area1_offset_color: vec4<f32>,
@location(4) @interpolate(flat) flat_base_color: vec4<f32>,
@location(5) @interpolate(flat) flat_offset_color: vec4<f32>,
@location(6) @interpolate(flat) area1_flat_base_color: vec4<f32>,
@location(7) @interpolate(flat) area1_flat_offset_color: vec4<f32>,
@location(4) @interpolate(flat) flat_base_color: u32,
@location(5) @interpolate(flat) flat_offset_color: u32,
@location(6) @interpolate(flat) area1_flat_base_color: u32,
@location(7) @interpolate(flat) area1_flat_offset_color: u32,
@location(8) @interpolate(flat) tex_idx_shading_instr: vec2<u32>,
@location(9) @interpolate(flat) area1_tex_idx_shading_instr: vec2<u32>,
@location(10) uv: vec2<f32>,
Expand Down Expand Up @@ -82,12 +65,12 @@ fn main(

let gouraud = ((shading_instructions >> 23) & 1) == 1;
var final_color = fragment_color(
select(flat_base_color, base_color / inv_w, gouraud),
select(flat_offset_color, offset_color / inv_w, gouraud),
select(unpack4x8unorm(flat_base_color).zyxw, base_color / inv_w, gouraud),
select(unpack4x8unorm(flat_offset_color).zyxw, offset_color / inv_w, gouraud),
uv / inv_w,
tex_idx_shading_instr,
select(area1_flat_base_color, area1_base_color / inv_w, gouraud),
select(area1_flat_offset_color, area1_offset_color / inv_w, gouraud),
select(unpack4x8unorm(area1_flat_base_color).zyxw, area1_base_color / inv_w, gouraud),
select(unpack4x8unorm(area1_flat_offset_color).zyxw, area1_offset_color / inv_w, gouraud),
area1_uv / inv_w,
area1_tex_idx_shading_instr,
inv_w,
Expand All @@ -108,7 +91,7 @@ fn main(
if frag_index < oit_uniforms.max_fragments {
let last_head = atomicExchange(&heads.data[heads_index], frag_index);
linked_list.data[frag_index].depth = position_clip.z;
linked_list.data[frag_index].color = final_color.area0; // TODO: Handle Modifier volumes/Area 1
linked_list.data[frag_index].color = pack4x8unorm(final_color.area0); // TODO: Handle Modifier volumes/Area 1
linked_list.data[frag_index].index_and_blend_mode = ((shading_instructions >> 10) & 0x3F) | (index << 6);
linked_list.data[frag_index].next = last_head;
}
Expand Down
16 changes: 16 additions & 0 deletions src/shaders/oit_structs.wgsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
struct OITUniforms {
max_fragments: u32,
target_width: u32,
start_y: u32,
};

struct LinkedListElement {
color: u32,
depth: f32,
index_and_blend_mode: u32,
next: u32,
};

struct LinkedList {
data: array<LinkedListElement>
};
Loading

0 comments on commit 0349143

Please sign in to comment.