OpenGL Playground
In den letzten Wochen habe ich mir über ein Youtube Tutorial einen OpenGL Playground zusammengebastelt. Dieses kleine Programm dient zum Test neuer Klassen und Darstellung von 3D Objekten unter OpenGL. Es läuft auch am Raspberry Pi!
OpenGL Playground
Im letzten Artikel habe ich euch gezeigt wie man mit SDL und GLEW ein Dreieck auf dem Raspberry Pi rendert. Dieses Programm habe ich nun erweitert. Den Source Code findet ihr wie immer auf meiner GitHub Seite. Es ist nach wie vor systemunabhängig entwickelt, lässt sich unter Windows und Linux am Raspberry Pi bauen und starten. Dabei sind Projektdateien für Visual Studio 2019 und CodeLite. Neu sind:
- bewegliche Camera
es wurde eine Minecraft ähnliche Camera implementiert die man über WASD und SHIFT bzw. SPACE steuert. Weiters ändert man die Blickrichtung über die Maus. Damit ist es nun möglich sich frei im 3D Raum zu bewegen - Shader
das Rendersystem wurde komplett auf Shader umgestellt. - einfache Objekte
einfache Objekte wie das Grid, der Koordinatenursprung und ein Dreieck wurde jeweils als eigene Klasse implementiert.
Führt man das Programm aus bekommt man ein von 3D Programmen wie Blender übliche Standardansicht auf ein Grid und einem Beispielobjekt. Man kann sich frei bewegen. Das ist mein Playground, ein 3D Raum in dem die nötigsten Informationen angezeigt werden und von dem ich Weg neue Klassen entwickeln kann. Neues Ziel: eine einfache Engine entwickeln.
Implementierung
Im folgenden einige Details zur Implementierung. Ich bin weitgehend mehreren Tutorials gefolgt um mir die nötigsten Klassen und Funktionen zusammenzubauen. Der Code ist recht übersichtlich, könnte aber besser organisiert sein. Der nächste Schritt ist für mich der Bau einer („meiner“) Engine in dem ich noch besser organisiere und mich an aktuellen Coding Standards halten möchte (C++ 17 Standard).
Probleme bei der Portierung auf Linux
Ich entwickle primär auf Windows und unter Visual Studio 2019. Der Code soll jedoch immer auch unter Linux am Raspberry Pi compilierbar sein und visuell das selbe Ergebnis zeigen. Problematisch war das bei den Shadern. Der Windows Code 1:1 unter Linux gebaut lieferte folgenden OpenGL Fehler zur Laufzeit:
GLSL 3.30 is not supported.
Das liegt daran, dass ich im Shader zuvor mit #version 330 core explizit OpenGL 3.3 vorausgesetzt habe. Der Raspberry Pi unterstützt die OpenGL Shader nur bis Version 1.4. Für neuere Funktionen wird OpenGL ES verwendet. Das ist im Prinzip eine abgespeckte Version der am Desktop PC üblichen Shading Language für mobile Geräte. Der Raspberry Pi besteht im wesentlichen aus Smartphone Teilen, weshalb dort diese Version zu finden ist.
Lösung
OpenGL ES ist nicht wirklich ein Problem, es ist eine Herausforderung. Man muss ein wenig umdenken und dazulernen. Dabei überdenkt man aber den zuvor geschriebenen Code und macht nötige Optimierungen. Wenn der Code auf OpenGL ES schnell läuft, dann ist die Anzeige am PC gar kein Problem mehr. In meinem Fall ist jeweils ein neuer basic Fragment und Vertex Shader entstanden. Ihr könnt diese gerne mit den PC Shadern vergleichen. Es gibt kaum Unterschiede nur:
#version 300 es
die explizite Prüfung auf die Version läuft nun auf die ES Version der Sprache und zusätzlich musste im Fragment Shader die precision definiert werden:
precision mediump float;
im C++ Code musste jeder Aufruf der Shader angepasst werden. Über unschöne Präprozessoranweisungen wurde nun der Aufruf zwischen Windows und nicht Windows erzwungen:
#ifdef _WIN32 // nur für Windows shader = new Shader("shaders/basic.vert", "shaders/basic.frag"); #else shader = new Shader("shaders/basic_raspi.vert", "shaders/basic_raspi.frag"); #endif
Das funktioniert super, sollte ich aber in der kommenden „Engine“ aber noch besser umsetzen.
Ergebnis
Ich denke das Ergebnis kann sich aber schon sehen lassen.
Fazit
Mein OpenGL Playground ist eine recht überschaubare C++ Anwendung in der man schnell neue Klassen testen kann. Gerendert wird in OpenGL und über Shader. Das ganze ist unabhängig vom Betriebssystem und danke frei bewegbarer Kamera kann man in diesem Raum neue Objekte begutachten.
Für mich beginnt nun der lange Weg die gewonnenen Erkenntnisse in einer möglichst gut strukturierten Engine einzuarbeiten um die Erstellung eines Programms damit so einfach und effizient wie möglich zu gestalten. Ziel ist „meine“ 3D Engine für weitere zukünftige Projekte.