Subsurface scattering in Vulkan path tracing

Started by
68 comments, last by taby 2 months, 1 week ago

Aressera said:
I'm not sure it's worth doing the fancy human eye lens flare calculations over proper bloom.

I have downloaded the papers, putting them in the folder ‘stuff i'll surely never have the time to work on’ : )

Btw, i have piled up gigabytes of papers over the years.
If i had a NV GPU, i would train Chat with RTX with it, and see how smart it could answer my questions.

Too mad they totally fail at motivating me to upgrade… :D

Advertisement

OK, I'm having some serious weirdness issues happening. I decided to comment out everything related to subsurface scattering, and it's still doing subsurface scattering. So, I think it's safe to say that I don't need any fancy code to achieve subsurface scattering in general.

Yes, indeed. Fully transparent objects don't scatter the light, and fully opaque objects don't scatter the light either. It's eveyrthing in between that gets scattered.

I found a solution to the problem of subsurface scattering of light by opaque objects.

Here is a plain shot:

Here are some colour shots:

(without subsurface scattering)

With subsurface scattering:

The code is at https://github.com/sjhalayka/bidirectional_path_tracer

Thanks for the sounding board!

Hmm, it seems the scattering ball raises energy, since the whole scene gets brighter.
Not sure, but maybe you need to absorb some light while scattering. (If you care at all.)

What happens if you put the bunny into the ball?
It should become blurry, but still be visible, which might look cool.

Let me try these things. Thank you so much for your input. I do care, I just need time to process the ideas in my head before turning those into code.

For now: in this screenshot, even the walls glow a little bit with the subsurface scattering of light.

LOL

No blurry bunny? :D

Maybe you need to make the sphere transparent as well, in case you didn't.

You've figured out my secret. I am using ray tracing to determine path length, instead of using ray marching. It's a hack, but it works quite well.

Believe me, I tried other methods… 5 in total, over the past month. I'm just glad to have finally found a solution.

What benefits would there be if I did use ray marching?

P.S. The relevant code is:

const vec3 light_dir = normalize(light_o - o_subsurface);
vec3 trace_position = o_subsurface;
const float total_depth = distance(light_o, o_subsurface);
float running_depth = 0;
		
vec3 last_trace_position = trace_position;

while(true)
{
	traceRayEXT(topLevelAS, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, trace_position, tmin, light_dir, tmax, 0);

	// Hit the sky
	if(rayPayload.dist == -1.0)
		break;

	last_trace_position = trace_position;
	trace_position += light_dir*rayPayload.dist;

	if(dot(light_dir, rayPayload.normal) >= 0.0)
		running_depth += distance(trace_position, last_trace_position);

	// Hit the light
	if(rayPayload.color.r > 1
	|| rayPayload.color.g > 1
	|| rayPayload.color.b > 1)
	{
		break;
	}
}

rayPayload = r;

total += mask.r;
total += mask.g;
total += mask.b;

float x = 1.0 - running_depth/total_depth;
x = (x - 0.5) * 5.0 + 0.5; // contrast

local_colour += x*rayPayload.subsurface;

ret_colour += local_colour;

This topic is closed to new replies.

Advertisement