コード例 #1
0
ファイル: Sphere.cs プロジェクト: Tilps/Stash
 public override RealHitInfo DelayedHitCalc(Line by, HitInfo hit)
 {
     RealHitInfo realHit = new RealHitInfo();
     realHit.HitStuff = Surface;
     realHit.Pigment = Pigment;
     realHit.Normal = new Line();
     realHit.Normal.Start = by.Project(hit.HitDist);
     realHit.Normal.Direct.Dx = 0;
     realHit.Normal.Direct.Dy = 0;
     realHit.Normal.Direct.Dz = 0;
     switch (hit.SurfaceIndex)
     {
         case 0:
             Point hitLoc2 = inv.Apply(realHit.Normal.Start);
             realHit.Normal.Direct.Dx = hitLoc2.X;
             realHit.Normal.Direct.Dy = hitLoc2.Y;
             realHit.Normal.Direct.Dz = hitLoc2.Z;
             break;
         default:
             throw new InvalidOperationException("Invalid surface index in hitdata");
     }
     Vector before = realHit.Normal.Direct;
     realHit.Normal.Direct = trans.Apply(realHit.Normal.Direct);
     if (realHit.Normal.Direct.Dot(by.Direct) > 0)
     {
         realHit.Normal.Direct.ScaleSelf(-1.0);
     }
     return realHit;
 }
コード例 #2
0
ファイル: Cylinder.cs プロジェクト: Tilps/Stash
 public override RealHitInfo DelayedHitCalc(Line by, HitInfo hit)
 {
     RealHitInfo realHit = new RealHitInfo();
     realHit.HitStuff = Surface;
     realHit.Pigment = Pigment;
     realHit.Normal = new Line();
     realHit.Normal.Start = by.Project(hit.HitDist);
     realHit.Normal.Direct.Dx = 0;
     realHit.Normal.Direct.Dy = 0;
     realHit.Normal.Direct.Dz = 0;
     Point hitLoc;
     Vector deviance = new Vector();
     if (rounded)
     {
         hitLoc = inv.Apply(realHit.Normal.Start);
         if (hit.SurfaceIndex == 1 || (!RoundedTopOnly && hit.SurfaceIndex == 2))
         {
             double r = Math.Sqrt(hitLoc.X * hitLoc.X + hitLoc.Y * hitLoc.Y);
             if (r > 1 - RRounding)
             {
                 double dr = (1 - (1 - r) / RRounding) / (r);
                 deviance.Dx = hitLoc.X * dr;
                 deviance.Dy = hitLoc.Y * dr;
             }
         }
         if (!RoundedTopOnly && hitLoc.Z < -1 + ZRounding)
         {
             switch (hit.SurfaceIndex)
             {
                 case 0:
                     deviance.Dz = -1 + (hitLoc.Z + 1) / ZRounding;
                     break;
             }
         }
         if (hitLoc.Z > 1 - ZRounding)
         {
             switch (hit.SurfaceIndex)
             {
                 case 0:
                     deviance.Dz = 1 - (1 - hitLoc.Z) / ZRounding;
                     break;
             }
         }
     }
     switch (hit.SurfaceIndex)
     {
         case 0:
             Point hitLoc2 = inv.Apply(realHit.Normal.Start);
             realHit.Normal.Direct.Dx = hitLoc2.X;
             realHit.Normal.Direct.Dy = hitLoc2.Y;
             break;
         case 1:
             realHit.Normal.Direct.Dz = 1;
             break;
         case 2:
             realHit.Normal.Direct.Dz = -1;
             break;
         default:
             throw new InvalidOperationException("Invalid surface index in hitdata");
     }
     Vector before = realHit.Normal.Direct;
     realHit.Normal.Direct = trans.Apply(realHit.Normal.Direct);
     if (realHit.Normal.Direct.Dot(by.Direct) > 0)
     {
         if (rounded)
         {
             before.ScaleSelf(-1.0);
             deviance.ScaleSelf(-1.0);
         }
         else
             realHit.Normal.Direct.ScaleSelf(-1.0);
     }
     if (rounded)
     {
         realHit.Normal.Direct = before;
         realHit.Normal.Direct.Add(deviance);
         realHit.Normal.Direct = trans.Apply(realHit.Normal.Direct);
         if (realHit.Normal.Direct.Dot(by.Direct) > 0)
         {
             Vector perp1 = realHit.Normal.Direct.Cross(by.Direct);
             realHit.Normal.Direct = by.Direct.Cross(perp1);
         }
        }
     return realHit;
 }
コード例 #3
0
ファイル: ToyTracer.cs プロジェクト: Tilps/Stash
        private ColorIntensity ShadowShade(RealHitInfo hit, Line by, int recurse, double ratio, bool inside, int threadId, double lightdist)
        {
            #if DEBUG
            if (Gathering)
            {
                CurrentGather.Weight = ratio;
                CurrentGather.RealInfo = hit;
            }
            #endif
            ColorIntensity colors;
            Material surf = hit.HitStuff;
            double[] atten = new double[3];
            double rI, gI, bI;
            double dist = hit.Normal.Start.LineTo(by.Start).Length;
            lightdist -= dist;
            bool stop = lightdist < 0;
            if (lightdist < 0)
                dist += lightdist;
            if (surf.Attenutive && inside)
            {
                atten[0] = Math.Exp(-(1.0 - surf.Attenuation[0]) * dist / surf.AttenuationDistance);
                atten[1] = Math.Exp(-(1.0 - surf.Attenuation[1]) * dist / surf.AttenuationDistance);
                atten[2] = Math.Exp(-(1.0 - surf.Attenuation[2]) * dist / surf.AttenuationDistance);
                ratio = ratio * (atten[0] + atten[1] + atten[2]) / 3;
            }

            if (recurse < maxrecurse && ratio > minratio)
            {
                if (!stop)
                {
                    Line newray = new Line();
                    newray.Direct = new Vector(by.Direct.Dx, by.Direct.Dy, by.Direct.Dz);
                    newray.Start = hit.Normal.Start.MoveBy(newray.Direct.Scale(EPSILON * 10));
                    SetIn(ref newray.Start, threadId);
                    HitInfo hitnew = scene.Intersect(newray, threadId);
                    if (!(hitnew.HitDist == -1))
                    {
            #if DEBUG
                        GatherInfo last = null;
                        if (Gathering)
                        {
                            last = CurrentGather;
                            CurrentGather = new GatherInfo();
                        }
            #endif
                        ColorIntensity cl = ShadowShade(hitnew.GetReal(newray), newray, recurse + 1, ratio, !inside, threadId, lightdist);
            #if DEBUG
                        if (Gathering)
                        {
                            last.LightChildren.Add(CurrentGather);
                            CurrentGather = last;
                        }
            #endif
                        rI = cl.R;
                        gI = cl.G;
                        bI = cl.B;
                    }
                    else
                    {
                        rI = 1.0;
                        gI = 1.0;
                        bI = 1.0;
                    }
                }
                else
                {
                    rI = 1.0;
                    gI = 1.0;
                    bI = 1.0;
                }
            }
            else
            {
                if (recurse >= maxrecurse)
                {
                    // Recurse limit reached.
                    int i = 0;
                    i = i * 3;
                }
                rI = 0;
                bI = 0;
                gI = 0;
            }
            if (surf.Attenutive && inside)
            {
                rI *= atten[0];
                gI *= atten[1];
                bI *= atten[2];
            }
            if (!stop)
            {
                // Correct for how much light would be diffused at each interface.
                rI *= surf.Specularity;
                gI *= surf.Specularity;
                bI *= surf.Specularity;
                // Correct for reflection.
                double minFresnelReflectence = (surf.RefractIndex - 1) / (surf.RefractIndex + 1);
                minFresnelReflectence *= minFresnelReflectence;
                rI *= 1.0 - surf.Reflectance[0] - minFresnelReflectence;
                gI *= 1.0 - surf.Reflectance[1] - minFresnelReflectence;
                bI *= 1.0 - surf.Reflectance[2] - minFresnelReflectence;
            }
            colors.R = rI;
            colors.G = gI;
            colors.B = bI;
            return colors;
        }
コード例 #4
0
ファイル: ToyTracer.cs プロジェクト: Tilps/Stash
 private ColorIntensity Shade(RealHitInfo hit, Line by, int threadId)
 {
     return Shade(hit, by, 0, 1.0, false, threadId);
 }
コード例 #5
0
ファイル: ToyTracer.cs プロジェクト: Tilps/Stash
        private ColorIntensity Shade(RealHitInfo hit, Line by, int recurse, double ratio, bool inside, int threadId)
        {
            #if DEBUG
            if (Gathering)
            {
                CurrentGather.Weight = ratio;
                CurrentGather.RealInfo = hit;
            }
            #endif
            ColorIntensity colors, shadowcolors;
            Material surf = hit.HitStuff;
            ColorIntensity pigment = hit.Pigment.GetTexture(hit.Normal, 0);
            ColorIntensity atten = new ColorIntensity();
            if (surf.Attenutive && inside)
            {
                double dist = hit.Normal.Start.LineTo(by.Start).Length;
                atten.R = Math.Exp(-(1.0 - surf.Attenuation[0]) * dist / surf.AttenuationDistance);
                atten.G = Math.Exp(-(1.0 - surf.Attenuation[1]) * dist / surf.AttenuationDistance);
                atten.B = Math.Exp(-(1.0 - surf.Attenuation[2]) * dist / surf.AttenuationDistance);
                ratio = ratio * (atten.R + atten.G + atten.B) / 3;
            }
            double rI = 0;
            double gI = 0;
            double bI = 0;
            Vector lightdir;
            Line newray = new Line();
            HitInfo hitnewray = new HitInfo();
            hit.Normal.Direct = hit.Normal.Direct.Scale(1 / hit.Normal.Direct.Length);
            Vector eye = by.Direct.Scale(-1 / by.Direct.Length);

            int lightCount = (allLightsArePhotons && photons) ? 0 : lights.Count;
            //lightCount = 0;
            for (int i = 0; i < lightCount; i++)
            {
                double lightdist = double.PositiveInfinity;
                switch (lights[i].LightType)
                {
                    case LightType.Ambient:
                        rI += lights[i].Color.R * surf.Ambient[0];
                        gI += lights[i].Color.G * surf.Ambient[1];
                        bI += lights[i].Color.B * surf.Ambient[2];
                        continue;
                    case LightType.Directional:
                        lightdir = lights[i].Direction.Direct.Scale(-1);
                        break;
                    case LightType.Point:
                        lightdir = hit.Normal.Start.LineTo(lights[i].Direction.Start);
                        lightdist = lightdir.Length;
                        break;
                    default:
                        continue;
                }
                // Add double illuminate flag or something to turn this off.
                if (true)
                {
                    if (lightdir.Dot(hit.Normal.Direct) <= 0.0)
                        continue;
                }
                newray.Direct = lightdir.Scale(1.0/lightdir.Length);
                if (newray.Direct.Dot(hit.Normal.Direct) >= 0)
                    newray.Start = hit.Normal.Start.MoveBy(newray.Direct.Scale(EPSILON * 10));
                else
                    newray.Start = hit.Normal.Start.MoveBy(newray.Direct.Scale(-EPSILON * 10));
                SetIn(ref newray.Start, threadId);
                HitInfo info = scene.Intersect(newray, false, threadId);
                if (!(info.HitDist == -1 || info.HitDist > lightdist))
                    continue;
                shadowcolors.R = 1.0;
                shadowcolors.G = 1.0;
                shadowcolors.B = 1.0;
                // Don't need to setIn again, seperate intersect cache for shadow vs non-shadow rays.
                hitnewray = scene.Intersect(newray, threadId);
                if (!photons)
                {
                    if (!(hitnewray.HitDist == -1 || hitnewray.HitDist > lightdist))
                    {
            #if DEBUG
                        GatherInfo last = null;
                        if (Gathering)
                        {
                            last = CurrentGather;
                            CurrentGather = new GatherInfo();
                        }
            #endif
                        shadowcolors = ShadowShade(hitnewray.GetReal(newray), newray, recurse + 1, ratio, inside, threadId, lightdist);
            #if DEBUG
                        if (Gathering)
                        {
                            last.LightChildren.Add(CurrentGather);
                            CurrentGather = last;
                        }
            #endif
                    }
                }
                else
                {
                    if (!(hitnewray.HitDist == -1 || hitnewray.HitDist > lightdist))
                        continue;
                }
                shadowcolors.R *= lights[i].Color.R;
                shadowcolors.G *= lights[i].Color.G;
                shadowcolors.B *= lights[i].Color.B;
                if (realLighting && lightdist < double.PositiveInfinity)
                {
                    double lightdistSq = lightdist * lightdist;
                    shadowcolors.R /= lightdistSq;
                    shadowcolors.G /= lightdistSq;
                    shadowcolors.B /= lightdistSq;
                }
                CalculateLightContrib(hit.Normal.Direct, shadowcolors, surf, pigment, ref rI, ref gI, ref bI, lightdir, eye);
            }
            if (photons)
            {
                double scaleRadSq;
                List<Photon> closePhotons = Map.GetClosest(hit.Normal.Start, hit.Normal.Direct, out scaleRadSq, threadId);
                double photoR = 0.0;
                double photoG = 0.0;
                double photoB = 0.0;
                foreach (Photon photon in closePhotons)
                {
                    lightdir.Dx = -photon.TravelDir.Dx;
                    lightdir.Dy = -photon.TravelDir.Dy;
                    lightdir.Dz = -photon.TravelDir.Dz;
                    if (true)
                    {
                        if (lightdir.Dot(hit.Normal.Direct) <= 0.0)
                            continue;
                    }
                    ColorIntensity photonColor;
                    photonColor.R = photon.PhotonColorPower.R;
                    photonColor.G = photon.PhotonColorPower.G;
                    photonColor.B = photon.PhotonColorPower.B;
                    CalculateLightContrib(hit.Normal.Direct, photonColor, surf, pigment, ref photoR, ref photoG, ref photoB, lightdir, eye);
            #if DEBUG
                    if (Gathering)
                    {
                        CurrentGather.GatheredPhotons.Add(photon);
                    }
            #endif
                }
                if (closePhotons.Count > 0)
                {
                    rI += photoR / Math.PI / scaleRadSq;
                    if (rI > 3)
                    {
                        int breakpoint = 3;
                        breakpoint *= 34;
                    }
                    gI += photoG / Math.PI / scaleRadSq;
                    if (gI > 3)
                    {
                        int breakpoint = 3;
                        breakpoint *= 34;
                    }
                    bI += photoB / Math.PI / scaleRadSq;
                    if (bI > 3)
                    {
                        int breakpoint = 3;
                        breakpoint *= 34;
                    }
                }
            }
            if ((surf.Refractive || surf.Reflective) && recurse < maxrecurse)
            {
                by.Direct = by.Direct.Scale(1 / by.Direct.Length);
                ColorIntensity reflectance = new ColorIntensity();
                reflectance.R = surf.Reflective ? surf.Reflectance[0] : 0.0;
                reflectance.G = surf.Reflective ? surf.Reflectance[1] : 0.0;
                reflectance.B = surf.Reflective ? surf.Reflectance[2] : 0.0;
                if (surf.Refractive)
                {
                    double ni = inside ? surf.RefractIndex : 1.0;
                    double nt = (!inside) ? surf.RefractIndex : 1.0;
                    double cratio = ni / nt;
                    double ct1 = -by.Direct.Dot(hit.Normal.Direct);
                    double ct2sqrd = 1 - cratio * cratio * (1 - ct1 * ct1);
                    if (ct2sqrd <= 0)
                    {
                        reflectance.R = 1;
                        reflectance.G = 1;
                        reflectance.B = 1;
                    }
                    else
                    {
                        double ct2 = Math.Sqrt(ct2sqrd);
                        // fresnel equations for reflectance perp and parallel.
                        double rperp = (ni * ct1 - nt * ct2) / (ni * ct1 + nt * ct2);
                        double rpll = (nt * ct1 - ni * ct2) / (ni * ct2 + nt + ct1);
                        // assume unpolarised light always - better then tracing 2
                        // rays for both sides of every interface.
                        double reflectanceval = (rperp * rperp + rpll * rpll) / 2;
                        reflectance.R = Math.Min(1.0, reflectance.R + reflectanceval);
                        reflectance.G = Math.Min(1.0, reflectance.G + reflectanceval);
                        reflectance.B = Math.Min(1.0, reflectance.B + reflectanceval);
                        ColorIntensity transmitance = new ColorIntensity();
                        transmitance.R = 1 - reflectance.R;
                        transmitance.G = 1 - reflectance.G;
                        transmitance.B = 1 - reflectance.B;
                        double avt = transmitance.R + transmitance.G + transmitance.B;
                        avt /= 3;
                        if (avt * ratio*surf.Specularity > minratio)
                        {
                            Line newray2 = new Line();
                            newray2.Direct = by.Direct.Scale(cratio);
                            newray2.Direct.Add(hit.Normal.Direct.Scale(cratio * (ct1) - ct2));
                            newray2.Start = hit.Normal.Start.MoveBy(newray2.Direct.Scale(EPSILON * 10));
                            SetIn(ref newray2.Start, threadId);
                            HitInfo hitnew = scene.Intersect(newray2, threadId);
                            if (!(hitnew.HitDist == -1))
                            {
            #if DEBUG
                                GatherInfo last2 = null;
                                if (Gathering)
                                {
                                    last2 = CurrentGather;
                                    CurrentGather = new GatherInfo();
                                }
            #endif
                                ColorIntensity cl = Shade(hitnew.GetReal(newray2), newray2, recurse + 1, avt * ratio * surf.Specularity, !inside, threadId);
            #if DEBUG
                                if (Gathering)
                                {
                                    last2.Children.Add(CurrentGather);
                                    CurrentGather = last2;
                                }
            #endif
                                rI = rI + ((double)transmitance.R * cl.R) * surf.Specularity;
                                gI = gI + ((double)transmitance.G * cl.G) * surf.Specularity;
                                bI = bI + ((double)transmitance.B * cl.B) * surf.Specularity;
                            }
                        }
                    }
                }
                double avr = reflectance.R + reflectance.G + reflectance.B;
                avr /= 3;
                double specularity = surf.Refractive ? surf.Specularity : 1.0;
                if (avr * ratio*specularity > minratio)
                {
                    Line newray2 = new Line();
                    newray2.Direct = new Vector(by.Direct.Dx, by.Direct.Dy, by.Direct.Dz);
                    newray2.Direct.Add(hit.Normal.Direct.Scale(-2 * by.Direct.Dot(hit.Normal.Direct)));
                    newray2.Start = hit.Normal.Start.MoveBy(newray2.Direct.Scale(EPSILON * 10));
                    SetIn(ref newray2.Start, threadId);
                    HitInfo hitnew2 = scene.Intersect(newray2, threadId);
                    if (!(hitnew2.HitDist == -1))
                    {
            #if DEBUG
                        GatherInfo last3 = null;
                        if (Gathering)
                        {
                            last3 = CurrentGather;
                            CurrentGather = new GatherInfo();
                        }
            #endif
                        ColorIntensity cl2 = Shade(hitnew2.GetReal(newray2), newray2, recurse + 1, avr * ratio * specularity, inside, threadId);
            #if DEBUG
                        if (Gathering)
                        {
                            last3.Children.Add(CurrentGather);
                            CurrentGather = last3;
                        }
            #endif
                        rI = rI + ((double)reflectance.R * cl2.R) * specularity;
                        gI = gI + ((double)reflectance.G * cl2.G) * specularity;
                        bI = bI + ((double)reflectance.B * cl2.B) * specularity;
                    }
                }
            }
            else
            {
                if (recurse >= maxrecurse)
                {
                    // Recurse limit reached.
                    int i = 0;
                    i = i * 3;
                }
            }
            if (surf.Attenutive && inside)
            {
                rI *= atten.R;
                gI *= atten.G;
                bI *= atten.B;
            }
            colors.R = rI;
            colors.G = gI;
            colors.B = bI;
            return colors;
        }
コード例 #6
0
ファイル: ToyTracer.cs プロジェクト: Tilps/Stash
 private ColorIntensity ShadowShade(RealHitInfo hit, Line by, int threadId, double lightdist)
 {
     return ShadowShade(hit, by, 0, 1.0, false, threadId, lightdist);
 }
コード例 #7
0
ファイル: Box.cs プロジェクト: Tilps/Stash
 public override RealHitInfo DelayedHitCalc(Line by, HitInfo hit)
 {
     RealHitInfo realHit = new RealHitInfo();
     realHit.Normal = new Line();
     realHit.HitStuff = Surface;
     realHit.Pigment = Pigment;
     realHit.Normal.Start = by.Project(hit.HitDist);
     realHit.Normal.Direct.Dx = 0;
     realHit.Normal.Direct.Dy = 0;
     realHit.Normal.Direct.Dz = 0;
     Point hitLoc;
     Vector deviance = new Vector();
     if (rounded)
     {
         hitLoc = inv.Apply(realHit.Normal.Start);
         if (hit.SurfaceIndex != 5 || !RoundedTopOnly)
         {
             if (hitLoc.X < -1 + XRounding)
             {
                 switch (hit.SurfaceIndex)
                 {
                     case 2:
                     case 3:
                     case 4:
                     case 5:
                         deviance.Dx = -1 + (hitLoc.X + 1) / XRounding;
                         break;
                 }
             }
             if (hitLoc.X > 1 - XRounding)
             {
                 switch (hit.SurfaceIndex)
                 {
                     case 2:
                     case 3:
                     case 4:
                     case 5:
                         deviance.Dx = 1 - (1 - hitLoc.X) / XRounding;
                         break;
                 }
             }
             if (hitLoc.Y < -1 + YRounding)
             {
                 switch (hit.SurfaceIndex)
                 {
                     case 0:
                     case 1:
                     case 4:
                     case 5:
                         deviance.Dy = -1 + (hitLoc.Y + 1) / YRounding;
                         break;
                 }
             }
             if (hitLoc.Y > 1 - YRounding)
             {
                 switch (hit.SurfaceIndex)
                 {
                     case 0:
                     case 1:
                     case 4:
                     case 5:
                         deviance.Dy = 1 - (1 - hitLoc.Y) / YRounding;
                         break;
                 }
             }
         }
         if (!RoundedTopOnly && hitLoc.Z < -1 + ZRounding)
         {
             switch (hit.SurfaceIndex)
             {
                 case 0:
                 case 1:
                 case 2:
                 case 3:
                     deviance.Dz = -1 +(hitLoc.Z + 1) / ZRounding;
                     break;
             }
         }
         if (hitLoc.Z > 1 - ZRounding)
         {
             switch (hit.SurfaceIndex)
             {
                 case 0:
                 case 1:
                 case 2:
                 case 3:
                     deviance.Dz = 1 - (1 - hitLoc.Z) / ZRounding;
                     break;
             }
         }
     }
     switch (hit.SurfaceIndex)
     {
         case 0:
             realHit.Normal.Direct.Dx = 1;
             break;
         case 1:
             realHit.Normal.Direct.Dx = -1;
             break;
         case 2:
             realHit.Normal.Direct.Dy = 1;
             break;
         case 3:
             realHit.Normal.Direct.Dy = -1;
             break;
         case 4:
             realHit.Normal.Direct.Dz = 1;
             break;
         case 5:
             realHit.Normal.Direct.Dz = -1;
             break;
         default:
             throw new InvalidOperationException("Invalid surface index in hitdata");
     }
     Vector before = realHit.Normal.Direct;
     realHit.Normal.Direct = trans.Apply(realHit.Normal.Direct);
     if (realHit.Normal.Direct.Dot(by.Direct) > 0)
     {
         if (rounded)
         {
             before.ScaleSelf(-1.0);
             deviance.ScaleSelf(-1.0);
         }
         else
             realHit.Normal.Direct.ScaleSelf(-1.0);
     }
     if (rounded)
     {
         realHit.Normal.Direct = before;
         realHit.Normal.Direct.Add(deviance);
         realHit.Normal.Direct = trans.Apply(realHit.Normal.Direct);
         if (realHit.Normal.Direct.Dot(by.Direct) > 0)
         {
             Vector perp1 = realHit.Normal.Direct.Cross(by.Direct);
             realHit.Normal.Direct = by.Direct.Cross(perp1);
         }
     }
     return realHit;
 }