示例#1
0
        public static Vec trace(Vec origin, Vec direction)
        {
            var    hitPoint     = new Vec(0, 0, 0);
            var    normal       = new Vec(0, 0, 0);
            var    result       = new Vec(0, 0, 0);
            double attenuation  = 1.0;
            var    newDirection = new Vec(direction.x, direction.y, direction.z);
            var    newOrigin    = new Vec(origin.x, origin.y, origin.z);

            for (int bounceCount = 3; bounceCount > 0; --bounceCount)
            {
                Hit hitType = rayMarching(newOrigin, newDirection, ref hitPoint, ref normal);
                if (hitType == Hit.None)
                {
                    break;
                }
                if (hitType == Hit.Figure)   // Specular bounce on a letter. No color acc.

                {
                    newDirection.minusM(normal.times(normal.dot(newDirection) * 2.0));
                    newOrigin    = hitPoint.plus(newDirection.times(0.1));
                    attenuation *= 0.2;
                }
                else if (hitType == Hit.Wall)
                {
                    double incidence = normal.dot(lightDirection);
                    double p         = 6.283185 * rnd.NextDouble();
                    double c         = rnd.NextDouble();
                    double s         = Math.Sqrt(1.0 - c);
                    double g         = normal.z < 0 ? -1 : 1;
                    double u         = -1 / (g + normal.z);
                    double v         = normal.x * normal.y * u;
                    Vec    a         = new Vec(v, g + normal.y * normal.y * u, -normal.y);
                    a.timesM(s * Math.Cos(p));
                    Vec b = new Vec(1 + g * normal.x * normal.x * u, g * v, -g * normal.x);
                    b.timesM(s * Math.Sin(p));

                    newDirection = a;
                    newDirection.plusM(b);
                    newDirection.plusM(normal.times(Math.Sqrt(c)));
                    newOrigin    = hitPoint.plus(newDirection.times(0.1));
                    attenuation *= 0.2;
                    var ptAbove = hitPoint.plus(normal.times(0.1));
                    if (incidence > 0)
                    {
                        var tmp = rayMarching(ptAbove, lightDirection, ref hitPoint, ref normal);
                        if (tmp == Hit.Sun)
                        {
                            result.plusM(colorWall.times(attenuation * incidence));
                        }
                    }
                }
                else if (hitType == Hit.Sun)
                {
                    result.plusM(colorSun.times(attenuation));
                    break;
                }
            }
            return(result);
        }
示例#2
0
        public static Hit rayMarching(Vec origin, Vec direction, ref Vec hitPos, ref Vec hitNorm)
        {
            Hit    hitType    = Hit.None;
            int    noHitCount = 0;
            double d          = 0.0; // distance from the closest object in the world.

            for (double totalD = 0; totalD < 100; totalD += d)
            {
                hitPos = origin.plus(direction.times(totalD));
                d      = queryDatabase(hitPos, ref hitType);
                if (d < 0.01 || ++noHitCount > 99)
                {
                    Hit    temp  = Hit.None;
                    double normX = queryDatabase(hitPos.plus(dX), ref temp) - d;
                    double normY = queryDatabase(hitPos.plus(dY), ref temp) - d;
                    double normZ = queryDatabase(hitPos.plus(dZ), ref temp) - d;
                    hitNorm = (new Vec(normX, normY, normZ)).normalize();
                    return(hitType);
                }
            }
            return(Hit.None);
        }