Very good overview of soft shadow mapping

Soft Shadow Mapping from codeflow.org

Soft Shadow Mapping from codeflow.org

Florian Boesch has written an awesome article showing standard shadow mapping and lots of way to create soft shadows. He does not only present the pro and cons of each technique, he even shows the results as interactive WebGL applications and provides the source code for these.

Check out his article here

Ziele für 2013

Feuerwerk

Photo von Bayasaaa unter CC BY 2.0 Lizenz

So schnell kanns gehen: Gerade noch im Weihnachtsurlaub, jetzt schon im neuen Jahr und fleissig dabei die Pläne für die kommenden 12 Monate zu konkretisieren.

Einer meiner wichtigsten Punkte für dieses Jahr ist, ein neues Release der Engine herauszubringen. Das letzte Release der ParrotEngine ist ja schon eine ganze Weile her und inzwischen hat sich sehr viel intern verändert. Das nächste Release plane ich dann auch zusammen mit mehr Dokumentation und Beispielen zu kombinieren.

Ausserdem geistert in meinem Kopf noch die Idee von einer komponentenbasierten Architektur für die Engine herum. Ich überlege der Engine nur einen minimalen Rahmen zu geben. In diese können sich Erweiterungen “einklinken”. Jede Erweiterung kann weitere Punkte definieren in die sich abhängige Erweiterungen einhängen können. Das Prinzip folgt den “Extension Points”, welche z.B. aus der Eclipse Plugin Entwicklung bekannt sind. Der Vorteil wäre, dass ganze Elemente durch Konfiguration ausgetauscht oder ganz entfernt werden könnten – und das pro Projekt das die Engine nutzt. Wenn ein Projekt z.B. keinerlei Beleuchtung braucht, könnte die komplette Lighting Extension entfernt werden. In diesem Fall würden dann nur Vertex-Colors zum Einsatz kommen. Andererseits kann man Elemente durch bessere austauschen oder durch Ergänzung von Erweiterungen neue Funktionalitäten bereitstellen.

Je mehr ich darüber nachdenke, umso besser gefällt mir dieser Ansatz. Die Idee muss aber noch etwas reifen – sobald es konkrete Ideen gibt, poste ich diese natürlich.

Ein gutes 2013 euch allen
Stefan

Ich habe mir in den letzten Tagen mir meine Engine mal genauer angesehen: Den Code, die Strukturen der Klassen untereinander und auch deren Aufgabenverteilung. Da ich das ganze als Hobby-Projekt betreibe, treibt mich auch niemand an die Engine zu einem gewissen Termin fertigstellen zu müssen. Daher kann ich mir den Luxus leisten, viel Zeit in die Struktur und den Aufbau der Engine zu investieren.

Ein paar Sachen die mich gestört haben und die ich bereits geändert habe:

  • Es gab mehr als eine Stelle wo Bitmap Fonts gezeichnet wurden. Unter anderem im Renderer und in der Console Klasse. Jetzt gibt es nur noch eine Stelle – und zwar im Renderer.
  • Variablen die über die Konsole änderbar sein sollen, mussten in einer speziellen Klasse definiert werden und diese Klasse wurde dann der Konsole übergeben. Diese hat dann per Reflection nach bestimmten Namens-Konventionen gesucht und diese Variablen dann der Konsole verfügbar gemacht… nicht schön. Jetzt verwende ich die Annotation @ConsoleVar(name=”con_var”, help=”Helptext”) dafür.
  • Änderungen die während der step() Methode am Szene-Baum vorgenommen wurden, wurden gesammelt und erst danach gebündelt durchgeführt. Dies war unnötig, da es keinen Performance-Engpass darstellt direkt die Änderungen anzuwenden.
  • Ein Octree wurde implementiert – diese Implementierung kann alle Objekte verwalten die IOctreeUsable implementieren. So kann ich dieselbe Implementierung für SceneNodes als auch für Triangle Objekte verwenden.
  • Shader-Programme können nun automatisch generiert werden. Es gibt Shader-Komponenten die Einzelfunktionen wie z.B. das Skinning oder das Lighting machen. Über einen ShaderState im RenderState kann festgelegt werden welche Features für das Rendern gewünscht sind. Die ShaderFactory kombiniert alle Shader-Elemente zusammen und, falls nötig, compiliert und linkt den Shader dann noch. Natürlich werden die Shader die bereits gelink sind gecached wiederverwendet.
  • Um Autoboxing zu sparen, gibt es nun eine QuickIntList und ein IntHashSet die direkt mit dem primitiven Datentyp “int” arbeiten.
  • Wenn RenderBlock Objekte sortiert werden müssen (z.B. wenn solide vor transparenten und dann die transparenten von hinten nach vorne gezeichnet werden sollen), kommt nun eine QSortList Klasse zu Einsatz. Diese sortiert ihre Elemente nach dem Quicksort Algorithmus und gibt ein Objekt das IQSortContext implementiert and die Compare-Methode weiter. Hier kann z.B. ein Frustum mitgegeben werden um von hinten nach vorne sortieren zu können.

Aktuell schaue ich mir den Rendering-Core an. Die Engine nutzt bereits sehr einfaches Deferred Rendering, doch das möchte ich weiter ausbauen und unter anderem richtig schön weiche Schatten einbauen.

Intel HD 3000 und GLSL

Die Treiber der verschiedenen Grafikkarten treiben mich irgendwann nochmal in den Wahnsinn… habe gerade die “Ursache” gefunden, warum sich ein GLSL Programm auf der internen Intel HD 3000 Grafikkarte nicht linken lässt, auf der NVIDIA GT 555M aber völlig ohne Probleme: Es sind Vierecke im GL_LINE Polygon Modus!

Aber jetzt mal der Reihe nach…

Das Problem war, dass sich ein Shader, der sich ausserhalb meiner Engine wunderbar compilieren und linken ließ, innerhalb nicht linken ließ. Es wurde ein Fehler per

glGetProgrami(programId, GL.GL_LINK_STATUS)

zurückgegeben, jedoch das Info Log

glGetProgramInfoLog(obj, params[0], intBuf, byteBuf)

war leer. Nicht nötig zu sagen, dass dies die Fehlersuche nicht gerade einfach gemacht hat. Glücklicherweise hatte ich ein anderes Programm mit einer ähnlichen 3D Szene, welches wunderbar lief. Nachdem ich wie ein Archäologe in feinster Kleinarbeit die Programme und deren Unterschiede analysiert habe, stieß ich dann letztendlich auf die oben bereits genannte Tatsache: Sobald

glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)

aufgerufen wurde, liess sich anschließend der Shader nicht mehr linken – als ich diesen Aufruf in dem problematischen Programm entfernt hatte, lief es wie erwartet. Leider klappte aber die Gegenprobe nicht: Im zu Beginn fehlerfreien Programm erzeugte das Einbauen des Aufrufs

glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)

nicht den beobachteten Fehler… es musste also noch etwas anderes dahinterstecken.

Ich habe also ein möglichst kleines Programm ertstellt, um den diesen Fehler reproduzieren zu können und nach einigen Experimenten ist es mir endlich gelungen:

Der Fehler tritt auf, wenn mit dem GL_LINE-PolygonMode GL_QUADS mit glDrawElements gezeichnet wurden und danach ein Shader Programm gelinkt werden soll! Sobald der PolygonMode bei GL_FILL bleibt, oder anstatt GL_QUADS, GL_TRIANGES oder gar nichts gezeichnet wird, bleibt der Fehler aus. Die Schritte um den Fehler zu erzeugen sind also:

  1. glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_LINE)
  2. glDrawElements(GL2.GL_QUADS, 4, GL.GL_UNSIGNED_INT, 0)
  3. (compile, link and activate a new shader) <--- hier wird der Fehler ausgegeben

Falls ihr dieses seltsame Verhalten auch mal ausprobieren wollt, habe ich an diesem Blog Post ein ZIP Archiv mit meinem Eclipse-Projekt mitsamt passenden JOGL Binaries angehangen: Test Projekt für Shader Link Error (697 mal heruntergeladen)