# OpenGL vernünftige Tutorial?



## Helgon (14. Jan 2012)

Hey, mich würd gern interessieren welche Quellen ihr genutzt habt um OpenGL zu lernen.

Ich hab natürlich einiges gefunden, auch massenweise an A-Z Tutorial, aber mich würde interessieren ob ihr nicht vllt auch welche habt, die ihr empfehlen könnt/die gut sind/auf alles eingehen oder einfach mal Posten womit ihrs gelernt habt.

Grüße


----------



## Marco13 (14. Jan 2012)

Ich kann zwar kein OpenGL, aber ER wird dir sicher einige Tipps geben.

Angefangen habe ich mit dem The OpenGL Programming Guide - The Redbook (Allerdings aus Papier... Seiten... das sind so Dinger, die NOCH dünner sind, als ein iPad, aber dafür gaaanz viele). Es kann nicht schaden, sich das mal anzusehen, ist aber hoffnungslos veraltet. 

Ich habe es noch nicht gelesen, aber vom drüberschauen her sah Learning Modern 3D Graphics Programming sehr gut aus (ein Tipp vpn IHM). Die meisten Seiten und Tutorials haben beim "Stakkato der neuen OpenGL-Versionen" (und den damit verbundenen Änderungen und depracations) nicht mithalten können, aber das ist wohl sehr aktuell, sehr ausführlich und sehr klar strukturiert (letzteres ist aber nur der erste Eindruck).

Was ich ganz cool fand war nopper.tv - Norbert Nopper's Homepage - Dort gibt es "KSKBs", aufeinander aufbauend, aktuell, ausführlich und mit Verlinkungen zu den Dokumentationen der eizelnen Befehle. Zwar in C++, aber darauf aufbauend kann man mit JOGL/LWJGL schnell was basteln, und erspart sich potentiell viele "...ach Mist, das funktioniert nur seit 2 Stunden nicht, weil hier ein *2 steht, obwohl da ein *3 stehen müßte". 

Das OpenGL.org kann bei manchen Punkten hilfreich sein, ist aber auch nicht mehr überall auf dem neuesten Stand...


----------



## Helgon (14. Jan 2012)

Danke für die Links.

Ich weis nicht, irgendwie find ich openGL komisch. Ich klick mich grad durch alles was ich finde und irgendwie dreht sich jedes Tutorial/Kapitel grob darum, wie man Kreise, Quadrate, Rechteecke zeichnet, aber nix was man irgendwie wirklich in der Praxis anwenden könnte (kommt mir zumindest beim überfliegen so vor).

Grüße


----------



## Spacerat (14. Jan 2012)

Ich lass' trotz des anscheinend besseren Links von Marco13 (nopper.tv) auch mal meinen bisherigen Favoriten da -> NeHe Productions - Everything OpenGL. Quellcode der Beispiele ist dort auch für viele Sprachen mitunter auch JOGL und LWJGL vorhanden.


----------



## Helgon (14. Jan 2012)

Ah danke für die Links!

Nehe und Noppper sind beide echt gut!

@Spacerat: Wo ist den auf Nehe irgendwas Java geschweige LWJGL?  Ich seh da nur C

Danke und Grüße!


----------



## Guest2 (14. Jan 2012)

Moin,

angefangen habe ich mit dem OpenGL Bluebook (ebenfalls aus Papier ). Das ist aber nicht nur mindestens so alt wie das Redbook, sondern didaktisch auch nicht wirklich empfehlenswert. Meins behandelt noch OpenGL 1.1.

Wie Marco schon angedeutet hat, ist die Aktualität auch das größte Problem. Die meisten Tutorials im Netz beziehen sich auf ~OpenGL 2.1. Danach hat sich aber alles geändert und nur wenige Seiten haben das überlebt. Zwei interessante Links hat Marco auch schon gezeigt.

Falls man mit ~GL 2.1 einsteigen will (schaden kann das nicht) hat Spacerat auch schon den Link zu den legacy tutorials von NeHe gezeigt. Es muss einem nur bewusst sein, das sich vieles (alles?) von dem da gezeigtem heute anderes realisieren lässt.

Hier m Forum gab es auch schon den einen oder anderen Thread mit der Frage nach Tutorials, evtl. findest Du da noch was Passendes.

(Ich persönlich würde ich heute mit dem Link aus Marcos Beitrag (Learning Modern 3D Graphics Programming) anfangen. Das ist nicht einfach, aber lohnt imho.)



Helgon hat gesagt.:


> Ich weis nicht, irgendwie find ich openGL komisch. Ich klick mich grad durch alles was ich finde und irgendwie dreht sich jedes Tutorial/Kapitel grob darum, wie man Kreise, Quadrate, Rechteecke zeichnet, aber nix was man irgendwie wirklich in der Praxis anwenden könnte (kommt mir zumindest beim überfliegen so vor).



Kreise, Quadrate und Rechteecke sind tatsächlich nicht relevant. Wichtig sind nur Dreiecke und nicht anderes. Modernes OpenGL besteht im wesentlichen aus einem "Array" mit Dreieckskoordinaten und Texturkoordinaten (ggf. weitere Vertexattribute), 2 bis 5 Shadern pro "Pass" und "Object" und einem bunten Blumenstrauß an Quellcode um das zu initialisieren / handeln.

Alles andere muss man selber machen.

Viele Grüße,
Fancy


----------



## Helgon (14. Jan 2012)

Danke für die ausführliche Antwort.

Bei Learning Modern 3D Graphics Programming ist ein Problemchen (auch wenn ich ja nicht alles verstehen muss), dass ich nur in der 12 bin (zwar LK) aber noch nicht wirklich was mit Vektoren etc. und dem ganzen anderen Mathematischen KrimsKrams dort anfangen kann. Werde auf jeden Fall anfangen und gucken wie weit ich komme.

Vielleicht habe ich mich von vornherein etwas falsch ausgedrückt. Ich würde wohl gerne eher openGL soweit lernen, um vernünftig damit und der LWJGL umgehen zu können (nicht "reines openGL", falls man da überhaupt differenzieren kann)

Naja. Morgen versuch ich mir mal alle Kapitel an zu tuen  Hatte die bis grade übersehen und nur die "List of Figures" gesehen. Die Kapitel scheinen interessant und praxisorientiert zu sein, sehr gut 

Grüße


----------



## Guest2 (14. Jan 2012)

Ohne Dich demotivieren zu wollen, aber sofern Dein Tag auch nur 24 Stunden hat, glaube ich nicht das Du weit über die ersten Seiten hinauskommst. (Nicht alle Seiten sind im Inhaltsverzeichnis) 

Das ist schon ne ganze Menge an Stoff, der da vermittelt wird. (Auf den ersten Seiten gibt es auch einen groben Abriss zu Vektoren.) Das ist da auch alles ziemlich stark aufeinander aufbauend aber sollte auch ohne allzu großes Vorwissen machbar sein. Allerdings kaut einem der Autor auch keine Trivialitäten vor und man sollte vermutlich versuchen jedes Beispiel umzusetzen (eben z.B. in LWJGL oder JOGL).

Der GL Teil von LWJGL ist auch "nur" ein wrapper, das ist reines OpenGL (plus ein paar Toolklassen).

Viele Grüße,
Fancy


----------



## Spacerat (14. Jan 2012)

Helgon hat gesagt.:


> @Spacerat: Wo ist den auf Nehe irgendwas Java geschweige LWJGL?  Ich seh da nur C


Hmm... man kann sich Quelltext ansehen, man kann ihn aber auch downloaden... :lol:
Und zwar am Ende jeder Lesson. Okay, für LWJGL gilt das afaik zwar nicht für jede aber immerhin... sie sind da.


----------



## Fu3L (14. Jan 2012)

Ich hatte mir den viel gepriesenen Link auch angesehen, aber das nach den ersten Seiten auf die Vorlesungsfreie Zeit verschoben, weils n bisschen ungwohnt ist. Der Autor geht eben von C++ aus und mal eben nen Pointer aufn Float-Array rumschiebt, was in Java ja nicht so eben geht^^ (Zumindest glaube ich, dass es so ist^^ ). Da braucht man als Anfänger etwas länger um das zu überblicken.

Ich finde es sehr schade, dass auf der LWJGL Seite einfach gesagt wird: Hier 5 Grundlagen. Den Rest bitte in den zahlreichen anderen Tutorials gucken.. Bissl mehr wäre wünschenswert^^ (Diese Zauberrei mit den DirectBuffern^^)

@Helgon: Du wirst Vektoren und Matrizen sowieso noch lernen müssen (für die Schule UND fürs Programmieren.. Beides ganz sicher), also kanns nicht schaden das schonma zu tun. Wenn du jetzt denkst: "Mathe ohne Lehrer lernen?", dann mach dir da keine Sorgen, wenn du dir selbst Programmieren beigebracht hast. Außerdem läufts in der Uni normal meistens auch drauf hinaus


----------



## Marco13 (14. Jan 2012)

Die Buffer (bzw. DirectBuffer) sind in Java die einzig vernünftige Möglichkeit, das zu machen, was man in C++ eben mit Zeigern auf Datenblöcke macht: Ein Buffer bzw. ByteBuffer ist für solche Dinge näher an einem void*-Pointer als alles andere. Die "asFloatBuffer" (etc) Methoden sind quais die "casts", und sowas wie "position" oder auch "slice" erlaubt quasi Zeigerarithmetik.


----------



## Helgon (15. Jan 2012)

Wollt mal nun kurz hier lassen was ich so gefunden hab, damit auch andere in Zukunft was von haben.

Hauptseite ? DGL Wiki ist sehr nice zum lernen und nachschlagen! Auf Deutsch, lediglich einziges "Manko" Delphi, aber sollte wohl keine Probleme darstellen damit klar zu kommen.

Was mir jedoch wirklich geholfen hat einfach direkt Fuß zu fassen, damit ich überhaupt ne Vorstellung hab was ich mache und es tatsächlich auf anhieb verstehe und den "Aha-Effekt" habe, was beim lernen ja unbedingt notwendig ist:

Kanal von TheCodingUniverse - YouTube

Dachte erst, der klingt recht kindlich und kopiert nur die LWJGL Wiki Tutorials, aber weit gefehlt. Hat einen guten Programmierstil, kommentiert ab #4 nur noch sehr wenig, praktisch guckt man ihm einfach nur zu wie er codet und hört ab und an paar Kommentare, aber gerade das ist für mich sehr gut, kein unnötiges Gelabber das man einschläft sonder einfach harte Fakten -)) und man sieht sofort Resultate / wie man es anwenden kann, weil seine Tutorials im folgenden etwas komplexer und wirklich auf irgendwas Anwendungsspezifisches abzielen. 

Jedoch muss man Java wirklich beherrschen (Hello World reicht hier nicht ) um dem 1:1 folgen zu können ohne alle paar Sekunden zu pausieren. Für komplette Neueinsteiger ist das nix.

Echt gut!

Wenn man was nicht weis im Video, einfach googeln oder der Delphi Wiki nachschauen, sehr gut!

Außerdem hat die Delphi Wiki viele Sachen, die ich gern umsetzen würd, allein aber niemals wüsste wie. Gut das ich die nächsten   Wochen viele Freistunden hab 

Grüße und danke für die ganzen Tipps von euch. Wenn ich damit fertig bin (dauert wohl noch paar gute Tage) werde ich mir auch Nehe genauer anschauen, weil da auch echt viele praxisorientierte Tuts bei waren!

P.S.: In den Tutorials verwendet er auch Slick (momentan zumindest nur um die Textures zu laden)


----------



## Evil-Devil (16. Jan 2012)

Die Verwendung der Buffer in LWJGL ist recht einfach. Entweder erstellst du dir selbst einen Buffer oder du nutzt die BufferUtils Klasse von LWJGL. Dann befüllst du den Buffer sofern notwendig und übergibst ihn an die jeweilige Funktion. Oder du lässt ihn von der jeweiligen Funktion der du den Buffer übergeben hast befüllen.


----------



## Spacerat (16. Jan 2012)

[OT]





Evil-Devil hat gesagt.:


> ...oder du nutzt die BufferUtils Klasse von LWJGL.


...oder JOAL oder JOGL oder oder oder...
Mal ehrlich... gehört eine solche BufferUtils Klasse nicht eigentlich schon in das [c]java.nio[/c] Paket?[/OT]


----------



## Helgon (16. Jan 2012)

In der Wiki der LWJGL steht ja was zu Buffern. Z.B.: http://lwjgl.org/wiki/index.php?title=Using_Frame_Buffer_Objects_(FBO)

Wann verwendet man den Buffer, sollte man das immer machen?


----------



## Evil-Devil (16. Jan 2012)

Spacerat hat gesagt.:


> [OT]...oder JOAL oder JOGL oder oder oder...
> Mal ehrlich... gehört eine solche BufferUtils Klasse nicht eigentlich schon in das [c]java.nio[/c] Paket?[/OT]



Naja, eine Util Klasse für einen einzelnen Aufruf ala

```
ByteBuffer textureData = ByteBuffer.allocateDirect(textureSize).order(ByteBuffer.nativeOrder());
```
ist hier und da nützlich. Die meisten haben am Ende ohnehin eigene Util-Klassen. Denn ein Float Array in einen FloatBuffer zu schieben ist nervige Schreibarbeit. Bzw. jedes Array in einen Buffer zu schieben ist nervig...

Helgon, die Buffer verwendest du in allen Fällen in denen du OpenGL Daten übergeben willst oder von OpenGL Daten bekommst. Also sehr häufig 

Das von dir verlinkte FBO ist ein OpenGL spezifischer Buffer und hat nichts mit dem NIO Buffer von Java zu tun.


----------



## Spacerat (16. Jan 2012)

[ot]





Evil-Devil hat gesagt.:


> Die meisten haben am Ende ohnehin eigene Util-Klassen.


...und alle funktionieren immer ein wenig anders (z.B. andere Methodennamen) aber das aber müssten sie nicht, wenn es eine davon bereits in der Standard-API geben würde. [/ot]


----------



## Evil-Devil (16. Jan 2012)

[ot]


Spacerat hat gesagt.:


> [ot]...und alle funktionieren immer ein wenig anders (z.B. andere Methodennamen) aber das aber müssten sie nicht, wenn es eine davon bereits in der Standard-API geben würde. [/ot]



Ja, nur wie weit sollte man die Util Klasse dann ausbauen? Es gibt imho zu viele verschiedene Fälle als das man alles abdecken können sollte.
[/ot]


----------



## Spacerat (16. Jan 2012)

[ot]Ich lehne mich mal aus dem Fenster... :lol:
1. Es existieren 7 Buffertypen in Java (byte, short, char, int, long, float und double).
2. Für das Erstellen existieren 2 Optionen (Direct und Order). ReadOnly auf gerade erstellte, leere Buffer anzuwenden ist nicht sinnvoll. Daraus ergeben sich 28 Methoden zum Erstellen eines beliebigen Buffers, 4 pro Primitivtyp.

```
public static ByteBuffer createByteBuffer(int size);
public static ByteBuffer createByteBuffer(int size, ByteOrder order);
public static ByteBuffer createByteBuffer(int size, boolean direct);
public static ByteBuffer createByteBuffer(int size, boolean direct, ByteOrder order);
```
3. Für das Wrappen existieren 5 Optionen (Offset, Länge, Direct, Order und ReadOnly). Offset und Länge können entweder nur Paarweise oder für jeden Puffer nur einer von beiden verwendet werden. Daraus ergeben sich 112 Methoden zum Erstellen von gefüllten Buffern, 16 pro Primitivtyp, 8 davon sind ReadOnly.

```
public static ByteBuffer wrap(byte[] elements);
public static ByteBuffer wrap(byte[] elements, int offset);
public static ByteBuffer wrap(byte[] elements, int offset, int length);
public static ByteBuffer wrap(byte[] elements, ByteOrder order);
public static ByteBuffer wrap(byte[] elements, boolean direct);
public static ByteBuffer wrap(byte[] elements, boolean direct, ByteOrder order);
public static ByteBuffer wrap(byte[] elements, int offset, boolean direct, ByteOrder order);
public static ByteBuffer wrap(byte[] elements, int offset, int length, boolean direct, ByteOrder order);

public static ByteBuffer wrapReadOnly(byte[] elements);
public static ByteBuffer wrapReadOnly(byte[] elements, int offset);
public static ByteBuffer wrapReadOnly(byte[] elements, int offset, int length);
public static ByteBuffer wrapReadOnly(byte[] elements, ByteOrder order);
public static ByteBuffer wrapReadOnly(byte[] elements, boolean direct);
public static ByteBuffer wrapReadOnly(byte[] elements, boolean direct, ByteOrder order);
public static ByteBuffer wrapReadOnly(byte[] elements, int offset, boolean direct, ByteOrder order);
public static ByteBuffer wrapReadOnly(byte[] elements, int offset, int length, boolean direct, ByteOrder order);
```

Fazit: Es gibt genau 140 Methoden in Java einen Buffer zu erstellen, 20 pro Primitivtyp.
Wer bietet mehr? Hab' ich was vergessen?[/ot]


----------



## Marco13 (16. Jan 2012)

Das 'direct' kann man sich nicht aussuchen (bzw. bei direct wäre 'wrap' ein unpassender Name). Abgesehen davon geben die ganzen Buffer-Methoden ja den Buffer wieder zurück, und insbesondere ist die Buffer.slice Methode ja nicht zuletzt dafür da, sich das meiste davon zu sparen.

Statt sowas wie

```
public static ByteBuffer wrapReadOnly(byte[] elements, int offset, int length, boolean direct, ByteOrder order);
```
schreibt man halt
ByteBuffer.wrap(array).position(offset).limit(offset+lengt).byteOrder(ByteOrder.nativeOrder());

Aber... ich habe auch mehrere BufferUtils-Klassen in meinen Projekten...


----------



## Spacerat (16. Jan 2012)

@Marco13: Nur weil sich wrap und direct von der Standard-API her auszuschliessen scheinen, heisst es nicht, dass es nicht möglich ist. Wrap heisst (afaik), einen Buffer in einer vorgegebenen Grösse (möglw. durch array.length) zu erstellen und ein gegebenes Array dort hineinzuschreiben. Innerhalb meiner Methoden geschieht dies zwar "von Hand" nacheinander, aber von aussen her passt der Methodenname trotzdem und am Ende ist eine einzige passend benannte Methode plus sinnvoller Parameter stets hilfreicher als jegliche "Methoden-Batterien". Selbst wenn
	
	
	
	





```
(ByteBuffer) ByteBuffer.allocateDirect(length).order(order).put(elements, offset, length).flip();
```
nicht wie
	
	
	
	





```
wrapDirect(byte[] elements, int offset, int length, ByteOrder order);
```
aussieht, der Name passt. Und weil man mehrere Methoden auch gut auf mehrere Zeilen ausdehnen kann, kann man auch per boolean 'direct' selektieren. Mit zwei boolean-Parametern hat man aber eben jene Probs, wie auch bei offset und length, man muss sich "aussuchen" (offset ist natürlich sinnvoller), welches man als einzelnen Parameter nimmt. Deswegen gibt es bei mir halt "wrap" und "wrapReadOnly" (hätte in diesem Fall auch "wrapDirect" heissen können).
BTT:
Noch ein Nachtrag... NeHe in deutsch... www.joachimrohde.com - Artikel


----------



## Marco13 (17. Jan 2012)

Spacerat hat gesagt.:


> Wrap heisst (afaik), einen Buffer in einer vorgegebenen Grösse (möglw. durch array.length) zu erstellen und ein gegebenes Array dort hineinzuschreiben.



Nicht so ganz. Warp liefert einen Buffer, der intern diesen Array speichert. Wenn man in den Buffer schreibt, schreibt man in den Array. Man kann sich den Array wieder abholen, und es ist der_selbe_ wie der, den man eingewrappt hat. Es wird nichts kopiert. (Und: Solche Buffer kann man in JOGL/LWJGL üblicherweise nicht verwenden - weil der Zugriff darauf auf JNI-Seite etwas diffiziler ist). 

Mit allocateDirect allokiert man einen Buffer, auf dessen Inhalt man von Java aus keinen direkten Zugriff hat, außer eben über den Buffer selbst. (Damit kann man nebenbei auch das -Xmx umgehen, und sich so viel Speicher krallen, wie man gerne hätte  )


----------



## Spacerat (17. Jan 2012)

Okay, danke, gut zu wissen. Dann muss ich meine "wrap"-Methoden halt umbenennen... vllt. "copy" und "copyReadOnly"... dürfte aber halb so wild sein. 
[edit]ähh... soviel Speicher wie man will? Coool... :lol:[/edit]


----------

