Constant CONTENT_WGSL
Source pub const CONTENT_WGSL: &str = r#"
override use_content: bool = true;
override use_content_cutout: bool = true;
@group(3) @binding(18) var content0: texture_2d<f32>;
@group(3) @binding(19) var content1: texture_2d<f32>;
@group(3) @binding(20) var content2: texture_2d<f32>;
@group(3) @binding(21) var content3: texture_2d<f32>;
@group(3) @binding(22) var content_sampler: sampler;
struct ContentCaustic {
rect: vec4f,
plane: vec4f,
info: vec4f,
}
@group(3) @binding(27) var<uniform> content_caustic: ContentCaustic;
fn caustic_uv(world: vec3f) -> vec2f {
let toward = content_caustic.plane.xyz;
let along = (content_caustic.plane.w - world.y) / max(toward.y, 1e-4);
let q = world.xz + toward.xz * along;
return (q - content_caustic.rect.xy) / content_caustic.rect.zw;
}
fn caustic_gain(at: vec2f, dx: vec2f, dy: vec2f) -> vec3f {
if (content_caustic.info.z < 0.5 || any(at < vec2f(0.0)) || any(at > vec2f(1.0))) {
return vec3f(1.0);
}
let texel = content_texel(i32(content_caustic.info.x), at, dx, dy).rgb;
return max(vec3f(1.0) + texel * content_caustic.info.y, vec3f(0.0));
}
fn content_size(slot: i32) -> vec2f {
switch slot {
case 0: { return vec2f(textureDimensions(content0)); }
case 1: { return vec2f(textureDimensions(content1)); }
case 2: { return vec2f(textureDimensions(content2)); }
case 3: { return vec2f(textureDimensions(content3)); }
default: { return vec2f(1.0); }
}
}
fn content_texel(slot: i32, at: vec2f, dx: vec2f, dy: vec2f) -> vec4f {
switch slot {
case 0: { return textureSampleGrad(content0, content_sampler, at, dx, dy); }
case 1: { return textureSampleGrad(content1, content_sampler, at, dx, dy); }
case 2: { return textureSampleGrad(content2, content_sampler, at, dx, dy); }
case 3: { return textureSampleGrad(content3, content_sampler, at, dx, dy); }
default: { return vec4f(0.0); }
}
}
fn content_alpha(slot: i32, at: vec2f) -> f32 {
switch slot {
case 0: { return textureSampleLevel(content0, content_sampler, at, 0.0).a; }
case 1: { return textureSampleLevel(content1, content_sampler, at, 0.0).a; }
case 2: { return textureSampleLevel(content2, content_sampler, at, 0.0).a; }
case 3: { return textureSampleLevel(content3, content_sampler, at, 0.0).a; }
default: { return 0.0; }
}
}
fn content_cut(material_index: u32, uv: vec2f, transform: vec4f, crop: vec4f, cutoff: f32) -> bool {
let slot = i32(round(map_materials[material_index].content.x));
if (slot < 0) {
return true;
}
let at = content_uv(uv, transform);
if (!content_inside(at, crop)) {
return true;
}
return content_alpha(slot, at) < cutoff;
}
fn content_apply(surface_in: Shaded, material_index: u32, uv: vec2f, uv_dx: vec2f, uv_dy: vec2f, transform: vec4f, crop: vec4f, tangent: vec3f, bitangent: vec3f, geometric: vec3f) -> Shaded {
var surface = surface_in;
if (!use_content) {
return surface;
}
let layer = map_materials[material_index].content;
let slot = i32(round(layer.x));
if (slot < 0) {
return surface;
}
let at = content_uv(uv, transform);
if (!content_inside(at, crop)) {
return surface;
}
let dx = uv_dx * transform.zw;
let dy = uv_dy * transform.zw;
let sharpen = map_materials[material_index].content_extra.y;
let texel = content_texel(slot, at, dx * sharpen, dy * sharpen);
let blend = u32(round(layer.y));
var out = content_composite(surface, blend, texel, layer.z, map_materials[material_index].content_extra.x);
if (layer.w != 0.0) {
let step = max(1.5 / content_size(slot), max(abs(dx), abs(dy)));
let ax = content_texel(slot, at + vec2f(step.x, 0.0), dx, dy).a - content_texel(slot, at - vec2f(step.x, 0.0), dx, dy).a;
let ay = content_texel(slot, at + vec2f(0.0, step.y), dx, dy).a - content_texel(slot, at - vec2f(0.0, step.y), dx, dy).a;
var n = content_emboss(out.normal, tangent, bitangent, vec2f(ax, ay), layer.w);
if (dot(n, geometric) < 0.05) {
n = normalize(n + geometric * 0.1);
}
out.normal = n;
}
return out;
}
"#;