Beispiel #1
0
        public static RayImage Render(int width, int height, int samples)
        {
            // As simple as possible code for now.
            var img = new RayImage();

            img.Width  = width;
            img.Height = height;
            img.Pixels = new Rgb3f[width * height];
            //int samples = 50;

            var   lookFrom      = new Vec3f(5f, 5f, 5f);
            var   lookAt        = new Vec3f(0, 0, -1f);
            float dist_to_focus = (lookFrom - lookAt).GetLength();
            float aperture      = 2.0f;

            var cam = new Camera(lookFrom, lookAt, Vec3f.UnitY,
                                 40, (float)width / (float)height, aperture, dist_to_focus);

            var drand = new Random();

            var world = RandomScene(drand);

            //var world = new HitableList(
            //    new Sphere(new Vec3f(0f, 0f, -1f), 0.5f, new Lambertian(new Vec3f(0.1f, 0.2f, 0.5f))),
            //    new Sphere(new Vec3f(0, -100.5f, -1f), 100, new Lambertian(new Vec3f(0.8f, 0.8f, 0.0f))),
            //    new Sphere(new Vec3f(1f, 0f, -1f), 0.5f, new Metal(new Vec3f(0.8f, 0.6f, 0.2f), 0.0f)),
            //    new Sphere(new Vec3f(-1f, 0f, -1f), 0.5f, new Dielectric(1.5f)),
            //    new Sphere(new Vec3f(-1f, 0f, -1f), -0.45f, new Dielectric(1.5f))
            //    );

            int cur = 0;

            for (int j = height - 1; j >= 0; j--)
            {
                for (int i = 0; i < width; i++)
                {
                    Vec3f col = Vec3f.Zero;

                    for (int s = 0; s < samples; s++)
                    {
                        float u = (float)(i + drand.NextDouble()) / (float)width;
                        float v = (float)(j + drand.NextDouble()) / (float)height;

                        Ray r = cam.GetRay(u, v, drand);
                        //Vec3f p = r.PointAtParameter(2.0f); // still not used.

                        col += Color(r, world, 0, drand);
                    }

                    col /= (float)samples;
                    // gamma correction ??
                    col = new Vec3f(MathF.Sqrt(col.X), MathF.Sqrt(col.Y), MathF.Sqrt(col.Z));
                    img.Pixels[cur++] = (Rgb3f)col;

                    //img.Pixels[cur++] = new Rgb3f() { R = r, G = g, B = b };
                }
            }

            return(img);
        }
Beispiel #2
0
        public static bool WriteTga(this RayImage img, Stream output)
        {
            try
            {
                var sizeHeader = Marshal.SizeOf <TgaHeader>();
                //const int sizeHeader = 18;
                var sizePixels = img.Width * img.Height * 3;

                var buffer = new byte[sizeHeader + sizePixels];
                var span   = new Span <byte>(buffer);

                // write header.
                // IMPORTENT TO USE REF HERE.
                ref TgaHeader header = ref MemoryMarshal.Cast <byte, TgaHeader>(span)[0];
                //var header = MemoryMarshal.Cast<byte, TgaHeader>(span)[0];
                //var header = MemoryMarshal.AsRef<TgaHeader>(span.Slice(0, sizeHeader));
                header.DataTypeCode = 2;
                header.Width        = (short)img.Width;
                header.Height       = (short)img.Height;
                header.BitsPerPixel = 24;


                // convert rgb3f to bgr8
                var slicePixels = span.Slice(sizeHeader, sizePixels);
                FormatUtils.ConvertBGR8(img, ref slicePixels);

                output.Write(span);

                output.Flush();

                return(true);
            }
        public static bool WritePpm(this RayImage img, Stream output)
        {
            try
            {
                using (var writer = new StreamWriter(output))
                {
                    //var writer = new StreamWriter(output);

                    writer.WriteLine("P3");
                    writer.WriteLine($"{img.Width} {img.Height}");
                    writer.WriteLine("255");

                    foreach (var p in img.Pixels)
                    {
                        int ir = (int)(255.99 * p.R);
                        int ig = (int)(255.99 * p.G);
                        int ib = (int)(255.99 * p.B);

                        writer.WriteLine($"{ir} {ig} {ib} ");
                    }

                    writer.Flush();
                }

                return(true);
            }
            catch (Exception)
            {
                return(false);
            }
        }
Beispiel #4
0
        public static bool WriteBmp(this RayImage img, Stream output)
        {
            try
            {
                var sizeFileHeader = Marshal.SizeOf <BmpFileHeader>();
                //const int sizeFileHeader = 14;
                var sizeInfoHeader = Marshal.SizeOf <BmpInfoHeader>();
                //const int sizeInfoHeader = 40;
                var sizePixels = img.Width * img.Height * 3;

                var buffer = new byte[sizeFileHeader + sizeInfoHeader + sizePixels];
                var span   = new Span <byte>(buffer);

                // write file header.
                ref BmpFileHeader fileHeader = ref MemoryMarshal.Cast <byte, BmpFileHeader>(span)[0];
                fileHeader.Signature  = (int)('B') + ((int)('M') << 8);
                fileHeader.FileSize   = buffer.Length;
                fileHeader.DataOffset = sizeFileHeader + sizeInfoHeader;

                // write info header.
                ref BmpInfoHeader infoHeader = ref MemoryMarshal.Cast <byte, BmpInfoHeader>(span.Slice(sizeFileHeader, sizeInfoHeader))[0];
        public static void ConvertBGR8(RayImage img, ref Span <byte> output, bool FlipHorizontal = false)
        {
            if (output.Length < (img.Pixels.Length * 3))
            {
                throw new ArgumentException("output cant hold all of the pixel data...");
            }

            int cur = 0;

            //TODO: Fold this code into single algorithm.

            if (FlipHorizontal)
            {
                for (int y = img.Height - 1; y > 0; y--)
                {
                    int line = y * img.Width;

                    for (int x = 0; x < img.Width; x++)
                    {
                        var p = img.Pixels[line + x];

                        output[cur++] = (byte)(255.99 * p.B);
                        output[cur++] = (byte)(255.99 * p.G);
                        output[cur++] = (byte)(255.99 * p.R);
                    }
                }
            }
            else
            {
                foreach (var p in img.Pixels)
                {
                    output[cur++] = (byte)(255.99 * p.B);
                    output[cur++] = (byte)(255.99 * p.G);
                    output[cur++] = (byte)(255.99 * p.R);
                }
            }
        }
Beispiel #6
0
        public static RayImage RenderParallelFor(int width, int height, int samples)
        {
            // creating image and storage.
            var img = new RayImage();

            img.Width  = width;
            img.Height = height;
            img.Pixels = new Rgb3f[width * height];

            // setting up camera:
            var   lookFrom      = new Vec3f(5f, 5f, 5f);
            var   lookAt        = new Vec3f(0, 0, -1f);
            float dist_to_focus = (lookFrom - lookAt).GetLength();
            float aperture      = 2.0f;

            var cam = new Camera(lookFrom, lookAt, Vec3f.UnitY,
                                 40, (float)width / (float)height, aperture, dist_to_focus);

            var wrand = new Random();

            var world = RandomScene(wrand);

            // creating world.
            //var world = new HitableList(
            //    new Sphere(new Vec3f(0f, 0f, -1f), 0.5f, new Lambertian(new Vec3f(0.1f, 0.2f, 0.5f))),
            //    new Sphere(new Vec3f(0, -100.5f, -1f), 100, new Lambertian(new Vec3f(0.8f, 0.8f, 0.0f))),
            //    new Sphere(new Vec3f(1f, 0f, -1f), 0.5f, new Metal(new Vec3f(0.8f, 0.6f, 0.2f), 0.0f)),
            //    new Sphere(new Vec3f(-1f, 0f, -1f), 0.5f, new Dielectric(1.5f)),
            //    new Sphere(new Vec3f(-1f, 0f, -1f), -0.45f, new Dielectric(1.5f))
            //    );

            // looping height lines.
            Parallel.For(0, height - 1, (cur) => {
                var j       = height - cur - 1; // invert it?
                int curLine = cur * width;
                var drand   = new Random();     // create unique random object for each thread to prevent locking.

                for (int i = 0; i < width; i++)
                {
                    Vec3f col = Vec3f.Zero;

                    for (int s = 0; s < samples; s++)
                    {
                        float u = (float)(i + drand.NextDouble()) / (float)width;
                        float v = (float)(j + drand.NextDouble()) / (float)height;

                        Ray r = cam.GetRay(u, v, drand);
                        //Vec3f p = r.PointAtParameter(2.0f); // still not used.

                        col += Color(r, world, 0, drand);
                    }

                    col /= (float)samples;

                    col = new Vec3f(MathF.Sqrt(col.X), MathF.Sqrt(col.Y), MathF.Sqrt(col.Z));
                    img.Pixels[curLine + i] = (Rgb3f)col;
                    //img.Pixels[curLine + i] = new Rgb3f(0.3f, 0.4f, 0.6f);
                }

                //System.Threading.Thread.Sleep(5);
            });


            return(img);
        }