Пример #1
0
    static Color GetColor(Ray ray, HitableList world)
    {
        //Sphere sphere = new Sphere(new Vector3(0, 0, -1), 0.5f);
        //float enter = 0;
        m_maxStackDepth += 1;
        HitRecord hitRecord = new HitRecord();

        if (m_maxStackDepth <= 5 && world.Hit(ray, out hitRecord))
        {
            //return 0.5f * new Color(hitRecord.m_normal.x + 1f, hitRecord.m_normal.y + 1f, hitRecord.m_normal.z + 1f);
            Vector3 target = hitRecord.m_point + hitRecord.m_normal + RandomInUnitSphere();
            return(0.5f * GetColor(new Ray(hitRecord.m_point, target - hitRecord.m_point), world));
        }
        else
        {
            //Color src = Color.white;
            //Color des = Color.blue;

            float y      = ray.direction.y;
            float weight = (y + 1) / 2;
            //float range = 1 - (-1);
            //float weight = -1 + offset * range;

            //int r = (int)((1 - weight) * src.R + weight * des.R);
            //int g = (int)((1 - weight) * src.G + weight * des.G);
            //int b = (int)((1 - weight) * src.B + weight * des.B);

            //return Color.FromArgb(255, r, g, b);
            return(Color.Lerp(Color.white, new Color(0.5f, 0.7f, 1.0f), weight));
        }
    }
Пример #2
0
        private Vector3D GetColor(Ray r, HitableList world, int depth)
        {
            HitRecord rec;

            if (world.Hit(r, 0.001, double.MaxValue, out rec))
            {
                Ray      scattered;
                Vector3D attenuation;
                if (depth < 50 && rec.matPtr.Scatter(r, rec, out attenuation, out scattered)) //只递归50次,避免无谓的性能浪费
                {
                    Vector3D color = GetColor(scattered, world, depth + 1);                   //每次光线衰减之后深度加一
                    return(new Vector3D(attenuation.X * color.X, attenuation.Y * color.Y, attenuation.Z * color.Z));
                }
                else
                {
                    return(new Vector3D(0, 0, 0));
                }
            }
            else
            {
                Vector3D unitDirection = r.Direction.UnitVector();
                double   t             = 0.5 * (unitDirection.Y + 1);
                return((1 - t) * new Vector3D(1, 1, 1) + t * new Vector3D(0.5, 0.7, 1));
            }
        }
Пример #3
0
    void DrawPicture()
    {
        int            sampleCount = 1;
        Hitable        sphere1     = new Sphere(new Vector3(0, 0, -1), 0.5f);
        Hitable        sphere2     = new Sphere(new Vector3(0, -100.5f, -1), 100);
        List <Hitable> hitList     = new List <Hitable>();

        hitList.Add(sphere1);
        hitList.Add(sphere2);
        Hitable   world  = new HitableList(hitList);
        CameraRay camRay = new CameraRay();

        for (int i = 0; i < screenWidth; ++i)
        {
            for (int j = 0; j < screenHeight; ++j)
            {
                Color c = Color.black;
                for (int k = 0; k < sampleCount; ++k)
                {
                    float t1 = Random.Range(0.0f, 1.0f);
                    float t2 = Random.Range(0.0f, 1.0f);
                    Ray   r  = camRay.GetRay((i + t1) / screenWidth, (j + t2) / screenHeight);
                    c += GetColor(r, world);
                }
                c = c / sampleCount;
                MoDraw.Instance.DrawPoint(new Vector2Int(i, j), c);
            }
        }
    }
Пример #4
0
        public PixelBuffer Execute(int width, int height)
        {
            var pixelBuffer     = new PixelBuffer(width, height);
            var lowerLeftCorner = new Vector3(-2.0f, -1.0f, -1.0f);
            var horizontal      = new Vector3(4.0f, 0.0f, 0.0f);
            var vertical        = new Vector3(0.0f, 2.0f, 0.0f);
            var origin          = Vector3.Zero;

            var hitables = new HitableList
            {
                new Sphere(new Vector3(0.0f, 0.0f, -1.0f), 0.5f),
                new Sphere(new Vector3(0.0f, -100.5f, -1.0f), 100.0f)
            };

            var world = new HitableList
            {
                hitables
            };

            for (int j = height - 1; j >= 0; j--)
            {
                for (int i = 0; i < width; i++)
                {
                    float u = Convert.ToSingle(i) / Convert.ToSingle(width);
                    float v = Convert.ToSingle(j) / Convert.ToSingle(height);
                    var   r = new Ray(origin, lowerLeftCorner + (u * horizontal) + (v * vertical));

                    var color = GetRayColor(r, world);
                    pixelBuffer.SetPixelColor(i, j, color);
                }
            }

            return(pixelBuffer);
        }
Пример #5
0
        private Vector3D GetColor(Ray r, HitableList world, int depth)
        {
            HitRecord rec;

            /*这里的0.001不能改为0,当tmin设0的时候会导致,遍历hitlist时候,ray的t求解出来是0,
             * hit的时候全走了else,导致递归到50层的时候,最后return的是0,* attenuation结果还是0。
             * 距离越远,散射用到random_in_unit_sphere生成的ray误差越大
             */
            if (world.Hit(r, 0.001, double.MaxValue, out rec))
            {
                Ray      scattered;
                Vector3D attenuation;
                Vector3D emitted = rec.matPtr.Emitted(rec.u, rec.v, rec.p);
                if (depth < 50 && rec.matPtr.Scatter(r, rec, out attenuation, out scattered)) //只递归50次,避免无谓的性能浪费
                {
                    Vector3D color = GetColor(scattered, world, depth + 1);                   //每次光线衰减之后深度加一
                    return(emitted + new Vector3D(attenuation.X * color.X, attenuation.Y * color.Y, attenuation.Z * color.Z));
                }
                else
                {
                    return(emitted);
                }
            }
            else
            {
                return(new Vector3D(0, 0, 0));
            }
        }
Пример #6
0
        internal static Vector3 Color(Ray3 r, HitableList world, int depth)
        {
            HitRecord record = world.Hit(r, 0.01, 10000);

            if (null != record)
            {
                if (depth < 50)
                {
                    ScatterRecord sr = record.Material.Scatter(r, record);
                    if (null != sr)
                    {
                        return(sr.Attenuation * Color(sr.Scatter, world, depth + 1));
                    }
                }

                // Either got absorbed by material or this ray refracted/reflected 50 times.
                // Don't want to go more than 50 depth so stop here in that case.
                return(BlackColor);
            }

            Vector3 unitDir = r.Direction.ToUnitVector();
            double  t       = 0.5 * (unitDir.Y + 1.0);

            return((1.0 - t) * WhiteColor + t * SkyColor);
        }
Пример #7
0
        private void InitScene()
        {
            int  width  = 2000;
            int  height = 1000;
            bool isSky  = false;

            Vector3D lookFrom    = new Vector3D(13, 15, 25);
            Vector3D lookAt      = new Vector3D(0, 0, 0);
            float    diskToFocus = (lookFrom - lookAt).Length();
            float    aperture    = 0;
            Camera   camera      = new Camera(lookFrom, lookAt, new Vector3D(0, 1, 0), 20,
                                              (float)width / (float)height, aperture, 0.7f * diskToFocus, 0, 1);


            HitableList    world   = new HitableList();
            List <Hitable> list    = new List <Hitable>();
            Texture        perText = new NoiseTexture(5f);

            list.Add(new Sphere(new Vector3D(0, -1000, 0), 1000, new Lambertian(perText)));
            list.Add(new Sphere(new Vector3D(0, 2, 0), 2, new Lambertian(perText)));
            list.Add(new Sphere(new Vector3D(0, 7, 0), 2, new DiffuseLight(new ConstantTexture(new Vector3D(10, 10, 10)))));
            list.Add(new XYRect(3, 5, 1, 3, -2, new DiffuseLight(new ConstantTexture(new Vector3D(10, 10, 10)))));
            world.list = list;
            scene      = new Scene(width, height, world, isSky, camera, 0, true);

            //使用直接光源采样
            //HitableList lightShapeList = new HitableList();
            //lightShapeList.list.Add(new Sphere(new Vector3D(0, 7, 0), 2, null));
            //lightShapeList.list.Add(new XYRect(3, 5, 1, 3, -2, null));
            //scene = new Scene(width, height, world, isSky, camera, 1, false, lightShapeList);
        }
Пример #8
0
        private IHitable CreateRandomScene()
        {
            var list = new HitableList
            {
                new Sphere(new Vector3(0.0f, -1000.0f, 0.0f), 1000.0f, new LambertianMaterial(new ColorTexture(0.5f, 0.5f, 0.5f)))
            };

            for (int a = -11; a < 11; a++)
            {
                for (int b = -11; b < 11; b++)
                {
                    float chooseMat = RandomService.Nextfloat();
                    var   center    = new Vector3(
                        Convert.ToSingle(a) * RandomService.Nextfloat(),
                        0.2f,
                        Convert.ToSingle(b) + (0.9f * RandomService.Nextfloat()));
                    if ((center - new Vector3(4.0f, 0.2f, 0.0f)).Length() > 0.9)
                    {
                        if (chooseMat < 0.8)
                        {
                            // diffuse
                            list.Add(
                                new Sphere(
                                    center,
                                    0.2f,
                                    new LambertianMaterial(
                                        new ColorTexture(
                                            RandomService.Nextfloat() * RandomService.Nextfloat(),
                                            RandomService.Nextfloat() * RandomService.Nextfloat(),
                                            RandomService.Nextfloat() * RandomService.Nextfloat()))));
                        }
                        else if (chooseMat < 0.95)
                        {
                            // metal
                            list.Add(
                                new Sphere(
                                    center,
                                    0.2f,
                                    new MetalMaterial(
                                        new ColorVector(
                                            0.5f * (1.0f + RandomService.Nextfloat()),
                                            0.5f * (1.0f + RandomService.Nextfloat()),
                                            0.5f * (1.0f + RandomService.Nextfloat())),
                                        0.5f * RandomService.Nextfloat())));
                        }
                        else
                        {
                            // glass
                            list.Add(new Sphere(center, 0.2f, new DialectricMaterial(1.5f)));
                        }
                    }
                }
            }

            list.Add(new Sphere(new Vector3(0.0f, 1.0f, 0.0f), 1.0f, new DialectricMaterial(1.5f)));
            list.Add(new Sphere(new Vector3(-4.0f, 1.0f, 0.0f), 1.0f, new LambertianMaterial(new ColorTexture(0.4f, 0.2f, 0.1f))));
            list.Add(new Sphere(new Vector3(4.0f, 1.0f, 0.0f), 1.0f, new MetalMaterial(new ColorVector(0.7f, 0.6f, 0.5f), 0.0f)));

            return(list);
        }
Пример #9
0
        /// <inheritdoc />
        public IHitable GetWorld()
        {
            var red   = new LambertianMaterial(new ColorTexture(0.65f, 0.05f, 0.05f));
            var white = new LambertianMaterial(new ColorTexture(0.73f, 0.73f, 0.73f));
            var green = new LambertianMaterial(new ColorTexture(0.12f, 0.45f, 0.15f));

            var b1 = new Translate(
                new RotateY(new Box(new Vector3(0.0f, 0.0f, 0.0f), new Vector3(165.0f, 165.0f, 165.0f), white), -18.0f),
                new Vector3(130.0f, 0.0f, 65.0f));
            var b2 = new Translate(
                new RotateY(new Box(new Vector3(0.0f, 0.0f, 0.0f), new Vector3(165.0f, 330.0f, 165.0f), white), 15.0f),
                new Vector3(265.0f, 0.0f, 295.0f));

            var list = new HitableList()
            {
                new FlipNormals(new YzRect(0.0f, 555.0f, 0.0f, 555.0f, 555.0f, green)),
                new YzRect(0.0f, 555.0f, 0.0f, 555.0f, 0.0f, red),
                new FlipNormals(_light),
                new FlipNormals(new XzRect(0.0f, 555.0f, 0.0f, 555.0f, 555.0f, white)),
                new XzRect(0.0f, 555.0f, 0.0f, 555.0f, 0.0f, white),
                new FlipNormals(new XyRect(0.0f, 555.0f, 0.0f, 555.0f, 555.0f, white)),

                new ConstantMedium(b1, 0.01f, new ColorTexture(1.0f, 1.0f, 1.0f)),
                new ConstantMedium(b2, 0.01f, new ColorTexture(0.0f, 0.0f, 0.0f))
            };

            return(new BvhNode(list, 0.0f, 1.0f));
        }
Пример #10
0
    private Vector3D GetColor(Ray r, HitableList world, int depth)
    {
        HitRecord rec;

        /*这里的0.001不能改为0,当tmin设0的时候会导致,遍历hitlist时候,ray的t求解出来是0,
         * hit的时候全走了else,导致递归到50层的时候,最后return的是0,* attenuation结果还是0。
         * 距离越远,散射用到random_in_unit_sphere生成的ray误差越大
         */
        if (world.Hit(r, 0.001f, float.MaxValue, out rec))
        {
            Ray      scattered;
            Vector3D attenuation;
            Vector3D emitted = rec.matPtr.Emitted(rec.u, rec.v, rec.p);
            if (depth < 4 && rec.matPtr.Scatter(r, rec, out attenuation, out scattered))
            {
                Vector3D color = GetColor(scattered, world, depth + 1);      //每次光线衰减之后深度加一
                return(emitted + new Vector3D(attenuation.X * color.X, attenuation.Y * color.Y, attenuation.Z * color.Z));
            }
            else
            {
                return(emitted);
            }
        }
        else
        {
            //Vector3D unitDirection = r.Direction.UnitVector();
            //float t = 0.5 * (unitDirection.Y + 1);
            //return (1 - t) * new Vector3D(1, 1, 1) + t * new Vector3D(0.5, 0.7, 1);
            return(new Vector3D(0, 0, 0));
        }
    }
Пример #11
0
        private void InitScene()
        {
            int  width  = 2000;
            int  height = 1000;
            bool isSky  = true;

            Vector3D lookFrom    = new Vector3D(13, 2, 3);
            Vector3D lookAt      = new Vector3D(0, 0, 0);
            float    diskToFocus = (lookFrom - lookAt).Length();
            float    aperture    = 0;
            Camera   camera      = new Camera(lookFrom, lookAt, new Vector3D(0, 1, 0), 20,
                                              (float)width / (float)height, aperture, 0.7f * diskToFocus, 0, 1);

            Texture checker = new CheckerTexture(
                new ConstantTexture(new Vector3D(0.2f, 0.3f, 0.1f)),
                new ConstantTexture(new Vector3D(0.9f, 0.9f, 0.9f)));
            List <Hitable> list = new List <Hitable>();

            list.Add(new Sphere(new Vector3D(0, -1000, 0), 1000, new Lambertian(checker)));
            for (int a = -11; a < 11; a++)
            {
                for (int b = -11; b < 11; b++)
                {
                    double   chooseMat = Mathf.Randomfloat();
                    Vector3D center    = new Vector3D(a + 0.9f * Mathf.Randomfloat(), 0.2f, b + 0.9f * Mathf.Randomfloat());
                    if ((center - new Vector3D(4, 0.2f, 0)).Length() > 0.9)
                    {
                        if (chooseMat < 0.8)
                        {
                            list.Add(new MovingSphere(center, center + new Vector3D(0, 0.5f * Mathf.Randomfloat(), 0), 0, 1, 0.2f,
                                                      new Lambertian(new ConstantTexture(new Vector3D(
                                                                                             Mathf.Randomfloat() * Mathf.Randomfloat(),
                                                                                             Mathf.Randomfloat() * Mathf.Randomfloat(),
                                                                                             Mathf.Randomfloat() * Mathf.Randomfloat())))));
                        }
                        else if (chooseMat < 0.95)
                        {
                            list.Add(new Sphere(center, 0.2f, new Metal(new Vector3D(
                                                                            0.5f * (1 + Mathf.Randomfloat()),
                                                                            0.5f * (1 + Mathf.Randomfloat()),
                                                                            0.5f * (1 + Mathf.Randomfloat())),
                                                                        0.5f * (1 + Mathf.Randomfloat()))));
                        }
                        else
                        {
                            list.Add(new Sphere(center, 0.2f, new Dielectric(1.5f)));
                        }
                    }
                }
            }
            list.Add(new Sphere(new Vector3D(0, 1, 0), 1, new Dielectric(1.5f)));
            list.Add(new Sphere(new Vector3D(-4, 1, 0), 1, new Lambertian(new ConstantTexture(new Vector3D(0.4f, 0.2f, 0.1f)))));
            list.Add(new Sphere(new Vector3D(4, 1, 0), 1, new Metal(new Vector3D(0.7f, 0.6f, 0.5f), 0)));
            BVHNode     bb    = new BVHNode(list, list.Count, 0, 1);
            HitableList world = new HitableList();

            world.list.Add(bb);
            scene = new Scene(width, height, world, isSky, camera, 0, false);
        }
Пример #12
0
    protected override void Awake()
    {
        base.Awake();

        scene = new HitableList();

        scene.list.Add(new RTSphere().Set(new Vector3(0, 0, -1), 0.5f));
        scene.list.Add(new RTSphere().Set(new Vector3(0, -100.5f, -1), 100));
    }
Пример #13
0
        public PixelBuffer Execute(int width, int height)
        {
            var   pixelBuffer     = new PixelBuffer(width, height);
            float aperture        = 2.0f;
            var   lookFrom        = new Vector3(3.0f, 3.0f, 2.0f);
            var   lookAt          = new Vector3(0.0f, 0.0f, -1.0f);
            float distanceToFocus = (lookFrom - lookAt).Length(); // .Magnitude();
            var   camera          = new Camera(
                lookFrom,
                lookAt,
                new Vector3(0.0f, 1.0f, 0.0f),
                30.0f,
                Convert.ToSingle(width) / Convert.ToSingle(height),
                aperture,
                distanceToFocus);

            var hitables = new HitableList
            {
                new Sphere(new Vector3(0.0f, 0.0f, -1.0f), 0.5f, new LambertianMaterial(new ColorTexture(0.1f, 0.2f, 0.5f))),
                new Sphere(new Vector3(0.0f, -100.5f, -1.0f), 100.0f, new LambertianMaterial(new ColorTexture(0.8f, 0.8f, 0.0f))),
                new Sphere(new Vector3(1.0f, 0.0f, -1.0f), 0.5f, new MetalMaterial(new ColorVector(0.8f, 0.6f, 0.2f), 0.3f)),
                new Sphere(new Vector3(-1.0f, 0.0f, -1.0f), 0.5f, new DialectricMaterial(1.5f)),
                new Sphere(new Vector3(-1.0f, 0.0f, -1.0f), -0.45f, new DialectricMaterial(1.5f)),
            };

            var world = new HitableList
            {
                hitables
            };

            for (int j = height - 1; j >= 0; j--)
            {
                for (int i = 0; i < width; i++)
                {
                    ColorVector color = new ColorVector(0.0f, 0.0f, 0.0f);
                    for (int sample = 0; sample < _numSamples; sample++)
                    {
                        float u = Convert.ToSingle(i + RandomService.Nextfloat()) / Convert.ToSingle(width);
                        float v = Convert.ToSingle(j + RandomService.Nextfloat()) / Convert.ToSingle(height);
                        var   r = camera.GetRay(u, v);

                        color += GetRayColor(r, world, 0);
                    }

                    color /= Convert.ToSingle(_numSamples);
                    color  = color.ApplyGamma2();

                    pixelBuffer.SetPixelColor(i, j, color);
                }

                Console.Write(".");
            }

            Console.WriteLine();
            return(pixelBuffer);
        }
Пример #14
0
    public int[] changes;                   //記錄每個點的采樣率

    public Renderer(Scene scene, int samples = 1000)
    {
        this.scene   = scene;
        this.width   = scene.Width;
        this.height  = scene.Height;
        this.isSky   = scene.IsSky;
        this.world   = scene.World;
        this.camera  = scene.Camera;
        this.samples = samples;
        Init();
    }
Пример #15
0
    private Vector3D GetColor(Ray r, HitableList world, Hitable lightShape, int depth)
    {
        HitRecord hRec;

        /*这里的0.001不能改为0,当tmin设0的时候会导致,遍历hitlist时候,ray的t求解出来是0,
         * hit的时候全走了else,导致递归到50层的时候,最后return的是0,* attenuation结果还是0。
         * 距离越远,散射用到random_in_unit_sphere生成的ray误差越大
         */
        if (world.Hit(r, 0.001f, float.MaxValue, out hRec))
        {
            ScatterRecord sRec;
            Vector3D      emitted = hRec.matPtr.Emitted(r, hRec, hRec.u, hRec.v, hRec.p);
            if (depth < 50 && hRec.matPtr.Scatter(r, hRec, out sRec))
            {
                if (sRec.isSpecular)
                {
                    Vector3D c = GetColor(sRec.specularRay, world, lightShape, depth + 1);
                    return(new Vector3D(sRec.attenuation.X * c.X, sRec.attenuation.Y * c.Y, sRec.attenuation.Z * c.Z));
                }
                PDF p;
                if (lightShape != null)
                {
                    HitablePDF p0 = new HitablePDF(lightShape, hRec.p);
                    p = new MixturePDF(p0, sRec.pdfPtr);
                    ((MixturePDF)p).MixRatio = scene.MixRatio;
                }
                else
                {
                    p = sRec.pdfPtr;
                }
                //CosinePDF p = new CosinePDF(hRec.normal);
                Ray      scattered = new Ray(hRec.p, p.Generate(), r.Time);
                float    pdfVal    = p.Value(scattered.Direction);
                Vector3D color     = GetColor(scattered, world, lightShape, depth + 1);  //每次光线衰减之后深度加一
                return(emitted + hRec.matPtr.ScatteringPDF(r, hRec, scattered)
                       * new Vector3D(sRec.attenuation.X * color.X, sRec.attenuation.Y
                                      * color.Y, sRec.attenuation.Z * color.Z) / pdfVal);
            }
            else
            {
                return(emitted);
            }
        }
        else
        {
            if (isSky)
            {
                Vector3D unitDirection = r.Direction.UnitVector();
                float    t             = 0.5f * (unitDirection.Y + 1f);
                return((1 - t) * new Vector3D(1, 1, 1) + t * new Vector3D(0.5f, 0.7f, 1));
            }
            return(new Vector3D(0, 0, 0));
        }
    }
Пример #16
0
        private SColor NormalMap(Ray ray, HitableList hitableList)
        {
            ShadeRec record = new ShadeRec();

            if (hitableList.Hit(ray, 0.0, double.MaxValue, ref record))
            {
                return(0.5 * new SColor(record.normal.X + 1, record.normal.Y + 1, record.normal.Z + 1, 2.0));
            }
            double t = 0.5 * ray.normalDirection.Y + 1.0;

            return((1 - t) * new SColor(1, 1, 1) + t * new SColor(0.5, 0.7, 1));
        }
Пример #17
0
        private Color32 NormalMap(Ray ray, HitableList hitableList)
        {
            var record = new HitRecord();

            if (hitableList.Hit(ray, 0f, float.MaxValue, ref record))
            {
                return(0.5f * new Color32(record.normal.x + 1, record.normal.y + 1, record.normal.z + 1, 2f));
            }
            var t = 0.5f * ray.normalDirection.y + 1f;

            return((1 - t) * new Color32(1, 1, 1) + t * new Color32(0.5f, 0.7f, 1));
        }
Пример #18
0
        Color GetColorForTestHitRecord(Ray ray, HitableList hitableList)
        {
            HitRecord record = new HitRecord();

            if (hitableList.Hit(ray, 0f, float.MaxValue, ref record))
            {
                return(0.5f * new Color(record.normal.x + 1, record.normal.y + 1, record.normal.z + 1, 2f));
            }
            float t = 0.5f * ray.normalDirection.y + 1f;

            return((1 - t) * new Color(1, 1, 1) + t * new Color(0.5f, 0.7f, 1));
        }
Пример #19
0
    private static Color GetColorFromScene(Ray ray, HitableList hitableList)
    {
        HitRecord record = new HitRecord();

        if (hitableList.Hit(ray, 0f, float.MaxValue, ref record))
        {
            return(0.5f * new Color(record.normal.x + 1, record.normal.y + 1, record.normal.z + 1, 1f));
        }

        float t = (ray.direction.y + 1) * .5f;

        return((1 - t) * Color.white + new Color(0.5f, 0.7f, 1.0f));
    }
Пример #20
0
    private static Color GetColorForTestDiffusing(Ray ray, HitableList hitableList)
    {
        HitRecord record = new HitRecord();

        if (hitableList.Hit(ray, 0.0001f, float.MaxValue, ref record))
        {
            Vector3 target = record.p + record.normal + GetRandomDir();
            return(0.5f * GetColorForTestDiffusing(new Ray(record.p, target - record.p), hitableList));
        }

        float t = (ray.direction.y + 1) * .5f;

        return((1 - t) * Color.white + new Color(0.5f, 0.7f, 1.0f));
    }
Пример #21
0
        public PixelBuffer Execute(int width, int height)
        {
            var pixelBuffer     = new PixelBuffer(width, height);
            var lowerLeftCorner = new Vector3(-2.0f, -1.0f, -1.0f);
            var horizontal      = new Vector3(4.0f, 0.0f, 0.0f);
            var vertical        = new Vector3(0.0f, 2.0f, 0.0f);
            var origin          = Vector3.Zero;

            var camera = new BasicCamera(origin, lowerLeftCorner, horizontal, vertical);

            var hitables = new HitableList
            {
                new Sphere(new Vector3(0.0f, 0.0f, -1.0f), 0.5f, new LambertianMaterial(new ColorTexture(0.8f, 0.3f, 0.3f))),
                new Sphere(new Vector3(0.0f, -100.5f, -1.0f), 100.0f, new LambertianMaterial(new ColorTexture(0.8f, 0.8f, 0.0f))),
                new Sphere(new Vector3(1.0f, 0.0f, -1.0f), 0.5f, new MetalMaterial(new ColorVector(0.8f, 0.6f, 0.2f), 0.3f)),
                new Sphere(new Vector3(-1.0f, 0.0f, -1.0f), 0.5f, new DialectricMaterial(1.5f)),
                new Sphere(new Vector3(-1.0f, 0.0f, -1.0f), -0.45f, new DialectricMaterial(1.5f)),
            };

            var world = new HitableList
            {
                hitables
            };

            for (int j = height - 1; j >= 0; j--)
            {
                for (int i = 0; i < width; i++)
                {
                    ColorVector color = new ColorVector(0.0f, 0.0f, 0.0f);
                    for (int sample = 0; sample < _numSamples; sample++)
                    {
                        float u = Convert.ToSingle(i + RandomService.Nextfloat()) / Convert.ToSingle(width);
                        float v = Convert.ToSingle(j + RandomService.Nextfloat()) / Convert.ToSingle(height);
                        var   r = camera.GetRay(u, v);

                        color += GetRayColor(r, world, 0);
                    }

                    color /= Convert.ToSingle(_numSamples);
                    color  = color.ApplyGamma2();

                    pixelBuffer.SetPixelColor(i, j, color);
                }

                Console.Write(".");
            }

            Console.WriteLine();
            return(pixelBuffer);
        }
Пример #22
0
        public static Color32 GetColor(Ray ray, HitableList hitableList)
        {
            var record = new HitRecord();

            if (hitableList.Hit(ray, 0f, float.MaxValue, ref record))
            {
                ScatterRecord trash = new ScatterRecord();
                record.shader.scatter(ray, ref record, ref trash);
                return(0.5f * new Color32(record.normal.x + 1, record.normal.y + 1, record.normal.z + 1, 2f));
            }
            var t = 0.5f * ray.normal_direction.y + 1f;

            return((1 - t) * new Color32(1, 1, 1) + t * new Color32(0.5f, 0.7f, 1));
        }
Пример #23
0
    private Vector3D GetColor(Ray r, HitableList world, int depth)
    {
        HitRecord rec;

        /*这里的0.001不能改为0,当tmin设0的时候会导致,遍历hitlist时候,ray的t求解出来是0,
         * hit的时候全走了else,导致递归到50层的时候,最后return的是0,* attenuation结果还是0。
         * 距离越远,散射用到random_in_unit_sphere生成的ray误差越大
         */
        if (world.Hit(r, 0.001f, float.MaxValue, out rec))
        {
            Ray      scattered;
            Vector3D emitted = rec.matPtr.Emitted(r, rec, rec.u, rec.v, rec.p);
            float    pdf;
            Vector3D albedo;
            if (depth < 50 && rec.matPtr.Scatter(r, rec, out albedo, out scattered, out pdf))
            {
                Vector3D onLight         = new Vector3D(213 + Mathf.Randomfloat() * (343 - 213), 554, 227 + Mathf.Randomfloat() * (332 - 227));
                Vector3D toLight         = onLight - rec.p;
                float    distanceSquared = toLight.SquaredMagnitude();
                toLight.Normalize();
                if (toLight * rec.normal < 0)
                {
                    return(emitted);
                }
                float lightArea   = (343 - 213) * (332 - 227);
                float lightCosine = Math.Abs(toLight.Y);
                if (lightCosine < 0.000001)
                {
                    return(emitted);
                }
                pdf       = distanceSquared / (lightCosine * lightArea);
                scattered = new Ray(rec.p, toLight, r.Time);
                Vector3D color = GetColor(scattered, world, depth + 1);      //每次光线衰减之后深度加一
                return(emitted + rec.matPtr.ScatteringPDF(r, rec, scattered)
                       * new Vector3D(albedo.X * color.X, albedo.Y * color.Y, albedo.Z * color.Z) / pdf);
            }
            else
            {
                return(emitted);
            }
        }
        else
        {
            //Vector3D unitDirection = r.Direction.UnitVector();
            //float t = 0.5f * (unitDirection.Y + 1f);
            //return (1 - t) * new Vector3D(1, 1, 1) + t * new Vector3D(0.5f, 0.7f, 1);
            return(new Vector3D(0, 0, 0));
        }
    }
Пример #24
0
        Color GetColorForTestDiffusing(Ray ray, HitableList hitableList)
        {
            HitRecord record = new HitRecord();

            if (hitableList.Hit(ray, 0.0001f, float.MaxValue, ref record))
            {
                Vector3 target = record.p + record.normal + GetRandomPointInUnitSphereForTestDiffusing();
                //此处假定有50%的光被吸收,剩下的则从入射点开始取随机方向再次发射一条射线
                return(0.5f * GetColorForTestDiffusing(new Ray(record.p, target - record.p), hitableList));
            }

            return(new Color(0.8f, 0.8f, 0.8f, 1));
            // float t = 0.5f * ray.normalDirection.y + 1f;
            // return (1 - t) * new Color(1, 1, 1) + t * new Color(0.5f, 0.7f, 1);
        }
Пример #25
0
    public Box(Vector3D p0, Vector3D p1, Material ptr)
    {
        pMin = p0;
        pMax = p1;
        List <Hitable> list = new List <Hitable>();

        list.Add(new XYRect(p0.X, p1.X, p0.Y, p1.Y, p1.Z, ptr));
        list.Add(new FlipNormals(new XYRect(p0.X, p1.X, p0.Y, p1.Y, p0.Z, ptr)));
        list.Add(new XZRect(p0.X, p1.X, p0.Z, p1.Z, p1.Y, ptr));
        list.Add(new FlipNormals(new XZRect(p0.X, p1.X, p0.Z, p1.Z, p0.Y, ptr)));
        list.Add(new YZRect(p0.Y, p1.Y, p0.Z, p1.Z, p1.X, ptr));
        list.Add(new FlipNormals(new YZRect(p0.Y, p1.Y, p0.Z, p1.Z, p0.X, ptr)));

        listPtr = new HitableList(list);
    }
    protected override void Awake()
    {
        base.Awake();

        isScreenSize    = true;
        numSamples      = 800;
        ppmTexture.sRGB = true;

        scene = new HitableList();

        scene.list.Add(
            new RTSphere().
            Set(new Vector3(0, 0, 0), 0.5f).
            SetMaterial <RTSphere>(
                new Lambertian().
                SetAlbedo <Lambertian>(new Color(0.8f, 0.3f, 0.3f))
                )
            );
        scene.list.Add(
            new RTSphere().
            Set(new Vector3(0, -100.5f, 0), 100).
            SetMaterial <RTSphere>(
                new Lambertian().
                SetAlbedo <Lambertian>(new Color(0.8f, 0.8f, 0.0f))
                )
            );

        scene.list.Add(
            new RTSphere().
            Set(new Vector3(1, 0, 0), 0.5f).
            SetMaterial <RTSphere>(
                new Metal().
                SetAlbedo <Metal>(new Color(0.8f, 0.6f, 0.2f)).
                SetFuzz(0.25f)
                )
            );

        scene.list.Add(
            new RTSphere().
            Set(new Vector3(-1, 0, 0), 0.5f).
            SetMaterial <RTSphere>(
//                    new Metal().
//                        SetAlbedo<Metal>(new Color(0.8f, 0.8f, 0.8f)).
//                        SetFuzz(0.5f)
                new Dielectric().SetRefractiveIndex(1.5f)
                )
            );
    }
Пример #27
0
 public Cube(Vector3 p0, Vector3 p1, Material mat, Material m2 = null)
 {
     pmax = p1;
     pmin = p0;
     if (m2 == null)
     {
         m2 = mat;
     }
     list = new HitableList();
     list.list.Add(new PlaneXY(p0.x, p1.x, p0.y, p1.y, p1.z, m2));
     list.list.Add(new FilpNormals(new PlaneXY(p0.x, p1.x, p0.y, p1.y, p0.z, m2)));
     list.list.Add(new PlaneXZ(p0.x, p1.x, p0.z, p1.z, p1.y, mat));
     list.list.Add(new FilpNormals(new PlaneXZ(p0.x, p1.x, p0.z, p1.z, p0.y, mat)));
     list.list.Add(new PlaneYZ(p0.y, p1.y, p0.z, p1.z, p1.x, m2));
     list.list.Add(new FilpNormals(new PlaneYZ(p0.y, p1.y, p0.z, p1.z, p0.x, m2)));
 }
Пример #28
0
 public Cube(Vector3D p0, Vector3D p1, Material mat, Material m2 = null)
 {
     pmax = p1;
     pmin = p0;
     if (m2 == null)
     {
         m2 = mat;
     }
     list = new HitableList();
     list.list.Add(new PlaneXY(p0.X, p1.X, p0.Y, p1.Y, p1.Z, m2));
     list.list.Add(new FilpNormals(new PlaneXY(p0.X, p1.X, p0.Y, p1.Y, p0.Z, m2)));
     list.list.Add(new PlaneXZ(p0.X, p1.X, p0.Z, p1.Z, p1.Y, mat));
     list.list.Add(new FilpNormals(new PlaneXZ(p0.X, p1.X, p0.Z, p1.Z, p0.Y, mat)));
     list.list.Add(new PlaneYZ(p0.Y, p1.Y, p0.Z, p1.Z, p1.X, m2));
     list.list.Add(new FilpNormals(new PlaneYZ(p0.Y, p1.Y, p0.Z, p1.Z, p0.X, m2)));
 }
Пример #29
0
        public Box(Vec3 p0, Vec3 p1, Material mat)
        {
            _pMin = p0;
            _pMax = p1;

            List <Hitable> tmpList = new List <Hitable>();

            tmpList.Add(new XYRect(p0.X(), p1.X(), p0.Y(), p1.Y(), p1.Z(), mat));
            tmpList.Add(new FlipNormals(new XYRect(p0.X(), p1.X(), p0.Y(), p1.Y(), p0.Z(), mat)));
            tmpList.Add(new XZRect(p0.X(), p1.X(), p0.Z(), p1.Z(), p1.Y(), mat));
            tmpList.Add(new FlipNormals(new XZRect(p0.X(), p1.X(), p0.Z(), p1.Z(), p0.Y(), mat)));
            tmpList.Add(new YZRect(p0.Y(), p1.Y(), p0.Z(), p1.Z(), p1.X(), mat));
            tmpList.Add(new FlipNormals(new YZRect(p0.Y(), p1.Y(), p0.Z(), p1.Z(), p0.X(), mat)));

            _list = new HitableList(tmpList);
        }
Пример #30
0
        /// <inheritdoc />
        public IHitable GetWorld()
        {
            var globe = PixelBuffer.FromFile(_globeImagePath);
            var list  = new HitableList()
            {
                new Sphere(
                    new Vector3(0.0f, -1000.0f, 0.0f),
                    1000.0f,
                    new LambertianMaterial(new VectorNoiseTexture(VectorNoiseMode.Soft, 3.0f))),
                new Sphere(
                    new Vector3(0.0f, 2.0f, 0.0f),
                    2.0f,
                    new LambertianMaterial(new ImageTexture(globe)))
            };

            return(new BvhNode(list, 0.0f, 1.0f));
        }