pouët.net

Raymarching Beginners' Thread

category: code [glöplog]
chock: whaa forgot the link, here it is
added on the 2012-05-15 11:42:27 by voxelizr voxelizr
I thought landscapes were parts of a big sphere? ;)
Otherwise think of them as half-spaces, not planes.
added on the 2012-05-15 12:23:29 by Psycho Psycho
voxelizr: you're using tiny step sizes and *massive* numbers of iterations - no wonder it's slow :D What you want is the opposite - step sizes as big as possible, small numbers of iterations.

And yes, it was the lack of signed distances causing your problem. If you set the step size to 1.0 in your original version you see the same holes in the terrain because the ray steps past the surface. I removed the abs() from the terrain distance and it works fine (1.0 is too high, but it just causes artefacts, not holes).

Forked version: http://glsl.heroku.com/e#2510.1
added on the 2012-05-15 12:40:54 by psonice psonice
Quote:
My first brute-force try was a 1200x1200 height-map and I got way less than 1fps, I think (max-dist of 3000000 doesn't help here too I guess).


Well, i was using 3 height maps at 1024x1024 (maybe POT textures will help performance btw - not sure, but check it). Frame rates were pretty reasonable, quality was good, draw distance was pretty good too. But if you're using those tiny step sizes + huge iteration counts, anything complex is going to crawl ;) Think I was using ~200 iterations btw.

Quote:
At least I was glad to see that sampling isn't that slow with small maps. By the way, how do you interpolate between height values, just linearly or with some sort of fractal magic? The normal map idea sounds really smart but doesn't linear interpolation in-between fetched normal texels give you the weirdest artefacts?


Straight linear interpolation, using 8 bit textures (and even 8 bit normal maps). I was using a 1024x1024 repeating texture to define the large-scale landscape. Obviously it looks pretty crappy, because the landscape is very low res. I then use 2 additional height maps with different textures and much smaller scales to add detail - this way you get big mountains, but when you fly in close it's still very detailed. The mip-map technique means you don't see any serious detail until you get close - otherwise you get horrible aliasing problems.

The normal mapping: It works pretty well. It's linear interpolated, yes - but so is the terrain, so that's actually correct :) It doesn't look too good up close with only one height map, but if you combine 3 then the detail masks it.
added on the 2012-05-15 12:54:20 by psonice psonice
Psycho you're onto something -- I should trace the whole planet as a fractal-noise-augmented sphere... :D actually was thinking about this more than once. Would be incredibly cool. Just wanted to get something "simpler" on the screen first.

psonice:

"you're using tiny step sizes and" -- the step-size only *starts* at 0.1 for the distances closest to the ray, it increases fast each additional iteration based on distance... will test with an initial value of 0.9 later (too bad glsl sandbox doesn't have an fps counter) but in my many experiments with this, I never seemed to get a huge speed-up but always much more artifacts or holes close-by with higher initial values. Though it is true that being close to some elevation slows down FPS, which would support your theory. Have to play with this even further.

"and *massive* numbers of iterations" -- I don't believe the 12345 iterations are ever really reached. Indeed with the desktop version I have an unlimited loop (only breaks out if marching ends "properly"). Note due to the intersection testing with the terrain-bounding-planes approx. 99% of rays that "end up in the sky" don't even enter the marching loop. When I change your 200 limit to 60000 at the sandbox version at low quality, I don't notice a (perceived) drop in performance. That said, measuring is everything... but the issue here wasn't performance but heightfield-marching. Thanks for playing with this and glad to hear your removing abs() solved the holes issue -- did you actually test this with a terrain heightmap though? Cos with the sin()/cos() "terrain" there wasn't any issue to begin with :D

Curious what exactly is the idea of combining 3 heightmaps into one? So one is for the big coarse terrain and the other two at the same resolution add details somehow?
added on the 2012-05-15 16:48:32 by voxelizr voxelizr
voxelizr: Those pyramids with holes look great. Why not keep em that way? :)
added on the 2012-05-15 17:14:00 by vibrator vibrator
voxelizr:

Quote:
the step-size only *starts* at 0.1 for the distances closest to the ray, it increases fast each additional iteration based on distance... will test with an initial value of 0.9 later (too bad glsl sandbox doesn't have an fps counter) but in my many experiments with this, I never seemed to get a huge speed-up but always much more artifacts or holes close-by with higher initial values. Though it is true that being close to some elevation slows down FPS, which would support your theory. Have to play with this even further.


Remember that you're using an extremely simple distance field here - with a complex distance field any speed issues suddenly get 10x worse real fast. It's worth getting these basic bits as fast as possible early, otherwise your scene gets complex, things slow down, and you're not sure where the slow part is any more.

With those few changes I was getting pretty good looking results with an initial ray step of 0.9 instead of 0.1. That means the ray is going 9x faster through the scene - and it still accelerates. This made the scene noticeably faster when I ran it fullscreen at decent res & 1x rendering.

Speaking of accelerating the ray - your code is quite complex for calculating that. And that complex bit of code is happening inside the marching loop - meaning it's potentially executed hundreds of times per pixel. This is an obvious place to optimise. You could probably move the bit that calculates the acceleration amount outside the loop for a good speedup, or you could even just replace it with a constant (stepsize += totalDist * 0.01 say).

Quote:
"and *massive* numbers of iterations" -- I don't believe the 12345 iterations are ever really reached. Indeed with the desktop version I have an unlimited loop (only breaks out if marching ends "properly"). Note due to the intersection testing with the terrain-bounding-planes approx. 99% of rays that "end up in the sky" don't even enter the marching loop. When I change your 200 limit to 60000 at the sandbox version at low quality, I don't notice a (perceived) drop in performance. That said, measuring is everything... but the issue here wasn't performance but heightfield-marching.


Yeah, but as I said - if you leave these bits until the end, it's harder to optimise. When it's nice and simple like this it's easier. Also, unlimited iterations is a bad idea. When it works OK, it's fine. When you make a small mistake somewhere though it can get very painful (I've had quite a few reboots because of that!). Realistically, you never want 12345 iterations anyway unless you're going for perfect rendering quality. Less iterations means more time per iteration - which means you can add more complex distance function code and make prettier pictures :)

Quote:
Thanks for playing with this and glad to hear your removing abs() solved the holes issue -- did you actually test this with a terrain heightmap though? Cos with the sin()/cos() "terrain" there wasn't any issue to begin with :D


Try changing the step size on your original one to 1.0 and the sin/cos waves have holes too. It's a flaw in your algorithm - if the step size is too big, the ray can step inside the surface. Without the abs(), it returns a negative value, and the marching part knows it is inside the surface and steps back. With the abs(), it just knows it's not close to the surface so it shoots out the other side, causing a hole. The same thing will happen with a height map, but it will happen with smaller step sizes because the distance function is inaccurate with a height map.

Quote:
Curious what exactly is the idea of combining 3 heightmaps into one? So one is for the big coarse terrain and the other two at the same resolution add details somehow?


One is for big coarse terrain, the next is for smaller detail, the 3rd is for fine detail. So if your standard height map function is like this:

Code:terrain(vec3 position){ return position.y - texture2D(heightMap, position.xz).r; }


with 3 height maps it's like this:

Code:terrain(vec3 position){ return position.y - ( (texture2D(heightMap0, position.xz).r) + (texture2D(heightMap1, position.xz * 4.).r * 0.25) + (texture2D(heightMap2, position.xz * 16.).r * 0.01625) ); }


Maybe I have some of those numbers the wrong way round, but the idea is simply to have one large height map, then a smaller (1/4 size on xyz) detail map, then another 1/4 the size again. I'll try to find some screenshots of it.
added on the 2012-05-16 00:13:15 by psonice psonice
Thanks a lot psonice -- thanks to your help I'm actually getting some pyramids now -- still need a decent-sized texture, Psycho and kusma were correct too with the precision issues. And that kinda sucks if you want to be able to "zoom in and out deep and far at will". But that's another issue... however, making the distance function signed was indeed it.

Now... a 512x512 runtime-generated R16F heightfield texture:

BB Image

BB Image

BB Image

Looks like I over-fine-tuned all my stepping and normals too much for the sin()/cos() "terrain" use-case earlier on. Now with anything else except that sin/cos terrain nothing looks as it should. Why do I still get those weird artifacts... the reflections and transitions are so extremely smooth for my sin/cos "terrain" and yet weird pixels all over the place for "simple linear pyramids" -- especially close-by. But reflections look oddly-pixelated instead of smoothly-linear no matter what distance they're viewed from. fuuuuu....

Btw psonice just found your youtube channel while looking for raymarching/raytracing vids -- neat stuff indeed!

And then also on utube BOOM I found THIS... how the HECK does he do it?

I mean "Rendered at 1920x1080@60fps with NVIDIA GeForce GTS 250" ... for real? Probably this isn't fractal / heightfield raymarching. But what is he raytracing I wonder... triangle meshes?

Anyway, cheers for all the helpful input guys!
added on the 2012-05-16 06:12:28 by voxelizr voxelizr
OK with tweaking tweaking and more tweaking I'm making slow progress now but I'll spare you further screens... :D at least I got kicked back into the groove now, thx again! Stunning terrains, here I come in 1... 2... 3... years... o_O
added on the 2012-05-16 07:34:14 by voxelizr voxelizr
Actually seeing linear filtering and its precision limits in action very close-by is curious: http://dl.dropbox.com/u/2166329/raymarch09.png -- at least in case you actually *want* pyramids, you gets the staircasing for free. Note the big staircasing (actual texels) and the smaller (limited-precision interpolation). But yeah, enough of pyramids for real now.

psonice "though it can get very painful (I've had quite a few reboots because of that" -- yeah I had that too. No reboots though, just have to wait 5 minutes until Linux lets me kill the process. Come to think of it, rebooting would be faster.

Btw. an initial step factor of 0.5 works fine if I render my pyramids terrain with a certain slope but for a higher/narrower one then again I need to push it down to 0.1. That's why I had it at 0.1 to begin with -- the curves looked fine even with 0.7 at the slope I demoed it, but earlier I tried to find a "safe" value even for crazy outlier slopes.
added on the 2012-05-16 10:06:38 by voxelizr voxelizr
shader source for suhinat
would you have any suggestions for improvement? :)
added on the 2012-05-22 01:05:22 by nystep nystep
Just don't go for fractals - Fractals are just boring. Do you really need axis angle rotations? I think you can get away with some euler rotations while using less space. And you have quite a lot of branching instructions - I don't think that's so much of an problem nowadays but I still tend to code shaders as branchless as possible.
added on the 2012-05-22 09:40:33 by las las
Clouds.

Credits to las

BB Image

http://glsl.heroku.com/e#2809.11
added on the 2012-06-17 19:10:12 by tz tz
nice - the storm clouds variant looks really cool.
added on the 2012-06-18 02:13:19 by las las
uhm. are those clouds seamless? they look kinda same.
added on the 2012-06-18 02:29:24 by rudi rudi
Anyone need some high quality 4096x4096 terrain maps? I've uploaded a few in I made case you need them for testing. Also, raymarching high res height maps + procedural detail would blow everything else out of the water.

https://dl.dropbox.com/u/17070747/HM.zip
added on the 2012-06-18 05:29:51 by Mewler Mewler
There's a lot of banding there mewler... you're gonna get unwanted terraces.
I'm generating my heightmaps for my next 64k procedurally with floats, they look smoother when I export them: BB Image
added on the 2012-06-18 09:20:16 by xTr1m xTr1m
Thinking some more about raymarching these height maps: in flat areas it's safe to step large distances, but in areas with cliff-type structures you need a short step. It makes some sense then to store some info about the surrounding pixels with the height map.

If you're pre-computing the normals as a normal map (like I do), you can easily get a value for the 'steepness' of the current pixel and write that out. Then blur it, invert it (1. - v) and store it with the height map. This gives you a quick + dirty step 'safe step size' when you're doing the marching. Downside: you're now looking at 5 values to store, height, step size and normal, so you lose the option of storing everything in the one texture. Maybe it's possible to store the normal as just xz?

Also, found an early screenshot of my height field marcher:

BB Image

It got improved a whole lot after that, but it's currently broken mid-improvement, but i've been too busy with other stuff to touch it in months :( Looks pretty standard, but with multiple levels of detail it's possible to zoom right in and it still looks good.
added on the 2012-06-18 13:01:16 by psonice psonice
@xTr1m Those are nice rivers-like pattern you got there... May I ask what is your magic sauce ?
I wanted to launch myself in developping such a raymarching animation but I felt so bad that I must stop the try. Lately, I was studying porn, and actually I think computer is a trap like porn. So I've wrote a book about brain. And my life is greater. It could be a good idea to make tutorials like Inigo Quilez with all sort of raymarching to develop new ideas like giving source code of 4k in compos could be a good share of intelligence.
added on the 2012-06-18 14:00:49 by Bartoshe Bartoshe
marmakoide: to keep it short: start with a seed heightfield that defines the general shape of the terrain (eg 8x8), then grow it using diamond square algorithm, and during (some of) those iterations apply some naive fluvial erosion (for every pixel: 1) take a bit of height from the current pixel, 2) visit the steepest neighbour pixel, goto 1) unless there's no steeper pixel, finally 3) deposit a bit of height on the current pixel). Eroding during different heightmap resolutions generates all that low- and highfrequency details.
For completeness, but doesn't really apply to raymarching, here's a 3D mesh from my heightmap:
BB Image
added on the 2012-06-18 17:20:40 by xTr1m xTr1m
@xTr1m I see, it's a simulation of actual erosion. I've been tinkering to *directly* generates that kind of pattern without an explicit erosion simulation step. Something like diffusion limited aggregation patterns (http://en.wikipedia.org/wiki/Diffusion-limited_aggregation), but just with some functions composition. I'm not sure it's possible, actually :p
if you manage to do that, you win the Siggraph :)
added on the 2012-06-18 19:12:46 by iq iq
BB Image
hmmmm - some fbm + atan2 could do the job?
added on the 2012-06-18 21:08:17 by las las
yes, but only for star-shaped peaks, if you want bifurcations / treelike peaks like in your picture above, this won't work.
added on the 2012-06-18 22:19:22 by xTr1m xTr1m

login