Raymarching Beginners' Thread

category: code [glöplog]
but oh so right.
added on the 2012-03-17 10:54:24 by ferris ferris

"he was raymarching me"

sounds like he came a bit too close in the end ;)
it's all about defining your epsilons, man.
added on the 2012-03-17 18:37:47 by iq iq
it's only gay for epsilon <= 0.
added on the 2012-03-17 18:47:07 by las las
it's only gay for epsilon <= 0

and both objects need to be of same type of course.

is that gaymarching then?
added on the 2012-03-17 21:56:18 by gopher gopher
mad: about gaymarching some fmodded geometry:
just put an offset, so no negative numbers exist in the end, in your distance-function that is:
p=fmod(p+1000.0, 2.0)-1.0;
the +1000.0 being the offset here ofcoz.
It's all about gaymarching, forward and back until you reach the sweet spot.
added on the 2012-03-18 08:25:48 by Voltage Voltage
i see, you are deep into the materia already :p
deep is the word, indeed
added on the 2012-03-19 08:30:06 by iq iq
any ideas how to set up a simple raymarcher in dx11? ive just compiled my first pixel and vertex-shader program!
added on the 2012-03-20 18:33:38 by rudi rudi
then you are done! copy & paste any of the examples in Shadertoy
added on the 2012-03-21 00:37:27 by iq iq
added on the 2012-03-21 12:06:11 by rudi rudi
Just got my new gpu! Raymarching time! I've been messing with smash's ao from GDC. This seem ok?

Code: float aot = 0.0; [fastopt] for( float i = 1.; i < 16.0; ++i ) { float3 mcn = float3( 0.0, 1.0, 0.0 ); float2 mc = rand3d_2d( p * i * time ) * 4.0; mcn.x += mc.x; mcn.z += mc.y; aot += softshadow( p, mcn, 512 ) / 16.0f; // IQ's softshadow code works fine here :3 }

150 fps 760p on my Radeon 7850 ( Basically the equivalent of the Nvidia 570 ).
added on the 2012-04-06 09:26:19 by Mewler Mewler
Ok sorry, updated a bit:
[fastopt] for( float i = 1.; i < 16.0; ++i )
float3 mcn = normal;
mcn.xz += rand3d_2d( p * i * time ) * 4.0;

aot += softshadow( p, mcn, 512 ) / 16.0f;
added on the 2012-04-06 09:33:34 by Mewler Mewler
This call to softshadow() at every of the 16 iterations looks extremely inefficient and slow!!!... :O

Try this rather:

Code: uniform float aoIntensity; // {"label":"AO intensity", "min":0, "max":1, "step":0.01, "default":0.15, "group":"Shading", "group_label":"Ambient occlusion"} uniform float aoSpread; // {"label":"AO spread", "min":0, "max":20, "step":0.01, "default":9, "group":"Shading"} // Ambient occlusion approximation. // Based upon boxplorer's implementation which is derived from: // http://www.iquilezles.org/www/material/nvscene2008/rwwtt.pdf float ambientOcclusion(vec3 p, vec3 n, float eps) { float o = 1.0; // Start at full output colour intensity eps *= aoSpread; // Spread diffuses the effect float k = aoIntensity / eps; // Set intensity factor float d = 2.0 * eps; // Start ray a little off the surface for (int i = 0; i < aoIterations; ++i) { o -= (d - dE(p + n * d).x) * k; d += eps; k *= 0.5; // AO contribution drops as we move further from the surface } return clamp(o, 0.0, 1.0); }

Here I get good results from 6 to 8 iterations, in the direction of the normal.

And as an epsilon I'd advise the "radius" of the cone at your intersection point, if you use cone-marching. If you don't, you do it wrong. ;)
added on the 2012-04-06 11:58:54 by nystep nystep
I was using that method before, it works fine for a lot of scenes. My implementation may be quite slow, but its also more accurate, though also more noisy. Plus, it works better if the samples are accumulated over time like in smashes talk http://directtovideo.wordpress.com/2012/03/15/get-my-slides-from-gdc2012/#commen ts

BB Image - Your AO

BB Image - Mine at 512 iterations

Still, both are better than SSAO!
added on the 2012-04-06 12:32:27 by Mewler Mewler
kk i see :) i'm so shit myself i thought you didn't know iq's method :)
but it's because i'm a miserable individual, it's my fault. i apoligize.
added on the 2012-04-06 12:40:29 by nystep nystep

No its fine, its nice to talk and bounce idea's around. :3

Oh and with IQs method you can sometimes speed things up a tiny bit by adding this to the beginning:

Code:float potential = distance( p + n ); if( potential > 0.9 ) return 1.0;
added on the 2012-04-06 12:50:32 by Mewler Mewler
can I play, too?

I totally cheat using pre-rendered height and texture maps.

It's been a while since i've so much as lurked on pouet, but I always find myself stumbling on threads like this when I'm researching relatively obscure graphics techniques.
added on the 2012-04-11 08:52:05 by louman louman
Oh, for those who want a screenshot: BB Image

This is entirely javascript/canvas. No webGL or anything like that... which explains why it's so damn slow. ;)
added on the 2012-04-11 08:58:48 by louman louman
Louman: that's fantastic - really takes me back to the old times of voxel rendering :)
added on the 2012-04-11 12:33:52 by psonice psonice
reminds me comanche
@louman Very nice, but I guess the texture helps a lot here. Nothing that some procedural tinkering can't replace ^^ I noticed that things slow down a lot when going on the borders of the map. You might compute a bounding box of the height map and compute the distance (point of view, to the bounding box) to bound the maximum distance for the ray-marching.
I've recently switched over to DX11 and I'm having trouble with getting a uv's working properly for a fullscreen quad. Works fine until you change the size of the rendertarget, then it gets weird. Also tried the code from here: http://www.pouet.net/topic.php?which=8244&page=1 but still no luck.

Code: SimpleVertexCombined* Verts = new SimpleVertexCombined[4]; Verts[0].Pos = D3DXVECTOR3( -1.0f, -1.0f, 0.0f ); Verts[0].UV = D3DXVECTOR2( 0.0f, 1.0f ); Verts[1].Pos = D3DXVECTOR3( -1.0f, 1.0f, 0.0f ); Verts[1].UV = D3DXVECTOR2( 0.0f, 0.0f ); Verts[2].Pos = D3DXVECTOR3( 1.0f, -1.0f, 0.0f ); Verts[2].UV = D3DXVECTOR2( 1.0f, 1.0f ); Verts[3].Pos = D3DXVECTOR3( 1.0f, 1.0f, 0.0f ); Verts[3].UV = D3DXVECTOR2( 1.0f, 0.0f ); D3D11_SUBRESOURCE_DATA vertexData, indexData; D3D11_BUFFER_DESC vertexBufferDesc, indexBufferDesc; vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT; vertexBufferDesc.ByteWidth = sizeof( SimpleVertexCombined ) * 4; vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; vertexBufferDesc.CPUAccessFlags = 0; vertexBufferDesc.MiscFlags = 0; vertexData.pSysMem = Verts; vertexData.SysMemPitch = 0; vertexData.SysMemSlicePitch = 0; device->CreateBuffer( &vertexBufferDesc, &vertexData, &VertBuffer ); indexBufferDesc.Usage = D3D11_USAGE_DEFAULT; indexBufferDesc.ByteWidth = sizeof( WORD ) * 6; indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; indexBufferDesc.CPUAccessFlags = 0; indexBufferDesc.MiscFlags = 0; indexData.pSysMem = Indices; indexData.SysMemPitch = 0; indexData.SysMemSlicePitch = 0; device->CreateBuffer( &indexBufferDesc, &indexData, &IndBuffer ); UINT stride = sizeof( SimpleVertexCombined ); UINT offset = 0; context->IASetVertexBuffers( 0, 1, &VertBuffer, &stride, &offset ); context->IASetIndexBuffer( IndBuffer, DXGI_FORMAT_R16_UINT, 0 ); context->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
added on the 2012-04-17 07:08:45 by Mewler Mewler
using compute shaders instead is much easier/smaller for fullscreen (but not quite as efficient if you have a high fillrate, as you cant utilize the RBEs).
added on the 2012-04-17 11:07:34 by Psycho Psycho