170 lines
4.5 KiB
HLSL
170 lines
4.5 KiB
HLSL
|
#ifndef RAY_MARCH_LIB_INCLUDED
|
||
|
#define RAY_MARCH_LIB_INCLUDED
|
||
|
/*
|
||
|
define IS_SECONDARY_SHAPE to only render the second shape
|
||
|
*/
|
||
|
|
||
|
#include "UnityCG.cginc"
|
||
|
|
||
|
struct appdata
|
||
|
{
|
||
|
float4 vertex : POSITION;
|
||
|
};
|
||
|
|
||
|
struct v2f
|
||
|
{
|
||
|
float4 vertex : SV_POSITION;
|
||
|
float3 ro : TEXCOORD1;
|
||
|
float3 hitPos : TEXCOORD2;
|
||
|
};
|
||
|
|
||
|
struct fragOut
|
||
|
{
|
||
|
fixed4 col : SV_Target;
|
||
|
float depth : SV_Depth;
|
||
|
};
|
||
|
|
||
|
int _MaxSteps;
|
||
|
float _MaxDist;
|
||
|
float _SurfDist;
|
||
|
|
||
|
v2f vert (appdata v) {
|
||
|
v2f o;
|
||
|
o.vertex = UnityObjectToClipPos(v.vertex);
|
||
|
//object space
|
||
|
o.ro = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos, 1));
|
||
|
o.hitPos = v.vertex;
|
||
|
//world space
|
||
|
//o.ro = _WorldSpaceCameraPos;
|
||
|
//o.hitPos = mul(unity_ObjectToWorld, v.vertex);
|
||
|
return o;
|
||
|
}
|
||
|
|
||
|
float smin(float a, float b, float k) {
|
||
|
return min(a, b) - pow(max(k - abs(a-b), 0), 3)/(6*k*k);
|
||
|
}
|
||
|
|
||
|
float sdSphere(float3 p, float3 o, float r) {
|
||
|
return length(p - o) - r;
|
||
|
}
|
||
|
|
||
|
float sdBox(float3 p, float3 dim) {
|
||
|
return length(float3(
|
||
|
max(abs(p.x) - dim.x/2.0, 0),
|
||
|
max(abs(p.y) - dim.y/2.0, 0),
|
||
|
max(abs(p.z) - dim.z/2.0, 0)));
|
||
|
}
|
||
|
|
||
|
float sdLine(float3 p, float3 a, float3 b, float r) {
|
||
|
float3 pa = p - a;
|
||
|
float3 ba = b - a;
|
||
|
float h = clamp(dot(pa, ba) / dot(ba, ba), 0, 1);
|
||
|
return length(pa - ba * h) - r;
|
||
|
}
|
||
|
|
||
|
float sdCappedTorus( float3 p, float2 sc, float ra, float rb) {
|
||
|
p.x = abs(p.x);
|
||
|
float k = (sc.y*p.x>sc.x*p.y) ? dot(p.xy,sc) : length(p.xy);
|
||
|
return sqrt( dot(p,p) + ra*ra - 2.0*ra*k ) - rb;
|
||
|
}
|
||
|
|
||
|
float3 RotateY(float3 p, float a) {
|
||
|
return mul(float3x3(cos(a), 0, sin(a), 0, 1, 0, -sin(a), 0, cos(a)), p);
|
||
|
}
|
||
|
|
||
|
float Kijetesantakalu(float3 p, float r) {
|
||
|
float d = sdSphere(p, float3(0, 0, 0.2f), r);// left eye
|
||
|
d = min(d, sdSphere(p, float3(0.15f, 0, 0.2f), r)); // right eye
|
||
|
d = min(d, sdLine(p, float3(0, 0, -0.4f), float3(-0.35f, 0, -0.4f), r)); // bottom line
|
||
|
d = smin(d, sdLine(p, float3(0, 0, -0.4f), float3(-0.1f, 0, -0.15f), r), 0.003f); // leg hook
|
||
|
d = min(d, sdLine(p, float3(0.15f, 0, -0.4f), float3(0.15f, 0, -0.1f), r)); // middle leg
|
||
|
d = min(d, sdLine(p, float3(0.3f, 0, -0.4f), float3(0.3f, 0, 0), r)); // front leg
|
||
|
d = smin(d, sdLine(p, float3(0.45f, 0, 0.1f), float3(0.3f, 0, 0), r), 0.003f); // lower snout
|
||
|
d = smin(d, sdLine(p, float3(0.45f, 0, 0.1f), float3(0.2f, 0, 0.35f), r), 0.003f); // upper snout
|
||
|
d = smin(d, sdLine(p, float3(0.2f, 0, 0.45f), float3(0.2f, 0, 0.35f), r), 0.003f); // ear
|
||
|
float an = 0.9;
|
||
|
d = smin(d, sdCappedTorus((RotateY(p, 0.8f) - float3(0.15f, 0, -0.05f)).xzy, float2(sin(an),cos(an)), 0.4, r), 0.003f); // ear
|
||
|
d = smin(d, sdLine(p, float3(-0.25f, 0, 0), float3(-0.25f, 0, -0.4f), r), 0.003f); // back
|
||
|
d = smin(d, sdLine(p, float3(-0.25f, 0, -0.1f), float3(-0.35f, 0, -0.1f), r), 0.003f); // tail top
|
||
|
d = smin(d, sdLine(p, float3(-0.35f, 0, -0.1f), float3(-0.35f, 0, -0.4f), r), 0.003f); // stripe
|
||
|
an = 3.1415f*0.5;
|
||
|
d = smin(d, sdCappedTorus((RotateY(p, an) - float3(-0.25f, 0, 0.35f)).xzy, float2(sin(an),cos(an)), 0.15f, r), 0.003f); // tail
|
||
|
|
||
|
return d;
|
||
|
}
|
||
|
|
||
|
float FirstShape(float3 p) {
|
||
|
return Kijetesantakalu(p, 0.05f);
|
||
|
}
|
||
|
|
||
|
float SecondShape(float3 p) {
|
||
|
// return sdBox(p, 0.3f) - 0.01f;
|
||
|
// return Kijetesantakalu(p, 0.04f) - 0.01f;
|
||
|
return sdSphere(p, 0, 0.3f);
|
||
|
}
|
||
|
|
||
|
|
||
|
float GetDist(float3 p) {
|
||
|
#ifdef IS_SECONDARY_SHAPE
|
||
|
return SecondShape(p);
|
||
|
#else
|
||
|
float first = FirstShape(p);
|
||
|
float3 second_pos = mul(unity_WorldToObject, _WorldSpaceLightPos0);
|
||
|
float second = SecondShape(p - second_pos);
|
||
|
return smin(first, second, 0.15f);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
//marches a ray through the scene
|
||
|
float Raymarch(float3 ro, float3 rd) {
|
||
|
float rayLen = 0;// total distance marched / distance from origin
|
||
|
float dist; // distance from the raymarched scene
|
||
|
for ( int i = 0; i < _MaxSteps; i++)
|
||
|
{
|
||
|
//position = origin + distance * direction
|
||
|
float3 p = ro + rayLen * rd;
|
||
|
dist = GetDist(p);
|
||
|
rayLen += dist;// move forward
|
||
|
if (dist < _SurfDist || rayLen > _MaxDist) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return rayLen;
|
||
|
}
|
||
|
|
||
|
float3 GetNormal(float3 p) {
|
||
|
float2 e = float2(0.001, 0);
|
||
|
float3 n = GetDist(p) - float3(
|
||
|
GetDist(p-e.xyy),
|
||
|
GetDist(p-e.yxy),
|
||
|
GetDist(p-e.yyx));
|
||
|
return normalize(n);
|
||
|
}
|
||
|
|
||
|
fragOut frag (v2f i) {
|
||
|
float3 ro = i.ro;
|
||
|
float3 rd = normalize(i.hitPos - ro);
|
||
|
|
||
|
float d = Raymarch(ro, rd);
|
||
|
fixed4 col = 1;
|
||
|
|
||
|
if (d >= _MaxDist)
|
||
|
{
|
||
|
discard;
|
||
|
}
|
||
|
float3 p = ro + rd * d;
|
||
|
float3 n = GetNormal(p);
|
||
|
|
||
|
// col.rgb = max(dot(n, normalize(float3(1,0.5,1))), 0.05f);
|
||
|
col.r = dot(-rd, n);
|
||
|
|
||
|
// col *= float4(d, 1, 1, 1);
|
||
|
fragOut o;
|
||
|
o.col = col;
|
||
|
float4 vClipPos = mul(UNITY_MATRIX_VP, mul(unity_ObjectToWorld, float4(p, 1)));
|
||
|
o.depth = (vClipPos.z / vClipPos.w + 1.0) * 0.5;
|
||
|
return o;
|
||
|
}
|
||
|
|
||
|
#endif
|