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