mirror of
https://github.com/bevyengine/bevy
synced 2024-12-23 03:23:20 +00:00
61bad4eb57
# Objective - bump naga_oil to 0.10 - update shader imports to use rusty syntax ## Migration Guide naga_oil 0.10 reworks the import mechanism to support more syntax to make it more rusty, and test for item use before importing to determine which imports are modules and which are items, which allows: - use rust-style imports ``` #import bevy_pbr::{ pbr_functions::{alpha_discard as discard, apply_pbr_lighting}, mesh_bindings, } ``` - import partial paths: ``` #import part::of::path ... path::remainder::function(); ``` which will call to `part::of::path::remainder::function` - use fully qualified paths without importing: ``` // #import bevy_pbr::pbr_functions bevy_pbr::pbr_functions::pbr() ``` - use imported items without qualifying ``` #import bevy_pbr::pbr_functions::pbr // for backwards compatibility the old style is still supported: // #import bevy_pbr::pbr_functions pbr ... pbr() ``` - allows most imported items to end with `_` and numbers (naga_oil#30). still doesn't allow struct members to end with `_` or numbers but it's progress. - the vast majority of existing shader code will work without changes, but will emit "deprecated" warnings for old-style imports. these can be suppressed with the `allow-deprecated` feature. - partly breaks overrides (as far as i'm aware nobody uses these yet) - now overrides will only be applied if the overriding module is added as an additional import in the arguments to `Composer::make_naga_module` or `Composer::add_composable_module`. this is necessary to support determining whether imports are modules or items.
152 lines
5.6 KiB
WebGPU Shading Language
152 lines
5.6 KiB
WebGPU Shading Language
#import bevy_pbr::{
|
||
prepass_bindings,
|
||
mesh_functions,
|
||
prepass_io::{Vertex, VertexOutput, FragmentOutput},
|
||
skinning,
|
||
morph,
|
||
mesh_view_bindings::{view, previous_view_proj},
|
||
}
|
||
|
||
#import bevy_render::instance_index::get_instance_index
|
||
|
||
#ifdef DEFERRED_PREPASS
|
||
#import bevy_pbr::rgb9e5
|
||
#endif
|
||
|
||
#ifdef MORPH_TARGETS
|
||
fn morph_vertex(vertex_in: Vertex) -> Vertex {
|
||
var vertex = vertex_in;
|
||
let weight_count = morph::layer_count();
|
||
for (var i: u32 = 0u; i < weight_count; i ++) {
|
||
let weight = morph::weight_at(i);
|
||
if weight == 0.0 {
|
||
continue;
|
||
}
|
||
vertex.position += weight * morph::morph(vertex.index, morph::position_offset, i);
|
||
#ifdef VERTEX_NORMALS
|
||
vertex.normal += weight * morph::morph(vertex.index, morph::normal_offset, i);
|
||
#endif
|
||
#ifdef VERTEX_TANGENTS
|
||
vertex.tangent += vec4(weight * morph::morph(vertex.index, 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::morph_vertex(vertex_no_morph);
|
||
#else
|
||
var vertex = vertex_no_morph;
|
||
#endif
|
||
|
||
#ifdef SKINNED
|
||
var model = skinning::skin_model(vertex.joint_indices, vertex.joint_weights);
|
||
#else // SKINNED
|
||
// 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 // SKINNED
|
||
|
||
out.position = mesh_functions::mesh_position_local_to_clip(model, vec4(vertex.position, 1.0));
|
||
#ifdef DEPTH_CLAMP_ORTHO
|
||
out.clip_position_unclamped = out.position;
|
||
out.position.z = min(out.position.z, 1.0);
|
||
#endif // DEPTH_CLAMP_ORTHO
|
||
|
||
#ifdef VERTEX_UVS
|
||
out.uv = vertex.uv;
|
||
#endif // VERTEX_UVS
|
||
|
||
#ifdef NORMAL_PREPASS_OR_DEFERRED_PREPASS
|
||
#ifdef SKINNED
|
||
out.world_normal = skinning::skin_normals(model, vertex.normal);
|
||
#else // SKINNED
|
||
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 // SKINNED
|
||
|
||
#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 // VERTEX_TANGENTS
|
||
#endif // NORMAL_PREPASS_OR_DEFERRED_PREPASS
|
||
|
||
#ifdef VERTEX_COLORS
|
||
out.color = vertex.color;
|
||
#endif
|
||
|
||
#ifdef MOTION_VECTOR_PREPASS_OR_DEFERRED_PREPASS
|
||
out.world_position = mesh_functions::mesh_position_local_to_world(model, vec4<f32>(vertex.position, 1.0));
|
||
#endif // MOTION_VECTOR_PREPASS_OR_DEFERRED_PREPASS
|
||
|
||
#ifdef MOTION_VECTOR_PREPASS
|
||
// 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.previous_world_position = mesh_functions::mesh_position_local_to_world(
|
||
mesh_functions::get_previous_model_matrix(vertex_no_morph.instance_index),
|
||
vec4<f32>(vertex.position, 1.0)
|
||
);
|
||
#endif // MOTION_VECTOR_PREPASS
|
||
|
||
#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;
|
||
}
|
||
|
||
#ifdef PREPASS_FRAGMENT
|
||
@fragment
|
||
fn fragment(in: VertexOutput) -> FragmentOutput {
|
||
var out: FragmentOutput;
|
||
|
||
#ifdef NORMAL_PREPASS
|
||
out.normal = vec4(in.world_normal * 0.5 + vec3(0.5), 1.0);
|
||
#endif
|
||
|
||
#ifdef DEPTH_CLAMP_ORTHO
|
||
out.frag_depth = in.clip_position_unclamped.z;
|
||
#endif // DEPTH_CLAMP_ORTHO
|
||
|
||
#ifdef MOTION_VECTOR_PREPASS
|
||
let clip_position_t = view.unjittered_view_proj * in.world_position;
|
||
let clip_position = clip_position_t.xy / clip_position_t.w;
|
||
let previous_clip_position_t = prepass_bindings::previous_view_proj * in.previous_world_position;
|
||
let previous_clip_position = previous_clip_position_t.xy / previous_clip_position_t.w;
|
||
// These motion vectors are used as offsets to UV positions and are stored
|
||
// in the range -1,1 to allow offsetting from the one corner to the
|
||
// diagonally-opposite corner in UV coordinates, in either direction.
|
||
// A difference between diagonally-opposite corners of clip space is in the
|
||
// range -2,2, so this needs to be scaled by 0.5. And the V direction goes
|
||
// down where clip space y goes up, so y needs to be flipped.
|
||
out.motion_vector = (clip_position - previous_clip_position) * vec2(0.5, -0.5);
|
||
#endif // MOTION_VECTOR_PREPASS
|
||
|
||
#ifdef DEFERRED_PREPASS
|
||
// There isn't any material info available for this default prepass shader so we are just writing
|
||
// emissive magenta out to the deferred gbuffer to be rendered by the first deferred lighting pass layer.
|
||
// The is here so if the default prepass fragment is used for deferred magenta will be rendered, and also
|
||
// as an example to show that a user could write to the deferred gbuffer if they were to start from this shader.
|
||
out.deferred = vec4(0u, bevy_pbr::rgb9e5::vec3_to_rgb9e5_(vec3(1.0, 0.0, 1.0)), 0u, 0u);
|
||
out.deferred_lighting_pass_id = 1u;
|
||
#endif
|
||
|
||
return out;
|
||
}
|
||
#endif // PREPASS_FRAGMENT
|