Example #1
0
        private IntersectInfo IntersectSlab(Ray ray, Vector P1, Vector P2, Vector P3)
        {
            Vector        N    = (P1 - P3).Cross(P2 - P3).Normalize();
            double        d    = N.Dot(P1);
            IntersectInfo info = new IntersectInfo();
            double        Vd   = N.Dot(ray.Direction);

            if (Vd == 0)
            {
                return(info);         // no intersection
            }
            double t = -(N.Dot(ray.Position) - d) / Vd;

            if (t <= 0)
            {
                return(info);
            }
            Vector hit = ray.Position + ray.Direction * t;

            if ((hit.x < P1.x || hit.x > P2.x) && (P1.x != P2.x))
            {
                return(info);
            }
            if ((hit.y < P3.y || hit.y > P1.y) && (P1.y != P2.y))
            {
                return(info);
            }
            //if ((hit.z < P1.z || hit.z > P3.z) && (P1.z != P3.z)) return info;
            if ((hit.z < P1.z || hit.z > P2.z) && (P1.z != P2.z))
            {
                return(info);
            }


            info.Element  = this;
            info.IsHit    = true;
            info.Position = hit;
            info.Normal   = N;// *-1;
            info.Distance = t;

            if (Material.HasTexture)
            {
                //Vector vecU = new Vector(hit.y - Position.y, hit.z - Position.z, Position.x-hit.x);
                Vector vecU = new Vector((P1.y + P2.y) / 2 - Position.y, (P1.z + P2.z) / 2 - Position.z, Position.x - (P1.x + P2.x) / 2).Normalize();
                Vector vecV = vecU.Cross((P1 + P2) / 2 - Position).Normalize();

                double u = info.Position.Dot(vecU);
                double v = info.Position.Dot(vecV);
                info.Color = Material.GetColor(u, v);
            }
            else
            {
                info.Color = Material.GetColor(0, 0);
            }

            return(info);
        }
Example #2
0
        public override IntersectInfo Intersect(Ray ray)
        {
            IntersectInfo info = new IntersectInfo();

            info.Element = this;

            Vector dst = ray.Position - this.Position;
            double B   = dst.Dot(ray.Direction);
            double C   = dst.Dot(dst) - (R * R);
            double D   = B * B - C;

            if (D > 0)
            {
                info.IsHit    = true;
                info.Distance = -B - (double)Math.Sqrt(D);
                info.Position = ray.Position + ray.Direction * info.Distance;
                info.Normal   = (info.Position - Position).Normalize();

                if (Material.HasTexture)
                {
                    Vector vn = new Vector(0, 1, 0).Normalize();
                    Vector ve = new Vector(0, 0, 1).Normalize();
                    Vector vp = (info.Position - Position).Normalize();

                    double phi = Math.Acos(-vp.Dot(vn));
                    double v   = (phi / Math.PI);

                    double sinphi = ve.Dot(vp) / Math.Sin(phi);
                    double theta  = Math.Acos(sinphi) / (Math.PI * 2);

                    double u;
                    if (vn.Cross(ve).Dot(vp) > 0)
                    {
                        u = theta;
                    }
                    else
                    {
                        u = 1 - theta;
                    }

                    info.Color = this.Material.GetColor(1 - u, 1 - v);
                }
                else
                {
                    info.Color = this.Material.GetColor(0, 0);
                }
            }
            else
            {
                info.IsHit = false;
            }
            return(info);
        }
Example #3
0
        /// <summary>
        /// 返回光线跟踪后的颜色
        /// </summary>
        /// <param name="ray">射线</param>
        /// <param name="scene">场景</param>
        /// <returns></returns>
        public Color CalculateColor(Ray ray, Scene scene)
        {
            IntersectInfo info = TestIntersection(ray, scene, null);

            if (info.IsHit)
            {
                // 进行光线跟踪
                Color c = RayTrace(info, ray, scene, 0);
                return(c);
            }

            return(scene.Background.Color);
        }
Example #4
0
        private IntersectInfo TestIntersection(Ray ray, Scene scene, IShape exclude)
        {
            int           hitcount = 0;
            IntersectInfo best     = new IntersectInfo();

            best.Distance = double.MaxValue;

            foreach (IShape elt in scene.Shapes)
            {
                if (elt == exclude)
                {
                    continue;
                }

                IntersectInfo info = elt.Intersect(ray);
                if (info.IsHit && info.Distance < best.Distance && info.Distance >= 0)
                {
                    best = info;
                    hitcount++;
                }
            }
            best.HitCount = hitcount;
            return(best);
        }
Example #5
0
        /// <summary>
        /// 进行真正的光线跟踪
        /// </summary>
        /// <param name="info">击中信息</param>
        /// <param name="ray">射线</param>
        /// <param name="scene">场景</param>
        /// <param name="depth">递归深度</param>
        /// <returns></returns>
        private Color RayTrace(IntersectInfo info, Ray ray, Scene scene, int depth)
        {
            // 计算环境光
            Color  color     = info.Color * scene.Background.Ambience;
            double shininess = Math.Pow(10, info.Element.Material.Gloss + 1);

            foreach (Light light in scene.Lights)
            {
                // 计算漫射光
                Vector v = (light.Position - info.Position).Normalize();

                if (RenderDiffuse)
                {
                    double L = v.Dot(info.Normal);
                    if (L > 0.0f)
                    {
                        color += info.Color * light.Color * L;
                    }
                }


                //最大深度
                if (depth < 10)
                {
                    // 计算反射
                    if (RenderReflection && info.Element.Material.Reflection > 0)
                    {
                        Ray           reflectionray = GetReflectionRay(info.Position, info.Normal, ray.Direction);
                        IntersectInfo refl          = TestIntersection(reflectionray, scene, info.Element);
                        if (refl.IsHit && refl.Distance > 0)
                        {
                            // 递归计算反射 ----要改成迭代
                            refl.Color = RayTrace(refl, reflectionray, scene, depth + 1);
                        }
                        else //MISS 返回背景色
                        {
                            refl.Color = scene.Background.Color;
                        }
                        color = color.Blend(refl.Color, info.Element.Material.Reflection);
                    }

                    //计算折射
                    if (RenderRefraction && info.Element.Material.Transparency > 0)
                    {
                        Ray           refractionray = GetRefractionRay(info.Position, info.Normal, ray.Direction, info.Element.Material.Refraction);
                        IntersectInfo refr          = info.Element.Intersect(refractionray);
                        if (refr.IsHit)
                        {
                            refractionray = GetRefractionRay(refr.Position, refr.Normal, refractionray.Direction, refr.Element.Material.Refraction);
                            refr          = TestIntersection(refractionray, scene, info.Element);
                            if (refr.IsHit && refr.Distance > 0)
                            {
                                // 递归计算折射 ----要改成迭代
                                refr.Color = RayTrace(refr, refractionray, scene, depth + 1);
                            }
                            else
                            {
                                refr.Color = scene.Background.Color;
                            }
                        }
                        else
                        {
                            refr.Color = scene.Background.Color;
                        }
                        color = color.Blend(refr.Color, info.Element.Material.Transparency);
                    }
                }


                IntersectInfo shadow = new IntersectInfo();
                if (RenderShadow)
                {
                    // 计算阴影
                    Ray shadowray = new Ray(info.Position, v);

                    // 该点的直射光线是否被遮挡
                    shadow = TestIntersection(shadowray, scene, info.Element);
                    if (shadow.IsHit && shadow.Element != info.Element)
                    {
                        color *= 0.5 + 0.5 * Math.Pow(shadow.Element.Material.Transparency, 0.5); // Math.Pow(.5, shadow.HitCount);
                    }
                }

                if (RenderHighlights && !shadow.IsHit && info.Element.Material.Gloss > 0)
                {
                    // Phong 模型计算
                    Vector Lv = (info.Element.Position - light.Position).Normalize();
                    Vector E  = (scene.Camera.Position - info.Element.Position).Normalize();
                    Vector H  = (E - Lv).Normalize();

                    double Glossweight = 0.0;
                    Glossweight = Math.Pow(Math.Max(info.Normal.Dot(H), 0), shininess);
                    color      += light.Color * (Glossweight);
                }
            }

            //整合光照
            color.Limit();
            return(color);
        }
Example #6
0
        public override IntersectInfo Intersect(Ray ray)
        {
            IntersectInfo best = new IntersectInfo();

            best.Distance = double.MaxValue;
            IntersectInfo info = null;


            Vector P1 = null;
            Vector P2 = null;
            Vector P3 = null;

            if (ray.Direction.z > 0)
            {
                //前
                P1   = UpperLeftFront;
                P2   = new Vector(LowerRightBack.x, LowerRightBack.y, P1.z);
                P3   = new Vector(P1.x, P2.y, P1.z);
                info = IntersectSlab(ray, P1, P2, P3);
                if (info.IsHit && info.Distance < best.Distance)
                {
                    best = info;
                }
            }
            else
            {
                //后
                P1   = new Vector(UpperLeftFront.x, UpperLeftFront.y, LowerRightBack.z);
                P2   = LowerRightBack;
                P3   = new Vector(P1.x, P2.y, P1.z);
                info = IntersectSlab(ray, P1, P2, P3);
                if (info.IsHit && info.Distance < best.Distance)
                {
                    best = info;
                }
            }

            if (ray.Direction.x < 0)
            {
                //左
                P1   = new Vector(LowerRightBack.x, UpperLeftFront.y, UpperLeftFront.z);
                P2   = LowerRightBack;
                P3   = new Vector(P1.x, P2.y, P1.z);
                info = IntersectSlab(ray, P1, P2, P3);
                if (info.IsHit && info.Distance < best.Distance)
                {
                    best = info;
                }
            }
            else
            {
                //右
                P1   = UpperLeftFront;
                P2   = new Vector(UpperLeftFront.x, LowerRightBack.y, LowerRightBack.z);
                P3   = new Vector(P1.x, P2.y, P1.z);
                info = IntersectSlab(ray, P1, P2, P3);
                if (info.IsHit && info.Distance < best.Distance)
                {
                    best = info;
                }
            }

            if (ray.Direction.y < 0)
            {
                //上
                P1   = UpperLeftFront;
                P2   = new Vector(LowerRightBack.x, UpperLeftFront.y, LowerRightBack.z);
                P3   = new Vector(P2.x, P1.y, P1.z);
                info = IntersectSlab(ray, P1, P2, P3);
                if (info.IsHit && info.Distance < best.Distance)
                {
                    best = info;
                }
            }
            else
            {
                //下
                P1   = new Vector(UpperLeftFront.x, LowerRightBack.y, UpperLeftFront.z);
                P2   = LowerRightBack;
                P3   = new Vector(P2.x, P1.y, P1.z);
                info = IntersectSlab(ray, P1, P2, P3);
                if (info.IsHit && info.Distance < best.Distance)
                {
                    best = info;
                }
            }
            return(best);
        }