Fractal Derivatives
category: code [glöplog]
HI I need help from some math wizards pls pls pls :)
I'm trying to analytically calculate the derivatives (for fast lighting normal calculation) of a FBM type fractal:
vec2 dxy = vec2(0.0, 0.0);
float f = .0;
float f2 = .0;
float flip = 1.0;
norm=0;
float sw=0;
const float mully=0.5;
for (int i = 0; i < 12; i++)
{
vec3 v = SmoothNoise(pos);
dxy += v.yz();
sw+=w;
f += (w * v.x )/ (1.0 + dxy.Dot(dxy)) * flip;
flip = -flip;
w*=0.942;
pos = pos*mully;
}
it's from IQ's work here:
www.iquilezles.org/www/articles/morenoise/morenoise.htm
I managed to figure out the standard FBM and it's weighted by the position scale
vec2 dxy = vec2(0.0, 0.0);
float f = .0;
float f2 = .0;
float flip = 1.0;
norm=0;
float sw=0;
const float mully=0.5;
float weights=mully;
for (int i = 0; i < 12; i++)
{
vec3 v = SmoothNoise(pos);
dxy += v.yz();
sw+=w;
norm+=(v.yz()*w*weights);
f += (w * v.x );
w*=0.942;
weights*=mully;
pos = pos*mully;
}
norm/=12;
and that works great - normals look correct and awesome.
I can't figure out the weights when the /(1+dot(dxy,dxy)*flip terms are added - anyone know to do this?
many thanks
Shabby
I'm trying to analytically calculate the derivatives (for fast lighting normal calculation) of a FBM type fractal:
vec2 dxy = vec2(0.0, 0.0);
float f = .0;
float f2 = .0;
float flip = 1.0;
norm=0;
float sw=0;
const float mully=0.5;
for (int i = 0; i < 12; i++)
{
vec3 v = SmoothNoise(pos);
dxy += v.yz();
sw+=w;
f += (w * v.x )/ (1.0 + dxy.Dot(dxy)) * flip;
flip = -flip;
w*=0.942;
pos = pos*mully;
}
it's from IQ's work here:
www.iquilezles.org/www/articles/morenoise/morenoise.htm
I managed to figure out the standard FBM and it's weighted by the position scale
vec2 dxy = vec2(0.0, 0.0);
float f = .0;
float f2 = .0;
float flip = 1.0;
norm=0;
float sw=0;
const float mully=0.5;
float weights=mully;
for (int i = 0; i < 12; i++)
{
vec3 v = SmoothNoise(pos);
dxy += v.yz();
sw+=w;
norm+=(v.yz()*w*weights);
f += (w * v.x );
w*=0.942;
weights*=mully;
pos = pos*mully;
}
norm/=12;
and that works great - normals look correct and awesome.
I can't figure out the weights when the /(1+dot(dxy,dxy)*flip terms are added - anyone know to do this?
many thanks
Shabby
From a fast look at your code, if you derive the fbm function analytically you need the second derivative of smoothnoise, since you are allready using the first one at the calculation of the fbm function.
I don't know how complex is calculating the analytic second derivative of smoothnoise is, but the derivative formula of this fbm function is complex allready. Maybe you should consider to approximate the derivative of this function with the finite differences method.
I'm not an expert on this stuff, maybe another scener may help you.
I don't know how complex is calculating the analytic second derivative of smoothnoise is, but the derivative formula of this fbm function is complex allready. Maybe you should consider to approximate the derivative of this function with the finite differences method.
I'm not an expert on this stuff, maybe another scener may help you.
thanks Jarod - but I don't want to use central differences - it's really the whole point of this - is to not use CD to calculate the lighting normals - because it's slow (3x slower in the frag shader).
The second derivatives could be easy enough to calculate? but how to plug that in to the normal creation. I'm addiing more "stuff" to the fractal later on so I need to know the method of this so I can work out the normals myself.
e.g.
f += -(f*f*IslandScale)-(f/(1+f*f)*0.5)+(w * v.x / (1.0 + dot(dxy, dxy))) * flip;
I'll be adding that lot later on (creates islands and swamps) and I'll prolly add a few more after that - so it would be really handy to know the method of calculating the Analytic Normal.
The second derivatives could be easy enough to calculate? but how to plug that in to the normal creation. I'm addiing more "stuff" to the fractal later on so I need to know the method of this so I can work out the normals myself.
e.g.
f += -(f*f*IslandScale)-(f/(1+f*f)*0.5)+(w * v.x / (1.0 + dot(dxy, dxy))) * flip;
I'll be adding that lot later on (creates islands and swamps) and I'll prolly add a few more after that - so it would be really handy to know the method of calculating the Analytic Normal.
Central differences yes :P
First of all:
Df(x)/dx = f'(x) (in classic fbm is the derivative of smoothnoise)
Df(g(x))/dx =f'(g(x))*g'(x)
so you will need to calculate the derivative of -(f*f*IslandScale)-(f/(1+f*f)*0.5)+(w * v.x / (1.0 + dot(dxy, dxy))) * flip; as a whole which is not very convinient for every function you come up with (and includes noise second derivatives, which i don't know how they are calculated).
I still think the central differences is your best bet, and use some sort of Level of Detail to reduce the calculations.
First of all:
Df(x)/dx = f'(x) (in classic fbm is the derivative of smoothnoise)
Df(g(x))/dx =f'(g(x))*g'(x)
so you will need to calculate the derivative of -(f*f*IslandScale)-(f/(1+f*f)*0.5)+(w * v.x / (1.0 + dot(dxy, dxy))) * flip; as a whole which is not very convinient for every function you come up with (and includes noise second derivatives, which i don't know how they are calculated).
I still think the central differences is your best bet, and use some sort of Level of Detail to reduce the calculations.
Jarod the LOD is a great Idea and it already does this:
http://www.youtube.com/watch?v=-4GBD1j_ALA
The problem with LOD is that if you are close enough to the 'scape the whole screen is full of maximum detail shader fills. (which on my vidia 320m grinds down to 15fps).
I was thinking have a SmoothNoiseD1(pos) which gets me the second derivative - it's 1 extra texture lookup - but it would still be faster than using CD. Just how to calc the normal using that. I guess it would still be weighted by the position scale e.t.c.?
http://www.youtube.com/watch?v=-4GBD1j_ALA
The problem with LOD is that if you are close enough to the 'scape the whole screen is full of maximum detail shader fills. (which on my vidia 320m grinds down to 15fps).
I was thinking have a SmoothNoiseD1(pos) which gets me the second derivative - it's 1 extra texture lookup - but it would still be faster than using CD. Just how to calc the normal using that. I guess it would still be weighted by the position scale e.t.c.?