Here is an example of that. is a regular flat static mesh and the box with subtracted cylinder are entirely generated by the distance field code. Normals are also generated (and packed into alpha as float which is absurd but custom node only outputs single float4 for now).
The grid texture is by using the standard world aligned texture material function using the results of normal and worldposition from the raytracer.
All the h,b vars define the cylinder and box. “quickend” is just a hacky way of tracing into difficult corners with less steps but causes artifacts. The TempAA thing is purely experimental as a way to “fuzz” some of the step artifacts since I wasn’t doing thing correctly.
The really painful thing about is that to generate the normal, the code has to be repeated 3 times so the function is nasty since you have to update it in all places to change it.
Super experimental distance field raytracer function:
float3 p=View.ViewOrigin.xyz;
float3 CamVec = normalize(Parameters.WorldPosition-View.ViewOrigin.xyz);
float4 HitSpot=0;
float3 normal=0;
int HitMask = 0;
float3 offsets[3];
offsets[0]=float3(1,0,0)*noffset;
offsets[1]=float3(0,1,0)*noffset;
offsets[2]=float3(0,0,1)*noffset;
int i=0;
while(i<Steps)
{
//sphere distance
float3 di = abs(p) - b;
float shape1= min(max(di.x,max(di.y,di.z)),0.0) + length(max(di,0.0));
//float shape1=length(max(abs(p)-b,0));
float2 d = abs(float2(length(p.xz-ShapeOffset.xz),p.y-ShapeOffset.y))-h;
float shape2= min(max(d.x,d.y),0)+length(max(d,0));
float CurDist= max(shape1,-shape2);
//float CurDist = shape1;
//HitMask=(CurDist <= TempAA ? 0:1);
if(CurDist <= TempAA)
{
float hitmiss = bias*(CurDist);
float3 o = p+(CamVec*hitmiss);
HitSpot.xyz=o;
//x
di = abs(o+offsets[0]) - b;
shape1= min(max(di.x,max(di.y,di.z)),0.0) + length(max(di,0.0));
//shape1=length(max(abs(o+offsets[0])-b,0));
d = abs(float2(length(o.xz-ShapeOffset.xz+offsets[0].xz),o.y-ShapeOffset.y+offsets[0].y))-h;
shape2= min(max(d.x,d.y),0)+length(max(d,0));
normal.x = CurDist*.1-max(shape1,-shape2);
//y
di = abs(o+offsets[1]) - b;
shape1= min(max(di.x,max(di.y,di.z)),0.0) + length(max(di,0.0));
//shape1=length(max(abs(o+offsets[1])-b,0));
d = abs(float2(length(o.xz-ShapeOffset.xz+offsets[1].xz),o.y-ShapeOffset.y+offsets[1].y))-h;
shape2= min(max(d.x,d.y),0)+length(max(d,0));
normal.y = CurDist*0.1-max(shape1,-shape2);
//z
di = abs(o+offsets[2]) - b;
shape1= min(max(di.x,max(di.y,di.z)),0.0) + length(max(di,0.0));
//shape1=length(max(abs(o+offsets[2])-b,0));
d = abs(float2(length(o.xz-ShapeOffset.xz+offsets[2].xz),o.y-ShapeOffset.y+offsets[2].y))-h;
shape2= min(max(d.x,d.y),0)+length(max(d,0));
normal.z = CurDist*0.1-max(shape1,-shape2);
break;
}
p+=CamVec*(max(MinStepSize,CurDist));
MinStepSize+=saturate(i-8)*QuickEnd;
i++;
}
normal=-normalize(normal);
//normal=clamp(normal, -0.999,0.999);//multiply is cheaper
float normalpack=sign(normal.z+0.000068);
normalpack*=floor((1+normal.x)*0.5*1000)+(0.99+normal.y)*0.499;
HitSpot.w = normalpack;
//HitSpot.xyz=normal;
return HitSpot;
It is probably better to wait for the other solution that lets you input the distance field function externally, but is something to mess with for those curious.
I also made another one that raytraces the global distance fields of the world (thanks to Daniels awesome nodes for returning the global value).
float3 p=View.ViewOrigin.xyz;
float3 CamVec = normalize(Parameters.WorldPosition-View.ViewOrigin.xyz);
float4 HitSpot=0;
int i=0;
while(i<Steps)
{
//sphere distance
float CurDist= GetDistanceToNearestSurfaceGlobal(p);
if(CurDist <= TempAA)
{
HitSpot.xyz=p;
normal= GetDistanceFieldGradientGlobal(p);
break;
}
p+=CamVec*(max(MinStepSize,CurDist));
MinStepSize+=saturate(i-8)*QuickEnd;
i++;
}
normal=normalize(normal);
float normalpack=sign(normal.z+0.000068);
normalpack*=floor((1+normal.x)*0.5*1000)+(0.99+normal.y)*0.499;
HitSpot.w = normalpack;
return HitSpot;
one is much easier to implement but of course the result is very blobby because it is the low res global distance fields.
of course if I had bothered to take an image of a dynamic actor it would appear high quality through “DF x-ray” material, since dynamic actors use their full own local distance field and not the global one.