// A standard square grid 2D blobby Truchet routine: Render circles
        // in opposite corners of a tile, reverse the pattern on alternate
        // checker tiles, and randomly rotate.
        private static float Truchet(Float2 p)
        {
            const float sc = 0.5f;
            Float2      ip = Hlsl.Floor(p / sc) + 0.5f;

            p -= ip * sc;

            float rnd = Hlsl.Frac(Hlsl.Sin(Hlsl.Dot(ip, new Float2(1, 113))) * 45758.5453f);

            if (rnd < .5)
            {
                p.Y = -p.Y;
            }

            float d = Hlsl.Min(Distance(p - 0.5f * sc), Distance(p + 0.5f * sc)) - 0.5f * sc;

            if (SHAPE == 4)
            {
                d += (0.5f - 0.5f / Hlsl.Sqrt(2.0f)) * sc;
            }

            if (rnd < 0.5f)
            {
                d = -d;
            }
            if (Mod(ip.X + ip.Y, 2.0f) < 0.5f)
            {
                d = -d;
            }

            return(d - 0.03f);
        }
        // Cheap shadows are hard. In fact, I'd almost say, shadowing particular scenes with limited
        // iterations is impossible... However, I'd be very grateful if someone could prove me wrong. :)
        private static float SoftShadow(Float3 ro, Float3 lp, Float3 n, float k)
        {
            const int iter = 24;

            ro += n * 0.0015f;

            Float3 rd    = lp - ro;
            float  shade = 1.0f;
            float  t     = 0;
            float  end   = Hlsl.Max(Hlsl.Length(rd), 0.0001f);

            rd /= end;

            for (int i = 0; i < iter; i++)
            {
                float d = M(ro + rd * t);

                shade = Hlsl.Min(shade, k * d / t);
                t    += Hlsl.Clamp(d, 0.01f, 0.25f);

                if (d < 0.0f || t > end)
                {
                    break;
                }
            }

            return(Hlsl.Max(shade, 0.0f));
        }
Пример #3
0
        static float SDBox(float3 p, float3 b)
        {
            float3 q = Hlsl.Abs(p) - b;

            return(Hlsl.Length(Hlsl.Max(q, 0.0f)) +
                   Hlsl.Min(Hlsl.Max(q.X, Hlsl.Max(q.Y, q.Z)), 0.0f));
        }
        // The scene's distance function: There'd be faster ways to do this, but it's
        // more readable this way. Plus, this  is a pretty simple scene, so it's
        // efficient enough.
        private static float M(Float3 p)
        {
            float fl  = -p.Z;
            float obj = Truchet(p.XY);

            obj = Hlsl.Max(obj, Hlsl.Abs(p.Z) - 0.125f) - Hlsl.SmoothStep(0.03f, 0.25f, -obj) * 0.1f;

            float       studs = 1e5f;
            const float sc    = 0.5f;
            Float2      q     = p.XY + 0.5f * sc;
            Float2      iq    = Hlsl.Floor(q / sc) + 0.5f;

            q -= iq * sc;

            if (Mod(iq.X + iq.Y, 2.0f) > 0.5f)
            {
                studs = Hlsl.Max(Hlsl.Length(q) - 0.1f * sc - 0.02f, Hlsl.Abs(p.Z) - 0.26f);
            }

            objID = fl < obj && fl < studs ? 0 : obj < studs ? 1 : 2;

            return(Hlsl.Min(Hlsl.Min(fl, obj), studs));
        }