mirror of
https://github.com/bevyengine/bevy
synced 2024-12-25 20:43:07 +00:00
979c4094d4
# Objective cleanup some pbr shader code. improve shader stage io consistency and make pbr.wgsl (probably many people's first foray into bevy shader code) a little more human-readable. also fix a couple of small issues with deferred rendering. ## Solution mesh_vertex_output: - rename to forward_io (to align with prepass_io) - rename `MeshVertexOutput` to `VertexOutput` (to align with prepass_io) - move `Vertex` from mesh.wgsl into here (to align with prepass_io) prepass_io: - remove `FragmentInput`, use `VertexOutput` directly (to align with forward_io) - rename `VertexOutput::clip_position` to `position` (to align with forward_io) pbr.wgsl: - restructure so we don't need `#ifdefs` on the actual entrypoint, use VertexOutput and FragmentOutput in all cases and use #ifdefs to import the right struct definitions. - rearrange to make the flow clearer - move alpha_discard up from `pbr_functions::pbr` to avoid needing to call it on some branches and not others - add a bunch of comments deferred_lighting: - move ssao into the `!unlit` block to reflect forward behaviour correctly - fix compile error with deferred + premultiply_alpha ## Migration Guide in custom material shaders: - `pbr_functions::pbr` no longer calls to `pbr_functions::alpha_discard`. if you were using the `pbr` function in a custom shader with alpha mask mode you now also need to call alpha_discard manually - rename imports of `bevy_pbr::mesh_vertex_output` to `bevy_pbr::forward_io` - rename instances of `MeshVertexOutput` to `VertexOutput` in custom material prepass shaders: - rename instances of `VertexOutput::clip_position` to `VertexOutput::position`
101 lines
3.2 KiB
WebGPU Shading Language
101 lines
3.2 KiB
WebGPU Shading Language
#import bevy_pbr::mesh_functions as mesh_functions
|
|
#import bevy_pbr::skinning
|
|
#import bevy_pbr::morph
|
|
#import bevy_pbr::mesh_bindings mesh
|
|
#import bevy_pbr::forward_io Vertex, VertexOutput
|
|
#import bevy_render::instance_index get_instance_index
|
|
|
|
#ifdef MORPH_TARGETS
|
|
fn morph_vertex(vertex_in: Vertex) -> Vertex {
|
|
var vertex = vertex_in;
|
|
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 * bevy_pbr::morph::morph(vertex.index, bevy_pbr::morph::position_offset, i);
|
|
#ifdef VERTEX_NORMALS
|
|
vertex.normal += weight * bevy_pbr::morph::morph(vertex.index, bevy_pbr::morph::normal_offset, i);
|
|
#endif
|
|
#ifdef VERTEX_TANGENTS
|
|
vertex.tangent += vec4(weight * bevy_pbr::morph::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 model = bevy_pbr::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 model = mesh_functions::get_model_matrix(vertex_no_morph.instance_index);
|
|
#endif
|
|
|
|
#ifdef VERTEX_NORMALS
|
|
#ifdef SKINNED
|
|
out.world_normal = bevy_pbr::skinning::skin_normals(model, 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
|
|
get_instance_index(vertex_no_morph.instance_index)
|
|
);
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef VERTEX_POSITIONS
|
|
out.world_position = mesh_functions::mesh_position_local_to_world(model, vec4<f32>(vertex.position, 1.0));
|
|
out.position = mesh_functions::mesh_position_world_to_clip(out.world_position);
|
|
#endif
|
|
|
|
#ifdef VERTEX_UVS
|
|
out.uv = vertex.uv;
|
|
#endif
|
|
|
|
#ifdef VERTEX_TANGENTS
|
|
out.world_tangent = mesh_functions::mesh_tangent_local_to_world(
|
|
model,
|
|
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
|
|
get_instance_index(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 = get_instance_index(vertex_no_morph.instance_index);
|
|
#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
|
|
}
|