Raytracing Teil 6: Das erste Bild rendern

Mit den Grundlagen, die wir in den vorherigen Teilen dieser Artikelserie erarbeitet haben, werden wir nun unsere erste 3D Grafik rendern. Zunächst erweitern wir die Klasse Scene um zwei Methoden „AddSphere“ und „AddParallelepiped“, mit denen wir einen Spat (bzw. Quader oder Würfel) und eine Kugel in die Szene einfügen können. Diese Methoden berechnen alle einzelnen Primitive, aus denen der Spat bzw. die Kugel besteht und fügen diese in die Szene ein.

Wir fügen die folgenden Methoden in die Klasse Scene ein:

        public void AddParallelepiped(Vector3D Origin, Vector3D U, Vector3D V, Vector3D W, Color color)
        { // Spat hinzufügen
            Primitives.Add(new Lozenge(Origin, U, V, color));
            Primitives.Add(new Lozenge(Origin, U, W, color));
            Primitives.Add(new Lozenge(Origin, V, W, color));
            Primitives.Add(new Lozenge(Origin + W, U, V, color));
            Primitives.Add(new Lozenge(Origin + V, U, W, color));
            Primitives.Add(new Lozenge(Origin + U, V, W, color));
        }

        public void AddSphere(Vector3D center, double radius, int noOfSteps, Color color)
        {
            double step = Math.PI / noOfSteps;

            for (int bN = 1; bN < noOfSteps; bN++)
            {
                double b = bN * step;
                for (int aN = 0; aN < noOfSteps * 2; aN++)
                {
                    double a = aN * step;

                    Vector3D p1 = new Vector3D(radius * Math.Cos(a) * Math.Sin(b), radius * Math.Cos(b), radius * Math.Sin(a) * Math.Sin(b)) + center;
                    Vector3D p2 = new Vector3D(radius * Math.Cos(a + step) * Math.Sin(b), radius * Math.Cos(b), radius * Math.Sin(a + step) * Math.Sin(b)) + center;
                    Vector3D p3 = new Vector3D(radius * Math.Cos(a) * Math.Sin(b + step), radius * Math.Cos(b+step), radius * Math.Sin(a) * Math.Sin(b + step)) + center;
                    Primitives.Add(new Trapezoid(p1, p2 - p1, p3 - p1, color));
                } 
            }

            for (int aN = 0; aN < noOfSteps * 2; aN++)
            {
                double a = aN * step;
                double b = step;
                Vector3D p1 = new Vector3D(radius * Math.Cos(a) * Math.Sin(b), radius * Math.Cos(b), radius * Math.Sin(a) * Math.Sin(b)) + center;
                Vector3D p2 = new Vector3D(radius * Math.Cos(a + step) * Math.Sin(b), radius * Math.Cos(b), radius * Math.Sin(a + step) * Math.Sin(b)) + center;
                Vector3D p3 = new Vector3D(0,radius,0) + center;
                Primitives.Add(new Trapezoid(p1, p2 - p1, p3 - p1, color));
            }
        }

Wir erstellen nun ein neues Fenster, bzw. eine Form und fügen eine PictureBox mit dem Namen „picture“ ein. Den Quelltext der Form ändern wir wie folgt:

    public partial class Form1 : Form
    {
        Scene scene = new Scene();
        RayTraceCamera cam;
        double camAngle = 0;

        public Form1()
        {
            InitializeComponent();

            // Elemente zur Szene hinzufügen:
            scene.Primitives.Add(new Plane(Vector3D.Zero, Vector3D.eX, Vector3D.eZ, Color.Green)); // Endlos ausgedehnter grüner Boden
            scene.AddParallelepiped(Vector3D.Zero, Vector3D.eX*4, Vector3D.eY*2, Vector3D.eZ*4, Color.Blue); // Blauer Quader
            scene.AddSphere(new Vector3D(-3,2.5,0), 2.5, 6, Color.Red); // Rote Kugel

            camAngle = 2.0; // Der Winkel, aus dem die Kamera auf die Szene schaut (in Radiant).
            Vector3D p = new Vector3D(Math.Cos(camAngle) * 23, 7, Math.Sin(camAngle) * 23); // Position der Kamera aus Winkel berechnen
            cam = new RayTraceCamera(scene, p, new Vector3D(0, 3, 0) - p);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            cam.ResizeScreen(picture.Width, picture.Height); // Kamera-Screen an PictureBox anpassen
            picture.Image = cam.RenderBitmap(); // Das fertige Bild Rendern und in der PictureBox anzeigen
        }
    }

Beim Start der Applikation wird eine Szene erstellt und ein grüner Plane als Boden eingefügt. Es folgt ein blauer Quader und eine rote Kugel, welche durch viele kleine Primitive angenähert wird. Anschließend wird eine RayTraceCamera erstellt, welche ein Bild der Szene rendert. Nach dem Start der Applikation wird folgendes Bild angezeigt:

Alle Objekte werfen Schatten auf den Boden. Der Schatten der Kugel fällt sogar teilweise auf den Quader. Der Boden ist unendlich ausgedehnt und trifft hinten im Bild auf den Horizont. Die Farbe des Himmels ist die Farbe „Background“ des Scene-Objekts.

Ein Gedanke zu „Raytracing Teil 6: Das erste Bild rendern

  1. Pingback: RayTracing Teil 5: Dreiecke, Trapeze und Rauten als weitere ebene Primitive | Volkers Blog

Kommentare sind geschlossen.