예제 #1
0
파일: Shader.cs 프로젝트: furaga/CGs
        public Vector3 shading(Vector3 pos, Vector3 norm, Ray ray, Actor actor, bool isShade)
        {
            // 点光源
            var l = light - pos;
            var l2 = l.LengthSquared();
            l.Normalize();

            // 視線
            var dir = ray.Position - pos;
            dir.Normalize();

            // ハーフベクトル
            var h = dir + l;
            h.Normalize();

            var ln = Vector3.Dot(l, norm);
            var hn = Vector3.Dot(h, norm);
            if (ln < 0) ln = 0;
            if (hn < 0) hn = 0;

            var dst = actor.GetColor(isShade ? 0.0f : ln, hn, pos);

            // 光源の色の反映
            dst.X *= lightColor.X;
            dst.Y *= lightColor.Y;
            dst.Z *= lightColor.Z;

            // 光の強さの適当な補正
            //dst *= Math.Min(1.5f, 500000.0f / (10000.0f + l2));
            //dst *= Math.Min(1.0f, l.Y + 0.1f);

            return dst;
        }
예제 #2
0
파일: Raytrace.cs 프로젝트: furaga/CGs
        Vector3 trace(Ray ray, Actor sender, int depth)
        {
            if (depth > MAX_DEPTH) return Vector3.Zero;

            var nearestNorm = Vector3.Zero;
            var nearestPos = Vector3.Zero;
            Actor nearestActor = null;
            var color = Vector3.Zero;

            foreach (var actor in actors)
            {
                if (actor == sender) continue;

                var norm = Vector3.Zero;
                var pos = Vector3.Zero;

                if (actor.isIntersect(ray, out norm, out pos))
                {
                    var d1 = pos - ray.Position;
                    var d2 = nearestPos - ray.Position;
                    if (nearestActor == null)
                    {
                        nearestActor = actor;
                        nearestNorm = norm;
                        nearestPos = pos;
                    }
                    else if (d1.LengthSquared() < d2.LengthSquared())
                    {
                        nearestActor = actor;
                        nearestNorm = norm;
                        nearestPos = pos;
                    }
                }
            }

            if (nearestActor == null)
            {
                return Vector3.Zero;
            }

            var crl = nearestActor.material.reflection;
            var crr = nearestActor.material.refraction;
            var cr = nearestActor.material.refraction;

            // 反射ベクトル
            var v = ray.Direction - 2 * Vector3.Dot(nearestNorm, ray.Direction) * nearestNorm;
            v.Normalize();
            var reflectionRay = new Ray(nearestPos, v);

            // 屈折ベクトル
            var vn = Vector3.Dot(ray.Direction, nearestNorm);
            float eta = 1.5f; // 屈折率
            Vector3 t;
            if (vn < 0)
            {
                var d = 1 - (1 + vn) * (1 + vn) / (eta * eta);
                if (d < 0)
                {
                    t = Vector3.Zero;
                }
                else
                {
                    t = (-vn / eta - (float)Math.Sqrt(d)) * nearestNorm + (1 / eta) * ray.Direction;
                }
            }
            else
            {
                var d = (1 - vn) * (1 - vn) / (eta * eta);
                if (d < 0)
                {
                    t = Vector3.Zero;
                }
                else
                {
                    t = -(vn / eta - (float)Math.Sqrt(d)) * nearestNorm + eta * ray.Direction;
                }
            }

            t.Normalize();
            var refractionRay = new Ray(nearestPos, t);

            var reflect = nearestActor.material.reflection <= 0.00001f ? Vector3.Zero : trace(reflectionRay, nearestActor, depth + 1);
            var refraction = nearestActor.material.refraction <= 0.00001f ? Vector3.Zero : trace(refractionRay, nearestActor, depth + 1);

            bool shade = false;
            foreach (var actor in actors)
            {
                if (actor == nearestActor) continue;
                var norm = Vector3.Zero;
                var pos = Vector3.Zero;
                var d = shader.light - nearestPos;
                d.Normalize();
                if (actor.isIntersect(new Ray(nearestPos, d), out norm, out pos))
                {
                    shade = true;
                    break;
                }
            }

            var diffuse = shader.shading(nearestPos, nearestNorm, ray, nearestActor, shade);

            return
                nearestActor.material.diffuse * diffuse +
                nearestActor.material.reflection * reflect +
                nearestActor.material.refraction * refraction;
        }