Skip to content

Instantly share code, notes, and snippets.

@prime31
Created March 28, 2023 14:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save prime31/c0b07abb8d53f2053a1a688ba2251fee to your computer and use it in GitHub Desktop.
Save prime31/c0b07abb8d53f2053a1a688ba2251fee to your computer and use it in GitHub Desktop.
Bevy Material Example
#import bevy_pbr::mesh_view_bindings
#import bevy_pbr::mesh_bindings
#import bevy_pbr::pbr_types
#import bevy_pbr::utils
#import bevy_pbr::clustered_forward
#import bevy_pbr::lighting
#import bevy_pbr::shadows
#import bevy_pbr::pbr_functions
@group(1) @binding(0)
var texture: texture_2d<f32>;
@group(1) @binding(1)
var texture_sampler: sampler;
struct FragmentInput {
@builtin(front_facing) is_front: bool,
@builtin(position) frag_coord: vec4<f32>,
#import bevy_pbr::mesh_vertex_output
};
let TAU: f32 = 6.28318530717958647692528676655900577;
fn dir_to_equirectangular(dir: vec3<f32>) -> vec2<f32> {
let x = atan2(dir.z, dir.x) / (2.0 * PI) + 0.5; // 0-1
let y = acos(dir.y) / PI; // 0-1
return vec2<f32>(x, y);
}
fn refract(I: vec3<f32>, N: vec3<f32>, eta: f32) -> vec3<f32> {
let k = max((1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I))), 0.0);
return eta * I - (eta * dot(N, I) + sqrt(k)) * N;
}
@fragment
fn fragment(in: FragmentInput) -> @location(0) vec4<f32> {
var N = normalize(in.world_normal);
var V = normalize(view.world_position.xyz - in.world_position.xyz);
var NdotV = max(dot(N, V), 0.0001);
var fresnel = clamp(1.0 - NdotV, 0.0, 1.0);
fresnel = pow(fresnel, 5.0) * 2.0;
let glow = pow(NdotV, 10.0) * 50.0;
var col = vec3(0.0, 0.0, 0.0);
col = mix(col, vec3(0.5, 0.1, 0.0), glow);
let bump_coords = dir_to_equirectangular(N * vec3(1.0, -0.5, 1.0) - vec3(0.0, 0.5, 0.0));
let bump = textureSample(texture, texture_sampler, bump_coords).r;
var reflect_coords = dir_to_equirectangular(reflect(-V, N));
let reflection = textureSample(texture, texture_sampler, reflect_coords).rgb;
var refract_coords = dir_to_equirectangular(refract(-V, N + bump * 2.0, 1.0/1.52));
let refraction = textureSample(texture, texture_sampler, refract_coords).rgb;
col = (col * refraction) + reflection * (fresnel + 0.05);
return tone_mapping(vec4(col, 1.0));
}
#[derive(AsBindGroup, TypeUuid, Debug, Clone, Reflect)]
#[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e1"]
pub struct GlowyMaterial {
#[texture(0)]
#[sampler(1)]
pub env_texture: Option<Handle<Image>>,
}
impl Material for GlowyMaterial {
fn fragment_shader() -> ShaderRef {
"shaders/glowy.wgsl".into()
}
}
fn main() {
App::new()
.add_plugins(DefaultPlugins.set(AssetPlugin {
watch_for_changes: true, // for shader hot reload
..Default::default()
}))
.add_plugin(MaterialPlugin::<GlowyMaterial>::default())
.add_plugin(bevy_inspector_egui::quick::AssetInspectorPlugin::<GlowyMaterial>::default()) // egui material inspector
.add_startup_system(setup)
.run();
}
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut glowy_materials: ResMut<Assets<GlowyMaterial>>,
asset_server: Res<AssetServer>,
) {
let env_texture = asset_server.load("textures/colosseum.hdr");
let glowy_material = glowy_materials.add(GlowyMaterial {
env_texture: Some(env_texture),
});
commands.spawn(MaterialMeshBundle {
mesh: meshes.add(Mesh::from(shape::UVSphere {
radius: 0.5,
..default()
})),
material: glowy_material.clone(),
transform: Transform::from_xyz(0.0, 1.5, 0.0),
..default()
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment