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#ifdef SKINNED
70 var world_from_local = skinning::skin_model(vertex.joint_indices, vertex.joint_weights);
71#else // SKINNED
72 // Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug.
73 // See https://github.com/gfx-rs/naga/issues/2416
74 var world_from_local = mesh_functions::get_world_from_local(vertex_no_morph.instance_index);
75#endif // SKINNED
77 out.world_position = mesh_functions::mesh_position_local_to_world(world_from_local, vec4<f32>(vertex.position, 1.0));
78 out.position = position_world_to_clip(out.world_position.xyz);
79#ifdef DEPTH_CLAMP_ORTHO
80 out.clip_position_unclamped = out.position;
81 out.position.z = min(out.position.z, 1.0);
82#endif // DEPTH_CLAMP_ORTHO
84#ifdef VERTEX_UVS_A
85 out.uv = vertex.uv;
86#endif // VERTEX_UVS_A
88#ifdef VERTEX_UVS_B
89 out.uv_b = vertex.uv_b;
90#endif // VERTEX_UVS_B
92#ifdef NORMAL_PREPASS_OR_DEFERRED_PREPASS
93#ifdef SKINNED
94 out.world_normal = skinning::skin_normals(world_from_local, vertex.normal);
95#else // SKINNED
96 out.world_normal = mesh_functions::mesh_normal_local_to_world(
97 vertex.normal,
98 // Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug.
99 // See https://github.com/gfx-rs/naga/issues/2416
100 vertex_no_morph.instance_index
101 );
102#endif // SKINNED
104#ifdef VERTEX_TANGENTS
105 out.world_tangent = mesh_functions::mesh_tangent_local_to_world(
106 world_from_local,
107 vertex.tangent,
108 // Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug.
109 // See https://github.com/gfx-rs/naga/issues/2416
110 vertex_no_morph.instance_index
111 );
112#endif // VERTEX_TANGENTS
113#endif // NORMAL_PREPASS_OR_DEFERRED_PREPASS
115#ifdef VERTEX_COLORS
116 out.color = vertex.color;
117#endif
119 // Compute the motion vector for TAA among other purposes. For this we need
120 // to know where the vertex was last frame.
121#ifdef MOTION_VECTOR_PREPASS
123 // Take morph targets into account.
124#ifdef MORPH_TARGETS
126#ifdef HAS_PREVIOUS_MORPH
127 let prev_vertex = morph_prev_vertex(vertex_no_morph);
128#else // HAS_PREVIOUS_MORPH
129 let prev_vertex = vertex_no_morph;
130#endif // HAS_PREVIOUS_MORPH
132#else // MORPH_TARGETS
133 let prev_vertex = vertex_no_morph;
134#endif // MORPH_TARGETS
136 // Take skinning into account.
137#ifdef SKINNED
139#ifdef HAS_PREVIOUS_SKIN
140 let prev_model = skinning::skin_prev_model(
141 prev_vertex.joint_indices,
142 prev_vertex.joint_weights,
143 );
144#else // HAS_PREVIOUS_SKIN
145 let prev_model = mesh_functions::get_previous_world_from_local(prev_vertex.instance_index);
146#endif // HAS_PREVIOUS_SKIN
148#else // SKINNED
149 let prev_model = mesh_functions::get_previous_world_from_local(prev_vertex.instance_index);
150#endif // SKINNED
152 out.previous_world_position = mesh_functions::mesh_position_local_to_world(
153 prev_model,
154 vec4<f32>(prev_vertex.position, 1.0)
155 );
156#endif // MOTION_VECTOR_PREPASS
158#ifdef VERTEX_OUTPUT_INSTANCE_INDEX
159 // Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug.
160 // See https://github.com/gfx-rs/naga/issues/2416
161 out.instance_index = vertex_no_morph.instance_index;
162#endif
164 return out;
167#ifdef PREPASS_FRAGMENT
168@fragment
169fn fragment(in: VertexOutput) -> FragmentOutput {
170 var out: FragmentOutput;
172#ifdef NORMAL_PREPASS
173 out.normal = vec4(in.world_normal * 0.5 + vec3(0.5), 1.0);
174#endif
176#ifdef DEPTH_CLAMP_ORTHO
177 out.frag_depth = in.clip_position_unclamped.z;
178#endif // DEPTH_CLAMP_ORTHO
180#ifdef MOTION_VECTOR_PREPASS
181 let clip_position_t = view.unjittered_clip_from_world * in.world_position;
182 let clip_position = clip_position_t.xy / clip_position_t.w;
183 let previous_clip_position_t = prepass_bindings::previous_view_uniforms.clip_from_world * in.previous_world_position;
184 let previous_clip_position = previous_clip_position_t.xy / previous_clip_position_t.w;
185 // These motion vectors are used as offsets to UV positions and are stored
186 // in the range -1,1 to allow offsetting from the one corner to the
187 // diagonally-opposite corner in UV coordinates, in either direction.
188 // A difference between diagonally-opposite corners of clip space is in the
189 // range -2,2, so this needs to be scaled by 0.5. And the V direction goes
190 // down where clip space y goes up, so y needs to be flipped.
191 out.motion_vector = (clip_position - previous_clip_position) * vec2(0.5, -0.5);
192#endif // MOTION_VECTOR_PREPASS
194#ifdef DEFERRED_PREPASS
195 // There isn't any material info available for this default prepass shader so we are just writing 
196 // emissive magenta out to the deferred gbuffer to be rendered by the first deferred lighting pass layer.
197 // This is here so if the default prepass fragment is used for deferred magenta will be rendered, and also
198 // as an example to show that a user could write to the deferred gbuffer if they were to start from this shader.
199 out.deferred = vec4(0u, bevy_pbr::rgb9e5::vec3_to_rgb9e5_(vec3(1.0, 0.0, 1.0)), 0u, 0u);
200 out.deferred_lighting_pass_id = 1u;
201#endif
203 return out;
205#endif // PREPASS_FRAGMENT
Contents