Search across packages, versions, files, declarations, and comments. Use multiple terms to narrow results (AND), and add @vertex, @fragment, or @compute to filter by shader stage.
1import bevy_render::view::View;
2import bevy_pbr::render::utils::coords_to_viewport_uv;
4struct SkyboxUniforms {
5 brightness: f32,
6 transform: mat4x4<f32>,
7 @if(SIXTEEN_BYTE_ALIGNMENT)
8 _wasm_padding_8b: u32,
9 @if(SIXTEEN_BYTE_ALIGNMENT)
10 _wasm_padding_12b: u32,
11 @if(SIXTEEN_BYTE_ALIGNMENT)
12 _wasm_padding_16b: u32,
15@group(0) @binding(0) var skybox: texture_cube<f32>;
16@group(0) @binding(1) var skybox_sampler: sampler;
17@group(0) @binding(2) var<uniform> view: View;
18@group(0) @binding(3) var<uniform> uniforms: SkyboxUniforms;
20fn coords_to_ray_direction(position: vec2<f32>, viewport: vec4<f32>) -> vec3<f32> {
21 // Using world positions of the fragment and camera to calculate a ray direction
22 // breaks down at large translations. This code only needs to know the ray direction.
23 // The ray direction is along the direction from the camera to the fragment position.
24 // In view space, the camera is at the origin, so the view space ray direction is
25 // along the direction of the fragment position - (0,0,0) which is just the
26 // fragment position.
27 // Use the position on the near clipping plane to avoid -inf world position
28 // because the far plane of an infinite reverse projection is at infinity.
29 let view_position_homogeneous = view.view_from_clip * vec4(
30 coords_to_viewport_uv(position, viewport) * vec2(2.0, -2.0) + vec2(-1.0, 1.0),
31 1.0,
32 1.0,
33 );
35 // Transforming the view space ray direction by the skybox transform matrix, it is
36 // equivalent to rotating the skybox itself.
37 var view_ray_direction = view_position_homogeneous.xyz / view_position_homogeneous.w;
38 view_ray_direction = (view.world_from_view * vec4(view_ray_direction, 0.0)).xyz;
40 // Transforming the view space ray direction by the view matrix, transforms the
41 // direction to world space. Note that the w element is set to 0.0, as this is a
42 // vector direction, not a position, That causes the matrix multiplication to ignore
43 // the translations from the view matrix.
44 let ray_direction = (uniforms.transform * vec4(view_ray_direction, 0.0)).xyz;
46 return normalize(ray_direction);
49struct VertexOutput {
50 @builtin(position) position: vec4<f32>,
51};
53// 3 | 2.
54// 2 | : `.
55// 1 | x-----x.
56// 0 | | s | `.
57// -1 | 0-----x.....1
58// +---------------
59// -1 0 1 2 3
60//
61// The axes are clip-space x and y. The region marked s is the visible region.
62// The digits in the corners of the right-angled triangle are the vertex
63// indices.
64@vertex
65fn skybox_vertex(@builtin(vertex_index) vertex_index: u32) -> VertexOutput {
66 // See the explanation above for how this works.
67 let clip_position = vec2(
68 f32(vertex_index & 1u),
69 f32((vertex_index >> 1u) & 1u),
70 ) * 4.0 - vec2(1.0);
72 return VertexOutput(vec4(clip_position, 0.0, 1.0));
75@fragment
76fn skybox_fragment(in: VertexOutput) -> @location(0) vec4<f32> {
77 let ray_direction = coords_to_ray_direction(in.position.xy, view.main_pass_viewport);
79 // Cube maps are left-handed so we negate the z coordinate.
80 let out = textureSample(skybox, skybox_sampler, ray_direction * vec3(1.0, 1.0, -1.0));
81 return vec4(out.rgb * uniforms.brightness, out.a);
Contents