mirror of
https://github.com/bevyengine/bevy
synced 2024-12-24 12:03:14 +00:00
d235d41af1
The "uberbuffers" PR #14257 caused some examples to fail intermittently for different reasons: 1. `morph_targets` could fail because vertex displacements for morph targets are keyed off the vertex index. With buffer packing, the vertex index can vary based on the position in the buffer, which caused the morph targets to be potentially incorrect. The solution is to include the first vertex index with the `MeshUniform` (and `MeshInputUniform` if GPU preprocessing is in use), so that the shader can calculate the true vertex index before performing the morph operation. This results in wasted space in `MeshUniform`, which is unfortunate, but we'll soon be filling in the padding with the ID of the material when bindless textures land, so this had to happen sooner or later anyhow. Including the vertex index in the `MeshInputUniform` caused an ordering problem. The `MeshInputUniform` was created during the extraction phase, before the allocations occurred, so the extraction logic didn't know where the mesh vertex data was going to end up. The solution is to move the `MeshInputUniform` creation (the `collect_meshes_for_gpu_building` system) to after the allocations phase. This should be better for parallelism anyhow, because it allows the extraction phase to finish quicker. It's also something we'll have to do for bindless in any event. 2. The `lines` and `fog_volumes` examples could fail because their custom drawing nodes weren't updated to supply the vertex and index offsets in their `draw_indexed` and `draw` calls. This commit fixes this oversight. Fixes #14366.
114 lines
3.4 KiB
WebGPU Shading Language
114 lines
3.4 KiB
WebGPU Shading Language
#import bevy_pbr::{
|
|
mesh_bindings::mesh,
|
|
mesh_functions,
|
|
skinning,
|
|
morph::morph,
|
|
forward_io::{Vertex, VertexOutput},
|
|
view_transformations::position_world_to_clip,
|
|
}
|
|
|
|
#ifdef MORPH_TARGETS
|
|
fn morph_vertex(vertex_in: Vertex) -> Vertex {
|
|
var vertex = vertex_in;
|
|
let first_vertex = mesh[vertex.instance_index].first_vertex_index;
|
|
let vertex_index = vertex.index - first_vertex;
|
|
|
|
let weight_count = bevy_pbr::morph::layer_count();
|
|
for (var i: u32 = 0u; i < weight_count; i ++) {
|
|
let weight = bevy_pbr::morph::weight_at(i);
|
|
if weight == 0.0 {
|
|
continue;
|
|
}
|
|
vertex.position += weight * morph(vertex_index, bevy_pbr::morph::position_offset, i);
|
|
#ifdef VERTEX_NORMALS
|
|
vertex.normal += weight * morph(vertex_index, bevy_pbr::morph::normal_offset, i);
|
|
#endif
|
|
#ifdef VERTEX_TANGENTS
|
|
vertex.tangent += vec4(weight * morph(vertex_index, bevy_pbr::morph::tangent_offset, i), 0.0);
|
|
#endif
|
|
}
|
|
return vertex;
|
|
}
|
|
#endif
|
|
|
|
@vertex
|
|
fn vertex(vertex_no_morph: Vertex) -> VertexOutput {
|
|
var out: VertexOutput;
|
|
|
|
#ifdef MORPH_TARGETS
|
|
var vertex = morph_vertex(vertex_no_morph);
|
|
#else
|
|
var vertex = vertex_no_morph;
|
|
#endif
|
|
|
|
#ifdef SKINNED
|
|
var world_from_local = skinning::skin_model(vertex.joint_indices, vertex.joint_weights);
|
|
#else
|
|
// Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug.
|
|
// See https://github.com/gfx-rs/naga/issues/2416 .
|
|
var world_from_local = mesh_functions::get_world_from_local(vertex_no_morph.instance_index);
|
|
#endif
|
|
|
|
#ifdef VERTEX_NORMALS
|
|
#ifdef SKINNED
|
|
out.world_normal = skinning::skin_normals(world_from_local, vertex.normal);
|
|
#else
|
|
out.world_normal = mesh_functions::mesh_normal_local_to_world(
|
|
vertex.normal,
|
|
// Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug.
|
|
// See https://github.com/gfx-rs/naga/issues/2416
|
|
vertex_no_morph.instance_index
|
|
);
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef VERTEX_POSITIONS
|
|
out.world_position = mesh_functions::mesh_position_local_to_world(world_from_local, vec4<f32>(vertex.position, 1.0));
|
|
out.position = position_world_to_clip(out.world_position.xyz);
|
|
#endif
|
|
|
|
#ifdef VERTEX_UVS_A
|
|
out.uv = vertex.uv;
|
|
#endif
|
|
#ifdef VERTEX_UVS_B
|
|
out.uv_b = vertex.uv_b;
|
|
#endif
|
|
|
|
#ifdef VERTEX_TANGENTS
|
|
out.world_tangent = mesh_functions::mesh_tangent_local_to_world(
|
|
world_from_local,
|
|
vertex.tangent,
|
|
// Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug.
|
|
// See https://github.com/gfx-rs/naga/issues/2416
|
|
vertex_no_morph.instance_index
|
|
);
|
|
#endif
|
|
|
|
#ifdef VERTEX_COLORS
|
|
out.color = vertex.color;
|
|
#endif
|
|
|
|
#ifdef VERTEX_OUTPUT_INSTANCE_INDEX
|
|
// Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug.
|
|
// See https://github.com/gfx-rs/naga/issues/2416
|
|
out.instance_index = vertex_no_morph.instance_index;
|
|
#endif
|
|
|
|
#ifdef VISIBILITY_RANGE_DITHER
|
|
out.visibility_range_dither = mesh_functions::get_visibility_range_dither_level(
|
|
vertex_no_morph.instance_index, world_from_local[3]);
|
|
#endif
|
|
|
|
return out;
|
|
}
|
|
|
|
@fragment
|
|
fn fragment(
|
|
mesh: VertexOutput,
|
|
) -> @location(0) vec4<f32> {
|
|
#ifdef VERTEX_COLORS
|
|
return mesh.color;
|
|
#else
|
|
return vec4<f32>(1.0, 0.0, 1.0, 1.0);
|
|
#endif
|
|
}
|