Shader "CrispyPin/RaymarchMultiObject" { Properties { [Header(Object positions)] _ObjectA ("Object A", Vector) = (0, 0, 0) _ObjectB ("Object B", Vector) = (0, 0, 0) [Header(Raymarcher Properties)] _MaxSteps ("Max steps", Int) = 256 _MaxDist ("Max distance", Float) = 100 _SurfDist ("Surface distance threshold", Range(0.00001, 0.05)) = 0.001 } SubShader { Tags { "RenderType"="Opaque" } Cull Off LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #include "UnityLightingCommon.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; float3 _ObjectA; float3 _ObjectB; 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(p- a - (b-a) * 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; } float sdTorus( float3 p, float2 t) { float2 q = float2(length(p.xz) - t.x, p.y); return length(q) - t.y; } 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); float3 a =_ObjectA; float3 b =_ObjectB; float o = sdLine(p, a, b, 0.1); o = smin(o, sdSphere(p, a, 0.2), 0.05); o = smin(o, sdSphere(p, b, 0.2), 0.05); return o; // return sdTorus(p - _ObjectA, float2(, 0.2f)); } float GetDist(float3 p) { float first = FirstShape(p); // float3 second_pos = mul(unity_WorldToObject, _WorldSpaceLightPos0); float second = SecondShape(p); return smin(first, second, 0.15f); } //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); // float3 edgeCol = float3(0,1,1); float3 edgeCol = abs(p); col.rgb = lerp(0.001, edgeCol, pow(1 - dot(-rd, n), 2)); // col *= float4(d, 1, 1, 1); fragOut o; o.col = col; // o.col = _LightColor0; float4 vClipPos = mul(UNITY_MATRIX_VP, mul(unity_ObjectToWorld, float4(p, 1))); float zDepth = vClipPos.z / vClipPos.w; #if !defined(UNITY_REVERSED_Z) // basically only OpenGL (unity editor on linux) zDepth = zDepth * 0.5 + 0.5; // remap -1 to 1 range to 0.0 to 1.0 #endif o.depth = zDepth; return o; } ENDCG } } }