Benutzer:Mori/OGL3 Quickstart

Aus DGL Wiki
Wechseln zu: Navigation, Suche

OpenGL 3.x Quickstart

Info DGL.png Diese Seite ist noch in Bearbeitung/Planung

Vorwort

warum ogl3 / nachteile /vorteile OpenGL gibt es nun schon seit einigen Jahren und entwickelt sich auch seitdem kontinuierlich weiter. Einer der größten Änderungen erhielt Einzug mit OpenGL 3. Veraltete Befehle werden (unter bestimmten Umständen) nicht mehr supportet und es ist ein neuer Context erforderlich um OpenGL 3 nutzen zu können. Zu den weiteren Änderungen zählen auch das Wegfallen der statischen Renderpipeline und vorgegebene Variablen. Dies ermöglicht uns als Programmierern größere Freiheiten in der Verwendung von OpenGL erzwingt aber gleichzeitig, dass wir uns selber um bestimmte Dinge, wie Modelview- und Projectionmatrizen, kümmern. Dieses Tutorial soll einen kurzen Einstieg in die Möglichkeiten von OpenGL 3 geben und zeigen, wie man die erste Anwendung einfach selber compilieren kann. Da da dieses Tutorial nur einen kurzen Einstieg in OpenGl geben soll sind an den entsprechenden Stellen Verlinkungen zu weiterführenden Artikeln angegeben.

Context

Der erste wesentliche Unterschied zu OpenGL Versionen kleiner als 3.0 besteht in einem weiteren Rendercontext, welcher zusätzlich erstellt weren muss. Wie auch die 1.x/2.x Rendercontexte (im Folgenden RC), erzeugt man hiermit eine neue OpenGL "Instanz", welche zum Rendern auf einen DeviceContext(im Folgenden DC) genutzt werden kann. Der wesentliche Unterschied ist, dass wir einen gültigen 1.x/2.x RenderContext benötigen, um unseren 3.x'er Context anfordern zu können. Wesentliche Änderungen sind:

  • Wegfallen des Direct-mode (glBegin,glEnd)
  • Wegfallen des der festen Render-Pipeline
  • Wegfallen von Displaylisten

Dies führt zu einer Reihe von Neuerungen im Code, hilft aber auch eine gewisse Struktur in die API zu bringen und das OpenGL Interface zu vereinheitlichen.

Um den Context zu bekommen, könnte unsere Funktion in etwa so aussehen:

constructor TGLContext.Create(DeviceContext:HDC);
begin
  DC:=DeviceContext; RC:=0;
  if InitOpenGL()=false then exit;
  RC:=CreateRenderingContextVersion(DC,[opDoubleBuffered],3,1,false,32,24,0,0,0,0);
  ActivateRenderingContext(DC,RC);

  SetViewPort(1,1);

  glClearColor(0.0,0.4,0.8,0.0);
  glEnable(GL_DEPTH_TEST);
  //glEnable(GL_CULL_FACE);
end;

Unsere Funktion nimmt hierbei einen DeviceContext entgegen (dieser gibt die Zeichenfläche an und ist kann mit der GetDC Funktion abgefragt werden. ZB. getDC(Form1.Handle) ). InitOpenGL ist eine Funktion unseres Headers, welche die OpenGL Library in unser Programm lädt. Hiernach können wir unseren OpenGL 3.x Context anfordern. Die Header-Funktion CreateRenderingContextVersion nimmt uns den Aufwand des erstellen beider Contexte ab und gibt uns (falls OpenGL 3.0 Unterstützt wird) unseren gewünschten RenderContext zurück. Sollte eine andere OpenGL Version als 3.1 gewünscht werden kann diese in dieser Funktion mit den Parametern MajorVersion und MinorVersion angefordert werden. Weiterhin können auch Color-, Z-, Stencil, AccumBits und die Anzahl der AuxBuffers hier eingestellt werden. Zuletzt können wir mit dem Parameter ForwardCompatible wählen, ob der Kontext die veralteten 2.x Funktionen unterstützen soll. Wenn keine Notwendigkeit besteht, sollte dieser Parameter auf true gestellt werden um einen puren 3.x Kontext zu erzeugen. Um OpenGL im Folgenden verwenden zu können müssen wir unseren neuen Kontext aktivieren und ein paar Grundeinstellungen treffen.

Info DGL.png glClearColor gibt hierbei die Hintergrundfarbe der Zeichenfläche an, hierfür sollte zum Entwickeln eine andere Farbe als Weiß bzw. Schwarz gewählt werden (zB. wie im Beispiel ein Blauton), da sich hierdurch Objekte farbig vom Hintergrund abheben und Fehler leichter zu erkennen sind

error handling

VBOs

erstellen (laden?) binden

EABs

Ein Element Array Buffer (im folgenden EAB), "erweitert" die Möglichkeiten Meshes zu Zeichnen. Der Einsatz von EABs bietet sowohl die Möglichkeit Meshes dynamischer zu zeichnen, als auch den Speicherverbrauch (je nach Mesh) drastisch zu reduzieren. Wie der Name schon andeutet, handelt es sich um einen Buffer zum Speichern von Element Array's. Diese Elemente sind in diesem Fall die Indices der einzelnen Mesh-Vertices. In diesem Buffer geben wir daher die Daten nichtmehr direkt an, sondern nur noch einen Index und können erstens Vertices zwischen verschiedenen Faces sharen (zB. bei Ecken in Objekten, welche von mehreren Dreiecken verwendet werden) und zweitens, verschiedene Rendermodes (zB. GL_TRIANGLES, GL_TRIANGLE_STRIP, ...) auf ein und das selbe VBO anwenden, ohne die Reihenfolge der Vertices auf der Grafikkarte verändern zu müssen. Zuerst holen wir uns deshalb, wie schon beim VBO, ein Handle (hier hid:GLUInt) von OpenGL und binden dieses als GL_ELEMENT_ARRAY_BUFFER. Dieses Handle wird am Ende wieder mit glDeleteBuffers freigegeben:

constructor TGLEAB.Create;
begin
  glGenBuffers(1,@hid);
  bind();
end;

destructor TGLEAB.Destroy;
begin
  glDeleteBuffers(1,@hid);
  inherited;
end;

procedure TGLEAB.bind;
begin
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,hid);
end;

Nachdem wir jetzt unser EAB Handle erzeugt haben müssen wir es nur noch mit Daten befüllen. Dazu brauchen wir einen Vertex-count und die Größe (in Byte) eines einzelnen Vertex um den entsprechenden Speicher reservieren zu können.

function TGLEAB.startEdit(valType:Cardinal; count:Cardinal; size: Integer=-1; mode:Cardinal=GL_STATIC_DRAW): Pointer;
begin
  self.valType:=valType;
  elementsCount:=count;

  bind();
  if size>0 then
  glBufferData(GL_ELEMENT_ARRAY_BUFFER,size,nil,mode);

  Result:=glMapBuffer(GL_ELEMENT_ARRAY_BUFFER,GL_READ_WRITE);
end;

procedure TGLEAB.endEdit;
begin
  glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
end;

Hierbei erzeugen wir mit glBufferData einen neuen EAB mit der entsprechenden Größe (bei size=-1 lassen wir ein schon bestehendes EAB in der Größe unverändert). Wie schon beim VBO lassen wir uns danach mit glMapBuffer einen Pointer auf den reservierten Speicherbereich zurückgeben, welchen wir beschreiben können. Wie schon beim erzeugen müssen wir beim Binden wieder GL_ELEMENT_ARRAY_BUFFER angeben, damit OpenGL unser gebundenes EAB auswählt und nicht ein VBO.

glDrawElements(GL_TRIANGLES,indicies.elementsCount*3,indicies.valType,nil);

Shader

vorrausetzungen (benötigte matrizen + daten vbo mapping) shader arten

Matrizen

kurze! erläuterung. link zu "richtigen" artikeln/tutorials

Zeichnen

eab/vbo/shader binding

Weiterführendes/Aussicht

erläuterungen, weiterführende links