Shader "Unlit/QuadRaymarching" { Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag // make fog work #pragma multi_compile_fog #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; UNITY_FOG_COORDS(1) float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); UNITY_TRANSFER_FOG(o,o.vertex); return o; } // MOD float mod(float x, float y) { return x - y * floor(x / y); } float2 mod(float2 x, float2 y) { return x - y * floor(x / y); } float3 mod(float3 x, float3 y) { return x - y * floor(x / y); } float4 mod(float4 x, float4 y) { return x - y * floor(x / y); } // SMIN float smin(float a, float b, float k) { float res = exp2(-k * a) + exp2(-k * b); return -log2(res) / k; } float noise(float p) { float fl = floor(p); float fc = frac(p); return lerp(frac(sin(fl)), frac(sin(fl + 1.0)), fc); } // 回転 float2 rot(float2 p, float a) { return float2(p.x*cos(a) - p.y*sin(a), p.x*sin(a) + p.y*cos(a)); } float3 qrot(float3 p, float3 v, float a) { float4 q = float4(sin(a / 2.0) * v, cos(a / 2.0)); // quaternion return cross(cross(p, q.xyz) - q.w * p, q.xyz) * 2.0 + p; } // pmod(polar mod, fold rotate) float2 pmod(float2 p, float s) { float a = UNITY_PI / s - atan2(p.x, p.y); float n = UNITY_TWO_PI / s; a = floor(a / n) * n; return rot(p, a); } // box float box(float3 p, float3 q, float r) { float3 p2 = abs(p) - q; return length(max(p2, float3(0, 0, 0))); } // sphere float sphere(float3 p, float3 q, float r) { length(p - q) - r; } // Torus float torus(float3 p, float q, float r) { return length(float2(length(p.xz) - q, p.y)) - r; } // map float map(float3 p) { float3 q = p; q /= 2; for (int k = 0; k < 5; ++k) { q = abs(q) - 2; q.xy = pmod(q.xy, 2.4); q.xz = pmod(q.xz, -3.3); } /* for (int k = 0; k < 5; ++k) { q = abs(q) - 2; q.xy = rot(q.xy, 2.4); q.xz = rot(q.xz, -3.3); } */ return box(q, float3(1, 1, 1), 1); } // 法線 float3 normal(float3 p) { float2 xy = float2(0.001, 0); return normalize(float3( map(p + xy.xyy) - map(p - xy.xyy), map(p + xy.yxy) - map(p - xy.yxy), map(p + xy.yyx) - map(p - xy.yyx) )); } fixed4 frag (v2f i) : SV_Target { // 原点座標を四角形の中心に変更する float2 p = 2 * i.uv - 1; // position // 色を用意する float3 col = float3(0, 0, 0); // color // レイの初期位置 float3 ro = float3(1.5, 0.5, -3.0 + 3.0 * sin(_Time.y)); // ray origin // 暫定の「上」 float3 up = float3(0, 1, 0); // Y-up // ターゲット(カメラ向き) float3 ta = float3(0, 0, 0); // target // 前 float3 fwd = normalize(ta - ro); // forward // 横 float3 side = normalize(cross(up, fwd)); // side // 上 up = normalize(cross(fwd, side)); // FOV float fov = 1.0; // fov // レイの進む方向 float3 rd = normalize(p.x * side + p.y * up + fov * fwd); // ray direction // レイ float3 ray = ro; // 距離を格納する変数 float d; // 法線 float3 N; // ループの進んだ回数(アンビエントオクルージョン) int k; // マーチングループ for (int j = 0; j < 192; ++j) { d = map(ray); if (d < 0.001) { N = normal(ray); break; } k = j; ray += d * rd; } // 衝突したところを明るくする //col += 1 / d; // アンビエントオクルージョン col += (float)k / 192; // カメラ座標を光源のベクトルに利用する float3 L = normalize(ray - ro); // ランバートのライティング col += max(0,dot(N, L)); // 色の出力 return fixed4(col, 1.0); } ENDCG } } }