Ray marching accumulation

Started by
6 comments, last by taby 11 months, 4 weeks ago

I’m doing some ray marching to do volumetric effects in my renderer. It’s not working out so well. Do you have a favourite algorithm? do you have references?

Advertisement

I used to own a book on graphics algorithms, and it was red and had a baboon on the cover. Anyone know this book? I forget the title. :(

EDIT: found it… it’s called Advanced Graphics Programming using OpenGL.

The code is:

// Do some white fog
if(rays[i].external_reflection_ray || rays[i].external_refraction_ray)
{
	float t0 = 0.0;
	float t1 = 0.0;

	if(BBoxIntersect(aabb_min, aabb_max, rays[i].origin.xyz, rays[i].direction.xyz, t0, t1))
	{
		const float target_step_length = 0.125;

		const vec3 start = rays[i].origin.xyz + rays[i].direction.xyz*t0;
		const vec3 end = rays[i].origin.xyz + rays[i].direction.xyz*t1;
		const float num_steps = floor(distance(start, end) / target_step_length);
		const vec3 step = (start - end) / num_steps;

		vec3 curr_step = start;

		for(float j = 0; j < num_steps; j += 1.0)
		{
			for(int k = 0; k < max_lights; k++)
			{
				if(false == get_shadow(curr_step, rayPayload.wrd, rayPayload.hitt, ubo.light_positions[k].xyz, rayPayload.normal, 1.0))
				{
					const vec3 light_steps_start = curr_step;
					const vec3 light_steps_end = ubo.light_positions[k].xyz;
					const float light_num_steps = floor(distance(light_steps_start, light_steps_end) / target_step_length);
					const vec3 light_step = (light_steps_start - light_steps_end)/float(light_num_steps);
									
					vec3 light_curr_step = light_steps_start;

					float light_color = 1.0;

					for(float l = 0.0; l < light_num_steps; l += 1.0)
					{
						if(light_color <= 0 || false == in_aabb(light_curr_step, aabb_min, aabb_max))
							break;

						light_color -= get_sample(light_curr_step)*0.1;

						light_curr_step += light_step;
					}

					dist_color += clamp(light_color, 0.0, 1.0);
				}
			}	

			dist_opacity += 0.0001;

			curr_step += step;
		}
	}
}

rays[i].base_color = mix(rays[i].base_color, dist_color, clamp(dist_opacity, 0.0, 1.0));

A simpler fog is:

// Do some simple white fog
// It really makes the image better
if(rays[i].external_reflection_ray || rays[i].external_refraction_ray)
{
	float dist = 0.0;

	if(rays[i].parent_id != -1)
		dist = distance(rays[rays[i].parent_id].origin, rays[i].origin);

	dist_color = dist/10.0f; // suit to taste
}

I got fog working great:

Now the real deal is getting this from 2fps to 100fps.

Looks really good - the participating media (fog) looks a lot step-like. Try adding some small random number distance every time you step through it. It helps a LOT.

My current blog on programming, linux and stuff - http://gameprogrammerdiary.blogspot.com

Yeah, the fog takes no time at all. It's the refraction and reflection that are so GPU intensive.

I do randomization for shadows and glossy reflections. ?

This topic is closed to new replies.

Advertisement