Ja, die Abstraktionsebenen sind das entscheidende. Teilweise etwas vereinfachend und suggestiv:
LWJGL bietet direkten Zugriff auf OpenGL - auf der gleichen Ebene wie JOGL ( JOGL - Java Binding for the OpenGL API ). Das eröffnet natürlich alle Möglichkeiten, aber ist entsprechend aufwändig. Als Beispiel, ein Programm, wie man in JOGL (in LWJGL wäre es praktisch das gleiche) ein einzelnes Dreieck zeichnet: https://github.com/elect86/helloTriangle/blob/master/HelloTriangle/src/gl4/helloTriangle/HelloTriangle.java (Das ist nichtmal alles, die Shader sind getrennt davon). Das zu erweitern, damit man zwei Dreiecke zeichnen kann, wäre schon aufwändig. Das Dreieck mit einer Textur zu belegen würde den Code sicher um XX% vergrößern. Auf dieser Ebene ein Modell mit Texturen aus einer Datei zu laden, und die Möglichkeiten zu bieten, das Objekt mit der Maus zu drehen, würde sicher einige tausend Zeilen Code benötigen.
Und genau DIESE „einigen tausend Zeilen Code“ sind (etwas vereinfacht gesagt) das, was in Slick2D steckt. Slick (und andere „Game Engines“) bieten Klassen und Funktionen, die
- „Unwichtige“ Details verstecken
- „Die wichtigsten“ Freiheitsgrade (für ein Spiel) zur Konfiguration anbieten.
Zum Beispiel könnte man die oben angedeutete Aufgabe „Ein Texturiertes Modell laden und mit der Maus drehen“ mit einer (hypothetischen) SEHR stark abstrahierenden Game-Engine vielleicht schreiben als
RenderWindow renderWindow = new RenderWindow(); // Hier stecken 1000 Zeilen Code drin
Model model = new Model("C:/myModel.obj"); // Hier stecken 1000 Zeilen Code drin
Interaction interaction = new MouseInteraction() // Hier stecken 1000 Zeilen Code drin
renderWindow.attach(interaction); // Hier stecken 100 Zeilen Code drin
renderWindow.addModel(model); // Hier stecken 500 Zeilen Code drin
Das ist dann viel einfacher.
(Der Ka… Knackpunkt ist, genau die richtigen Freiheitsgrade zu liefern, die der Benutzer braucht. Wenn der Benutzer jetzt Antialiasing haben will, muss es die Möglichkeit geben, das mit sowas wie renderWindow.setAntialiasing(true);
dem Renderer mitzuteilen. Wenn er will, dass die Mausbewegung invertiert ist, muss man das mit interaction.setInverted(true);
umschalten können… so eine Abstraktion ist also immer auf ein bestimmtes Feld (z.B. Spiele) ausgerichtet, während LWJGL/JOGL/OpenGL mit ihrer „nicht-abstraktion“ darauf abzielen: Wenn ein Pixel auf dem Bildschirm landen soll, dann läuft er durch diese Pipeline. (Ja, auch DA steckt abstraktion drin… Am Ende geht es nur um „Strom oder nicht Stom“ ;-)))
EDIT:
Genau das ist die Abstraktion: Wenn man Slick verwendet, dann sieht man die LWJGL-Funktionen nicht mehr. Man kann also nicht schreiben
SlickModel slickModel = new SlickModel();
slickModel.callSomeLwjglFunction();
Intern ruft Slick diese LWJGL-Funktionen natürlich auf, aber diese Funktionen sind für den, der Slick benutzt, nicht mehr sichtbar (man muss sich also nicht mehr mit den Low-Level-OpenGL/LWJGL-Details rumschlagen)