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_deferred_functions
3#import bevy_pbr::{
4 pbr_types::{PbrInput, pbr_input_new, STANDARD_MATERIAL_FLAGS_UNLIT_BIT},
5 pbr_deferred_types as deferred_types,
6 pbr_functions,
7 rgb9e5,
8 mesh_view_bindings::view,
9 utils::{octahedral_encode, octahedral_decode},
10 prepass_io::FragmentOutput,
11 view_transformations::{position_ndc_to_world, frag_coord_to_ndc},
14#ifdef MESHLET_MESH_MATERIAL_PASS
15#import bevy_pbr::meshlet_visibility_buffer_resolve::VertexOutput
16#else
17#import bevy_pbr::prepass_io::VertexOutput
18#endif
20#ifdef MOTION_VECTOR_PREPASS
21 #import bevy_pbr::pbr_prepass_functions::calculate_motion_vector
22#endif
24// Creates the deferred gbuffer from a PbrInput.
25fn deferred_gbuffer_from_pbr_input(in: PbrInput) -> vec4<u32> {
26 // Only monochrome occlusion supported. May not be worth including at all.
27 // Some models have baked occlusion, GLTF only supports monochrome.
28 // Real time occlusion is applied in the deferred lighting pass.
29 // Deriving luminance via Rec. 709. coefficients
30 // https://en.wikipedia.org/wiki/Rec._709
31 let rec_709_coeffs = vec3<f32>(0.2126, 0.7152, 0.0722);
32 let diffuse_occlusion = dot(in.diffuse_occlusion, rec_709_coeffs);
33 // Only monochrome specular supported.
34 let reflectance = dot(in.material.reflectance, rec_709_coeffs);
35#ifdef WEBGL2 // More crunched for webgl so we can also fit depth.
36 var props = deferred_types::pack_unorm3x4_plus_unorm_20_(vec4(
37 reflectance,
38 in.material.metallic,
39 diffuse_occlusion,
40 in.frag_coord.z));
41#else
42 var props = deferred_types::pack_unorm4x8_(vec4(
43 reflectance, // could be fewer bits
44 in.material.metallic, // could be fewer bits
45 diffuse_occlusion, // is this worth including?
46 0.0)); // spare
47#endif // WEBGL2
48 let flags = deferred_types::deferred_flags_from_mesh_material_flags(in.flags, in.material.flags);
49 let octahedral_normal = octahedral_encode(normalize(in.N));
50 var base_color_srgb = vec3(0.0);
51 var emissive = in.material.emissive.rgb;
52 if ((in.material.flags & STANDARD_MATERIAL_FLAGS_UNLIT_BIT) != 0u) {
53 // Material is unlit, use emissive component of gbuffer for color data.
54 // Unlit materials are effectively emissive.
55 emissive = in.material.base_color.rgb;
56 } else {
57 base_color_srgb = pow(in.material.base_color.rgb, vec3(1.0 / 2.2));
58 }
60 // Utilize the emissive channel to transmit the lightmap data. To ensure
61 // it matches the output in forward shading, pre-multiply it with the
62 // calculated diffuse color.
63 let base_color = in.material.base_color.rgb;
64 let metallic = in.material.metallic;
65 let specular_transmission = in.material.specular_transmission;
66 let diffuse_transmission = in.material.diffuse_transmission;
67 let diffuse_color = pbr_functions::calculate_diffuse_color(
68 base_color,
69 metallic,
70 specular_transmission,
71 diffuse_transmission
72 );
73 emissive += in.lightmap_light * diffuse_color * view.exposure;
75 let deferred = vec4(
76 deferred_types::pack_unorm4x8_(vec4(base_color_srgb, in.material.perceptual_roughness)),
77 rgb9e5::vec3_to_rgb9e5_(emissive),
78 props,
79 deferred_types::pack_24bit_normal_and_flags(octahedral_normal, flags),
80 );
81 return deferred;
84// Creates a PbrInput from the deferred gbuffer.
85fn pbr_input_from_deferred_gbuffer(frag_coord: vec4<f32>, gbuffer: vec4<u32>) -> PbrInput {
86 var pbr = pbr_input_new();
88 let flags = deferred_types::unpack_flags(gbuffer.a);
89 let deferred_flags = deferred_types::mesh_material_flags_from_deferred_flags(flags);
90 pbr.flags = deferred_flags.x;
91 pbr.material.flags = deferred_flags.y;
93 let base_rough = deferred_types::unpack_unorm4x8_(gbuffer.r);
94 pbr.material.perceptual_roughness = base_rough.a;
95 let emissive = rgb9e5::rgb9e5_to_vec3_(gbuffer.g);
96 if ((pbr.material.flags & STANDARD_MATERIAL_FLAGS_UNLIT_BIT) != 0u) {
97 pbr.material.base_color = vec4(emissive, 1.0);
98 pbr.material.emissive = vec4(vec3(0.0), 0.0);
99 } else {
100 pbr.material.base_color = vec4(pow(base_rough.rgb, vec3(2.2)), 1.0);
101 pbr.material.emissive = vec4(emissive, 0.0);
102 }
103#ifdef WEBGL2 // More crunched for webgl so we can also fit depth.
104 let props = deferred_types::unpack_unorm3x4_plus_unorm_20_(gbuffer.b);
105 // Bias to 0.5 since that's the value for almost all materials.
106 pbr.material.reflectance = vec3(saturate(props.r - 0.03333333333));
107#else
108 let props = deferred_types::unpack_unorm4x8_(gbuffer.b);
109 pbr.material.reflectance = vec3(props.r);
110#endif // WEBGL2
111 pbr.material.metallic = props.g;
112 pbr.diffuse_occlusion = vec3(props.b);
113 let octahedral_normal = deferred_types::unpack_24bit_normal(gbuffer.a);
114 let N = octahedral_decode(octahedral_normal);
116 let world_position = vec4(position_ndc_to_world(frag_coord_to_ndc(frag_coord)), 1.0);
117 let is_orthographic = view.clip_from_view[3].w == 1.0;
118 let V = pbr_functions::calculate_view(world_position, is_orthographic);
120 pbr.frag_coord = frag_coord;
121 pbr.world_normal = N;
122 pbr.world_position = world_position;
123 pbr.N = N;
124 pbr.V = V;
125 pbr.is_orthographic = is_orthographic;
127 return pbr;
130#ifdef PREPASS_PIPELINE
131fn deferred_output(in: VertexOutput, pbr_input: PbrInput) -> FragmentOutput {
132 var out: FragmentOutput;
134 // gbuffer
135 out.deferred = deferred_gbuffer_from_pbr_input(pbr_input);
136 // lighting pass id (used to determine which lighting shader to run for the fragment)
137 out.deferred_lighting_pass_id = pbr_input.material.deferred_lighting_pass_id;
138 // normal if required
139#ifdef NORMAL_PREPASS
140 out.normal = vec4(in.world_normal * 0.5 + vec3(0.5), 1.0);
141#endif
142 // motion vectors if required
143#ifdef MOTION_VECTOR_PREPASS
144#ifdef MESHLET_MESH_MATERIAL_PASS
145 out.motion_vector = in.motion_vector;
146#else
147 out.motion_vector = calculate_motion_vector(in.world_position, in.previous_world_position);
148#endif
149#endif
151 return out;
153#endif
Contents