private ColorAccumulator CalculateLighting(HitInfo info, int count)
 {
     ColorAccumulator ca = new ColorAccumulator();
     foreach (Light lt in Scene.Lights)
     {
         GetColor(info, lt, ca, count);
     }
     return ca;
 }
예제 #2
0
        public static ColorAccumulator operator +(ColorAccumulator left, ColorAccumulator right)
        {
            ColorAccumulator sum = new ColorAccumulator();

            sum.R = left.R + right.R;
            sum.G = left.G + right.G;
            sum.B = left.B + right.B;
            return(sum);
        }
예제 #3
0
        private ColorAccumulator CastRay(Ray ray, int count)
        {
            if (count > RayDepth)
            {
                return(null);
            }

            ColorAccumulator colorAccumulator = null;
            HitInfo          info             = FindHitObject(ray);

            if (info.hitObject != null)
            {
                colorAccumulator = CalculateLighting(info, count);
                //colorAccumulator.Clamp();
            }
            else
            {
                colorAccumulator = new ColorAccumulator(BackColor.R, BackColor.G, BackColor.B);
            }

            return(colorAccumulator);
        }
예제 #4
0
        private ColorAccumulator CalculateLighting(HitInfo info, int count)
        {
            ColorAccumulator colorAccumulator = new ColorAccumulator();

            foreach (Light light in Scene.Lights)
            {
                GetColor(info, light, colorAccumulator, count);

                //Bidirectional ray tracing
                var randomDirection = StaticRandom.RandomVectorInUnitSphere();
                var randomRay       = new Ray(light.Location + randomDirection, randomDirection);
                var hitInfo         = FindHitObject(randomRay);
                var secondaryLight  = new Light();
                secondaryLight.Location = hitInfo.hitPoint - randomRay.Direction;
                int squaredDistance = (int)(secondaryLight.Location - randomRay.Source).LengthSquared + 1;
                secondaryLight.Color     = light.Color;
                secondaryLight.Intensity = light.Intensity / squaredDistance;

                GetColor(info, secondaryLight, colorAccumulator, count);
            }

            return(colorAccumulator);
        }
 public static ColorAccumulator operator +(ColorAccumulator left, ColorAccumulator right)
 {
     ColorAccumulator sum = new ColorAccumulator();
     sum.accumR = left.accumR + right.accumR;
     sum.accumG = left.accumG + right.accumG;
     sum.accumB = left.accumB + right.accumB;
     return sum;
 }
        private void GetColor(HitInfo info, Light lt, ColorAccumulator ca, int count)
        {
            Vector3D lightNormal = info.hitPoint - lt.Location;
            lightNormal.Normalize();

            if (InShadow(info, lt, lightNormal))
            {
                return;
            }

            double lambert = Vector3D.DotProduct(lightNormal, info.normal);
            if (lambert <= 0)
            {
                int r, g, b;
                r = b = g = 0;

                int r2 = 0;
                int g2 = 0;
                int b2 = 0;

                info.hitObj.GetColor(info.hitPoint, ref r, ref g, ref b);
                if (info.hitObj.Material != null && info.hitObj.Material is SolidColor)
                {
                    double phongTerm = Math.Pow(lambert, 20) * (info.hitObj.Material as SolidColor).Phong * 2;
                    r2 = (int)(lt.Color.R * phongTerm);
                    g2 = (int)(lt.Color.G * phongTerm);
                    b2 = (int)(lt.Color.B * phongTerm);
                    double reflet = 2.0f * (Vector3D.DotProduct(info.normal, info.ray.Direction));
                    Vector3D dir = info.ray.Direction - info.normal * reflet;
                    Ray reflect = new Ray(info.hitPoint + dir, dir);
                    ColorAccumulator rca = CastRay(reflect, ++count);
                    if (rca != null)
                    {
                        ca.accumR = ca.accumR + rca.accumR;
                        ca.accumG = ca.accumG + rca.accumG;
                        ca.accumB = ca.accumB + rca.accumB;
                    }
                }
                ca.accumR += (int)((lt.Color.R * r * -lambert) / 255) + r2;
                ca.accumG += (int)((lt.Color.G * g * -lambert) / 255) + g2;
                ca.accumB += (int)((lt.Color.B * b * -lambert) / 255) + b2;
            }
        }
        private ColorAccumulator CastRay(Ray ray, int count)
        {
            if (count > RayDepth)
            {
                return null;
            }

            ColorAccumulator ca = null;
            HitInfo info = FindHitObject(ray);

            if (info.hitObj != null)
            {
                ca = CalculateLighting(info, count);
                ca.Clamp();
            }
            else
            {
                ca = new ColorAccumulator(BackColor.R, BackColor.G, BackColor.B);
            }

            return ca;
        }
예제 #8
0
        private void GetColor(HitInfo info, Light light, ColorAccumulator colorAccu, int count)
        {
            Vector3D lightLocation = light.Location;
            Vector3D lightNormal   = info.hitPoint - lightLocation;

            lightNormal.Normalize();

            double lambert = Vector3D.DotProduct(lightNormal, info.normal);

            if (lambert <= 0)
            {
                int r, g, b;
                r = g = b = 0;

                int r2 = 0;
                int g2 = 0;
                int b2 = 0;

                info.hitObject.GetColor(info.hitPoint, ref r, ref g, ref b);

                if (info.hitObject.Material != null)
                {
                    var objectMaterial = info.hitObject.Material;

                    //Phong
                    if (objectMaterial is SolidColor)
                    {
                        if (InShadow(info, lightLocation, lightNormal))
                        {
                            return;
                        }

                        double phongTerm = Math.Pow(lambert, 20) * (objectMaterial as SolidColor).Phong * 2 * light.Intensity;
                        r2 = (int)(light.Color.R * phongTerm);
                        g2 = (int)(light.Color.G * phongTerm);
                        b2 = (int)(light.Color.B * phongTerm);

                        var intensityFactor = light.Intensity * -lambert / 255;

                        colorAccu.R += (int)(light.Color.R * r * intensityFactor) + r2;
                        colorAccu.G += (int)(light.Color.G * g * intensityFactor) + g2;
                        colorAccu.B += (int)(light.Color.B * b * intensityFactor) + b2;
                    }
                    //Reflection
                    else if (objectMaterial is Metal)
                    {
                        var metal = objectMaterial as Metal;

                        //double phongTerm = Math.Pow(lambert, 20) * 0.6 * 2 * light.Intensity;
                        //r2 = (int)(light.Color.R * phongTerm);
                        //g2 = (int)(light.Color.G * phongTerm);
                        //b2 = (int)(light.Color.B * phongTerm);

                        double   reflet    = 2.0f * (Vector3D.DotProduct(info.normal, info.ray.Direction));
                        Vector3D direction = info.ray.Direction - info.normal * reflet;
                        direction.Normalize();
                        direction += metal.Fuzz * StaticRandom.RandomVectorInUnitSphere(); //Random in cone
                        //direction.Normalize();
                        Ray reflect = new Ray(info.hitPoint + direction / 100000, direction);
                        ColorAccumulator reflectedColorAccu = CastRay(reflect, ++count);

                        if (reflectedColorAccu != null)
                        {
                            var attenuation = metal.Reflection * light.Intensity;
                            colorAccu.R += (int)(reflectedColorAccu.R * attenuation) + r2;
                            colorAccu.G += (int)(reflectedColorAccu.G * attenuation) + g2;
                            colorAccu.B += (int)(reflectedColorAccu.B * attenuation) + b2;
                        }
                    }
                }
            }
        }