\chapter{Vergleich OpenGL und Direct3D}
    
    Direct3D von Microsoft und OpenGL beanspruchen beide \emph{die} API für
    dreidimensionale Echtzeitanwenungen zu sein. In diesem Kapitel sollen sie
    verglichen und einige Unterschiede zwischen ihnen herausgearbeitet werden.
    Während der Autor dieses Dokumentes lange Zeit mit OpenGL gearbeitet hat
    beschränken sich seine Erfahrungen mit Direct3D auf einige wenige 
    Experimente, deswegen erhebt dieses Kapitel keinerlei Anspruch auf
    Vollständigkeit, Richtigkeit oder Freiheit von persönlicher Meinung.

    Zuallererst sei gesagt dass OpenGL und Direct3D sich sehr ähnlich sind,
    und sich vor allem in ihrer Mächtigkeit nicht unterscheiden. Dies wird
    auch im Aufbau der Grafik-Pipelines deutlich. Abbildung \ref{fig:pipelines} 
    zeigt die Pipeline von OpenGL, Abbildung \ref{fig:direct3dpipe} zeigt die
    von Direct3D. Wie man sehr leicht erkennen kann unterscheiden sich die Konzepte
    kaum.
    
    \begin{figure}
        \centering
        \includegraphics[width=0.9\textwidth]{images/direct3dpipe}
        \caption{Die Direct3D Visualisierungspipeline (aus \cite{direct3d9})}
        \label{fig:direct3dpipe}
    \end{figure}

    Einer der auffälligsten Unterschiede ist der dass Direct3D auf COM,
    dem Common Object Model - also C++ - basiert, während auf OpenGL im Grunde
    ein einfacher Zustandsautomat ist auf dessen Funktionalität 
    ausschließlich über plain C Methoden zugegriffen wird. 
    Im ersten Moment scheint Direct3D also die modernere API zu sein, allerdings wird OpenGL von
    vielen Entwicklern als sauberer empfunden, weil - im Gegensatz zu Direct3D - 
    auf komplizierte Makros verzichtet wird und die Dokumentation immer noch 
    kompletter erscheint. Allerdings hat Direct3D hier in den letzten Versionen
    deutlich aufgeholt. Das Interface von OpenGL ist prozedural, man führt
    Operationen aus die Vertices und Primitive an die Hardware schicken:

    \begin{lstlisting}[name=Ein Dreieck in OpenGL]
glBegin(GL_TRIANGLES);
    glVertex (0,0,0);
    glVertex (1,1,0);
    glVertex (2,0,0);
glEnd();
    \end{lstlisting}

    Direct3D hingegen operiert auf Puffern und sendet diese komplett an die Hardware.
    Dies scheint ein großer Geschwindigkeitsvorteil zu sein, da es viel Overhead
    beim Funktionsaufruf spart, was bei einigen Zehntausend oder gar Hunderttausend
    Vertices in einer Szene einer heutigen Applikation durchaus einen Vorteil bringt.
    In Wirklichkeit bedeutet dies aber einen großen programmiertechnischen Aufwand
    für den Entwickler:

    \begin{lstlisting}[name=Ein Dreieck in Direct3D pseudo Code]
v = &buffer.vertexes[0];
v->x = 0; v->y = 0; v->z = 0;
v++;
v->x = 1; v->y = 1; v->z = 0;
v++;
v->x = 2; v->y = 0; v->z = 0;
c = &buffer.commands;
c->operation = DRAW_TRIANGLE;
c->vertexes[0] = 0;
c->vertexes[1] = 1;
c->vertexes[2] = 2;
IssueExecuteBuffer (buffer);
    \end{lstlisting}

    Hier wird auch ersichtlich dass die Objektorientierung von Direct3D kaum
    Übersichtlichkeit bringt. Auch bietet OpenGL zur Reduktion des Overheads
    durch zu viele Funktionsaufrufe, den so genannten immediate mode. Anstatt einen
    Vertex einzeln durch viele Funktionsaufrufe zusammenzustellen

    \begin{lstlisting}[name=ein Vertex ohne immediate mode]
// send vertex normal
glNormal3f (0.5, 0.1, 0.3);
// send color
glColor4f (0.3, 0.3, 0.8, 1.0);
// send position
glVertex3i (2, 6, 8);
    \end{lstlisting}

    und dies beliebig oft zu wiederholen kann man die Daten einzeln als Streams 
    erstellen und dann gesammelt an die Hardware senden:

    \begin{lstlisting}[name=ein Vertex mit immediate mode]
// set the pointer to the area of memory that contains the data
glInterleavedArrays (GL_T2F_C4F_N3F_V3F, 0, myPointer);

// draw vertices (as triangles) according to a stream of indicies
glDrawElements (GL_TRIANGLES, numberOfIndicies, GL_UNSIGNED_SHORT, indexPointer );  
    \end{lstlisting}

    Eine derartige Vereinfachung bietet Direct3D wiederum nicht. Dafür ist die 
    DirectX API sehr viel umfangreicher und bietet unter anderem direkte
    Unterstützung zum Laden von Texturen und kompletten Modellen, was in OpenGL
    von weiteren APIs oder vom Entwickler selber geleistet werden muss.

    Eine weitere häufig gestellte Frage bei der Auswahl der 3D API ist die nach der
    Performance. Diese lässt sich allerdings nicht ohne weiteres beantworten: beide
    Seiten behaupten dass ihre API die schnellere ist und liefern dafür auch Beispiele.
    Die Antwort liegt wohl eher darin dass die Performanceunterschiede heutzutage kaum 
    mehr eine Rolle spielen, und dass ein Entwickler durch das Beherrschen einer der beiden
    APIs mehr Geschwindigkeit herausholen kann als durch marginale Unterschiede in
    speziellen Anwendungsfällen.

    Der Grund warum Direct3D überhaupt die Chance hatte sich zu einer
    bedenkenswerten Alternative zu entwickeln liegt in der Historie begründet.
    OpenGL wurde zu den Anfangszeiten von beschleunigender Hardware nur sehr
    rudimentär von Windows unterstützt während Direct3D diese zwar oft
    unschön aber viel schneller umgesetzt hat. Auch wurden neue Features 
    traditionell immer erst später in OpenGL implementiert, vor allem 
    programmierbare Vertex- und Pixel-Shader.

    Die Frage nach der besseren API ist sehr schwer zu beantworten. Soll die
    Applikation außerhalb von Windows (und XBox) eingesetzt werden führt kein
    Weg an OpenGL vorbei, da es sehr portabel ist und auf vielen Geräten
    - mit OpenGL ES (\cite{opengles}) auch immer mehr im embedded-Bereich - 
    lauffähig ist. Ist Portabilität allerdings kein Thema dann fällt 
    die Entscheidung sehr schwer. Die Empfehlung des Autors in diesem Fall
    ist eine Münze zu werfen. Der Autor selbst hat sich für OpenGL entschieden
    - nicht nur weil er kein Windows einsetzt, sondern auch weil er die API für
    schöner hält, und weil er generell den Einsatz offener Standards bevorzugt.

    

