Skip to content
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
73 changes: 50 additions & 23 deletions crates/renderide/shaders/materials/billboardunlit.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@
//#render_queue AlphaTest+200
//#texture_default _Tex white
//#texture_default _OffsetTex black
//#texture_default _MaskTex white
//#mat_default _Color vec4 1.0 1.0 1.0 1.0
//#mat_default _OffsetMagnitude vec4 0.1 0.1 0.0 0.0
//#mat_default _PointSize vec4 0.1 0.1 0.0 0.0
//#mat_default _PolarPow float 1.0
//#mat_default _Cutoff float 0.5
//#mat_default _Tex_LodBias float 0.0
//#mat_default _OffsetTex_LodBias float 0.0
//#mat_default _MaskTex_LodBias float 0.0

#import renderide::core::texture_sampling as ts
#import renderide::core::uv as uvu
Expand All @@ -27,6 +29,7 @@
#import renderide::frame::fog as rfog
#import renderide::draw::per_draw as pd
#import renderide::draw::types as dt
#import renderide::material::alpha as ma
#import renderide::material::variant_bits as vb
#import renderide::material::vertex_color as vc
#import renderide::mesh::billboard as mb
Expand All @@ -36,6 +39,7 @@ struct BillboardUnlitMaterial {
_Color: vec4<f32>,
_Tex_ST: vec4<f32>,
_RightEye_ST: vec4<f32>,
_MaskTex_ST: vec4<f32>,
_OffsetTex_ST: vec4<f32>,
_OffsetMagnitude: vec4<f32>,
_PointSize: vec4<f32>,
Expand All @@ -44,32 +48,37 @@ struct BillboardUnlitMaterial {
_RenderideVariantBits: u32,
_Tex_LodBias: f32,
_OffsetTex_LodBias: f32,
_pad0: vec2<f32>,
_MaskTex_LodBias: f32,
_pad0: f32,
}

const BILLBOARDUNLIT_KW_ALPHATEST: u32 = 1u << 0u;
const BILLBOARDUNLIT_KW_COLOR: u32 = 1u << 1u;
const BILLBOARDUNLIT_KW_MUL_ALPHA_INTENSITY: u32 = 1u << 2u;
const BILLBOARDUNLIT_KW_MUL_RGB_BY_ALPHA: u32 = 1u << 3u;
const BILLBOARDUNLIT_KW_OFFSET_TEXTURE: u32 = 1u << 4u;
const BILLBOARDUNLIT_KW_POINT_ROTATION: u32 = 1u << 5u;
const BILLBOARDUNLIT_KW_POINT_SIZE: u32 = 1u << 6u;
const BILLBOARDUNLIT_KW_POINT_UV: u32 = 1u << 7u;
const BILLBOARDUNLIT_KW_POLARUV: u32 = 1u << 8u;
const BILLBOARDUNLIT_KW_RIGHT_EYE_ST: u32 = 1u << 9u;
const BILLBOARDUNLIT_KW_TEXTURE: u32 = 1u << 10u;
const BILLBOARDUNLIT_KW_VERTEX_HDRSRGB_COLOR: u32 = 1u << 11u;
const BILLBOARDUNLIT_KW_VERTEX_HDRSRGBALPHA_COLOR: u32 = 1u << 12u;
const BILLBOARDUNLIT_KW_VERTEX_LINEAR_COLOR: u32 = 1u << 13u;
const BILLBOARDUNLIT_KW_VERTEX_SRGB_COLOR: u32 = 1u << 14u;
const BILLBOARDUNLIT_KW_VERTEXCOLORS: u32 = 1u << 15u;
const BILLBOARDUNLIT_KW_RENDER_BUFFER: u32 = 1u << 16u;
const BILLBOARDUNLIT_KW_MASK_TEXTURE_CLIP: u32 = 1u << 2u;
const BILLBOARDUNLIT_KW_MASK_TEXTURE_MUL: u32 = 1u << 3u;
const BILLBOARDUNLIT_KW_MUL_ALPHA_INTENSITY: u32 = 1u << 4u;
const BILLBOARDUNLIT_KW_MUL_RGB_BY_ALPHA: u32 = 1u << 5u;
const BILLBOARDUNLIT_KW_OFFSET_TEXTURE: u32 = 1u << 6u;
const BILLBOARDUNLIT_KW_POINT_ROTATION: u32 = 1u << 7u;
const BILLBOARDUNLIT_KW_POINT_SIZE: u32 = 1u << 8u;
const BILLBOARDUNLIT_KW_POINT_UV: u32 = 1u << 9u;
const BILLBOARDUNLIT_KW_POLARUV: u32 = 1u << 10u;
const BILLBOARDUNLIT_KW_RIGHT_EYE_ST: u32 = 1u << 11u;
const BILLBOARDUNLIT_KW_TEXTURE: u32 = 1u << 12u;
const BILLBOARDUNLIT_KW_VERTEX_HDRSRGB_COLOR: u32 = 1u << 13u;
const BILLBOARDUNLIT_KW_VERTEX_HDRSRGBALPHA_COLOR: u32 = 1u << 14u;
const BILLBOARDUNLIT_KW_VERTEX_LINEAR_COLOR: u32 = 1u << 15u;
const BILLBOARDUNLIT_KW_VERTEX_SRGB_COLOR: u32 = 1u << 16u;
const BILLBOARDUNLIT_KW_VERTEXCOLORS: u32 = 1u << 17u;
const BILLBOARDUNLIT_KW_RENDER_BUFFER: u32 = 1u << 18u;

@group(1) @binding(0) var<uniform> mat: BillboardUnlitMaterial;
@group(1) @binding(1) var _Tex: texture_2d<f32>;
@group(1) @binding(2) var _Tex_sampler: sampler;
@group(1) @binding(3) var _OffsetTex: texture_2d<f32>;
@group(1) @binding(4) var _OffsetTex_sampler: sampler;
@group(1) @binding(5) var _MaskTex: texture_2d<f32>;
@group(1) @binding(6) var _MaskTex_sampler: sampler;

fn bb_kw(mask: u32) -> bool {
return vb::enabled(mat._RenderideVariantBits, mask);
Expand All @@ -83,6 +92,14 @@ fn kw_COLOR() -> bool {
return bb_kw(BILLBOARDUNLIT_KW_COLOR);
}

fn kw_MASK_TEXTURE_CLIP() -> bool {
return bb_kw(BILLBOARDUNLIT_KW_MASK_TEXTURE_CLIP);
}

fn kw_MASK_TEXTURE_MUL() -> bool {
return bb_kw(BILLBOARDUNLIT_KW_MASK_TEXTURE_MUL);
}

fn kw_MUL_ALPHA_INTENSITY() -> bool {
return bb_kw(BILLBOARDUNLIT_KW_MUL_ALPHA_INTENSITY);
}
Expand Down Expand Up @@ -402,25 +419,35 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
let use_color = kw_COLOR();

var col: vec4<f32>;
var clip_alpha: f32;
if (use_texture) {
let tex = sample_main_texture(in.uv, in.view_layer);
clip_alpha = tex.a;
if (use_color) {
col = tex * mat._Color;
clip_alpha = clip_alpha * mat._Color.a;
} else {
col = tex;
}
} else if (use_color) {
col = mat._Color;
clip_alpha = mat._Color.a;
} else {
col = vec4<f32>(1.0);
clip_alpha = 1.0;
}

if (kw_ALPHATEST() && clip_alpha < mat._Cutoff) {
let mask_clip = kw_MASK_TEXTURE_CLIP();
let mask_mul = kw_MASK_TEXTURE_MUL();
if (mask_mul || mask_clip) {
let uv_mask = uvu::apply_st(in.uv, mat._MaskTex_ST);
let mask_sample = ts::sample_tex_2d(_MaskTex, _MaskTex_sampler, uv_mask, mat._MaskTex_LodBias);
let mask_lum = ma::mask_luminance(mask_sample);

if (mask_mul) {
col.a = col.a * mask_lum;
}
if (mask_clip && mask_lum < mat._Cutoff) {
discard;
}
}

if (kw_ALPHATEST() && !mask_clip && col.a < mat._Cutoff) {
discard;
}

Expand All @@ -433,7 +460,7 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
}

if (kw_MUL_ALPHA_INTENSITY()) {
col = vec4<f32>(col.rgb, col.a * dot(col.rgb, vec3<f32>(0.3333333)));
col = vec4<f32>(col.rgb, ma::alpha_intensity(col.a, col.rgb));
}

return rg::retain_globals_additive(rfog::apply_rgba(col, in.fog_coord));
Expand Down
6 changes: 2 additions & 4 deletions crates/renderide/shaders/materials/unlit.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -228,12 +228,10 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
let alpha_test = kw_ALPHATEST();
let mask_clip = kw_MASK_TEXTURE_CLIP();
let mask_mul = kw_MASK_TEXTURE_MUL();
let mul_rgb_by_alpha = kw_MUL_RGB_BY_ALPHA();

let uv_mask = uvu::apply_st(in.uv, mat._MaskTex_ST);
var mask_lum_for_clip = 1.0;

if (mask_mul || mask_clip) {
let uv_mask = uvu::apply_st(in.uv, mat._MaskTex_ST);
let mask_sample = ts::sample_tex_2d(_MaskTex, _MaskTex_sampler, uv_mask, mat._MaskTex_LodBias);
let mask_lum = ma::mask_luminance(mask_sample);
mask_lum_for_clip = mask_lum;
Expand Down Expand Up @@ -266,7 +264,7 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
color = color * vertex_color_to_linear(in.color);
}

if (mul_rgb_by_alpha) {
if (kw_MUL_RGB_BY_ALPHA()) {
color = vec4<f32>(ma::apply_premultiply(color.rgb, color.a, true), color.a);
}

Expand Down
28 changes: 15 additions & 13 deletions crates/renderide/src/materials/render_buffer_shader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
///
/// When set, `billboardunlit.wgsl` treats per-vertex point sizes as final particle sizes instead
/// of multiplying them by the material `_PointSize`.
pub(crate) const BILLBOARD_RENDER_BUFFER_ABSOLUTE_SIZE_BIT: u32 = 1u32 << 16;
pub(crate) const BILLBOARD_RENDER_BUFFER_ABSOLUTE_SIZE_BIT: u32 = 1u32 << 18;
/// Billboard/Unlit variant bit that enables per-particle color and alpha.
pub(crate) const BILLBOARD_RENDER_BUFFER_VERTEX_COLORS_BIT: u32 = 1u32 << 15;
pub(crate) const BILLBOARD_RENDER_BUFFER_VERTEX_COLORS_BIT: u32 = 1u32 << 17;

/// Returns whether `stem` names an embedded Unlit-family shader other than Billboard/Unlit.
pub(crate) fn is_unlit_family_embedded_stem(stem: &str) -> bool {
Expand Down Expand Up @@ -34,15 +34,17 @@ pub(crate) fn remap_unlit_variant_bits_for_billboard(unlit_bits: u32) -> u32 {
const PAIRS: &[(u32, u32)] = &[
(0, 0),
(1, 1),
(4, 2),
(5, 3),
(6, 4),
(7, 8),
(8, 9),
(9, 10),
(11, 13),
(12, 14),
(13, 15),
(2, 2),
(3, 3),
(4, 4),
(5, 5),
(6, 6),
(7, 10),
(8, 11),
(9, 12),
(11, 15),
(12, 16),
(13, 17),
];
let mut out = 0u32;
for &(from, to) in PAIRS {
Expand Down Expand Up @@ -70,8 +72,8 @@ mod tests {
let billboard = remap_unlit_variant_bits_for_billboard(unlit);

assert_eq!(billboard & (1u32 << 1), 1u32 << 1);
assert_eq!(billboard & (1u32 << 10), 1u32 << 10);
assert_eq!(billboard & (1u32 << 9), 0);
assert_eq!(billboard & (1u32 << 12), 1u32 << 12);
assert_eq!(billboard & (1u32 << 11), 0);
}

#[test]
Expand Down
5 changes: 3 additions & 2 deletions crates/renderide/tests/shader_module_audit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,8 +374,9 @@ fn billboard_render_buffer_uses_indexed_corner_separate_from_sample_uv() -> io::
"Render-buffer billboards must apply renderer alignment and screen-size clamp metadata"
);
assert!(
src.contains("if (kw_ALPHATEST() && clip_alpha < mat._Cutoff)")
&& !src.contains("clip_alpha <= mat._Cutoff"),
src.contains("if (kw_ALPHATEST() && !mask_clip && col.a < mat._Cutoff)")
&& src.contains("if (mask_clip && mask_lum < mat._Cutoff)")
&& !src.contains("<= mat._Cutoff"),
"Billboard/Unlit alpha test must match Unity clip(col.a - _Cutoff) equality semantics"
);
assert!(
Expand Down
Loading