Welcome to Fractal Forums

Fractal Software => Fragmentarium => Topic started by: Patryk Kizny on November 01, 2015, 11:20:14 AM




Title: Displacement and mapping fractals onto surfaces
Post by: Patryk Kizny on November 01, 2015, 11:20:14 AM
Hey,

At some point I wanted to do a true displacement add-on for the raytracer.
But sort of stuck. What I managed to do is simply a bump effect which manipulates normals so that the surface appears waved (depending on the texture used).
Bump is cool, but does not work on the edges, only on surfaces facing you.

Can you guys help me with how to do it?
Not asking for code, just the way to get there.

The other thing - how would I go about mapping a fractal onto a plane (so displaace a plane based on a DE) or further, onto a certain surface? Say hemisphere, sphere or sine-bent surface?



Title: Re: Displacement and mapping fractals onto surfaces
Post by: 3dickulus on November 01, 2015, 11:36:00 AM
check the terrain.frag in Examples/Experimental folder


Title: Re: Displacement and mapping fractals onto surfaces
Post by: Patryk Kizny on November 04, 2015, 01:52:50 PM
Thanks, I checked that and I understand how height mapping works. Pretty easy.
Still, I can't understand how to displace a point on the surface of a fractal.
I mean the DE concept is something I understand in theory but is hard for me to grasp intuitively.

Can anyone give me a big picture?


Title: Re: Displacement and mapping fractals onto surfaces
Post by: cKleinhuis on November 04, 2015, 04:51:04 PM
please read the awesome inigo quiles introduction to modelling with distance functions, and jump to the "displacement" part
http://iquilezles.org/www/articles/distfunctions/distfunctions.htm


Title: Re: Displacement and mapping fractals onto surfaces
Post by: Patryk Kizny on November 04, 2015, 05:56:02 PM
Yeah, basic adding operation sounds easy.

But:
To displace along normal I need another distance field that gives me normal at a given point.
So essentially I am thinking I need to:
- calculate DE for the fractal
- acquire normal
- construct displacement vector based on DE and normal
- calculate the new DE based on the acquired normal and displacement?





Title: Re: Displacement and mapping fractals onto surfaces
Post by: cKleinhuis on November 04, 2015, 06:24:06 PM
that is the point, you need the surface normal, transforming a already fractal surface is ultra heavy workload, because the distance is not enough, you then need to find the exact point for that particular distance, and then construct the surface normal for that point (could be done by shooting 2 rays from the CURRENT position) then transform the original found point by the displacement for that surface point and modify the resulting DE value that you obtained first ;)

that would be "basically" it ;)

but perhaps some clever dudes have another point of view for that case, this is just how i see it what has to be done to achieve the displacement effect for a fractal surface ....


Title: Re: Displacement and mapping fractals onto surfaces
Post by: Patryk Kizny on November 04, 2015, 08:01:16 PM
That looks like a path. Though I am still a bit unsure if it's doable at all within currently working architecture.

My reasoning is as follows (am I wrong?):
Even if I find a point on the fractal surface, its normal and push the point along the normal, the resulting displaced point will be a point somewhere else (for a different pixel or camera ray), not for the point that corresponds to the original ray.

Given the current tracer architecture, I think one can only displace along the camera ray. Which does not make much sense.

To do the real displacement, I guess I would need to cache all the calculated points somehow.
Now even if I did that, there will be 'black holes'.

Maybe this case could be worked around, by some clever analytical solution.
Or via some trickery on the input Z vector coming into DE function.











Title: Re: Displacement and mapping fractals onto surfaces
Post by: cKleinhuis on November 04, 2015, 09:32:07 PM
yay, you are right, there is a slight problem: you need the displaced forms of the neighbour points to obtain the normal ... :( i am out, perhaps someone else can help here to find a working/fast solution


Title: Re: Displacement and mapping fractals onto surfaces
Post by: cKleinhuis on November 04, 2015, 09:32:57 PM
stuff that would work is displacing the stuff with a map, and using a sphere mapping or something around your object, this way you would be pretty flexible and fast, and determined!


Title: Re: Displacement and mapping fractals onto surfaces
Post by: Patryk Kizny on November 04, 2015, 10:19:13 PM
I am thinking about some other trickery - leave the fractal alone, just distort the incoming position vector before letting it spin within the fractal DE loop. However, again, it's hard to to anything precise here, because reversing the distortion would be terribly tough.


Title: Re: Displacement and mapping fractals onto surfaces
Post by: Patryk Kizny on November 06, 2015, 02:16:50 PM
I got some success, but still it's not what I wanted.

Essentially, I am doing a "pretrace", store the light/shadow values in a variable and then re-trace again, but that time the DE function applies some noise based on the distort value obtained earlier.
It looks nice, however, the problem is that it does not give me a real 3d - it's only working more less as a map, thus the pixels change color, but are not shifted in fact. That causes problems with obscurance and depth.

Below is my color function.
Code:
[quote]SColor color(SRay Ray) {

float glow = 0.5;
vec3 hitNormal = vec3(0.0);

vec3 col = vec3(0.0);
vec3 col0 = vec3(0.0);
vec3 RWeight = vec3(1.);

SColor Color;

// Reflections loop
for(int i=0; i<= ReflectionsNumber; i++){
if (i>0) isPrimaryPass = false;
vec3 prevPos = SRCurrentPt(Ray);

// ----> TRACE <------
SRay RayOriginal = Ray;
Color = trace(Ray, hitNormal, glow);
vec3 curPos = SRCurrentPt(Ray);

// Re-trace for distortion
displacement.xyz = hitNormal;
displacement.w = (1-totalShadow) * totalLight;

hitNormal = vec3(0.);
Ray = RayOriginal;


// ----> TRACE Again <------
SColor Color2 = trace(Ray, hitNormal, glow);
Color.RGB =  Color2.RGB; // mix(Color.RGB, Color2.RGB, totalShadow);


col0 = Color.RGB;
...

and in DE

Code:
float DE(vec3 z){
        // some sin noise
float de_n = sin(z.x*DE_NoiseFreq.x)*DE_NoiseAmp.x + sin(z.y*DE_NoiseFreq.y)*DE_NoiseAmp.y + sin(z.z*DE_NoiseFreq.z)*DE_NoiseAmp.z;
float de_obj = Objects(z);
float de_hm = z.z;

        // displace only on the second pass
if (tracecount==1){
de_hm += de_n * displacement.w * ShadowDisplacement; // * gizmo;
}

float de_fin = smin(de_hm, de_obj, DE_HeightMapSmooth.y);

return de_fin;

}

Not sure if this approach will give me any good results.