cvr-props/Assets/raymarched/lib/libgarbage_operations.cginc

161 lines
3.5 KiB
HLSL

// soft min of a and b with smoothing factor k
float smin(float a, float b, float k) {
float h = max(k - abs(a-b), 0) / k;
return min(a, b) - h * h * h * k * (1 / 6.0);
}
// soft max of a and b with smoothing factor k
float smax(float a, float b, float k) {
float h = max(k - abs(a - b), 0) / k;
return max(a, b) + h * h * h * k * (1 / 6.0);
}
Material mixMat(Material a, Material b, float fac) {
Material m;
fac = clamp(fac * 1.1 - 0.05, 0, 1); // TODO make this configurable, also possibly use smoothstep
m.col = lerp(a.col, b.col, fac);
m.gloss = lerp(a.gloss, b.gloss, fac);
return m;
}
Material mixMat(SurfacePoint a, SurfacePoint b) {
float fac = clamp(a.dist/(a.dist + b.dist), 0, 1);
return mixMat(a.mat, b.mat, fac);
}
Material nearestMat(SurfacePoint a, SurfacePoint b) {
if (a.dist < b.dist) {
return a.mat;
} else {
return b.mat;
}
}
// --------------------------------
// base sdf operations
// --------------------------------
float qUnion(float a, float b) {
return min(a, b);
}
float qUnion(float a, float b, float smooth) {
return smin(a, b, smooth);
}
SurfacePoint qUnion(SurfacePoint a, SurfacePoint b) {
SurfacePoint o;
o.dist = min(a.dist, b.dist);
o.mat = nearestMat(a, b);
return o;
}
SurfacePoint qUnion(SurfacePoint a, SurfacePoint b, float smooth) {
SurfacePoint o;
o.dist = smin(a.dist, b.dist, smooth);
o.mat = mixMat(a, b);
return o;
}
float qSub(float a, float b) {
return max(a, -b);
}
float qSub(float a, float b, float smooth) {
return smax(a, -b, smooth);
}
SurfacePoint qSub(SurfacePoint a, SurfacePoint b) {
SurfacePoint o;
o.dist = max(a.dist, -b.dist);
o.mat = a.mat;
return o;
}
SurfacePoint qSub(SurfacePoint a, SurfacePoint b, float smooth) {
SurfacePoint o;
o.dist = smax(a.dist, -b.dist, smooth);
o.mat = a.mat;
return o;
}
float qIntersect(float a, float b) {
return max(a, b);
}
float qIntersect(float a, float b, float smooth) {
return smax(a, b, smooth);
}
SurfacePoint qIntersect(SurfacePoint a, SurfacePoint b) {
SurfacePoint o;
o.dist = max(a.dist, b.dist);
o.mat = nearestMat(a, b);
return o;
}
SurfacePoint qIntersect(SurfacePoint a, SurfacePoint b, float smooth) {
SurfacePoint o;
o.dist = smax(a.dist, b.dist, smooth);
o.mat = mixMat(a, b);
return o;
}
// --------------------------------
// single sdf operations
// --------------------------------
float qRound(float a, float radius) {
return a - radius;
}
SurfacePoint qRound(SurfacePoint a, float radius) {
a.dist -= radius;
return a;
}
// --------------------------------
// spatial warping
// --------------------------------
float3 rotX(float3 p, float a) {
return mul(float3x3(1, 0, 0, 0, cos(a), -sin(a), 0, sin(a), cos(a)), p);
}
float3 rotY(float3 p, float a) {
return mul(float3x3(cos(a), 0, sin(a), 0, 1, 0, -sin(a), 0, cos(a)), p);
}
float3 rotZ(float3 p, float a) {
return mul(float3x3(cos(a), -sin(a), 0, sin(a), cos(a), 0, 0, 0, 1), p);
}
// repeats space every r units, centered on the origin
float3 repXYZ(float3 p, float3 r) {
float3 o = p;
o = fmod(abs(p + r/2.0), r) - r/2.0;
o *= sign(o);
return o;
}
// repeats space every r units, centered on the origin, no sign
float3 repXYZUnsigned(float3 p, float3 r) {
return fmod(abs(p + r / 2.0), r) - r / 2.0;
}
// repeats space
float3 repXZ(float3 p, float x, float z) {
float3 o = p;
o.x = fmod(abs(p.x) + x / 2.0, x) - x / 2.0;
o.x *= sign(p.x);
o.z = fmod(abs(p.z) + z / 2.0, z) - z / 2.0;
o.z *= sign(p.z);
return o;
}
float3 repX(float3 p, float x) {
float3 o = p;
o.x = fmod(abs(p.x) + x / 2.0, x) - x / 2.0;
o.x *= sign(p.x);
return o;
}