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#import bevy_pbr::{
2 prepass_bindings,
3 mesh_bindings::mesh,
4 mesh_functions,
5 prepass_io::{Vertex, VertexOutput, FragmentOutput},
6 skinning,
7 morph,
8 mesh_view_bindings::view,
9 view_transformations::position_world_to_clip,
12#ifdef DEFERRED_PREPASS
13#import bevy_pbr::rgb9e5
14#endif
16#ifdef MORPH_TARGETS
17fn morph_vertex(vertex_in: Vertex) -> Vertex {
18 var vertex = vertex_in;
19 let first_vertex = mesh[vertex.instance_index].first_vertex_index;
20 let vertex_index = vertex.index - first_vertex;
22 let weight_count = morph::layer_count();
23 for (var i: u32 = 0u; i < weight_count; i ++) {
24 let weight = morph::weight_at(i);
25 if weight == 0.0 {
26 continue;
27 }
28 vertex.position += weight * morph::morph(vertex_index, morph::position_offset, i);
29#ifdef VERTEX_NORMALS
30 vertex.normal += weight * morph::morph(vertex_index, morph::normal_offset, i);
31#endif
32#ifdef VERTEX_TANGENTS
33 vertex.tangent += vec4(weight * morph::morph(vertex_index, morph::tangent_offset, i), 0.0);
34#endif
35 }
36 return vertex;
39// Returns the morphed position of the given vertex from the previous frame.
40//
41// This function is used for motion vector calculation, and, as such, it doesn't
42// bother morphing the normals and tangents.
43fn morph_prev_vertex(vertex_in: Vertex) -> Vertex {
44 var vertex = vertex_in;
45 let weight_count = morph::layer_count();
46 for (var i: u32 = 0u; i < weight_count; i ++) {
47 let weight = morph::prev_weight_at(i);
48 if weight == 0.0 {
49 continue;
50 }
51 vertex.position += weight * morph::morph(vertex.index, morph::position_offset, i);
52 // Don't bother morphing normals and tangents; we don't need them for
53 // motion vector calculation.
54 }
55 return vertex;
57#endif // MORPH_TARGETS
59@vertex
60fn vertex(vertex_no_morph: Vertex) -> VertexOutput {
61 var out: VertexOutput;
63#ifdef MORPH_TARGETS
64 var vertex = morph_vertex(vertex_no_morph);
65#else
66 var vertex = vertex_no_morph;
67#endif
69 let mesh_world_from_local = mesh_functions::get_world_from_local(vertex_no_morph.instance_index);
71#ifdef SKINNED
72 var world_from_local = skinning::skin_model(
73 vertex.joint_indices,
74 vertex.joint_weights,
75 vertex_no_morph.instance_index
76 );
77#else // SKINNED
78 // Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug.
79 // See https://github.com/gfx-rs/naga/issues/2416
80 var world_from_local = mesh_world_from_local;
81#endif // SKINNED
83 out.world_position = mesh_functions::mesh_position_local_to_world(world_from_local, vec4<f32>(vertex.position, 1.0));
84 out.position = position_world_to_clip(out.world_position.xyz);
85#ifdef UNCLIPPED_DEPTH_ORTHO_EMULATION
86 out.unclipped_depth = out.position.z;
87 out.position.z = min(out.position.z, 1.0); // Clamp depth to avoid clipping
88#endif // UNCLIPPED_DEPTH_ORTHO_EMULATION
90#ifdef VERTEX_UVS_A
91 out.uv = vertex.uv;
92#endif // VERTEX_UVS_A
94#ifdef VERTEX_UVS_B
95 out.uv_b = vertex.uv_b;
96#endif // VERTEX_UVS_B
98#ifdef NORMAL_PREPASS_OR_DEFERRED_PREPASS
99#ifdef VERTEX_NORMALS
100#ifdef SKINNED
101 out.world_normal = skinning::skin_normals(world_from_local, vertex.normal);
102#else // SKINNED
103 out.world_normal = mesh_functions::mesh_normal_local_to_world(
104 vertex.normal,
105 // Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug.
106 // See https://github.com/gfx-rs/naga/issues/2416
107 vertex_no_morph.instance_index
108 );
109#endif // SKINNED
110#endif // VERTEX_NORMALS
112#ifdef VERTEX_TANGENTS
113 out.world_tangent = mesh_functions::mesh_tangent_local_to_world(
114 world_from_local,
115 vertex.tangent,
116 // Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug.
117 // See https://github.com/gfx-rs/naga/issues/2416
118 vertex_no_morph.instance_index
119 );
120#endif // VERTEX_TANGENTS
121#endif // NORMAL_PREPASS_OR_DEFERRED_PREPASS
123#ifdef VERTEX_COLORS
124 out.color = vertex.color;
125#endif
127 // Compute the motion vector for TAA among other purposes. For this we need
128 // to know where the vertex was last frame.
129#ifdef MOTION_VECTOR_PREPASS
131 // Take morph targets into account.
132#ifdef MORPH_TARGETS
134#ifdef HAS_PREVIOUS_MORPH
135 let prev_vertex = morph_prev_vertex(vertex_no_morph);
136#else // HAS_PREVIOUS_MORPH
137 let prev_vertex = vertex_no_morph;
138#endif // HAS_PREVIOUS_MORPH
140#else // MORPH_TARGETS
141 let prev_vertex = vertex_no_morph;
142#endif // MORPH_TARGETS
144 // Take skinning into account.
145#ifdef SKINNED
147#ifdef HAS_PREVIOUS_SKIN
148 let prev_model = skinning::skin_prev_model(
149 prev_vertex.joint_indices,
150 prev_vertex.joint_weights,
151 vertex_no_morph.instance_index
152 );
153#else // HAS_PREVIOUS_SKIN
154 let prev_model = mesh_functions::get_previous_world_from_local(prev_vertex.instance_index);
155#endif // HAS_PREVIOUS_SKIN
157#else // SKINNED
158 let prev_model = mesh_functions::get_previous_world_from_local(prev_vertex.instance_index);
159#endif // SKINNED
161 out.previous_world_position = mesh_functions::mesh_position_local_to_world(
162 prev_model,
163 vec4<f32>(prev_vertex.position, 1.0)
164 );
165#endif // MOTION_VECTOR_PREPASS
167#ifdef VERTEX_OUTPUT_INSTANCE_INDEX
168 // Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug.
169 // See https://github.com/gfx-rs/naga/issues/2416
170 out.instance_index = vertex_no_morph.instance_index;
171#endif
173#ifdef VISIBILITY_RANGE_DITHER
174 out.visibility_range_dither = mesh_functions::get_visibility_range_dither_level(
175 vertex_no_morph.instance_index, mesh_world_from_local[3]);
176#endif // VISIBILITY_RANGE_DITHER
178 return out;
181#ifdef PREPASS_FRAGMENT
182@fragment
183fn fragment(in: VertexOutput) -> FragmentOutput {
184 var out: FragmentOutput;
186#ifdef NORMAL_PREPASS
187 out.normal = vec4(in.world_normal * 0.5 + vec3(0.5), 1.0);
188#endif
190#ifdef UNCLIPPED_DEPTH_ORTHO_EMULATION
191 out.frag_depth = in.unclipped_depth;
192#endif // UNCLIPPED_DEPTH_ORTHO_EMULATION
194#ifdef MOTION_VECTOR_PREPASS
195 let clip_position_t = view.unjittered_clip_from_world * in.world_position;
196 let clip_position = clip_position_t.xy / clip_position_t.w;
197 let previous_clip_position_t = prepass_bindings::previous_view_uniforms.clip_from_world * in.previous_world_position;
198 let previous_clip_position = previous_clip_position_t.xy / previous_clip_position_t.w;
199 // These motion vectors are used as offsets to UV positions and are stored
200 // in the range -1,1 to allow offsetting from the one corner to the
201 // diagonally-opposite corner in UV coordinates, in either direction.
202 // A difference between diagonally-opposite corners of clip space is in the
203 // range -2,2, so this needs to be scaled by 0.5. And the V direction goes
204 // down where clip space y goes up, so y needs to be flipped.
205 out.motion_vector = (clip_position - previous_clip_position) * vec2(0.5, -0.5);
206#endif // MOTION_VECTOR_PREPASS
208#ifdef DEFERRED_PREPASS
209 // There isn't any material info available for this default prepass shader so we are just writing 
210 // emissive magenta out to the deferred gbuffer to be rendered by the first deferred lighting pass layer.
211 // This is here so if the default prepass fragment is used for deferred magenta will be rendered, and also
212 // as an example to show that a user could write to the deferred gbuffer if they were to start from this shader.
213 out.deferred = vec4(0u, bevy_pbr::rgb9e5::vec3_to_rgb9e5_(vec3(1.0, 0.0, 1.0)), 0u, 0u);
214 out.deferred_lighting_pass_id = 1u;
215#endif
217 return out;
219#endif // PREPASS_FRAGMENT
Contents