Raymarching Toolbox Thread
category: code [glöplog]
100.
Some kind of bend operator.
Code:
void bend(inout vec2 p, float k, float s0, float sb, float se) {
float r = 1./k, ak = abs(k), sk = sign(k);
vec2 d = vec2(p.x - s0, (r - p.y) * sk);
float a = -atan(d.x, d.y);
float b = clamp(a, ak*(sb-s0), ak*(se-s0)) ;
float s = b*r+s0;
vec2 c = vec2(sin(b), cos(b));
p.xy = mix(
vec2(s, length(d) - abs(r)),
sk*(c.yx*d.xx*vec2(-1.,1) - c.xy*d.yy) + vec2(s, r),
abs(sign(a-b))
);
}
Some kind of bend operator.
A relativelly not so bad signed distance estimate to a metaball isosurface (used in our revision 4k..):
Code:
float metaboules(vec3 p)
{
float sum=0.0, i=0.0, nballs=5.0, isosurfacelevel=1.0;
while (i++<nballs)
{
sum += 0.3 / length(position_metaball_i - p);
}
return ((nballs*nballs+isosurfacelevel) / (sum*sum) - isosurfacelevel) * 0.3;
}
Really nice and well commented Raymarching implementation with source! http://www.mazapan.se/news/2010/07/15/gpu-ray-marching-with-distance-fields/
@Mewler:
Nice find! One of the nicer sources I have seen. Clear and well written.
Nice find! One of the nicer sources I have seen. Clear and well written.
I'm still searching for a good way to get a GOOD noise as small and as fast as possible... (fast is currently more important but it should also be small)
This needs a perlin noise thing as input - so it sucks buy design + also it seems to need a seamlessly tileable perlin noise.
You can get rid of the *2.0 - 1.0 for the lo - that's just an angle - therefore it shouldn't matter that much (little sift in the rotation angle nobody will care about).
The GLSL simplex noise thing is very cool and gives great visual results but is not fast enough for massive marching.
Also generating a 3D perlin noise via texture shaders (D3DX) is not a good idea - the noise is not seamless (therefore not well suited for the lookup/rotate method) and it's too much code to make it seamless.
Any good ideas?
Code:
float2 hi = tex3D(tex1, p).rg*2.0-1.0;
float lo = tex3D(tex1, p/9.0).r*2.0-1.0;
float s, c;
sincos(lo*PI2, s, c);
return hi.r * c + hi.g * s;
This needs a perlin noise thing as input - so it sucks buy design + also it seems to need a seamlessly tileable perlin noise.
You can get rid of the *2.0 - 1.0 for the lo - that's just an angle - therefore it shouldn't matter that much (little sift in the rotation angle nobody will care about).
The GLSL simplex noise thing is very cool and gives great visual results but is not fast enough for massive marching.
Also generating a 3D perlin noise via texture shaders (D3DX) is not a good idea - the noise is not seamless (therefore not well suited for the lookup/rotate method) and it's too much code to make it seamless.
Any good ideas?
Played around in rendermonkey with texture shaders...
GLSL version of the lookup thing
D3DX texture shader to generate a (hopefully) seamless noise
I use a 128^3 3D texture, but for some strange reason I see some artifacts...
GLSL version of the lookup thing
Code:
float tn(vec3 p) {
vec2 h = texture3D(tex, p).xy*2.-1.;
float l = texture3D(tex, p/9.).x*pi2;
return dot(h,vec2(cos(l),sin(l)));
}
D3DX texture shader to generate a (hopefully) seamless noise
Code:
float F(float3 p, float s) {
float v[8];
for (int i=0;i<8;i++)
v[i]=noise(s+5*(p-float3(int3(i,i/2,i/4)%2)));
for (int j=4, k=2, l=0; j>0; j/=2, k*=2, l++)
for (int m=0;m<j*k;m+=k)
v[m] = lerp(v[m],v[m+k/2],p[l]);
return v[0];
}
float2 f(float3 p:POSITION):COLOR {
return float2(F(p,0),F(p,1))/2+.5;
}
I use a 128^3 3D texture, but for some strange reason I see some artifacts...
Sorry if i may be wrong, but, shouldn't the tiling logic be somehow in the way you lookup the noise instead of in the noise itself?
If it's generated from a texture, it'd be logical to tile it so you can read past the texture size.
That's not the point here though.
The only way i managed to get some kind of noise octave to tile was by interpolating not neighbour values..
texture3D(tex, p/9.).x
for example this should interpolate the texels at a position (i,j) and (i+9,j+9,k+9) in the cube needed for trilinear filtering..
i've shared my code in the past and some people have blamed that i "didn't need" to do this, but still i don't know how to get a sum of octaves really perfectly tiling without it.
Does anyone has an idea?
texture3D(tex, p/9.).x
for example this should interpolate the texels at a position (i,j) and (i+9,j+9,k+9) in the cube needed for trilinear filtering..
i've shared my code in the past and some people have blamed that i "didn't need" to do this, but still i don't know how to get a sum of octaves really perfectly tiling without it.
Does anyone has an idea?
http://http.developer.nvidia.com/GPUGems/gpugems_ch05.html
The perlin noise there looks kinda tileable, the D3DX noise func is not...
Therefore I tried to make it tileable.
There you have a more readable version (the smoothstep line is new):
The results I get are kinda strange imho...
I have absolutely no clue where the noise comes from. You can also see serveral artifacts... :(
The perlin noise there looks kinda tileable, the D3DX noise func is not...
Therefore I tried to make it tileable.
There you have a more readable version (the smoothstep line is new):
Code:
float F(float3 p, float s) {
float v[8];
float3 x = smoothstep(0,1,p);
v[0] = noise(s+(p-float3(0,0,0)));
v[1] = noise(s+(p-float3(1,0,0)));
v[2] = noise(s+(p-float3(0,1,0)));
v[3] = noise(s+(p-float3(1,1,0)));
v[4] = noise(s+(p-float3(0,0,1)));
v[5] = noise(s+(p-float3(1,0,1)));
v[6] = noise(s+(p-float3(0,1,1)));
v[7] = noise(s+(p-float3(1,1,1)));
v[0] = lerp(v[0], v[1], x.x);
v[2] = lerp(v[2], v[3], x.x);
v[4] = lerp(v[4], v[5], x.x);
v[6] = lerp(v[6], v[7], x.x);
v[0] = lerp(v[0], v[2], x.y);
v[4] = lerp(v[4], v[6], x.y);
v[0] = lerp(v[0], v[4], x.z);
return v[0];
}
The results I get are kinda strange imho...
I have absolutely no clue where the noise comes from. You can also see serveral artifacts... :(
Though the obvious solution to make it more simple could be to provide completelly random levels of LOD filled with noise intead of generating mipmaps and getting averaged grey.. mm
And the final output in the shader has not to be tileable! jsyk.
Okay, I screwed up the gradient - too small epsilon => strange/cool things might happen while marching through foggy stuff.
The proposed code works very well (also the texture shader loop thing).
The proposed code works very well (also the texture shader loop thing).
Hopefully tileable perlin noise texture shader (tx_1_0)
Generates 4 different layers (RGBA)
Generates 4 different layers (RGBA)
Code:
// las/mercury
float4 t(float3 p:POSITION):COLOR {
float v[8];
float4 w;
for (int h=0;h<4;h++){
for(int i=0;i<8;i++)
v[i]=noise(16*(h+p-float3(int3(i,i/2,i/4)%2)));
for(int j=4,k=2,l=0;j>0;j/=2,k*=2,l++)
for(int m=0;m<j*k;m+=k)
v[m]=lerp(v[m],v[m+k/2],p[l]);;
w[h]=v[0]+1;
}
return w/2;
}
(can be further optimized j*k = 8...)
I don't know if it works in GLSL since I have no experience in shader programming, but in C, you can write x & 1 instead of x % 2. That should make it a bit faster. If you used integers, you could also write x << 4 instead of x * 16.
do you think hes joking?
Code:
$TOP_SECRET_PROJECT_PATH\assembly\memory(34,12): error X3082: int or unsigned
int type required
No binary operators in HLSL tx_1_0.
Adok: I tend to know - at least sometimes - what I am doing.
Adok: for some reason when that works on shaders it's actually slower.
Code:
float x = sign(p.x*2.0) * floor(abs(p.x*2.0) + 0.5);
float z = sign(p.z*2.0) * floor(abs(p.z*2.0) + 0.5);
float r = fract(sin(dot(vec2(x,z),vec2(31.9898,78.233)))*43758.5453)*2.0;
float d = cyl(vec3(sin(p.x),p.y-r+5.0,cos(p.z)),4.0,r);
Little bit of code I've been working on. Generates a infinite city by rounding the result of a repeated object and adding a random hight to the box. Is there a better way of doing this, lots of artifacts but looks good from a distance.
Work in progress :)
I guess the random height is your main problem, you use sin/cos for domain rep... What do you need the sign call for? And given that you use sin/cos for domain rep... maybe your cells overlap and everything becomes crappy (or something like that).
What I would do for a random city is just plain domain rep with fract/mod; determine the cell in which you are, do a perlin noise lookup for the random height of the cell (or something like that) - maybe jitter the object in the cell a bit in x/z direction (stay inside the cell /!\). You have to take care that your random heights don't differ too much. You can min something like 3 layers of that together and will end up with something that might be better.
The screenshot looks very promising anyways - love that style.
What I would do for a random city is just plain domain rep with fract/mod; determine the cell in which you are, do a perlin noise lookup for the random height of the cell (or something like that) - maybe jitter the object in the cell a bit in x/z direction (stay inside the cell /!\). You have to take care that your random heights don't differ too much. You can min something like 3 layers of that together and will end up with something that might be better.
The screenshot looks very promising anyways - love that style.
Quote:
it is. check _the_ paper.
http://graphics.cs.uiuc.edu/~jch/papers/zeno.pdf
offline
could you provide the full title?
Try this:
http://bedrock.cs.uiuc.edu/~jch/papers/zeno.pdf
Original title:
http://bedrock.cs.uiuc.edu/~jch/papers/zeno.pdf
Original title:
Quote:
Sphere tracing: A geometric method for the antialiased ray tracing of implicit surfaces
John C. Hart
The Visual Computer 12 (10), Dec. 1996, pp. 527-545
@Mewler : 1920x1080 bmp images are very lame....