Skip to content

Commit 402b072

Browse files
authored
Refactor raymarching code (#8)
1 parent cb297bd commit 402b072

2 files changed

Lines changed: 48 additions & 29 deletions

File tree

src/fly_camera.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ pub struct MovementSettings {
7575

7676
impl Default for MovementSettings {
7777
fn default() -> Self {
78-
Self { speed: 0.12 }
78+
Self { speed: 1e3 }
7979
}
8080
}
8181

src/shaders/clouds_compute.wgsl

Lines changed: 47 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#import bevy_open_world::common
22

33
const EPSILON = 0.000001;
4+
const MAX_DISTANCE = 1.0e9;
45
const WORLEY_RESOLUTION = 32;
56
const WORLEY_RESOLUTION_F32 = 32.0;
67

@@ -43,6 +44,12 @@ struct Config {
4344
@group(1) @binding(2) var clouds_worley_texture: texture_storage_3d<rgba32float, read_write>;
4445
@group(1) @binding(3) var sky_texture: texture_storage_2d<rgba32float, read_write>;
4546

47+
struct Ray {
48+
step_distance: f32,
49+
dir_length: f32,
50+
start: f32
51+
}
52+
4653
struct RaymarchResult {
4754
dist: f32,
4855
color: vec4f,
@@ -143,47 +150,53 @@ fn henyey_greenstein(ray_dot_sun: f32, g: f32) -> f32 {
143150
return (1.0 - g_squared) / pow(1.0 + g_squared - 2.0 * g * ray_dot_sun, 1.5);
144151
}
145152

146-
fn raymarch(_ray_origin: vec3f, ray_dir: vec3f, max_dist: f32) -> RaymarchResult {
147-
if (ray_dir.y < 0.0) {
148-
return RaymarchResult(max_dist, vec4f(0.0, 0.0, 0.0, 1.0));
149-
}
150-
151-
let ray_origin = vec3f(
152-
_ray_origin.x,
153-
config.planet_radius - _ray_origin.y,
154-
_ray_origin.z
155-
);
156-
157-
let start = intersect_planet_sphere(ray_dir, config.clouds_bottom_height);
158-
let end = min(intersect_planet_sphere(ray_dir, config.clouds_top_height), max_dist);
159-
160-
if (start > max_dist) {
161-
return RaymarchResult(max_dist, vec4f(0.0, 0.0, 0.0, 1.0));
153+
fn get_ray(ray_origin: vec3f, ray_dir: vec3f, max_dist: f32) -> Ray {
154+
var start = intersect_planet_sphere(ray_dir, config.clouds_bottom_height);
155+
var end = intersect_planet_sphere(ray_dir, config.clouds_top_height);
156+
var inside = intersect_planet_sphere(ray_dir, ray_origin.y - config.planet_radius);
157+
158+
if (start <= inside && inside <= end) {
159+
return Ray(0.0, 0.0, 0.0);
160+
if (ray_dir.y < 0.0) {
161+
end = inside;
162+
} else {
163+
start = inside;
164+
}
162165
}
163166

164-
let ray_dot_sun = dot(ray_dir, -config.sun_dir.xyz);
167+
end = min(end, max_dist);
165168

166169
let step_distance = (end - start) / f32(config.clouds_raymarch_steps_count);
167170
let hashed_offset = common::hash13(ray_dir + fract(config.time));
168171
var dir_length = start - step_distance * hashed_offset;
169172

173+
return Ray(step_distance, dir_length, start);
174+
}
175+
176+
fn raymarch(ray_origin: vec3f, ray_dir: vec3f, max_dist: f32) -> RaymarchResult {
177+
let ray = get_ray(ray_origin, ray_dir, max_dist);
178+
179+
if (ray.start > max_dist) {
180+
return RaymarchResult(max_dist, vec4f(0.0, 0.0, 0.0, 1.0));
181+
}
182+
170183
// Frostbite: dual-lobe phase function
184+
let ray_dot_sun = dot(ray_dir, -config.sun_dir.xyz);
171185
let scattering = mix(
172186
henyey_greenstein(ray_dot_sun, config.forward_scattering_g),
173187
henyey_greenstein(ray_dot_sun, config.backward_scattering_g),
174188
config.scattering_lerp
175189
);
176190

191+
var dir_length = ray.dir_length;
192+
var dist = max_dist;
177193
var scattered_light = vec3f(0.0, 0.0, 0.0);
178194
var transmittance = 1.0;
179195

180-
var dist = config.planet_radius;
181-
182196
for (var step: u32 = 0; step < config.clouds_raymarch_steps_count; step++) {
183197
let world_position = ray_origin + dir_length * ray_dir;
184198

185199
let normalized_height = clamp(get_normalized_height(world_position), 0.0, 1.0);
186-
187200
let clouds_density_sampled = get_cloud_map_density(world_position, normalized_height);
188201

189202
if (clouds_density_sampled > 0.0) {
@@ -200,7 +213,7 @@ fn raymarch(_ray_origin: vec3f, ray_dir: vec3f, max_dist: f32) -> RaymarchResult
200213
ambient_light.rgb +
201214
config.sun_color.rgb * scattering * volumetric_shadow(world_position, ray_dot_sun)
202215
);
203-
let delta_transmittance = exp(-clouds_density_sampled * step_distance);
216+
let delta_transmittance = exp(-clouds_density_sampled * ray.step_distance);
204217
let integrated_scattering = S * (1.0 - delta_transmittance) / clouds_density_sampled;
205218

206219
scattered_light += transmittance * integrated_scattering;
@@ -209,7 +222,7 @@ fn raymarch(_ray_origin: vec3f, ray_dir: vec3f, max_dist: f32) -> RaymarchResult
209222

210223
if transmittance <= config.clouds_min_transmittance { break; }
211224

212-
dir_length += step_distance;
225+
dir_length += ray.step_distance;
213226
}
214227

215228
return RaymarchResult(dist, vec4f(scattered_light, transmittance));
@@ -276,7 +289,7 @@ fn get_clouds_color(frag_coord: vec2f, camera: mat4x4f, old_cam: mat4x4f, ray_di
276289
return common::save_camera(camera, frag_coord, ray_origin);
277290
}
278291

279-
let result = raymarch(ray_origin, ray_dir, 1e9);
292+
let result = raymarch(ray_origin, ray_dir, MAX_DISTANCE);
280293
let transmittance = result.color.a;
281294

282295
let fog_falloff = 1.0e-4;
@@ -293,10 +306,12 @@ fn get_clouds_color(frag_coord: vec2f, camera: mat4x4f, old_cam: mat4x4f, ray_di
293306

294307
// For now, just don't mix two frames when camera transform changed too much.
295308
// TODO: properly reproject old frame's reprojected pixel onto current frame.
296-
if length(abs(old_cam[0] - camera[0])) > EPSILON ||
297-
length(abs(old_cam[1] - camera[1])) > EPSILON ||
298-
length(abs(old_cam[2] - camera[2])) > EPSILON ||
299-
length(abs(old_cam[3] - camera[3])) > EPSILON {
309+
if length(
310+
abs(old_cam[0] - camera[0]) +
311+
abs(old_cam[1] - camera[1]) +
312+
abs(old_cam[2] - camera[2]) +
313+
abs(old_cam[3] - camera[3])
314+
) > EPSILON {
300315
return col;
301316
}
302317

@@ -309,7 +324,11 @@ fn get_clouds_color(frag_coord: vec2f, camera: mat4x4f, old_cam: mat4x4f, ray_di
309324
}
310325

311326
fn get_ray_origin(time: f32) -> vec3f {
312-
return config.camera_translation - config.wind_displacement;
327+
return (
328+
config.camera_translation -
329+
config.wind_displacement +
330+
vec3f(0.0, config.planet_radius, 0.0)
331+
);
313332
}
314333

315334
fn get_ray_direction(frag_coord: vec2f) -> vec3f {

0 commit comments

Comments
 (0)