6import bevy_core_pipeline::fullscreen_vertex_shader::FullscreenVertexOutput; 7import bevy_pbr::render::mesh_view_bindings::view; 8import bevy_pbr::render::view_transformations::{ 11 position_ndc_to_world, 12 direction_view_to_world, 13 position_world_to_view, 16import bevy_pbr::deferred::functions::deferred_gbuffer_from_pbr_input; 17import bevy_pbr::render::pbr_types::{pbr_input_new, STANDARD_MATERIAL_FLAGS_ALPHA_MODE_OPAQUE}; 18import bevy_pbr::render::mesh_types::MESH_FLAGS_SHADOW_RECEIVER_BIT; 19import bevy_render::globals::Globals; 21@group(0) @binding(1) var<uniform> globals: Globals; 23const FAR: f32 = 100.0; 24const SURFACE_EPSILON: f32 = 0.001; 25const MAX_STEPS: u32 = 160u; 26const STEP_SCALE: f32 = 0.5; 30const GYROID_SCALE: f32 = 5.0; 32fn gyroid_field(p: vec3<f32>) -> f32 { 33 let q = p * GYROID_SCALE + globals.time * 0.6; 34 return dot(sin(q), cos(q.yzx)); 37fn map(p: vec3<f32>) -> f32 { 38 let shell = (abs(gyroid_field(p)) - 0.14) / GYROID_SCALE; 39 let ball = length(p) - 1.3; 40 return max(ball, shell); 43fn sdf_normal(p: vec3<f32>) -> vec3<f32> { 44 let e = vec2<f32>(1.0, -1.0) * 0.0005; 46 e.xyy * map(p + e.xyy) + 47 e.yyx * map(p + e.yyx) + 48 e.yxy * map(p + e.yxy) + 49 e.xxx * map(p + e.xxx) 53fn raymarch(ray_origin: vec3<f32>, ray_dir: vec3<f32>) -> f32 { 55 for (var i = 0u; i < MAX_STEPS; i++) { 56 let d = map(ray_origin + ray_dir * t); 57 if d < SURFACE_EPSILON { 73fn ray_for_uv(uv: vec2<f32>) -> Ray { 74 let ndc = uv_to_ndc(uv); 77 if view.clip_from_view[3].w == 1.0 { 78 ray.origin = position_ndc_to_world(vec3<f32>(ndc, 1.0)); 79 ray.dir = normalize(direction_view_to_world(vec3<f32>(0.0, 0.0, -1.0))); 81 ray.origin = view.world_position; 82 ray.dir = normalize(direction_view_to_world(position_ndc_to_view(vec3<f32>(ndc, 1.0)))); 87fn depth_for_world_pos(world_pos: vec3<f32>) -> f32 { 88 return view_z_to_depth_ndc(position_world_to_view(world_pos).z); 95 @location(0) deferred: vec4<u32>, 96 @location(1) deferred_lighting_pass_id: u32, 97 @builtin(frag_depth) depth: f32, 101fn fragment(in: FullscreenVertexOutput) -> GBufferOutput { 102 let ray = ray_for_uv(in.uv); 103 let t = raymarch(ray.origin, ray.dir); 110 let world_pos = ray.origin + ray.dir * t; 111 let normal = sdf_normal(world_pos); 114 var pbr_input = pbr_input_new(); 115 pbr_input.frag_coord = vec4<f32>(in.position.xy, depth_for_world_pos(world_pos), 1.0); 116 pbr_input.world_position = vec4<f32>(world_pos, 1.0); 117 pbr_input.world_normal = normal; 118 pbr_input.N = normal; 119 pbr_input.V = normalize(view.world_position - world_pos); 122 let field = gyroid_field(world_pos); 123 let color = 0.5 + 0.5 * cos( 124 6.2831 * (field * 0.4 + globals.time * 0.05) + vec3<f32>(0.0, 0.8, 1.6) 126 pbr_input.material.base_color = vec4<f32>(color, 1.0); 127 pbr_input.material.metallic = 0.7; 128 pbr_input.material.perceptual_roughness = 0.25; 129 pbr_input.material.flags = STANDARD_MATERIAL_FLAGS_ALPHA_MODE_OPAQUE; 131 pbr_input.flags = MESH_FLAGS_SHADOW_RECEIVER_BIT; 133 var out: GBufferOutput; 134 out.deferred = deferred_gbuffer_from_pbr_input(pbr_input); 137 out.deferred_lighting_pass_id = 1u; 138 out.depth = pbr_input.frag_coord.z; 144fn fragment_shadow(in: FullscreenVertexOutput) -> @builtin(frag_depth) f32 { 145 let ray = ray_for_uv(in.uv); 146 let t = raymarch(ray.origin, ray.dir); 150 return depth_for_world_pos(ray.origin + ray.dir * t);