mirror of
https://github.com/bevyengine/bevy
synced 2024-12-30 06:53:13 +00:00
4f20faaa43
# Objective - Implements a more efficient, GPU-driven (https://github.com/bevyengine/bevy/issues/1342) rendering pipeline based on meshlets. - Meshes are split into small clusters of triangles called meshlets, each of which acts as a mini index buffer into the larger mesh data. Meshlets can be compressed, streamed, culled, and batched much more efficiently than monolithic meshes. ![image](https://github.com/bevyengine/bevy/assets/47158642/cb2aaad0-7a9a-4e14-93b0-15d4e895b26a) ![image](https://github.com/bevyengine/bevy/assets/47158642/7534035b-1eb7-4278-9b99-5322e4401715) # Misc * Future work: https://github.com/bevyengine/bevy/issues/11518 * Nanite reference: https://advances.realtimerendering.com/s2021/Karis_Nanite_SIGGRAPH_Advances_2021_final.pdf Two pass occlusion culling explained very well: https://medium.com/@mil_kru/two-pass-occlusion-culling-4100edcad501 --------- Co-authored-by: Ricky Taylor <rickytaylor26@gmail.com> Co-authored-by: vero <email@atlasdostal.com> Co-authored-by: François <mockersf@gmail.com> Co-authored-by: atlas dostal <rodol@rivalrebels.com>
89 lines
2.3 KiB
WebGPU Shading Language
89 lines
2.3 KiB
WebGPU Shading Language
#import bevy_pbr::{
|
|
pbr_prepass_functions,
|
|
pbr_bindings::material,
|
|
pbr_types,
|
|
pbr_functions,
|
|
prepass_io,
|
|
mesh_view_bindings::view,
|
|
}
|
|
|
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
|
#import bevy_pbr::meshlet_visibility_buffer_resolve::resolve_vertex_output
|
|
#endif
|
|
|
|
#ifdef PREPASS_FRAGMENT
|
|
@fragment
|
|
fn fragment(
|
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
|
@builtin(position) frag_coord: vec4<f32>,
|
|
#else
|
|
in: prepass_io::VertexOutput,
|
|
@builtin(front_facing) is_front: bool,
|
|
#endif
|
|
) -> prepass_io::FragmentOutput {
|
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
|
let in = resolve_vertex_output(frag_coord);
|
|
let is_front = true;
|
|
#else
|
|
pbr_prepass_functions::prepass_alpha_discard(in);
|
|
#endif
|
|
|
|
var out: prepass_io::FragmentOutput;
|
|
|
|
#ifdef DEPTH_CLAMP_ORTHO
|
|
out.frag_depth = in.clip_position_unclamped.z;
|
|
#endif // DEPTH_CLAMP_ORTHO
|
|
|
|
#ifdef NORMAL_PREPASS
|
|
// NOTE: Unlit bit not set means == 0 is true, so the true case is if lit
|
|
if (material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_UNLIT_BIT) == 0u {
|
|
let double_sided = (material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_DOUBLE_SIDED_BIT) != 0u;
|
|
|
|
let world_normal = pbr_functions::prepare_world_normal(
|
|
in.world_normal,
|
|
double_sided,
|
|
is_front,
|
|
);
|
|
|
|
let normal = pbr_functions::apply_normal_mapping(
|
|
material.flags,
|
|
world_normal,
|
|
double_sided,
|
|
is_front,
|
|
#ifdef VERTEX_TANGENTS
|
|
#ifdef STANDARD_MATERIAL_NORMAL_MAP
|
|
in.world_tangent,
|
|
#endif // STANDARD_MATERIAL_NORMAL_MAP
|
|
#endif // VERTEX_TANGENTS
|
|
#ifdef VERTEX_UVS
|
|
in.uv,
|
|
#endif // VERTEX_UVS
|
|
view.mip_bias,
|
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
|
in.ddx_uv,
|
|
in.ddy_uv,
|
|
#endif // MESHLET_MESH_MATERIAL_PASS
|
|
);
|
|
|
|
out.normal = vec4(normal * 0.5 + vec3(0.5), 1.0);
|
|
} else {
|
|
out.normal = vec4(in.world_normal * 0.5 + vec3(0.5), 1.0);
|
|
}
|
|
#endif // NORMAL_PREPASS
|
|
|
|
#ifdef MOTION_VECTOR_PREPASS
|
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
|
out.motion_vector = in.motion_vector;
|
|
#else
|
|
out.motion_vector = pbr_prepass_functions::calculate_motion_vector(in.world_position, in.previous_world_position);
|
|
#endif
|
|
#endif
|
|
|
|
return out;
|
|
}
|
|
#else
|
|
@fragment
|
|
fn fragment(in: prepass_io::VertexOutput) {
|
|
pbr_prepass_functions::prepass_alpha_discard(in);
|
|
}
|
|
#endif // PREPASS_FRAGMENT
|