private ColorAccumulator CalculateLighting(HitInfo info, int count)
 {
     ColorAccumulator ca = new ColorAccumulator();
     foreach (Light lt in Scene.Lights)
     {
         GetColor(info, lt, ca, count);
     }
     return ca;
 }
 private bool InShadow(HitInfo info, Light lt, Vector3D lightNormal)
 {
     Ray shadowRay = new Ray(lt.Location, lightNormal);
     HitInfo shadinfo = FindHitObject(shadowRay, info.hitObj, HitMode.Closest);
     if (shadinfo.hitObj != null && Vector3D.Subtract(lt.Location, info.hitPoint).Length > Vector3D.Subtract(lt.Location, shadinfo.hitPoint).Length)
     {
         return true;
     }
     return false;
 }
 private HitInfo FindHitObject(Ray ray, Geometry originator, HitMode mode)
 {
     Vector3D intPoint = new Vector3D(double.MaxValue, double.MaxValue, double.MaxValue);
     HitInfo info = new HitInfo(null, intPoint, ray);
     double dist = double.MaxValue;
     foreach (Geometry geom in Scene.Geoms)
     {
         if (geom != originator && geom.Intersects(ray, ref intPoint))
         {
             double distToObj = Vector3D.Subtract(ray.Source, intPoint).Length;
             if (distToObj < dist)
             {
                 info.hitPoint = intPoint;
                 dist = distToObj;
                 info.hitObj = geom;
                 if (mode == HitMode.Any)
                 {
                     break;
                 }
             }
         }
     }
     return info;
 }
        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;
            }
        }
Beispiel #5
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;
                        }
                    }
                }
            }
        }