Search across packages, versions, files, declarations, and comments. Use multiple terms to narrow results (AND), and add @vertex, @fragment, or @compute to filter by shader stage.
1import package::render::mesh_bindings::mesh;
3@if(MULTIPLE_LIGHTMAPS_IN_ARRAY)
4enable wgpu_binding_array;
6@if(MULTIPLE_LIGHTMAPS_IN_ARRAY) {
7@group(2) @binding(4) var lightmaps_textures: binding_array<texture_2d<f32>, 4>;
8@group(2) @binding(5) var lightmaps_samplers: binding_array<sampler, 4>;
9}
10@else {
11@group(2) @binding(4) var lightmaps_texture: texture_2d<f32>;
12@group(2) @binding(5) var lightmaps_sampler: sampler;
15/// Samples the lightmap, if any, and returns indirect illumination from it.
16fn lightmap(uv: vec2<f32>, exposure: f32, instance_index: u32) -> vec3<f32> {
17 let packed_uv_rect = mesh[instance_index].lightmap_uv_rect;
18 let uv_rect = vec4<f32>(
19 unpack2x16unorm(packed_uv_rect.x),
20 unpack2x16unorm(packed_uv_rect.y),
21 );
22 let lightmap_uv = mix(uv_rect.xy, uv_rect.zw, uv);
23 let lightmap_slot = mesh[instance_index].material_and_lightmap_bind_group_slot >> 16u;
25 // Bicubic 4-tap
26 // https://developer.nvidia.com/gpugems/gpugems2/part-iii-high-quality-rendering/chapter-20-fast-third-order-texture-filtering
27 // https://advances.realtimerendering.com/s2021/jpatry_advances2021/index.html#/111/0/2
28 var color: vec3<f32>;
29@if(LIGHTMAP_BICUBIC_SAMPLING) {
30 let texture_size = vec2<f32>(lightmap_size(lightmap_slot));
31 let texel_size = 1.0 / texture_size;
32 let puv = lightmap_uv * texture_size + 0.5;
33 let iuv = floor(puv);
34 let fuv = fract(puv);
35 let g0x = g0(fuv.x);
36 let g1x = g1(fuv.x);
37 let h0x = h0_approx(fuv.x);
38 let h1x = h1_approx(fuv.x);
39 let h0y = h0_approx(fuv.y);
40 let h1y = h1_approx(fuv.y);
41 let p0 = (vec2(iuv.x + h0x, iuv.y + h0y) - 0.5) * texel_size;
42 let p1 = (vec2(iuv.x + h1x, iuv.y + h0y) - 0.5) * texel_size;
43 let p2 = (vec2(iuv.x + h0x, iuv.y + h1y) - 0.5) * texel_size;
44 let p3 = (vec2(iuv.x + h1x, iuv.y + h1y) - 0.5) * texel_size;
45 color = g0(fuv.y) * (g0x * sample(p0, lightmap_slot) + g1x * sample(p1, lightmap_slot)) + g1(fuv.y) * (g0x * sample(p2, lightmap_slot) + g1x * sample(p3, lightmap_slot));
46} @else {
47 color = sample(lightmap_uv, lightmap_slot);
50 return color * exposure;
53fn lightmap_size(lightmap_slot: u32) -> vec2<u32> {
54 @if(MULTIPLE_LIGHTMAPS_IN_ARRAY)
55 return textureDimensions(lightmaps_textures[lightmap_slot]);
56 @else
57 return textureDimensions(lightmaps_texture);
60fn sample(uv: vec2<f32>, lightmap_slot: u32) -> vec3<f32> {
61 // Mipmapping lightmaps is usually a bad idea due to leaking across UV
62 // islands, so there's no harm in using mip level 0 and it lets us avoid
63 // control flow uniformity problems.
64 @if(MULTIPLE_LIGHTMAPS_IN_ARRAY)
65 return textureSampleLevel(lightmaps_textures[lightmap_slot], lightmaps_samplers[lightmap_slot], uv, 0.0).rgb;
66 @else
67 return textureSampleLevel(lightmaps_texture, lightmaps_sampler, uv, 0.0).rgb;
70fn w0(a: f32) -> f32 {
71 return (1.0 / 6.0) * (a * (a * (-a + 3.0) - 3.0) + 1.0);
74fn w1(a: f32) -> f32 {
75 return (1.0 / 6.0) * (a * a * (3.0 * a - 6.0) + 4.0);
78fn w2(a: f32) -> f32 {
79 return (1.0 / 6.0) * (a * (a * (-3.0 * a + 3.0) + 3.0) + 1.0);
82fn w3(a: f32) -> f32 {
83 return (1.0 / 6.0) * (a * a * a);
86fn g0(a: f32) -> f32 {
87 return w0(a) + w1(a);
90fn g1(a: f32) -> f32 {
91 return w2(a) + w3(a);
94fn h0_approx(a: f32) -> f32 {
95 return -0.2 - a * (0.24 * a - 0.44);
98fn h1_approx(a: f32) -> f32 {
99 return 1.0 + a * (0.24 * a - 0.04);
Contents