# DirectX 光线跟踪中自相交伪影的求解

## 命中点

precise float3 edge1 = v1 - v0;
precise float3 edge2 = v2 - v0;

// interpolate triangle using barycentrics
// add in base vertex last to reduce object-space error
precise float3 objPosition = v0 + mad(barys.x, edge1, mul(barys.y, edge2));
float3 objNormal = cross(edge1, edge2);


const float3x4 o2w = ObjectToWorld3x4();

// transform object-space position
// add in translation last to reduce world-space error
precise float3 wldPosition;
wldPosition.x = o2w._m03 +
mul(o2w._m02, objPosition.z )));
wldPosition.y = o2w._m13 +
mul(o2w._m12, objPosition.z )));
wldPosition.z = o2w._m23 +
mul(o2w._m22, objPosition.z )));


const float3x4 w2o = WorldToObject3x4();

// transform normal to world-space using
// inverse transpose matrix
float3 wldNormal = mul(transpose((float3x3)w2o), objNormal);

// normalize world-space normal
const float wldScale = rsqrt(dot(wldNormal, wldNormal));
wldNormal = mul(wldScale, wldNormal);

// flip towards incoming ray
if(dot(WorldRayDirection(), wldNormal) > 0)
wldNormal = -wldNormal;


## 错误界限

const float c0 = 5.9604644775390625E-8f;
const float c1 = 1.788139769587360206060111522674560546875E-7f;

// compute twice the maximum extent of the triangle
const float3 extent3 = abs(edge1) + abs(edge2) +
abs(abs(edge1) - abs(edge2));
const float extent = max(max(extent3.x, extent3.y), extent3.z);

// bound object-space error due to reconstruction and intersection
float3 objErr = mad(c0, abs(v0), mul(c1, extent));


// bound world-space error due to object-to-world transform
const float c2 = 1.19209317972490680404007434844970703125E-7f;
float3 wldErr = mad(c1, mul(abs((float3x3)o2w), abs(objPosition)),
mul(c2, abs(transpose(o2w[3]))));


// bound object-space error due to world-to-object transform
objErr = mad(c2, mul(abs(w2o), float4(abs(wldPosition), 1)), objErr);


## 抵消

${\delta = \frac{\Delta \cdot {abs}\left(n\right)}{n \cdot n}}$

// compute world-space self-intersection avoidance offset
float objOffset = dot(objErr, abs(objNormal));
float wldOffset = dot(wldErr, abs(wldNormal));



${\delta_o M n_o \cdot M^{-T} n_o = \delta_o \left( M n_o \right)^T M^{-T} n_o = \delta_o n_o \cdot M^T M^{-T} n_o = \delta_o n_o \cdot n_o = \Delta \cdot {abs}\left(n\right)}$

// offset along the normal on either side.
precise float3 wldFront = mad( wldOffset, wldNormal, wldPosition);
precise float3 wldBack  = mad(-wldOffset, wldNormal, wldPosition);


## 连接射线

// connection ray direction
precise float3 wldDir = wldEndPosition - wldOrigin;

// bound endpoint object-space error due to object-to-world transform
float4 absOriginDir = (float4)(abs(wldOrigin) + abs(wldDir), 1);
objEndErr = mad(c2, mul(abs(w2oEnd), absOriginDir), objEndErr);


// offset ray direction along the endpoint normal towards the ray origin
wldDir = mad(wldEndOffset, wldEndNormal, wldDir) ;

// shorten the ray tmax by 1 ulp
const float tmax = 0.99999994039f;