# pouët.net

## Problem with RayMarching using DistanceFunctions when applying Twist-Distortion.

category: general [glöplog]
Hi all,

I have a very fundamental problem with domain-distortion as explained in rwwtt.pdf: With a (rectangular) column, everything runs just fine, but as soon as I apply the suggested twist-distortion to my column, shit starts to hit the fan.
The problem seems to be that the twist-domain-distortion will introduce errors in the way, thats the minimum distance is approximated too large in some cases, thus stepping too far ending up inside the geometry or missing it completely.
I'm not a math-expert, but my intuition tells me that this problem must arrise from that twist-distortion because the suggested distance function evaluates the twist-amount only for the current y-pos, neglecting the fact that the ray's y-direction may alter the y-pos along the path (and thatfore the twist) and the real intersection point may actually be closer if the column twists towards the ray.
do i get something wrong here or does that problem really exist ? i'm wondering because all the resources i've found dont mention any problem with that. and if it exists is there a cure for it except subdividing step-distances like a crazy bitch ? ;)
somebody please help me out on that... i'm kinda stuck here :(

many thanks :)
heres my code for the twisted box:

Code:``` float evaluateDistanceToBox(const Vector &vecPos, const Vector &vecBoxSize) { Vector vecDistance = vecMax(vecSub(Vector(fabsf(vecPos.x), fabsf(vecPos.y), fabsf(vecPos.z)), vecBoxSize), 0.0f); return vecLength(vecDistance); } float evaluateDistance(const Vector &vecPos) { float fAngle = (vecPos.y + 2.0f) * (1.0f / 4.0f) * PI; // twist by 180deg float fSin = getSin(fAngle); float fCos = getCos(fAngle); Vector vecSample = Vector(vecPos.x * fCos + vecPos.z * fSin, vecPos.y, vecPos.z * fCos - vecPos.x * fSin); return evaluateDistanceToBox(vecSample, Vector(1.0f, 2.0f, 1.0f)); } bool castRay(const Vector &vecPos, const Vector &vecDir) { const float fHitEpsilon = 0.001f; const float fFarPlane = 10.0f; float fDistance = evaluateDistance(vecOrigin); while (fDistance < fFarPlane) { Vector vecPos = vecAdd(vecOrigin, vecScale(vecDir, fDistance)); float fDistanceToSurface = evaluateDistance(vecPos); if (fDistanceToSurface < fHitEpsilon) { // we have a hit return true; } fDistance += fDistanceToSurface; } return false; // no hit } ```
Column density function: column(point) = 0
Distortion function: twist(point)
Distorted column: (column o twist)(point) = column(twist(point))
Distance operator: dist(func)
Distance to column: (dist(column))(point)
Distance to twisted column: dist(column o twist)(point) != (dist(column))(twist(point))

This is your problem. hth hand :)

Solution is to use a smaller step size. If you know the maximum gradient of your distortion function you can divide the stepsize by that.
and here is what i get: colors encode normals. rgb=xyz*0.5+0.5
positive xyz: right, top, depth, respectively

i get the grey areas (zero-normals) on heavy twisting, and they result from being inside the cube (and the cube-distance-function will just return 0 everywhere inside).
also notice the banding. i think also from being slightly inside (with some sample points for normal calc) :(
for some reason i still get those zero-normal/inside-hits when replacing
Code:`fDistance += fDistanceToSurface;`

by
Code:`fDistance += fDistanceToSurface * 0.1f;`

even tho it gets really slow it still will not work correctly for some reason.
float evaluateDistanceToBox(const Vector &vecPos, const Vector &vecBoxSize)
{
Vector vecDistance = vecMax(vecSub(Vector(fabsf(vecPos.x), fabsf(vecPos.y), fabsf(vecPos.z)), vecBoxSize), 0.0f);
return vecLength(vecDistance);
}

doesn't that function give you a distance to boundary, rather than a signed distance for the box? you need a signed distance so you can step back along the ray when you go inside the box.
xortdsc: it's also unlikely that the 6 point gradient sampling will give correct results for faces facing away from the screen unless you use signed distance functions... smash has a point btw.
216: i dont really get what the "o" operator is supposed to be. =/
and do you mean "distance function" in "Column density function: column(point) = 0" ?
and subdivision by 1/10th didnt solve the issue. only the banding got better, but not the quite large zero-normals.
okay, i'll try and fix the distance function to work correctly with inside-positions and see what happens. i've used the one from the tutorial for now assume it would work.
Quote:
i dont really get what the "o" operator is supposed to be. =/

http://en.wikipedia.org/wiki/Function_composition
ah, much better now. thank you very much :)
I only read the initial post, but I think you're looking for the Lipschitz constant of your distortion function.
kusma: ah okay, thats a good hint. then i use this constant as a factor of my distance-step ?
some further discussion on step size adjustments based on gradients, and what we later discovered was called "Lipschitz constant" (as just pointed out by Kusma) here http://www.pouet.net/topic.php?which=5604. Discussion starts at page 2, where Kusma himself asked your same question.
iq: a little website dedicated to this issue might come handy? if only we had a case studies section on pouet. but considering the richness in trollbase here, maybe displayhack.org will be a better bet.

gloom: any news on displayhack?
thanks guys. now i've got something to work with. i'm having some trouble following some of the explanations, but i'll try to dig into it...

here's the improved version, btw. Still not perfect, tho... cheers
Cool!
CUDA... omg that's a pain in the ass :) Thumbs up for that.
yeah, CUDA would be great if the compiler wouldn't screw up so badly sometimes. often i have to work around the compiler, so i got to think if it would be better to write the low-level shader-code directly (to not end up with implicit mem-reads were they could be avoided and such. i'm not really experienced with shaders, tho. Esp the recursions worry me... =/
has anyone experience with this (potential speed gains etc) and can tell me if it is worth the effort or should/can i stay with CUDA ?
Quote:
gloom: any news on displayhack?

Yes, it's coming along nicely. No releasedate, but it's coming.
Oh, and the primary programmer on the site is also arranging Function.. so... that'll have to finish first. :)
xortdsc, I porter Slisesix to CUDA, GLSL and HLSL. The three of them gave exactly the same framerate. That was more than one year ago tho.
gloom: regarding displayhack.org: good to hear that it's not been forgotten. take your time..
cool, good to know i dont need to switch api :)
could someone give me some reference-framerates for some demos or other simple scenes which use that rendering-method ? i have vista64 so i cannot run all those 4k-intros (only seem them on youtube).
with the scene posted above without the reflection i get around 50fps on a geforce285. that sounds rather slow compared to what i've read in another thread. esp if i enable shadows for the 2 lights the frame-rate drops to something like 10fps :(
casting shadow-rays seems to be especially slow since all the rays start very close to the surface. is there a cool trick to speed that up someone would be willing to share ? or maybe just a hint ? :)

cheers