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