Пример #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 void run(Vec position, Vec dirObserver, int samplesCount, int w, int h)
        {
            Vec dirLeft = (new Vec(dirObserver.z, 0, -dirObserver.x)).normalize();

            //dirLeft.timesM(1.0 / w);
            dirLeft.timesM(1.0 / h);
            // Cross-product to get the up vector

            Vec dirUp = new Vec(dirObserver.y * dirLeft.z - dirObserver.z * dirLeft.y,
                                dirObserver.z * dirLeft.x - dirObserver.x * dirLeft.z,
                                dirObserver.x * dirLeft.y - dirObserver.y * dirLeft.x);

            dirUp.normalizeM();
            dirUp.timesM(1.0 / h);
            byte[] pixels = new byte[3 * w * h];

            for (int y = h; y > 0; --y)
            {
                for (int x = w; x > 0; --x)
                {
                    Vec color = new Vec(0, 0, 0);
                    for (int p = samplesCount; p > 0; --p)
                    {
                        var randomLeft    = dirLeft.times(x - w / 2 + rnd.NextDouble());
                        var randomUp      = dirUp.times((y - h / 2 + rnd.NextDouble()));
                        var randomizedDir = new Vec(dirObserver.x, dirObserver.y, dirObserver.z);
                        randomizedDir.plusM(randomLeft);
                        randomizedDir.plusM(randomUp);
                        randomizedDir.normalizeM();
                        //Hit hType = Hit.None;
                        var incr = trace(position, randomizedDir);
                        if (y < h / 2)
                        {
                            ;
                        }
                        color.plusM(incr);
                    }

                    // Reinhard tone mapping
                    color.timesM(241.0 / samplesCount);
                    color = new Vec((color.x + 14.0) / (color.x + 255.0),
                                    (color.y + 14.0) / (color.y + 255.0),
                                    (color.z + 14.0) / (color.z + 255.0));
                    color.timesM(255.0);
                    int index = 3 * (w * y - w + x - 1);
                    pixels[index]     = (byte)color.x;
                    pixels[index + 1] = (byte)color.y;
                    pixels[index + 2] = (byte)color.z;
                }
            }
            Output.createBMP(pixels, w, h, "card.bmp");
        }
Пример #3
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);
        }