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.
1#define_import_path bevy_pbr::pbr_fragment
3#import bevy_render::bindless::{bindless_samplers_filtering, bindless_textures_2d}
5#import bevy_pbr::{
6 pbr_functions,
7 pbr_functions::SampleBias,
8 pbr_bindings,
9 pbr_types,
10 prepass_utils,
11 lighting,
12 mesh_bindings::mesh,
13 mesh_view_bindings::view,
14 parallax_mapping::parallaxed_uv,
15 lightmap::lightmap,
18#ifdef SCREEN_SPACE_AMBIENT_OCCLUSION
19#import bevy_pbr::mesh_view_bindings::screen_space_ambient_occlusion_texture
20#import bevy_pbr::ssao_utils::ssao_multibounce
21#endif
23#ifdef MESHLET_MESH_MATERIAL_PASS
24#import bevy_pbr::meshlet_visibility_buffer_resolve::VertexOutput
25#else ifdef PREPASS_PIPELINE
26#import bevy_pbr::prepass_io::VertexOutput
27#else
28#import bevy_pbr::forward_io::VertexOutput
29#endif
31#ifdef BINDLESS
32#import bevy_pbr::pbr_bindings::material_indices
33#endif // BINDLESS
35// prepare a basic PbrInput from the vertex stage output, mesh binding and view binding
36fn pbr_input_from_vertex_output(
37 in: VertexOutput,
38 is_front: bool,
39 double_sided: bool,
40) -> pbr_types::PbrInput {
41 var pbr_input: pbr_types::PbrInput = pbr_types::pbr_input_new();
43#ifdef MESHLET_MESH_MATERIAL_PASS
44 pbr_input.flags = in.mesh_flags;
45#else
46 pbr_input.flags = mesh[in.instance_index].flags;
47#endif
49 pbr_input.is_orthographic = view.clip_from_view[3].w == 1.0;
50 pbr_input.V = pbr_functions::calculate_view(in.world_position, pbr_input.is_orthographic);
51 pbr_input.frag_coord = in.position;
52 pbr_input.world_position = in.world_position;
54#ifdef VERTEX_COLORS
55 pbr_input.material.base_color = in.color;
56#endif
58 pbr_input.world_normal = pbr_functions::prepare_world_normal(
59 in.world_normal,
60 double_sided,
61 is_front,
62 );
64#ifdef LOAD_PREPASS_NORMALS
65 pbr_input.N = prepass_utils::prepass_normal(in.position, 0u);
66#else
67 pbr_input.N = normalize(pbr_input.world_normal);
68#endif
70 return pbr_input;
73// Prepare a full PbrInput by sampling all textures to resolve
74// the material members
75fn pbr_input_from_standard_material(
76 in: VertexOutput,
77 is_front: bool,
78) -> pbr_types::PbrInput {
79#ifdef MESHLET_MESH_MATERIAL_PASS
80 let slot = in.material_bind_group_slot;
81#else // MESHLET_MESH_MATERIAL_PASS
82 let slot = mesh[in.instance_index].material_and_lightmap_bind_group_slot & 0xffffu;
83#endif // MESHLET_MESH_MATERIAL_PASS
84#ifdef BINDLESS
85 let flags = pbr_bindings::material_array[material_indices[slot].material].flags;
86 let base_color = pbr_bindings::material_array[material_indices[slot].material].base_color;
87 let deferred_lighting_pass_id =
88 pbr_bindings::material_array[material_indices[slot].material].deferred_lighting_pass_id;
89#else // BINDLESS
90 let flags = pbr_bindings::material.flags;
91 let base_color = pbr_bindings::material.base_color;
92 let deferred_lighting_pass_id = pbr_bindings::material.deferred_lighting_pass_id;
93#endif
95 let double_sided = (flags & pbr_types::STANDARD_MATERIAL_FLAGS_DOUBLE_SIDED_BIT) != 0u;
97 var pbr_input: pbr_types::PbrInput = pbr_input_from_vertex_output(in, is_front, double_sided);
98 pbr_input.material.flags = flags;
99 pbr_input.material.base_color *= base_color;
100 pbr_input.material.deferred_lighting_pass_id = deferred_lighting_pass_id;
102 // Neubelt and Pettineo 2013, "Crafting a Next-gen Material Pipeline for The Order: 1886"
103 let NdotV = max(dot(pbr_input.N, pbr_input.V), 0.0001);
105 // Fill in the sample bias so we can sample from textures.
106 var bias: SampleBias;
107#ifdef MESHLET_MESH_MATERIAL_PASS
108 bias.ddx_uv = in.ddx_uv;
109 bias.ddy_uv = in.ddy_uv;
110#else // MESHLET_MESH_MATERIAL_PASS
111 bias.mip_bias = view.mip_bias;
112#endif // MESHLET_MESH_MATERIAL_PASS
114// TODO: Transforming UVs mean we need to apply derivative chain rule for meshlet mesh material pass
115#ifdef VERTEX_UVS
117#ifdef BINDLESS
118 let uv_transform = pbr_bindings::material_array[material_indices[slot].material].uv_transform;
119#else // BINDLESS
120 let uv_transform = pbr_bindings::material.uv_transform;
121#endif // BINDLESS
123#ifdef VERTEX_UVS_A
124 var uv = (uv_transform * vec3(in.uv, 1.0)).xy;
125#endif
127// TODO: Transforming UVs mean we need to apply derivative chain rule for meshlet mesh material pass
128#ifdef VERTEX_UVS_B
129 var uv_b = (uv_transform * vec3(in.uv_b, 1.0)).xy;
130#else
131 var uv_b = uv;
132#endif
134#ifdef VERTEX_TANGENTS
135 if ((flags & pbr_types::STANDARD_MATERIAL_FLAGS_DEPTH_MAP_BIT) != 0u) {
136 let V = pbr_input.V;
137 let TBN = pbr_functions::calculate_tbn_mikktspace(in.world_normal, in.world_tangent);
138 let T = TBN[0];
139 let B = TBN[1];
140 let N = TBN[2];
141 // Transform V from fragment to camera in world space to tangent space.
142 let Vt = vec3(dot(V, T), dot(V, B), dot(V, N));
143#ifdef VERTEX_UVS_A
144 // TODO: Transforming UVs mean we need to apply derivative chain rule for meshlet mesh material pass
145 uv = parallaxed_uv(
146#ifdef BINDLESS
147 pbr_bindings::material_array[material_indices[slot].material].parallax_depth_scale,
148 pbr_bindings::material_array[material_indices[slot].material].max_parallax_layer_count,
149 pbr_bindings::material_array[material_indices[slot].material].max_relief_mapping_search_steps,
150#else // BINDLESS
151 pbr_bindings::material.parallax_depth_scale,
152 pbr_bindings::material.max_parallax_layer_count,
153 pbr_bindings::material.max_relief_mapping_search_steps,
154#endif // BINDLESS
155 uv,
156 // Flip the direction of Vt to go toward the surface to make the
157 // parallax mapping algorithm easier to understand and reason
158 // about.
159 -Vt,
160 slot,
161 );
162#endif
164#ifdef VERTEX_UVS_B
165 // TODO: Transforming UVs mean we need to apply derivative chain rule for meshlet mesh material pass
166 uv_b = parallaxed_uv(
167#ifdef BINDLESS
168 pbr_bindings::material_array[material_indices[slot].material].parallax_depth_scale,
169 pbr_bindings::material_array[material_indices[slot].material].max_parallax_layer_count,
170 pbr_bindings::material_array[material_indices[slot].material].max_relief_mapping_search_steps,
171#else // BINDLESS
172 pbr_bindings::material.parallax_depth_scale,
173 pbr_bindings::material.max_parallax_layer_count,
174 pbr_bindings::material.max_relief_mapping_search_steps,
175#endif // BINDLESS
176 uv_b,
177 // Flip the direction of Vt to go toward the surface to make the
178 // parallax mapping algorithm easier to understand and reason
179 // about.
180 -Vt,
181 slot,
182 );
183#else
184 uv_b = uv;
185#endif
186 }
187#endif // VERTEX_TANGENTS
189 if ((flags & pbr_types::STANDARD_MATERIAL_FLAGS_BASE_COLOR_TEXTURE_BIT) != 0u) {
190 pbr_input.material.base_color *=
191#ifdef MESHLET_MESH_MATERIAL_PASS
192 textureSampleGrad(
193#else // MESHLET_MESH_MATERIAL_PASS
194 textureSampleBias(
195#endif // MESHLET_MESH_MATERIAL_PASS
196#ifdef BINDLESS
197 bindless_textures_2d[material_indices[slot].base_color_texture],
198 bindless_samplers_filtering[material_indices[slot].base_color_sampler],
199#else // BINDLESS
200 pbr_bindings::base_color_texture,
201 pbr_bindings::base_color_sampler,
202#endif // BINDLESS
203#ifdef STANDARD_MATERIAL_BASE_COLOR_UV_B
204 uv_b,
205#else
206 uv,
207#endif
208#ifdef MESHLET_MESH_MATERIAL_PASS
209 bias.ddx_uv,
210 bias.ddy_uv,
211#else // MESHLET_MESH_MATERIAL_PASS
212 bias.mip_bias,
213#endif // MESHLET_MESH_MATERIAL_PASS
214 );
216#ifdef ALPHA_TO_COVERAGE
217 // Sharpen alpha edges.
218 //
219 // https://bgolus.medium.com/anti-aliased-alpha-test-the-esoteric-alpha-to-coverage-8b177335ae4f
220 let alpha_mode = flags & pbr_types::STANDARD_MATERIAL_FLAGS_ALPHA_MODE_RESERVED_BITS;
221 if alpha_mode == pbr_types::STANDARD_MATERIAL_FLAGS_ALPHA_MODE_ALPHA_TO_COVERAGE {
223#ifdef BINDLESS
224 let alpha_cutoff = pbr_bindings::material_array[material_indices[slot].material].alpha_cutoff;
225#else // BINDLESS
226 let alpha_cutoff = pbr_bindings::material.alpha_cutoff;
227#endif // BINDLESS
229 pbr_input.material.base_color.a = (pbr_input.material.base_color.a - alpha_cutoff) /
230 max(fwidth(pbr_input.material.base_color.a), 0.0001) + 0.5;
231 }
232#endif // ALPHA_TO_COVERAGE
234 }
235#endif // VERTEX_UVS
237 pbr_input.material.flags = flags;
239 // NOTE: Unlit bit not set means == 0 is true, so the true case is if lit
240 if ((flags & pbr_types::STANDARD_MATERIAL_FLAGS_UNLIT_BIT) == 0u) {
241#ifdef BINDLESS
242 pbr_input.material.ior = pbr_bindings::material_array[material_indices[slot].material].ior;
243 pbr_input.material.attenuation_color =
244 pbr_bindings::material_array[material_indices[slot].material].attenuation_color;
245 pbr_input.material.attenuation_distance =
246 pbr_bindings::material_array[material_indices[slot].material].attenuation_distance;
247 pbr_input.material.alpha_cutoff =
248 pbr_bindings::material_array[material_indices[slot].material].alpha_cutoff;
249#else // BINDLESS
250 pbr_input.material.ior = pbr_bindings::material.ior;
251 pbr_input.material.attenuation_color = pbr_bindings::material.attenuation_color;
252 pbr_input.material.attenuation_distance = pbr_bindings::material.attenuation_distance;
253 pbr_input.material.alpha_cutoff = pbr_bindings::material.alpha_cutoff;
254#endif // BINDLESS
256 // reflectance
257#ifdef BINDLESS
258 pbr_input.material.reflectance =
259 pbr_bindings::material_array[material_indices[slot].material].reflectance;
260#else // BINDLESS
261 pbr_input.material.reflectance = pbr_bindings::material.reflectance;
262#endif // BINDLESS
264#ifdef PBR_SPECULAR_TEXTURES_SUPPORTED
265#ifdef VERTEX_UVS
267 // Specular texture
268 if ((flags & pbr_types::STANDARD_MATERIAL_FLAGS_SPECULAR_TEXTURE_BIT) != 0u) {
269 let specular =
270#ifdef MESHLET_MESH_MATERIAL_PASS
271 textureSampleGrad(
272#else // MESHLET_MESH_MATERIAL_PASS
273 textureSampleBias(
274#endif // MESHLET_MESH_MATERIAL_PASS
275#ifdef BINDLESS
276 bindless_textures_2d[material_indices[slot].specular_texture],
277 bindless_samplers_filtering[material_indices[slot].specular_sampler],
278#else // BINDLESS
279 pbr_bindings::specular_texture,
280 pbr_bindings::specular_sampler,
281#endif // BINDLESS
282#ifdef STANDARD_MATERIAL_SPECULAR_UV_B
283 uv_b,
284#else // STANDARD_MATERIAL_SPECULAR_UV_B
285 uv,
286#endif // STANDARD_MATERIAL_SPECULAR_UV_B
287#ifdef MESHLET_MESH_MATERIAL_PASS
288 bias.ddx_uv,
289 bias.ddy_uv,
290#else // MESHLET_MESH_MATERIAL_PASS
291 bias.mip_bias,
292#endif // MESHLET_MESH_MATERIAL_PASS
293 ).a;
294 // This 0.5 factor is from the `KHR_materials_specular` specification:
295 // <https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_specular#materials-with-reflectance-parameter>
296 pbr_input.material.reflectance *= specular * 0.5;
297 }
299 // Specular tint texture
300 if ((flags & pbr_types::STANDARD_MATERIAL_FLAGS_SPECULAR_TINT_TEXTURE_BIT) != 0u) {
301 let specular_tint =
302#ifdef MESHLET_MESH_MATERIAL_PASS
303 textureSampleGrad(
304#else // MESHLET_MESH_MATERIAL_PASS
305 textureSampleBias(
306#endif // MESHLET_MESH_MATERIAL_PASS
307#ifdef BINDLESS
308 bindless_textures_2d[material_indices[slot].specular_tint_texture],
309 bindless_samplers_filtering[material_indices[slot].specular_tint_sampler],
310#else // BINDLESS
311 pbr_bindings::specular_tint_texture,
312 pbr_bindings::specular_tint_sampler,
313#endif // BINDLESS
314#ifdef STANDARD_MATERIAL_SPECULAR_TINT_UV_B
315 uv_b,
316#else // STANDARD_MATERIAL_SPECULAR_TINT_UV_B
317 uv,
318#endif // STANDARD_MATERIAL_SPECULAR_TINT_UV_B
319#ifdef MESHLET_MESH_MATERIAL_PASS
320 bias.ddx_uv,
321 bias.ddy_uv,
322#else // MESHLET_MESH_MATERIAL_PASS
323 bias.mip_bias,
324#endif // MESHLET_MESH_MATERIAL_PASS
325 ).rgb;
326 pbr_input.material.reflectance *= specular_tint;
327 }
329#endif // VERTEX_UVS
330#endif // PBR_SPECULAR_TEXTURES_SUPPORTED
332 // emissive
333#ifdef BINDLESS
334 var emissive: vec4<f32> = pbr_bindings::material_array[material_indices[slot].material].emissive;
335#else // BINDLESS
336 var emissive: vec4<f32> = pbr_bindings::material.emissive;
337#endif // BINDLESS
339#ifdef VERTEX_UVS
340 if ((flags & pbr_types::STANDARD_MATERIAL_FLAGS_EMISSIVE_TEXTURE_BIT) != 0u) {
341 emissive = vec4<f32>(emissive.rgb *
342#ifdef MESHLET_MESH_MATERIAL_PASS
343 textureSampleGrad(
344#else // MESHLET_MESH_MATERIAL_PASS
345 textureSampleBias(
346#endif // MESHLET_MESH_MATERIAL_PASS
347#ifdef BINDLESS
348 bindless_textures_2d[material_indices[slot].emissive_texture],
349 bindless_samplers_filtering[material_indices[slot].emissive_sampler],
350#else // BINDLESS
351 pbr_bindings::emissive_texture,
352 pbr_bindings::emissive_sampler,
353#endif // BINDLESS
354#ifdef STANDARD_MATERIAL_EMISSIVE_UV_B
355 uv_b,
356#else
357 uv,
358#endif
359#ifdef MESHLET_MESH_MATERIAL_PASS
360 bias.ddx_uv,
361 bias.ddy_uv,
362#else // MESHLET_MESH_MATERIAL_PASS
363 bias.mip_bias,
364#endif // MESHLET_MESH_MATERIAL_PASS
365 ).rgb,
366 emissive.a);
367 }
368#endif
369 pbr_input.material.emissive = emissive;
371 // metallic and perceptual roughness
372#ifdef BINDLESS
373 var metallic: f32 = pbr_bindings::material_array[material_indices[slot].material].metallic;
374 var perceptual_roughness: f32 = pbr_bindings::material_array[material_indices[slot].material].perceptual_roughness;
375#else // BINDLESS
376 var metallic: f32 = pbr_bindings::material.metallic;
377 var perceptual_roughness: f32 = pbr_bindings::material.perceptual_roughness;
378#endif // BINDLESS
380 let roughness = lighting::perceptualRoughnessToRoughness(perceptual_roughness);
381#ifdef VERTEX_UVS
382 if ((flags & pbr_types::STANDARD_MATERIAL_FLAGS_METALLIC_ROUGHNESS_TEXTURE_BIT) != 0u) {
383 let metallic_roughness =
384#ifdef MESHLET_MESH_MATERIAL_PASS
385 textureSampleGrad(
386#else // MESHLET_MESH_MATERIAL_PASS
387 textureSampleBias(
388#endif // MESHLET_MESH_MATERIAL_PASS
389#ifdef BINDLESS
390 bindless_textures_2d[material_indices[slot].metallic_roughness_texture],
391 bindless_samplers_filtering[material_indices[slot].metallic_roughness_sampler],
392#else // BINDLESS
393 pbr_bindings::metallic_roughness_texture,
394 pbr_bindings::metallic_roughness_sampler,
395#endif // BINDLESS
396#ifdef STANDARD_MATERIAL_METALLIC_ROUGHNESS_UV_B
397 uv_b,
398#else
399 uv,
400#endif
401#ifdef MESHLET_MESH_MATERIAL_PASS
402 bias.ddx_uv,
403 bias.ddy_uv,
404#else // MESHLET_MESH_MATERIAL_PASS
405 bias.mip_bias,
406#endif // MESHLET_MESH_MATERIAL_PASS
407 );
408 // Sampling from GLTF standard channels for now
409 metallic *= metallic_roughness.b;
410 perceptual_roughness *= metallic_roughness.g;
411 }
412#endif
413 pbr_input.material.metallic = metallic;
414 pbr_input.material.perceptual_roughness = perceptual_roughness;
416 // Clearcoat factor
417#ifdef BINDLESS
418 pbr_input.material.clearcoat =
419 pbr_bindings::material_array[material_indices[slot].material].clearcoat;
420#else // BINDLESS
421 pbr_input.material.clearcoat = pbr_bindings::material.clearcoat;
422#endif // BINDLESS
424#ifdef VERTEX_UVS
425#ifdef PBR_MULTI_LAYER_MATERIAL_TEXTURES_SUPPORTED
426 if ((flags & pbr_types::STANDARD_MATERIAL_FLAGS_CLEARCOAT_TEXTURE_BIT) != 0u) {
427 pbr_input.material.clearcoat *=
428#ifdef MESHLET_MESH_MATERIAL_PASS
429 textureSampleGrad(
430#else // MESHLET_MESH_MATERIAL_PASS
431 textureSampleBias(
432#endif // MESHLET_MESH_MATERIAL_PASS
433#ifdef BINDLESS
434 bindless_textures_2d[material_indices[slot].clearcoat_texture],
435 bindless_samplers_filtering[material_indices[slot].clearcoat_sampler],
436#else // BINDLESS
437 pbr_bindings::clearcoat_texture,
438 pbr_bindings::clearcoat_sampler,
439#endif // BINDLESS
440#ifdef STANDARD_MATERIAL_CLEARCOAT_UV_B
441 uv_b,
442#else
443 uv,
444#endif
445#ifdef MESHLET_MESH_MATERIAL_PASS
446 bias.ddx_uv,
447 bias.ddy_uv,
448#else // MESHLET_MESH_MATERIAL_PASS
449 bias.mip_bias,
450#endif // MESHLET_MESH_MATERIAL_PASS
451 ).r;
452 }
453#endif // PBR_MULTI_LAYER_MATERIAL_TEXTURES_SUPPORTED
454#endif // VERTEX_UVS
456 // Clearcoat roughness
457#ifdef BINDLESS
458 pbr_input.material.clearcoat_perceptual_roughness =
459 pbr_bindings::material_array[material_indices[slot].material].clearcoat_perceptual_roughness;
460#else // BINDLESS
461 pbr_input.material.clearcoat_perceptual_roughness =
462 pbr_bindings::material.clearcoat_perceptual_roughness;
463#endif // BINDLESS
465#ifdef VERTEX_UVS
466#ifdef PBR_MULTI_LAYER_MATERIAL_TEXTURES_SUPPORTED
467 if ((flags & pbr_types::STANDARD_MATERIAL_FLAGS_CLEARCOAT_ROUGHNESS_TEXTURE_BIT) != 0u) {
468 pbr_input.material.clearcoat_perceptual_roughness *=
469#ifdef MESHLET_MESH_MATERIAL_PASS
470 textureSampleGrad(
471#else // MESHLET_MESH_MATERIAL_PASS
472 textureSampleBias(
473#endif // MESHLET_MESH_MATERIAL_PASS
474#ifdef BINDLESS
475 bindless_textures_2d[material_indices[slot].clearcoat_roughness_texture],
476 bindless_samplers_filtering[material_indices[slot].clearcoat_roughness_sampler],
477#else // BINDLESS
478 pbr_bindings::clearcoat_roughness_texture,
479 pbr_bindings::clearcoat_roughness_sampler,
480#endif // BINDLESS
481#ifdef STANDARD_MATERIAL_CLEARCOAT_ROUGHNESS_UV_B
482 uv_b,
483#else
484 uv,
485#endif
486#ifdef MESHLET_MESH_MATERIAL_PASS
487 bias.ddx_uv,
488 bias.ddy_uv,
489#else // MESHLET_MESH_MATERIAL_PASS
490 bias.mip_bias,
491#endif // MESHLET_MESH_MATERIAL_PASS
492 ).g;
493 }
494#endif // PBR_MULTI_LAYER_MATERIAL_TEXTURES_SUPPORTED
495#endif // VERTEX_UVS
497#ifdef BINDLESS
498 var specular_transmission: f32 = pbr_bindings::material_array[slot].specular_transmission;
499#else // BINDLESS
500 var specular_transmission: f32 = pbr_bindings::material.specular_transmission;
501#endif // BINDLESS
503#ifdef VERTEX_UVS
504#ifdef PBR_TRANSMISSION_TEXTURES_SUPPORTED
505 if ((flags & pbr_types::STANDARD_MATERIAL_FLAGS_SPECULAR_TRANSMISSION_TEXTURE_BIT) != 0u) {
506 specular_transmission *=
507#ifdef MESHLET_MESH_MATERIAL_PASS
508 textureSampleGrad(
509#else // MESHLET_MESH_MATERIAL_PASS
510 textureSampleBias(
511#endif // MESHLET_MESH_MATERIAL_PASS
512#ifdef BINDLESS
513 bindless_textures_2d[
514 material_indices[slot].specular_transmission_texture
515 ],
516 bindless_samplers_filtering[
517 material_indices[slot].specular_transmission_sampler
518 ],
519#else // BINDLESS
520 pbr_bindings::specular_transmission_texture,
521 pbr_bindings::specular_transmission_sampler,
522#endif // BINDLESS
523#ifdef STANDARD_MATERIAL_SPECULAR_TRANSMISSION_UV_B
524 uv_b,
525#else
526 uv,
527#endif
528#ifdef MESHLET_MESH_MATERIAL_PASS
529 bias.ddx_uv,
530 bias.ddy_uv,
531#else // MESHLET_MESH_MATERIAL_PASS
532 bias.mip_bias,
533#endif // MESHLET_MESH_MATERIAL_PASS
534 ).r;
535 }
536#endif
537#endif
538 pbr_input.material.specular_transmission = specular_transmission;
540#ifdef BINDLESS
541 var thickness: f32 = pbr_bindings::material_array[material_indices[slot].material].thickness;
542#else // BINDLESS
543 var thickness: f32 = pbr_bindings::material.thickness;
544#endif // BINDLESS
546#ifdef VERTEX_UVS
547#ifdef PBR_TRANSMISSION_TEXTURES_SUPPORTED
548 if ((flags & pbr_types::STANDARD_MATERIAL_FLAGS_THICKNESS_TEXTURE_BIT) != 0u) {
549 thickness *=
550#ifdef MESHLET_MESH_MATERIAL_PASS
551 textureSampleGrad(
552#else // MESHLET_MESH_MATERIAL_PASS
553 textureSampleBias(
554#endif // MESHLET_MESH_MATERIAL_PASS
555#ifdef BINDLESS
556 bindless_textures_2d[material_indices[slot].thickness_texture],
557 bindless_samplers_filtering[material_indices[slot].thickness_sampler],
558#else // BINDLESS
559 pbr_bindings::thickness_texture,
560 pbr_bindings::thickness_sampler,
561#endif // BINDLESS
562#ifdef STANDARD_MATERIAL_THICKNESS_UV_B
563 uv_b,
564#else
565 uv,
566#endif
567#ifdef MESHLET_MESH_MATERIAL_PASS
568 bias.ddx_uv,
569 bias.ddy_uv,
570#else // MESHLET_MESH_MATERIAL_PASS
571 bias.mip_bias,
572#endif // MESHLET_MESH_MATERIAL_PASS
573 ).g;
574 }
575#endif
576#endif
577 // scale thickness, accounting for non-uniform scaling (e.g. a “squished” mesh)
578 // TODO: Meshlet support
579#ifndef MESHLET_MESH_MATERIAL_PASS
580 thickness *= length(
581 (transpose(mesh[in.instance_index].world_from_local) * vec4(pbr_input.N, 0.0)).xyz
582 );
583#endif
584 pbr_input.material.thickness = thickness;
586#ifdef BINDLESS
587 var diffuse_transmission =
588 pbr_bindings::material_array[material_indices[slot].material].diffuse_transmission;
589#else // BINDLESS
590 var diffuse_transmission = pbr_bindings::material.diffuse_transmission;
591#endif // BINDLESS
593#ifdef VERTEX_UVS
594#ifdef PBR_TRANSMISSION_TEXTURES_SUPPORTED
595 if ((flags & pbr_types::STANDARD_MATERIAL_FLAGS_DIFFUSE_TRANSMISSION_TEXTURE_BIT) != 0u) {
596 diffuse_transmission *=
597#ifdef MESHLET_MESH_MATERIAL_PASS
598 textureSampleGrad(
599#else // MESHLET_MESH_MATERIAL_PASS
600 textureSampleBias(
601#endif // MESHLET_MESH_MATERIAL_PASS
602#ifdef BINDLESS
603 bindless_textures_2d[material_indices[slot].diffuse_transmission_texture],
604 bindless_samplers_filtering[material_indices[slot].diffuse_transmission_sampler],
605#else // BINDLESS
606 pbr_bindings::diffuse_transmission_texture,
607 pbr_bindings::diffuse_transmission_sampler,
608#endif // BINDLESS
609#ifdef STANDARD_MATERIAL_DIFFUSE_TRANSMISSION_UV_B
610 uv_b,
611#else
612 uv,
613#endif
614#ifdef MESHLET_MESH_MATERIAL_PASS
615 bias.ddx_uv,
616 bias.ddy_uv,
617#else // MESHLET_MESH_MATERIAL_PASS
618 bias.mip_bias,
619#endif // MESHLET_MESH_MATERIAL_PASS
620 ).a;
621 }
622#endif
623#endif
624 pbr_input.material.diffuse_transmission = diffuse_transmission;
626 var diffuse_occlusion: vec3<f32> = vec3(1.0);
627 var specular_occlusion: f32 = 1.0;
628#ifdef VERTEX_UVS
629 if ((flags & pbr_types::STANDARD_MATERIAL_FLAGS_OCCLUSION_TEXTURE_BIT) != 0u) {
630 diffuse_occlusion *=
631#ifdef MESHLET_MESH_MATERIAL_PASS
632 textureSampleGrad(
633#else // MESHLET_MESH_MATERIAL_PASS
634 textureSampleBias(
635#endif // MESHLET_MESH_MATERIAL_PASS
636#ifdef BINDLESS
637 bindless_textures_2d[material_indices[slot].occlusion_texture],
638 bindless_samplers_filtering[material_indices[slot].occlusion_sampler],
639#else // BINDLESS
640 pbr_bindings::occlusion_texture,
641 pbr_bindings::occlusion_sampler,
642#endif // BINDLESS
643#ifdef STANDARD_MATERIAL_OCCLUSION_UV_B
644 uv_b,
645#else
646 uv,
647#endif
648#ifdef MESHLET_MESH_MATERIAL_PASS
649 bias.ddx_uv,
650 bias.ddy_uv,
651#else // MESHLET_MESH_MATERIAL_PASS
652 bias.mip_bias,
653#endif // MESHLET_MESH_MATERIAL_PASS
654 ).r;
655 }
656#endif
657#ifdef SCREEN_SPACE_AMBIENT_OCCLUSION
658 let ssao = textureLoad(screen_space_ambient_occlusion_texture, vec2<i32>(in.position.xy), 0i).r;
659 let ssao_multibounce = ssao_multibounce(ssao, pbr_input.material.base_color.rgb);
660 diffuse_occlusion = min(diffuse_occlusion, ssao_multibounce);
661 // Use SSAO to estimate the specular occlusion.
662 // Lagarde and Rousiers 2014, "Moving Frostbite to Physically Based Rendering"
663 specular_occlusion = saturate(pow(NdotV + ssao, exp2(-16.0 * roughness - 1.0)) - 1.0 + ssao);
664#endif
665 pbr_input.diffuse_occlusion = diffuse_occlusion;
666 pbr_input.specular_occlusion = specular_occlusion;
668 // N (normal vector)
669#ifndef LOAD_PREPASS_NORMALS
671 pbr_input.N = normalize(pbr_input.world_normal);
672 pbr_input.clearcoat_N = pbr_input.N;
674#ifdef VERTEX_UVS
675#ifdef VERTEX_TANGENTS
677 let TBN = pbr_functions::calculate_tbn_mikktspace(pbr_input.world_normal, in.world_tangent);
679#ifdef STANDARD_MATERIAL_NORMAL_MAP
681 let Nt =
682#ifdef MESHLET_MESH_MATERIAL_PASS
683 textureSampleGrad(
684#else // MESHLET_MESH_MATERIAL_PASS
685 textureSampleBias(
686#endif // MESHLET_MESH_MATERIAL_PASS
687#ifdef BINDLESS
688 bindless_textures_2d[material_indices[slot].normal_map_texture],
689 bindless_samplers_filtering[material_indices[slot].normal_map_sampler],
690#else // BINDLESS
691 pbr_bindings::normal_map_texture,
692 pbr_bindings::normal_map_sampler,
693#endif // BINDLESS
694#ifdef STANDARD_MATERIAL_NORMAL_MAP_UV_B
695 uv_b,
696#else
697 uv,
698#endif
699#ifdef MESHLET_MESH_MATERIAL_PASS
700 bias.ddx_uv,
701 bias.ddy_uv,
702#else // MESHLET_MESH_MATERIAL_PASS
703 bias.mip_bias,
704#endif // MESHLET_MESH_MATERIAL_PASS
705 ).rgb;
707 pbr_input.N = pbr_functions::apply_normal_mapping(flags, TBN, double_sided, is_front, Nt);
709#endif // STANDARD_MATERIAL_NORMAL_MAP
711#ifdef STANDARD_MATERIAL_CLEARCOAT
713 // Note: `KHR_materials_clearcoat` specifies that, if there's no
714 // clearcoat normal map, we must set the normal to the mesh's normal,
715 // and not to the main layer's bumped normal.
717#ifdef STANDARD_MATERIAL_CLEARCOAT_NORMAL_MAP
719 let clearcoat_Nt =
720#ifdef MESHLET_MESH_MATERIAL_PASS
721 textureSampleGrad(
722#else // MESHLET_MESH_MATERIAL_PASS
723 textureSampleBias(
724#endif // MESHLET_MESH_MATERIAL_PASS
725#ifdef BINDLESS
726 bindless_textures_2d[material_indices[slot].clearcoat_normal_texture],
727 bindless_samplers_filtering[material_indices[slot].clearcoat_normal_sampler],
728#else // BINDLESS
729 pbr_bindings::clearcoat_normal_texture,
730 pbr_bindings::clearcoat_normal_sampler,
731#endif // BINDLESS
732#ifdef STANDARD_MATERIAL_CLEARCOAT_NORMAL_UV_B
733 uv_b,
734#else
735 uv,
736#endif
737#ifdef MESHLET_MESH_MATERIAL_PASS
738 bias.ddx_uv,
739 bias.ddy_uv,
740#else // MESHLET_MESH_MATERIAL_PASS
741 bias.mip_bias,
742#endif // MESHLET_MESH_MATERIAL_PASS
743 ).rgb;
745 pbr_input.clearcoat_N = pbr_functions::apply_normal_mapping(
746 flags,
747 TBN,
748 double_sided,
749 is_front,
750 clearcoat_Nt,
751 );
753#endif // STANDARD_MATERIAL_CLEARCOAT_NORMAL_MAP
755#endif // STANDARD_MATERIAL_CLEARCOAT
757#endif // VERTEX_TANGENTS
758#endif // VERTEX_UVS
760 // Take anisotropy into account.
761 //
762 // This code comes from the `KHR_materials_anisotropy` spec:
763 // <https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_anisotropy/README.md#individual-lights>
764#ifdef PBR_ANISOTROPY_TEXTURE_SUPPORTED
765#ifdef VERTEX_TANGENTS
766#ifdef STANDARD_MATERIAL_ANISOTROPY
768#ifdef BINDLESS
769 var anisotropy_strength =
770 pbr_bindings::material_array[material_indices[slot].material].anisotropy_strength;
771 var anisotropy_direction =
772 pbr_bindings::material_array[material_indices[slot].material].anisotropy_rotation;
773#else // BINDLESS
774 var anisotropy_strength = pbr_bindings::material.anisotropy_strength;
775 var anisotropy_direction = pbr_bindings::material.anisotropy_rotation;
776#endif // BINDLESS
778 // Adjust based on the anisotropy map if there is one.
779 if ((flags & pbr_types::STANDARD_MATERIAL_FLAGS_ANISOTROPY_TEXTURE_BIT) != 0u) {
780 let anisotropy_texel =
781#ifdef MESHLET_MESH_MATERIAL_PASS
782 textureSampleGrad(
783#else // MESHLET_MESH_MATERIAL_PASS
784 textureSampleBias(
785#endif // MESHLET_MESH_MATERIAL_PASS
786#ifdef BINDLESS
787 bindless_textures_2d[material_indices[slot].anisotropy_texture],
788 bindless_samplers_filtering[material_indices[slot].anisotropy_sampler],
789#else // BINDLESS
790 pbr_bindings::anisotropy_texture,
791 pbr_bindings::anisotropy_sampler,
792#endif
793#ifdef STANDARD_MATERIAL_ANISOTROPY_UV_B
794 uv_b,
795#else // STANDARD_MATERIAL_ANISOTROPY_UV_B
796 uv,
797#endif // STANDARD_MATERIAL_ANISOTROPY_UV_B
798#ifdef MESHLET_MESH_MATERIAL_PASS
799 bias.ddx_uv,
800 bias.ddy_uv,
801#else // MESHLET_MESH_MATERIAL_PASS
802 bias.mip_bias,
803#endif // MESHLET_MESH_MATERIAL_PASS
804 ).rgb;
806 let anisotropy_direction_from_texture = normalize(anisotropy_texel.rg * 2.0 - 1.0);
807 // Rotate by the anisotropy direction.
808 anisotropy_direction =
809 mat2x2(anisotropy_direction.xy, anisotropy_direction.yx * vec2(-1.0, 1.0)) *
810 anisotropy_direction_from_texture;
811 anisotropy_strength *= anisotropy_texel.b;
812 }
814 pbr_input.anisotropy_strength = anisotropy_strength;
816 let anisotropy_T = normalize(TBN * vec3(anisotropy_direction, 0.0));
817 let anisotropy_B = normalize(cross(pbr_input.world_normal, anisotropy_T));
818 pbr_input.anisotropy_T = anisotropy_T;
819 pbr_input.anisotropy_B = anisotropy_B;
821#endif // STANDARD_MATERIAL_ANISOTROPY
822#endif // VERTEX_TANGENTS
823#endif // PBR_ANISOTROPY_TEXTURE_SUPPORTED
825#endif // LOAD_PREPASS_NORMALS
827// TODO: Meshlet support
828#ifdef LIGHTMAP
830#ifdef BINDLESS
831 let lightmap_exposure =
832 pbr_bindings::material_array[material_indices[slot].material].lightmap_exposure;
833#else // BINDLESS
834 let lightmap_exposure = pbr_bindings::material.lightmap_exposure;
835#endif // BINDLESS
837 pbr_input.lightmap_light = lightmap(in.uv_b, lightmap_exposure, in.instance_index);
838#endif
839 }
841 return pbr_input;
Contents