Skip to content
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions assets/shaders/my_material.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#import bevy_pbr::{
pbr_fragment::pbr_input_from_standard_material,
pbr_functions::alpha_discard,
}

#ifdef PREPASS_PIPELINE
#import bevy_pbr::{
prepass_io::{VertexInput, VertexOutput, FragmentOutput},
pbr_deferred_functions::deferred_output,
}
#else
#import bevy_pbr::{
forward_io::{VertexOutput, FragmentOutput},
pbr_functions::{apply_pbr_lighting, main_pass_post_lighting_processing},
}
#endif

struct MyExtendedMaterial {
quantize_steps: u32,
}

@group(2) @binding(100)
var<uniform> my_extended_material: MyExtendedMaterial;

struct Vertex {
@location(0) position: vec3<f32>,
@location(1) blend_color: vec4<f32>,
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use packed data

Suggested change
@location(0) position: vec3<f32>,
@location(1) blend_color: vec4<f32>,
@location(0) packed_data: f32,

};

@vertex
fn vertex(vertex: Vertex) -> VertexOutput {
var out: VertexOutput;
out.clip_position = mesh_position_local_to_clip(
get_world_from_local(vertex.instance_index),
vec4<f32>(vertex.position, 1.0),
);
out.blend_color = vertex.blend_color;
return out;
}

@fragment
fn fragment(
in: VertexOutput,
@builtin(front_facing) is_front: bool,
) -> FragmentOutput {
// generate a PbrInput struct from the StandardMaterial bindings
var pbr_input = pbr_input_from_standard_material(in, is_front);

// we can optionally modify the input before lighting and alpha_discard is applied
pbr_input.material.base_color.b = pbr_input.material.base_color.r;

// alpha discard
pbr_input.material.base_color = alpha_discard(pbr_input.material, pbr_input.material.base_color);

#ifdef PREPASS_PIPELINE
// in deferred mode we can't modify anything after that, as lighting is run in a separate fullscreen shader.
let out = deferred_output(in, pbr_input);
#else
var out: FragmentOutput;
// apply lighting
out.color = apply_pbr_lighting(pbr_input);

// we can optionally modify the lit color before post-processing is applied
out.color = vec4<f32>(vec4<u32>(out.color * f32(my_extended_material.quantize_steps))) / f32(my_extended_material.quantize_steps);

// apply in-shader post processing (fog, alpha-premultiply, and also tonemapping, debanding if the camera is non-hdr)
// note this does not include fullscreen postprocessing effects like bloom.
out.color = main_pass_post_lighting_processing(pbr_input, out.color);

// we can optionally modify the final result here
out.color = out.color * 2.0;
#endif

return out;
}

66 changes: 66 additions & 0 deletions src/client/terrain/materials.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use crate::prelude::*;
use bevy::{
color::palettes::css::RED, pbr::MaterialExtension, reflect::Reflect, render::render_resource::{AsBindGroup, ShaderRef}
};

const SHADER_ASSET_PATH: &str = "shaders/my_material.glsl";

#[derive(Asset, AsBindGroup, Reflect, Debug, Clone)]
pub struct MyExtension {
// We need to ensure that the bindings of the base material and the extension do not conflict,
// so we start from binding slot 100, leaving slots 0-99 for the base material.
#[uniform(100)]
pub quantize_steps: u32,
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No parameter needed, wie just override the vertex shader

Suggested change
// We need to ensure that the bindings of the base material and the extension do not conflict,
// so we start from binding slot 100, leaving slots 0-99 for the base material.
#[uniform(100)]
pub quantize_steps: u32,

}

impl MaterialExtension for MyExtension {
fn vertex_shader() -> ShaderRef {
SHADER_ASSET_PATH.into()
}

fn fragment_shader() -> ShaderRef {
ShaderRef::Default
}

fn prepass_vertex_shader() -> ShaderRef {
ShaderRef::Default
}

fn prepass_fragment_shader() -> ShaderRef {
ShaderRef::Default
}

fn deferred_vertex_shader() -> ShaderRef {
ShaderRef::Default
}

fn deferred_fragment_shader() -> ShaderRef {
ShaderRef::Default
}

fn specialize(
pipeline: &MaterialExtensionPipeline,
descriptor: &mut bevy::render::render_resource::RenderPipelineDescriptor,
layout: &bevy::render::mesh::MeshVertexBufferLayoutRef,
key: MaterialExtensionKey<Self>,
) -> Result<(), bevy::render::render_resource::SpecializedMeshPipelineError> {
Ok(())
}
}

pub fn create_base_material(
texture_handle: Handle<Image>,
) -> ExtendedMaterial<StandardMaterial, MyExtension> {
ExtendedMaterial {
base: StandardMaterial {
opaque_render_method: OpaqueRendererMethod::Auto,
perceptual_roughness: 0.5,
reflectance: 0.0,
unlit: false,
specular_transmission: 0.0,
base_color_texture: Some(texture_handle),
..default()
},
extension: MyExtension { quantize_steps: 12 },
}
}
7 changes: 7 additions & 0 deletions src/client/terrain/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use materials::MyExtension;

use crate::prelude::*;

pub mod components;
pub mod events;
pub mod materials;
pub mod resources;
pub mod systems;
pub mod util;
Expand All @@ -15,6 +18,10 @@ impl Plugin for TerrainPlugin {
app.insert_resource(util::TextureManager::new());
app.insert_resource(resources::RenderMaterials::new());
app.insert_resource(resources::MesherTasks::default());
app.insert_resource(resources::MesherTasks::default());
app.add_plugins(MaterialPlugin::<
ExtendedMaterial<StandardMaterial, MyExtension>,
>::default());
app.add_event::<terrain_events::BlockUpdateEvent>();
app.add_event::<terrain_events::ChunkMeshUpdateEvent>();
app.add_event::<terrain_events::WorldRegenerateEvent>();
Expand Down
6 changes: 4 additions & 2 deletions src/client/terrain/resources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use bevy::tasks::Task;

use crate::prelude::*;

use super::materials::MyExtension;

#[derive(Resource)]
pub struct SpawnAreaLoaded(pub bool);

Expand Down Expand Up @@ -35,8 +37,8 @@ pub struct MesherTasks {

#[derive(Resource)]
pub struct RenderMaterials {
pub transparent_material: Option<Handle<StandardMaterial>>,
pub chunk_material: Option<Handle<StandardMaterial>>,
pub transparent_material: Option<Handle<ExtendedMaterial<StandardMaterial, MyExtension>>>,
pub chunk_material: Option<Handle<ExtendedMaterial<StandardMaterial, MyExtension>>>,
}

impl Default for RenderMaterials {
Expand Down
37 changes: 22 additions & 15 deletions src/client/terrain/systems.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,19 @@ use terrain_resources::{

use crate::prelude::*;

use super::materials::{create_base_material, MyExtension};

pub fn prepare_mesher_materials_system(
mut render_materials: ResMut<RenderMaterials>,
mut materials: ResMut<Assets<StandardMaterial>>,
mut materials: ResMut<Assets<ExtendedMaterial<StandardMaterial, MyExtension>>>,
asset_server: Res<AssetServer>,
) {
let texture_handle = obtain_texture_handle(&asset_server);

let material = create_transparent_material(texture_handle.clone());
render_materials.transparent_material = Some(materials.add(material));

let material = create_chunk_material(texture_handle);
let material = create_base_material(texture_handle);
render_materials.chunk_material = Some(materials.add(material));
}

Expand Down Expand Up @@ -171,12 +173,12 @@ fn create_chunk_bundle(
mesh_handle: Handle<Mesh>,
chunk_position: Vec3,
mesh_type: MeshType,
material_handle: Handle<StandardMaterial>,
material_handle: Handle<ExtendedMaterial<StandardMaterial, MyExtension>>,
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Define Type Alias for the material

Suggested change
material_handle: Handle<ExtendedMaterial<StandardMaterial, MyExtension>>,
material_handle: Handle<ChunkMaterial>,

) -> (
bevy::prelude::Mesh3d,
bevy::prelude::Transform,
ChunkMesh,
bevy::prelude::MeshMaterial3d<StandardMaterial>,
bevy::prelude::MeshMaterial3d<ExtendedMaterial<StandardMaterial, MyExtension>>,
) {
(
Mesh3d(mesh_handle),
Expand All @@ -197,17 +199,22 @@ fn create_chunk_bundle(
)
}

fn create_transparent_material(texture_handle: Handle<Image>) -> StandardMaterial {
StandardMaterial {
perceptual_roughness: 1.0,
double_sided: true,
cull_mode: None,
reflectance: 0.0,
unlit: false,
specular_transmission: 0.0,
alpha_mode: AlphaMode::Mask(1.0),
base_color_texture: Some(texture_handle),
..default()
fn create_transparent_material(
texture_handle: Handle<Image>,
) -> ExtendedMaterial<StandardMaterial, MyExtension> {
ExtendedMaterial {
base: StandardMaterial {
perceptual_roughness: 1.0,
double_sided: true,
cull_mode: None,
reflectance: 0.0,
unlit: false,
specular_transmission: 0.0,
alpha_mode: AlphaMode::Mask(1.0),
base_color_texture: Some(texture_handle),
..default()
},
extension: MyExtension { quantize_steps: 12 },
}
}

Expand Down
Loading