Fresnel reflection-refraction

Started by
9 comments, last by taby 1 year ago

So I've got the ray tracer to the point where it does chromatic aberration. I would also like to add in Fresnel reflection-refraction. I've been trying many codes, but none seem to do the trick, Any one with ideas?

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

The gist of it is:


	for(int i = current_buffer_index - 1; i >= 0; i--)
	{
		float accum = rays[i].base_color;

		// Fresnel code from some random book chapter that I can't find using Google any more
		const float eta = (red_eta + green_eta + blue_eta)/3.0;
		const float FresnelPower = 1.0;
		const float F = ((1.0 - eta) * (1.0 - eta)) / ((1.0 + eta) * (1.0 + eta));

		const vec3 incident = normalize(rays[i].direction.xyz);
		const vec3 normal = normalize(rays[i].normal);

		float Ratio = F + (1.0 - F) * pow((1.0 - dot(-incident, normal)), FresnelPower);

		float mixed_color = 0.0;

		if(rays[i].child_reflect_id != -1 && rays[i].child_refract_id != -1)
			mixed_color = mix(rays[rays[i].child_refract_id].accumulated_color, rays[rays[i].child_reflect_id].accumulated_color, Ratio);
		else if(rays[i].child_reflect_id != -1)
			mixed_color = rays[rays[i].child_reflect_id].accumulated_color;
		else if(rays[i].child_refract_id != -1)
			mixed_color = rays[rays[i].child_refract_id].accumulated_color;

		accum = mix(accum, mixed_color, 1.0 - rays[i].refraction_constant);
	
		rays[i].accumulated_color = accum;
	}

Where the basic non-Fresnel accumulator is:

	for(int i = current_buffer_index - 1; i >= 0; i--)
	{
		float accum = rays[i].base_color;

		if(rays[i].child_reflect_id != -1)
			accum = mix(accum, rays[rays[i].child_reflect_id].accumulated_color, rays[i].reflection_constant);

		if(rays[i].child_refract_id != -1)
			accum = mix(accum, rays[rays[i].child_refract_id].accumulated_color, 1.0 - rays[i].refraction_constant);

		rays[i].accumulated_color = accum;
	}
Advertisement

Are these Fresnel effects only suitable for a fully transparent mesh?

No, not really - Fresnel has its role for most of materials shading - ceramic material, metals, etc.

See F.e. Cook-Torrance specular model, which uses Fresnel in it.

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

OK, I got it working! Yay!

The accumulator is:


	// Step two: this is the Fresnel reflection-refraction code
	for(int i = current_buffer_index - 1; i >= 0; i--)
	{
		bool pure_refraction = false;
		bool pure_reflection = false;
		bool neither = false;
		bool both = false;

		if(rays[i].child_refract_id != -1 && rays[i].child_reflect_id == -1)
			pure_refraction = true;

		if(rays[i].child_refract_id == -1 && rays[i].child_reflect_id != -1)
			pure_reflection = true;

		if(rays[i].child_refract_id == -1 && rays[i].child_reflect_id == -1)
			neither = true;

		if(rays[i].child_refract_id != -1 && rays[i].child_reflect_id != -1)
			both = true;

		float accum = 0.0;

		if(neither)
		{
			accum = rays[i].base_color;
		}
		else if(both)
		{
			// Fake the Fresnel refraction-reflection
			const float Ratio = 1.0 - dot(-normalize(rays[i].direction.xyz), rays[i].normal);

			float reflect_accum = mix(rays[i].base_color, rays[rays[i].child_reflect_id].accumulated_color, rays[i].reflection_constant);
			float refract_accum = mix(rays[i].base_color, rays[rays[i].child_refract_id].accumulated_color, 1.0 - rays[i].refraction_constant);
		
			accum = mix(refract_accum, reflect_accum, Ratio);
		}
		else if(pure_refraction)
		{
			accum = mix(rays[i].base_color, rays[rays[i].child_refract_id].accumulated_color, 1.0 - rays[i].refraction_constant);	
		}
		else if(pure_reflection)
		{
			accum = mix(rays[i].base_color, rays[rays[i].child_reflect_id].accumulated_color, rays[i].reflection_constant);
		}
		
		rays[i].accumulated_color = accum;
	}

Along with chromatic aberration:

With multiple light sources:

At such point it becomes more surreal than realistic.

I also see aliasing hits you hard on the julia set - but that's expected. Temporal antialiasing and let it converge?

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

The aliasing could be worse – I use a custom vertex interpolation function in Marching Cubes that reduces the aliasing you'd get from doing it naively. It all runs on the GPU, so it’s fast. OpenGL 2.0 LOL – https://github.com/sjhalayka/qjs-isosurface

The problem aliasing that still exists would likely be fixed by using Dual Contouring. (?)

What do you mean by temporal antialiasing?

Aliased
Not as aliased

Note that both meshes have the same number of faces and vertices, and that all I’ve done is improved where to place the vertices. This improvement method applies to any parametric equation, not necessarily the quaternion Julia sets.

p.S. just for the record, @warp9 was the mastermind behind the ides of using the ambient occlusion map as the opacity map. It does look surreal, doesn’t it? That’s awesome, because I use the paranoiac critical method every day.

without transparency

This topic is closed to new replies.

Advertisement