Skip to content

Commit

Permalink
prepass wip
Browse files Browse the repository at this point in the history
  • Loading branch information
IceSentry committed Oct 27, 2022
1 parent 0b9f67b commit 793352e
Show file tree
Hide file tree
Showing 19 changed files with 443 additions and 399 deletions.
11 changes: 11 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -1176,6 +1176,17 @@ description = "A shader and a material that uses it"
category = "Shaders"
wasm = true

[[example]]
name = "shader_prepass"
path = "examples/shader/shader_prepass.rs"

[package.metadata.example.shader_prepass]
name = "Material Prepass"
description = "A shader that uses the depth texture generated in a prepass"
category = "Shaders"
wasm = true


[[example]]
name = "shader_material_screenspace_texture"
path = "examples/shader/shader_material_screenspace_texture.rs"
Expand Down
4 changes: 2 additions & 2 deletions assets/shaders/custom_material.wgsl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
struct CustomMaterial {
color: vec3<f32>,
color: vec4<f32>,
};

@group(1) @binding(0)
Expand All @@ -13,5 +13,5 @@ var base_color_sampler: sampler;
fn fragment(
#import bevy_pbr::mesh_vertex_output
) -> @location(0) vec4<f32> {
return vec4<f32>(material.color, 1.0) * textureSample(base_color_texture, base_color_sampler, uv);
return material.color * textureSample(base_color_texture, base_color_sampler, uv);
}
99 changes: 0 additions & 99 deletions assets/shaders/red.wgsl

This file was deleted.

9 changes: 2 additions & 7 deletions assets/shaders/show_depth.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,6 @@ fn fragment(
@builtin(sample_index) sample_index: u32,
#import bevy_pbr::mesh_vertex_output
) -> @location(0) vec4<f32> {
if frag_coord.y < 300.0 {
let depth = prepass_normal(frag_coord, sample_index);
return vec4<f32>(depth, 1.0);
} else {
let depth = prepass_depth(frag_coord, sample_index);
return vec4<f32>(depth, depth, depth, 1.0);
}
let depth = prepass_depth(frag_coord, sample_index);
return vec4<f32>(depth, depth, depth, 1.0);
}
2 changes: 1 addition & 1 deletion crates/bevy_core_pipeline/src/core_3d/main_pass_3d_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use bevy_utils::tracing::info_span;
pub struct PrepassSettings {
/// If true then depth values will be copied to a separate texture available to the main pass.
pub output_depth: bool,
/// If true then vertex world normals will be copied to a separate texture available to the main pass
/// If true then vertex world normals will be copied to a separate texture available to the main pass.
pub output_normals: bool,
}

Expand Down
8 changes: 8 additions & 0 deletions crates/bevy_pbr/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ pub const SHADOWS_HANDLE: HandleUntyped =
HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 11350275143789590502);
pub const PBR_SHADER_HANDLE: HandleUntyped =
HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 4805239651767701046);
pub const PBR_PREPASS_SHADER_HANDLE: HandleUntyped =
HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 9407115064344201137);
pub const PBR_FUNCTIONS_HANDLE: HandleUntyped =
HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 16550102964439850292);
pub const SHADOW_SHADER_HANDLE: HandleUntyped =
Expand Down Expand Up @@ -122,6 +124,12 @@ impl Plugin for PbrPlugin {
"render/depth.wgsl",
Shader::from_wgsl
);
load_internal_asset!(
app,
PBR_PREPASS_SHADER_HANDLE,
"render/pbr_prepass.wgsl",
Shader::from_wgsl
);

app.register_type::<CubemapVisibleEntities>()
.register_type::<DirectionalLight>()
Expand Down
24 changes: 22 additions & 2 deletions crates/bevy_pbr/src/material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,12 @@ pub trait Material: AsBindGroup + Send + Sync + Clone + TypeUuid + Sized + 'stat
ShaderRef::Default
}

/// Controls if this Material is used in the prepass
/// You also need to enable the prepass globally using `GlobalMaterialOptions` for this to work
fn prepass_enabled() -> bool {
true
}

/// Customizes the default [`RenderPipelineDescriptor`] for a specific entity using the entity's
/// [`MaterialPipelineKey`] and [`MeshVertexBufferLayout`] as input.
#[allow(unused_variables)]
Expand All @@ -162,6 +168,14 @@ pub trait Material: AsBindGroup + Send + Sync + Clone + TypeUuid + Sized + 'stat
}
}

/// Options that affects all materials
#[derive(Resource, Default)]
pub struct GlobalMaterialOptions {
// Controls if the prepass will be used when rendering
// Disabled by default
pub prepass_enabled: bool,
}

/// Adds the necessary ECS resources and render logic to enable rendering entities using the given [`Material`]
/// asset type.
pub struct MaterialPlugin<M: Material>(PhantomData<M>);
Expand All @@ -179,7 +193,8 @@ where
fn build(&self, app: &mut App) {
app.add_asset::<M>()
.add_plugin(ExtractComponentPlugin::<Handle<M>>::extract_visible())
.add_plugin(PrepassPlugin::<M>::default());
.init_resource::<GlobalMaterialOptions>();

if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
render_app
.add_render_command::<Transparent3d, DrawMaterial<M>>()
Expand All @@ -196,6 +211,11 @@ where
)
.add_system_to_stage(RenderStage::Queue, queue_material_meshes::<M>);
}

let options = app.world.resource::<GlobalMaterialOptions>();
if options.prepass_enabled && M::prepass_enabled() {
app.add_plugin(PrepassPlugin::<M>::default());
}
}
}

Expand Down Expand Up @@ -239,7 +259,7 @@ where
}

/// Render pipeline data for a given [`Material`].
#[derive(Resource)]
#[derive(Resource, Clone)]
pub struct MaterialPipeline<M: Material> {
pub mesh_pipeline: MeshPipeline,
pub material_layout: BindGroupLayout,
Expand Down
13 changes: 12 additions & 1 deletion crates/bevy_pbr/src/pbr_material.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use crate::{AlphaMode, Material, MaterialPipeline, MaterialPipelineKey, PBR_SHADER_HANDLE};
use crate::{
AlphaMode, Material, MaterialPipeline, MaterialPipelineKey, PBR_PREPASS_SHADER_HANDLE,
PBR_SHADER_HANDLE,
};
use bevy_asset::Handle;
use bevy_math::Vec4;
use bevy_reflect::TypeUuid;
Expand Down Expand Up @@ -425,6 +428,10 @@ impl Material for StandardMaterial {
Ok(())
}

fn prepass_fragment_shader() -> ShaderRef {
PBR_PREPASS_SHADER_HANDLE.typed().into()
}

fn fragment_shader() -> ShaderRef {
PBR_SHADER_HANDLE.typed().into()
}
Expand All @@ -438,4 +445,8 @@ impl Material for StandardMaterial {
fn depth_bias(&self) -> f32 {
self.depth_bias
}

fn prepass_enabled() -> bool {
true
}
}
2 changes: 0 additions & 2 deletions crates/bevy_pbr/src/render/pbr.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
struct FragmentInput {
@builtin(front_facing) is_front: bool,
@builtin(position) frag_coord: vec4<f32>,
@builtin(sample_index) sample_index: u32,
#import bevy_pbr::mesh_vertex_output
};

Expand Down Expand Up @@ -77,7 +76,6 @@ fn fragment(in: FragmentInput) -> @location(0) vec4<f32> {
pbr_input.N = prepare_normal(
material.flags,
in.world_normal,
// prepass_normal(in.frag_coord, in.sample_index),
#ifdef VERTEX_TANGENTS
#ifdef STANDARDMATERIAL_NORMAL_MAP
in.world_tangent,
Expand Down
60 changes: 60 additions & 0 deletions crates/bevy_pbr/src/render/pbr_prepass.wgsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// FIXME: These imports are wrong, but they make it possible to import pbr functions without copying any code

#import bevy_pbr::mesh_view_bindings
#import bevy_pbr::mesh_bindings
// #import bevy_pbr::prepass_bindings

#import bevy_pbr::pbr_bindings
#import bevy_pbr::utils
#import bevy_pbr::shadows
#import bevy_pbr::clustered_forward
#import bevy_pbr::lighting
#import bevy_pbr::pbr_functions

struct FragmentInput {
@builtin(front_facing) is_front: bool,
@builtin(position) frag_coord: vec4<f32>,
#ifdef OUTPUT_NORMALS
@location(0) world_normal: vec3<f32>,
#ifdef VERTEX_UVS
@location(1) uv: vec2<f32>,
#endif // VERTEX_UVS
#ifdef VERTEX_TANGENTS
@location(2) world_tangent: vec4<f32>,
#endif // VERTEX_TANGENTS
#endif // OUTPUT_NORMALS
};

@fragment
fn fragment(in: FragmentInput) -> @location(0) vec4<f32> {
var output_color: vec4<f32> = material.base_color;

#ifdef VERTEX_UVS
if ((material.flags & STANDARD_MATERIAL_FLAGS_BASE_COLOR_TEXTURE_BIT) != 0u) {
output_color = output_color * textureSample(base_color_texture, base_color_sampler, in.uv);
}
#endif

// NOTE: Unlit bit not set means == 0 is true, so the true case is if lit
if ((material.flags & STANDARD_MATERIAL_FLAGS_UNLIT_BIT) == 0u) {
let normal = prepare_normal(
material.flags,
in.world_normal,
#ifdef VERTEX_TANGENTS
#ifdef STANDARDMATERIAL_NORMAL_MAP
in.world_tangent,
#endif
#endif
#ifdef VERTEX_UVS
in.uv,
#endif
in.is_front,
);

alpha_discard(material, output_color);
return vec4<f32>(normal * 0.5 + vec3<f32>(0.5), 1.0);
} else {
alpha_discard(material, output_color);
return vec4<f32>(in.world_normal * 0.5 + vec3<f32>(0.5), 1.0);
}
}
Loading

0 comments on commit 793352e

Please sign in to comment.