Reihenfolge bei Matrizenzeug 3d

Hey Leute…
Ich hab jetzt mal versucht meine projektion und die “Kamera” in einer Matrix zusammenzufassen. (Lwjgl, 3d…)
Aus einem Tutorial mehr oder weniger abgekupfert, Pseudocode:


//global
projection = new matrix
projection.macheIrgendeineProjektion(...)
//projection nur bei fov oder render distance änderung ändern

//per Frame
update camera {
    camera = new matrix
    camera.rotate(um y, yaw)
    camera.rotate(um x, pitch)
    camera = projection * camera
    camera.translate(position halt...)
    updateuniform#camera
}

vertex shader:

gl_Position = camera * model * vertex

So. Das funktioniert… nicht so ganz. Im moment habe ich nur eine rotation “eingeschaltet”, die um die x achse.
Aber statt sich eben nach oben und unten um das objekt zu drehen, (ja, ich weiß das sich die welt dreht und nicht die kamera an sich…
aber letzendlich drehen wir sie ja doch [im code] und so ist es einfacher auszudrücken.), wird das objekt nur seltsam verzerrt… kann gleich mal nen screen posten.

Also was ist an dieser Reihenfolge oder generell falsch?

Ich bin ja immernoch der Meinung, dass die Projection-Matrix und die Camera-Matrix nichts miteinander zu tun haben (bzw. erst gaaanz am Ende im Shader zusammengewurstet werden, aber eben nicht zwischen einem translate und einem rotate). Aber Fancy wird da sicher fundiertere Infos/Links/Beispiele dazu geben können.

Na dann halt nicht, ich kann die ja auch wieder auseinander packen. Wurd emir halt voll pft so erklaert… naja. Jedenfalls, wenn ich es trenne habch wieder eineinderes problem… :smiley:
Naja ich warte erstmal was @Fancy sagt

Moin,

man kann die beiden Matrizen durchaus bereits auf der CPU multiplizieren. Theoretisch spart man dann im Vertex Shader etwas, aber selten soviel, als man das merken würde. Aber wie Marco schon schrieb, macht es keinen Sinn nach der Multiplikation noch ein translate auf die Matrix anzuwenden. Beide Matrizen müssen vor der Multiplikation “fertig” sein.

Ob man projection * camera oder camera * projection rechnen muss, hängt davon ab, ob die Matrizen zeilen- oder spaltenweise gespeichert wurden, bzw. ob die Multiplikations-Methode das bereits berücksichtigt. Die transponierte Matrix, (A * B)^T = B^T * A^T. Es kann deshalb passieren, das im Vertex Shader projection * camera auf der CPU zum camera * projection wird.

Im Allgemeinen hat man die Model-Matrix (Local Object Space -> World Space), die View-Matrix (World Space -> Eye Space) und die Projection-Matrix (Eye Space -> Clip Space). Hinzu kommt dann noch die Normal-Matrix. Normalerweise werden im Shader davon auch die Produkte Model-View-Matrix und Model-View-Projection-Matrix benötigt.

Wenn man UBOs (ab OpenGL 3.1) nutzt, lässt sich das einfach in einem Interface Block zusammenfassen, etwa:

layout(std140, binding = 0) uniform MVP {

    mat4 m;
    mat4 v;
    mat4 p
    mat4 mv;
    mat4 mvp;
    mat3 nm;

} mvp;

Das hat den Vorteil das die einzelnen Werte schnell geändert und von mehreren Shadern genutzt werden können.

In sehr einfachen Anwendungen wird die Unterteilung der Model-View-Matrix in Model-Matrix und View-Matrix auch oft weggelassen, wenn die Koordinaten der Objekte bereits im Word Space vorliegen, wäre die Model-Matrix ohnehin die Einheitsmatrix.

Viele Grüße
Fancy

hm.
danke für die information, ist ja schön und gut…
aber was nun? woher weiss ich denn ob es spalten oder zeilenweise eingelesen werden soll?
Ausserdem, egal wie rum, es kommt genau das selbe bei raus…

*** Edit ***

okay es lag wirklich an falscher reihenfolge. Ich hatte halt Rst im Kopf.
Aktueller (zusammengefasster) Code:

    private float pitch;
    private float yaw;
    private float z = -10.0f;
    public void updateCamera(float delta, float sensivity){
    	pitch += (float) (delta / 1e9) * Mouse.getDY() * sensivity;
    	yaw += (float) (delta / 1e9) * Mouse.getDX() * sensivity;
    	z += (float) (delta / 1e9) * 1;
    	camera = new Matrix4f();
    	camera.translate(new Vector3f(0.0f, -2.0f, z));
    	camera.rotate((float) Math.toRadians(-pitch), new Vector3f(1.0f, 0.0f, 0.0f));
    	camera.rotate((float) Math.toRadians(yaw), new Vector3f(0.0f, 1.0f, 0.0f));
    	Matrix4f.mul(projection, camera, camera);
    	FloatBuffer buffer = BufferUtils.createFloatBuffer(16);
    	camera.store(buffer);
        buffer.flip();
        GL20.glUniformMatrix4(GL20.glGetUniformLocation(shaderProgramID, "camera"), false, buffer);
    }

Nun, meine aktuellen Probleme dabei: Sobald die Kamera sich bewegt hat, gedreht oder sonstiges, und ich sie dann um eine der Achsen drehe,
dann dreht sie sich ja immer noch im die Ursprung x y matrizen. Ich will mich aber um die Kamera relativen achsen drehen… da war doch was mit erst bewegen dann drehen
dann zurückbewegen… kann man das hier genauso anwenden? aber wie und wohin bewegen und wie dann wieder zurück? Hoffentlich versteht ihr was ich meine :stuck_out_tongue:
Ausserdem: Wie man in dem Beispiel sieht bewegt sich das Objekt von -10 immer weiter richtung +z. Sobald es aber z hinter dem Objekt ist, kann ich mich nicht einfach
umdrehen und das Objekt von der anderen Seite anschauen - als wäre es verschwunden… das liegt doch am ersten Problem, oder etwa nicht?

Ich hänge hier mal die Jar mit rein, die zeigt beide Probleme ganz gut.

Ich hab mir Dein Beispiel noch nicht angesehen und Code ist leider auch keiner im JAR. Deiner Beschreibung nach klingt das ein wenig, als ob Du eine First Person Steuerung realisieren möchtest. Dann solltest Du Dir noch mal in diesem Beispiel die untere hdi() Methode ansehen. Dort wird genau so eine Matrix erzeugt.

posX, posY, posZ ist die aktuelle Position der Kamera.
rotV entspricht dem nicken
rotY dem seitlichen drehen
rotX und rotZ ist die Rotation um die jeweiligen Achsen (ergibt sich aus rotV und rotY)
die untere Matrix mv ist das Produkt aus Rotation und Translation.

Am besten mal auf Papier nachrechnen. Ansonsten versuche doch zu Deinem Problem ein KSKB zu bauen, dann ist das leichter nachzuvollziehen.

Viele Grüße
Fancy

Ich hab ja die relevante stelle gepostet. Ja ziel ist so ene kamera, aber die braucht man ja immer wenn man sich im raum bewegen will. Auch bei second person oder sonstwas :stuck_out_tongue: jedenfalls, ich schau mir das mal an… danke.

Ot: bekommen die abonennten eines threads benachrichtigungen wenn die letzte antwort editiert wird??

*** Edit ***

AAlso, danke nochmal für das kskb - aber leider besteht das problem nach wie vor.
Es ist einfach so das sich dir Kamera nicht ihrer eigenen Achsen nach dreht / bewegt, sondern den Ursprungsachsen nach…
Ich googel noch ein bisschen, aber hier nun die Kamera Update methode: (ja klar extrem unsauber, hab aber deinen code quasi reinkopiert…)

    private float pitch;
    private float yaw;
    private float posX, posY, posZ;
    
    public void updateCamera(float delta, float sensivity){    
            final long time;
            final double step = -10 * delta / 1e9;
     
            final double keySpeed = step;
            final double mouseSpeed = step * 0.01;
     
            final float rotVmax = 1;
            final float rotVMin = -1;
     
            yaw += Mouse.getDX() * mouseSpeed;
            pitch -= Mouse.getDY() * mouseSpeed;
     
            if (pitch > rotVmax)
                pitch = rotVmax;
     
            if (pitch < rotVMin)
                pitch = rotVMin;
     
            if(Keyboard.isKeyDown(Keyboard.KEY_W)){
                posX -= Math.sin(yaw) * keySpeed;
                posZ += Math.cos(yaw) * keySpeed;
            }
            if (Keyboard.isKeyDown(Keyboard.KEY_S)) {
                posX += Math.sin(yaw) * keySpeed;
                posZ -= Math.cos(yaw) * keySpeed;
            }
            if (Keyboard.isKeyDown(Keyboard.KEY_A)) {
                posX += Math.cos(yaw) * keySpeed;
                posZ += Math.sin(yaw) * keySpeed;
            }
            if (Keyboard.isKeyDown(Keyboard.KEY_D)) {
                posX -= Math.cos(yaw) * keySpeed;
                posZ -= Math.sin(yaw) * keySpeed;
            }
            
            float rotX = (float) (Math.cos(yaw) * pitch);
            float rotZ = (float) (Math.sin(yaw) * pitch);
            
            Matrix4f mv = new Matrix4f();
            
            final double sinX = Math.sin(rotX);
            final double sinY = Math.sin(yaw);
            final double sinZ = Math.sin(rotZ);
     
            final double cosX = Math.cos(rotX);
            final double cosY = Math.cos(yaw);
            final double cosZ = Math.cos(rotZ);
     
            mv.m00 = (float) (cosY * cosZ + sinY * sinX * sinZ);
            mv.m01 = (float) (cosX * sinZ);
            mv.m02 = (float) (-sinY * cosZ + cosY * sinX * sinZ);
            mv.m10 = (float) (-cosY * sinZ + sinY * sinX * cosZ);
            mv.m11 = (float) (cosX * cosZ);
            mv.m12 = (float) (sinY * sinZ + cosY * sinX * cosZ);
            mv.m20 = (float) (sinY * cosX);
            mv.m21 = (float) (-sinX);
            mv.m22 = (float) (cosY * cosX);
            mv.m30 = mv.m00 * posX + mv.m10 * posY + mv.m20 * posZ;
            mv.m31 = mv.m01 * posX + mv.m11 * posY + mv.m21 * posZ;
            mv.m32 = mv.m02 * posX + mv.m12 * posY + mv.m22 * posZ;
            mv.m33 = 1;
            mv.invert();
            FloatBuffer buffer = BufferUtils.createFloatBuffer(16);
            Matrix4f.mul(projection, mv, new Matrix4f()).store(buffer);
            buffer.flip();
            GL20.glUniformMatrix4(GL20.glGetUniformLocation(shaderProgramID, "camera"), false, buffer);
    }

Hm, da der Code im KSKB funktioniert, ist entweder beim Kopieren etwas schief gelaufen, irgend woanders noch ein Fehler oder ich verstehe nicht, wo das aktuelle Problem liegt.

Wenn kein anderer erkennt, wo das Problem ist, könntest Du vielleicht noch mal beschreiben, welches Verhalten Du aktuell hast und welches Verhalten Du haben möchtest. Bestenfalls anhand eines KSKB. Vermutlich wäre es dann einfacher.

Viele Grüße
Fancy

Okay also, in den Augen des Betrachters beschrieben:

“Ich gehe nach hinten, und bewege mich nach links. Dann drehe ich nach links und rechts.
Allerdings sieht es aus als ob sich die Pryamide drehen würde, nicht ich. Also drehe ich mich
irgendwie um die ursprungsachsen, nicht um meine eigenen achsen.”

So ungefähr verstanden? Hier also kskb:

package de.skysoldier.lwjgltest;

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;

import javax.imageio.ImageIO;

import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Cursor;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.lwjgl.util.vector.Matrix4f;
import org.lwjgl.util.vector.Vector3f;

import de.skysoldier.abstractgl.AGL;
import de.skysoldier.abstractgl.AGLCaps.AGLDisplayCap;

public class Cube {
	
	private final int VERTEX_LOCATION = 0;
	private final int TEXTURE_LOCATION = 1;

	private int shaderProgramID;
    private int vertexArrayObjectID;
    private int vertexBufferObjectID;
    private int textureID;
    
    private Matrix4f projection;
    
    public Cube(){
        initDisplay();
        initTexture();
        initShaders();
        initGl();
        startGameLoop();
    }

    private void initDisplay(){
    	AGL.createLwjglContext(AGLDisplayCap.NONE);
    }

    private void initTexture(){
        BufferedImage source = null;
        try{
            source = ImageIO.read(getClass().getClassLoader().getResourceAsStream("pic.png"));
        }
        catch(Exception e){

        }
        
        IntBuffer buffer = ByteBuffer.allocateDirect(4).asIntBuffer();
        GL11.glGenTextures(buffer);
        
        final BufferedImage textureImage;

        int textureWidth = 2;
        int textureHeight = 2;

        while (textureWidth < source.getWidth())
                textureWidth *= 2;
        while (textureHeight < source.getHeight())
                textureHeight *= 2;
        
        textureID = buffer.get();

    	textureImage = new BufferedImage(textureWidth, textureHeight, BufferedImage.TYPE_4BYTE_ABGR);
        Graphics2D graphics = (Graphics2D) textureImage.getGraphics();
        graphics.drawImage(source, 0, 0, null);
        graphics.dispose();
        
        byte[] data = (byte[]) textureImage.getRaster().getDataElements(0, 0, textureWidth, textureHeight, null);

        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(textureImage.getColorModel().getPixelSize() / 8 * textureWidth * textureHeight);
        byteBuffer.put(data);
        byteBuffer.rewind();

        GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID);
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP);
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
        GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, textureWidth, textureHeight, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, byteBuffer);
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
    }

    private void initShaders(){
        String vertexShaderCode = 
        		"#version 120
"+
        		"uniform sampler2D tex;
"+
        		"attribute vec2 vertTexCoord;
"+
        		"varying vec2 fragTexCoord;
"+
        		"uniform mat4 camera;
"+
        		"uniform mat4 model;
"+
        		"attribute vec3 vert;
"+
        		"void main() {
"+
        		"	fragTexCoord = vertTexCoord;
"+
        		"    gl_Position = camera * model * vec4(vert, 1);
"+
        		"}";
        String fragmentShaderCode = 
        		"#version 120
"+
        		"uniform sampler2D fragTex;
"+
        		"varying vec2 fragTexCoord;
"+
        		"void main(void){
"+
        		"	gl_FragColor = texture2D(fragTex, fragTexCoord);
"+
        		"}";

        int vertexShaderID = GL20.glCreateShader(GL20.GL_VERTEX_SHADER);
        GL20.glShaderSource(vertexShaderID, vertexShaderCode);
        GL20.glCompileShader(vertexShaderID);

        int fragmentShaderID = GL20.glCreateShader(GL20.GL_FRAGMENT_SHADER);
        GL20.glShaderSource(fragmentShaderID, fragmentShaderCode);
        GL20.glCompileShader(fragmentShaderID);

        shaderProgramID = GL20.glCreateProgram();
        GL20.glAttachShader(shaderProgramID, vertexShaderID);
        GL20.glAttachShader(shaderProgramID, fragmentShaderID);

        GL20.glBindAttribLocation(shaderProgramID, VERTEX_LOCATION, "vert");
        GL20.glBindAttribLocation(shaderProgramID, TEXTURE_LOCATION, "vertTexCoord");
        GL20.glLinkProgram(shaderProgramID);
        
        GL20.glDetachShader(shaderProgramID, vertexShaderID);
        GL20.glDetachShader(shaderProgramID, fragmentShaderID);

        GL20.glUseProgram(shaderProgramID);
        
        float zNear = 1f, zFar = 100.0f, fov = 60f;
        float top = (float) ((Math.tan(fov * Math.PI / 360.0f) * zNear));
        float bottom = -top;
        float left = (800.0f / 600.0f) * bottom;
        float right = (800.0f / 600.0f) * top;
        projection = new Matrix4f();
        projection.m00 = (2 * zNear) / (right - left);
        projection.m02 = (right + left) / (right - left);
        projection.m11 = (2 * zNear) / (top - bottom);
        projection.m12 = (top + bottom) / (top - bottom);
        projection.m22 = -(zFar + zNear) / (zFar - zNear);
        projection.m23 = -(2 * zFar * zNear) / (zFar - zNear);
        projection.m32 = -1;
        projection.m33 = 0;

        GL20.glUniform3f(GL20.glGetUniformLocation(shaderProgramID, "light1.position"), 2.0f, 1.0f, 0.0f);
        GL20.glUniform3f(GL20.glGetUniformLocation(shaderProgramID, "light1.intensities"), 1.0f, 1.0f, 0.0f);
        
        int compileStatus = GL20.glGetShaderi(vertexShaderID, GL20.GL_COMPILE_STATUS);
        if (compileStatus == GL11.GL_FALSE) {
            int infoLogLength = GL20.glGetShaderi(vertexShaderID, GL20.GL_INFO_LOG_LENGTH);
            String infoLog = GL20.glGetShaderInfoLog(vertexShaderID, infoLogLength);
            throw new RuntimeException(infoLog);
        }
        System.out.println("Compile Errors: " + GL20.glGetProgramInfoLog(shaderProgramID, GL20.glGetProgrami(shaderProgramID, GL20.GL_INFO_LOG_LENGTH)));
    }
    
    private void initGl(){
    	float vertices[] = new float[]{
    		1.0f, 1.0f, 1.0f,  1.0f, 1.0f,  
    		1.0f, 1.0f,-1.0f,  1.0f, 0.0f,  
    	   -1.0f, 1.0f, 1.0f,  0.0f, 1.0f,  
    	   
    	   -1.0f, 1.0f, 1.0f,  0.0f, 1.0f,  
    	    1.0f, 1.0f,-1.0f,  1.0f, 0.0f,  
    	   -1.0f, 1.0f,-1.0f,  0.0f, 0.0f,  
    	   
    	   
    	    1.0f, 1.0f,-1.0f,  1.0f, 0.0f,  
    	    0.0f, 3.0f, 0.0f,  0.5f, 1.0f,  
    	   -1.0f, 1.0f,-1.0f,  0.0f, 0.0f,  
    	    
    	   -1.0f, 1.0f,-1.0f,  0.0f, 0.0f,  
    	    0.0f, 3.0f, 0.0f,  0.5f, 1.0f,  
 	   	   -1.0f, 1.0f, 1.0f,  1.0f, 0.0f,  
	   	    
	   	    1.0f, 1.0f, 1.0f,  1.0f, 0.0f,  
	   	    0.0f, 3.0f, 0.0f,  0.5f, 1.0f,  
	   	   -1.0f, 1.0f, 1.0f,  0.0f, 0.0f,  
    	
	   	    1.0f, 1.0f,-1.0f,  0.0f, 0.0f,  
	   		0.0f, 3.0f, 0.0f,  0.5f, 1.0f,  
	   	    1.0f, 1.0f, 1.0f,  1.0f, 0.0f
    	};
        FloatBuffer verticesBuffer = BufferUtils.createFloatBuffer(vertices.length);
        verticesBuffer.put(vertices);
        verticesBuffer.flip(); 
        
        vertexArrayObjectID = GL30.glGenVertexArrays();
        GL30.glBindVertexArray(vertexArrayObjectID);

        vertexBufferObjectID = GL15.glGenBuffers();
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vertexBufferObjectID);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, verticesBuffer, GL15.GL_STATIC_DRAW);

        GL20.glEnableVertexAttribArray(VERTEX_LOCATION);
        GL20.glVertexAttribPointer(VERTEX_LOCATION, 3, GL11.GL_FLOAT, false, 5 * Float.SIZE / 8, 0);
        
        GL20.glEnableVertexAttribArray(TEXTURE_LOCATION);
        GL20.glVertexAttribPointer(TEXTURE_LOCATION, 2, GL11.GL_FLOAT, true, 5 * Float.SIZE / 8, 3 * Float.SIZE / 8);
        
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
        GL30.glBindVertexArray(0);
        
        GL11.glEnable(GL11.GL_BLEND);
        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
    
        GL11.glEnable(GL11.GL_DEPTH_TEST);
        GL11.glDepthFunc(GL11.GL_LESS);
    }

    private void startGameLoop(){
    	long lastFrame = System.nanoTime();
    	long thisFrame = System.nanoTime();
    	
    	long lastTime = System.nanoTime();
    	ArrayList<Long> fpsCollection = new ArrayList<>();
    	
    	long delta;
    	int mid = 0, min = Integer.MAX_VALUE, max = 0;   	
    	
    	try{
			Mouse.setGrabbed(true);
    	}
    	catch(Exception e){
    		e.printStackTrace();
    	}
    	
    	while(!Display.isCloseRequested()){
    		thisFrame = System.nanoTime();
    		delta = thisFrame - lastFrame;
    		lastFrame = thisFrame;
    		
    		GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
            GL11.glClearColor(0, 0, 0, 1);
            
            GL20.glUseProgram(shaderProgramID);
            GL13.glActiveTexture(GL13.GL_TEXTURE0);
    		GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID);
    		GL20.glUniform1i(GL20.glGetUniformLocation(shaderProgramID, "tex"), 0);
        	
            
            updateCamera(delta);
            
    		GL30.glBindVertexArray(vertexArrayObjectID);
            
    		GL20.glUniformMatrix4(GL20.glGetUniformLocation(shaderProgramID, "model"), false, testTranslate(delta, 0));
    		GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, 18);
            
            double fpsRaw = (1e9 / delta);
            int fps = (int) fpsRaw;
            if(min != 0 && fps < min){
            	min = fps;
            }
            if(fps > max){
            	max = fps;
            }
    		if(thisFrame / 1e9 - lastTime / 1e9 >= 1){
    			lastTime = thisFrame;
    			fpsCollection.add((long) fps);
    			mid = calcMid(fpsCollection);
    		}
    		Display.setTitle("mid: " + mid + " | min: " + min + " | max: " + max + " | now: " + fps + "");
            Display.update();
    	}
        destroy();
    }
    
    private float pitch;
    private float yaw;
    private float posX, posY, posZ;
    
    public void updateCamera(float delta){
            final double step = -10 * delta / 1e9;
     
            final double keySpeed = step;
            final double mouseSpeed = step * 0.01;
     
            final float rotVmax = 1;
            final float rotVMin = -1;
     
            yaw += Mouse.getDX() * mouseSpeed;
            pitch -= Mouse.getDY() * mouseSpeed;
     
            if (pitch > rotVmax)
                pitch = rotVmax;
     
            if (pitch < rotVMin)
                pitch = rotVMin;
     
            if(Keyboard.isKeyDown(Keyboard.KEY_W)){
                posX -= Math.sin(yaw) * keySpeed;
                posZ += Math.cos(yaw) * keySpeed;
            }
            if (Keyboard.isKeyDown(Keyboard.KEY_S)) {
                posX += Math.sin(yaw) * keySpeed;
                posZ -= Math.cos(yaw) * keySpeed;
            }
            if (Keyboard.isKeyDown(Keyboard.KEY_A)) {
                posX += Math.cos(yaw) * keySpeed;
                posZ += Math.sin(yaw) * keySpeed;
            }
            if (Keyboard.isKeyDown(Keyboard.KEY_D)) {
                posX -= Math.cos(yaw) * keySpeed;
                posZ -= Math.sin(yaw) * keySpeed;
            }
            
            float rotX = (float) (Math.cos(yaw) * pitch);
            float rotZ = (float) (Math.sin(yaw) * pitch);
            
            Matrix4f mv = new Matrix4f();
            
            final double sinX = Math.sin(rotX);
            final double sinY = Math.sin(yaw);
            final double sinZ = Math.sin(rotZ);
     
            final double cosX = Math.cos(rotX);
            final double cosY = Math.cos(yaw);
            final double cosZ = Math.cos(rotZ);
     
            mv.m00 = (float) (cosY * cosZ + sinY * sinX * sinZ);
            mv.m01 = (float) (cosX * sinZ);
            mv.m02 = (float) (-sinY * cosZ + cosY * sinX * sinZ);
            mv.m10 = (float) (-cosY * sinZ + sinY * sinX * cosZ);
            mv.m11 = (float) (cosX * cosZ);
            mv.m12 = (float) (sinY * sinZ + cosY * sinX * cosZ);
            mv.m20 = (float) (sinY * cosX);
            mv.m21 = (float) (-sinX);
            mv.m22 = (float) (cosY * cosX);
            mv.m30 = mv.m00 * posX + mv.m10 * posY + mv.m20 * posZ;
            mv.m31 = mv.m01 * posX + mv.m11 * posY + mv.m21 * posZ;
            mv.m32 = mv.m02 * posX + mv.m12 * posY + mv.m22 * posZ;
            mv.m33 = 1;
            mv.invert();
            FloatBuffer buffer = BufferUtils.createFloatBuffer(16);
            Matrix4f.mul(projection, mv, new Matrix4f()).store(buffer);
            buffer.flip();
            GL20.glUniformMatrix4(GL20.glGetUniformLocation(shaderProgramID, "camera"), false, buffer);
    }

    float test;
    public FloatBuffer testTranslate(long delta, int index){
    	Matrix4f mat = new Matrix4f();
    	mat.translate(new Vector3f(2 * index + (index * 0.5f), 0.0f, 0.0f));
    	if(index == 1){
    		mat.translate(new Vector3f(0.0f, 0.0f, 2.0f));
    		mat.rotate((float) (test), new Vector3f(1.0f, 0.0f, 0.0f));
    	}
    	FloatBuffer buffer = BufferUtils.createFloatBuffer(16);
    	mat.store(buffer);
    	buffer.flip();
    	test+=1  * delta / 1e9;
    	return buffer;
    }
    
    
    public int calcMid(ArrayList<Long> fpsCollection){
    	long lm = 0;
    	for(long l : fpsCollection){
    		lm+=l;
    	}
    	return (int) lm / fpsCollection.size();
    }

    private void destroy(){
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
        GL15.glDeleteBuffers(vertexBufferObjectID);

        GL30.glBindVertexArray(0);
        GL30.glDeleteVertexArrays(vertexArrayObjectID);

        Display.destroy();
    }

    public static void main(String[] args) {
//    	System.setProperty("org.lwjgl.util.Debug", "true");
    	new Cube();
    }
}

Okay, also offensichtlich falsch ist das negative step in Zeile 286 und das invert in Zeile 346. Trotzdem springen die Werte manchmal unnatürlich, woran das liegt, konnte ich auf die schnelle nicht finden.

Baue ich die Steuerung aus meinem KSKB 1 zu 1 in Dein KSKB ein (und damit auch meine KSKB Matrix Klasse) funktioniert die Steuerung jedenfalls problemlos:


import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

import javax.imageio.ImageIO;

import org.lwjgl.BufferUtils;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.ContextAttribs;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.lwjgl.opengl.PixelFormat;


public class Cube {

    private final int VERTEX_LOCATION = 0;
    private final int TEXTURE_LOCATION = 1;

    private int shaderProgramID;
    private int vertexArrayObjectID;
    private int vertexBufferObjectID;
    private int textureID;

    private boolean exit;
    private long time;
    private float rotX, rotY, rotZ, rotV;
    private float posX, posY, posZ;


    public Cube() {

        initDisplay();
        initTexture();
        initShaders();
        initGl();
        startGameLoop();

    }


    private void initDisplay() {

        try {

            final DisplayMode displayMode = new DisplayMode(800, 600);
            final PixelFormat pixelFormat = new PixelFormat();
            final ContextAttribs contextAttribs = new ContextAttribs(3, 0);

            Display.setDisplayMode(displayMode);
            Display.create(pixelFormat, contextAttribs);
            Display.setVSyncEnabled(true);

            Mouse.setGrabbed(true);

        } catch (final Exception e) {

            throw new RuntimeException(e);

        }
    }


    private void initTexture() {

        BufferedImage source = null;
        try {

            source = ImageIO.read(getClass().getClassLoader().getResourceAsStream("pic.jpg"));

        } catch (final Exception e) {

            throw new RuntimeException(e);

        }

        final IntBuffer buffer = ByteBuffer.allocateDirect(4).asIntBuffer();
        GL11.glGenTextures(buffer);

        final BufferedImage textureImage;

        int textureWidth = 2;
        int textureHeight = 2;

        while (textureWidth < source.getWidth())
            textureWidth *= 2;
        while (textureHeight < source.getHeight())
            textureHeight *= 2;

        textureID = buffer.get();

        textureImage = new BufferedImage(textureWidth, textureHeight, BufferedImage.TYPE_4BYTE_ABGR);
        final Graphics2D graphics = (Graphics2D) textureImage.getGraphics();
        graphics.drawImage(source, 0, 0, null);
        graphics.dispose();

        final byte[] data = (byte[]) textureImage.getRaster().getDataElements(0, 0, textureWidth, textureHeight, null);

        final ByteBuffer byteBuffer = ByteBuffer.allocateDirect(textureImage.getColorModel().getPixelSize() / 8 * textureWidth * textureHeight);
        byteBuffer.put(data);
        byteBuffer.rewind();

        GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID);
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP);
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
        GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, textureWidth, textureHeight, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, byteBuffer);
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);

    }


    private void initShaders() {

        final String vertexShaderCode =
                "#version 120
" +
                        "uniform sampler2D tex;
" +
                        "attribute vec2 vertTexCoord;
" +
                        "varying vec2 fragTexCoord;
" +
                        "uniform mat4 camera;
" +
                        "uniform mat4 model;
" +
                        "attribute vec3 vert;
" +
                        "void main() {
" +
                        "	fragTexCoord = vertTexCoord;
" +
                        "    gl_Position = camera * vec4(vert, 1);
" +
                        "}";

        final String fragmentShaderCode =
                "#version 120
" +
                        "uniform sampler2D fragTex;
" +
                        "varying vec2 fragTexCoord;
" +
                        "void main(void){
" +
                        "	gl_FragColor = texture2D(fragTex, fragTexCoord);
" +
                        "}";

        final int vertexShaderID = GL20.glCreateShader(GL20.GL_VERTEX_SHADER);
        GL20.glShaderSource(vertexShaderID, vertexShaderCode);
        GL20.glCompileShader(vertexShaderID);

        final int fragmentShaderID = GL20.glCreateShader(GL20.GL_FRAGMENT_SHADER);
        GL20.glShaderSource(fragmentShaderID, fragmentShaderCode);
        GL20.glCompileShader(fragmentShaderID);

        shaderProgramID = GL20.glCreateProgram();
        GL20.glAttachShader(shaderProgramID, vertexShaderID);
        GL20.glAttachShader(shaderProgramID, fragmentShaderID);

        GL20.glBindAttribLocation(shaderProgramID, VERTEX_LOCATION, "vert");
        GL20.glBindAttribLocation(shaderProgramID, TEXTURE_LOCATION, "vertTexCoord");
        GL20.glLinkProgram(shaderProgramID);

        GL20.glDetachShader(shaderProgramID, vertexShaderID);
        GL20.glDetachShader(shaderProgramID, fragmentShaderID);

        GL20.glUseProgram(shaderProgramID);


        final int compileStatus = GL20.glGetShaderi(vertexShaderID, GL20.GL_COMPILE_STATUS);
        if (compileStatus == GL11.GL_FALSE) {
            final int infoLogLength = GL20.glGetShaderi(vertexShaderID, GL20.GL_INFO_LOG_LENGTH);
            final String infoLog = GL20.glGetShaderInfoLog(vertexShaderID, infoLogLength);
            throw new RuntimeException(infoLog);
        }
        System.out.println("Compile Errors: " + GL20.glGetProgramInfoLog(shaderProgramID, GL20.glGetProgrami(shaderProgramID, GL20.GL_INFO_LOG_LENGTH)));

    }


    private void initGl() {

        final float vertices[] = new float[] {
                1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
                1.0f, 1.0f, -1.0f, 1.0f, 0.0f,
                -1.0f, 1.0f, 1.0f, 0.0f, 1.0f,

                -1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
                1.0f, 1.0f, -1.0f, 1.0f, 0.0f,
                -1.0f, 1.0f, -1.0f, 0.0f, 0.0f,


                1.0f, 1.0f, -1.0f, 1.0f, 0.0f,
                0.0f, 3.0f, 0.0f, 0.5f, 1.0f,
                -1.0f, 1.0f, -1.0f, 0.0f, 0.0f,

                -1.0f, 1.0f, -1.0f, 0.0f, 0.0f,
                0.0f, 3.0f, 0.0f, 0.5f, 1.0f,
                -1.0f, 1.0f, 1.0f, 1.0f, 0.0f,

                1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
                0.0f, 3.0f, 0.0f, 0.5f, 1.0f,
                -1.0f, 1.0f, 1.0f, 0.0f, 0.0f,

                1.0f, 1.0f, -1.0f, 0.0f, 0.0f,
                0.0f, 3.0f, 0.0f, 0.5f, 1.0f,
                1.0f, 1.0f, 1.0f, 1.0f, 0.0f
        };
        final FloatBuffer verticesBuffer = BufferUtils.createFloatBuffer(vertices.length);
        verticesBuffer.put(vertices);
        verticesBuffer.flip();

        vertexArrayObjectID = GL30.glGenVertexArrays();
        GL30.glBindVertexArray(vertexArrayObjectID);

        vertexBufferObjectID = GL15.glGenBuffers();
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vertexBufferObjectID);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, verticesBuffer, GL15.GL_STATIC_DRAW);

        GL20.glEnableVertexAttribArray(VERTEX_LOCATION);
        GL20.glVertexAttribPointer(VERTEX_LOCATION, 3, GL11.GL_FLOAT, false, 5 * Float.SIZE / 8, 0);

        GL20.glEnableVertexAttribArray(TEXTURE_LOCATION);
        GL20.glVertexAttribPointer(TEXTURE_LOCATION, 2, GL11.GL_FLOAT, true, 5 * Float.SIZE / 8, 3 * Float.SIZE / 8);

        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
        GL30.glBindVertexArray(0);

        GL11.glEnable(GL11.GL_BLEND);
        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);

        GL11.glEnable(GL11.GL_DEPTH_TEST);
        GL11.glDepthFunc(GL11.GL_LESS);

    }


    private void startGameLoop() {

        final FloatBuffer buffer = BufferUtils.createFloatBuffer(16);
        final Matrix4x4f p = Matrix4x4f.projection(45, (float) Display.getWidth() / (float) Display.getHeight(), 1f, 1000f);

        posZ = -10;

        while (!Display.isCloseRequested() && !exit) {

            GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
            GL11.glClearColor(0, 0, 0, 1);

            GL20.glUseProgram(shaderProgramID);
            GL13.glActiveTexture(GL13.GL_TEXTURE0);
            GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID);
            GL20.glUniform1i(GL20.glGetUniformLocation(shaderProgramID, "tex"), 0);

            final Matrix4x4f mv = hdi();
            final Matrix4x4f mvp = p.mul(mv);
            buffer.put(mvp.m);
            buffer.rewind();

            GL20.glUniformMatrix4(GL20.glGetUniformLocation(shaderProgramID, "camera"), false, buffer);

            GL30.glBindVertexArray(vertexArrayObjectID);

            GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, 18);

            Display.update();

        }

        destroy();

    }


    private Matrix4x4f hdi() {

        final double step = -(time - (time = System.nanoTime())) / 100000000.0;

        final double keySpeed = step;
        final double mouseSpeed = step * 0.01;

        final float rotVmax = 1;
        final float rotVMin = -1;

        rotY += Mouse.getDX() * mouseSpeed;
        rotV -= Mouse.getDY() * mouseSpeed;

        if (rotV > rotVmax)
            rotV = rotVmax;

        if (rotV < rotVMin)
            rotV = rotVMin;

        if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE))
            exit = true;

        if (Keyboard.isKeyDown(Keyboard.KEY_W)) {

            posX -= Math.sin(rotY) * keySpeed;
            posZ += Math.cos(rotY) * keySpeed;

        }

        if (Keyboard.isKeyDown(Keyboard.KEY_S)) {

            posX += Math.sin(rotY) * keySpeed;
            posZ -= Math.cos(rotY) * keySpeed;

        }

        if (Keyboard.isKeyDown(Keyboard.KEY_A)) {

            posX += Math.cos(rotY) * keySpeed;
            posZ += Math.sin(rotY) * keySpeed;

        }

        if (Keyboard.isKeyDown(Keyboard.KEY_D)) {

            posX -= Math.cos(rotY) * keySpeed;
            posZ -= Math.sin(rotY) * keySpeed;

        }

        rotX = (float) (Math.cos(rotY) * rotV);
        rotZ = (float) (Math.sin(rotY) * rotV);

        final float[] mv = new float[16];

        final double sinX = Math.sin(rotX);
        final double sinY = Math.sin(rotY);
        final double sinZ = Math.sin(rotZ);

        final double cosX = Math.cos(rotX);
        final double cosY = Math.cos(rotY);
        final double cosZ = Math.cos(rotZ);

        mv[0] = (float) (cosY * cosZ + sinY * sinX * sinZ);
        mv[1] = (float) (cosX * sinZ);
        mv[2] = (float) (-sinY * cosZ + cosY * sinX * sinZ);
        mv[4] = (float) (-cosY * sinZ + sinY * sinX * cosZ);
        mv[5] = (float) (cosX * cosZ);
        mv[6] = (float) (sinY * sinZ + cosY * sinX * cosZ);
        mv[8] = (float) (sinY * cosX);
        mv[9] = (float) (-sinX);
        mv[10] = (float) (cosY * cosX);

        mv[12] = mv[0] * posX + mv[4] * posY + mv[8] * posZ;
        mv[13] = mv[1] * posX + mv[5] * posY + mv[9] * posZ;
        mv[14] = mv[2] * posX + mv[6] * posY + mv[10] * posZ;
        mv[15] = 1;

        return new Matrix4x4f(mv);

    }


    private void destroy() {

        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
        GL15.glDeleteBuffers(vertexBufferObjectID);

        GL30.glBindVertexArray(0);
        GL30.glDeleteVertexArrays(vertexArrayObjectID);

        Display.destroy();

    }


    public static void main(final String[] args) {

        new Cube();

    }


    static final class Matrix4x4f {


        private final float[] m;


        public Matrix4x4f() {

            m = new float[16];

            for (int i = 0; i < 4; i++)
                m[i * 5] = 1.0f;

        }


        public Matrix4x4f(final float[] m) {

            this.m = m;

        }


        public static Matrix4x4f projection(final float fovy, final float aspect, final float zNear, final float zFar) {

            final double f = (1.0 / Math.tan(Math.toRadians(fovy / 2.0)));

            final float[] m = new float[16];

            m[0] = (float) (f / aspect);
            m[5] = (float) (f);
            m[10] = (zFar + zNear) / (zNear - zFar);
            m[11] = (-1);
            m[14] = (2 * zFar * zNear) / (zNear - zFar);
            m[15] = 0;

            return new Matrix4x4f(m);

        }


        public static Matrix4x4f translate(final float x, final float y, final float z) {

            final float[] m = new float[16];

            for (int i = 0; i < 4; i++)
                m[i * 5] = 1.0f;

            m[12] = x;
            m[13] = y;
            m[14] = z;

            return new Matrix4x4f(m);

        }


        public static Matrix4x4f rotate(float x, float y, float z, final double angle) {

            final float len = (float) Math.sqrt(x * x + y * y + z * z);
            final float c = (float) Math.cos(Math.toDegrees(angle));
            final float s = (float) Math.sin(Math.toDegrees(angle));

            x = x / len;
            y = y / len;
            z = z / len;

            final float[] m = new float[16];

            m[0] = x * x * (1 - c) + c;
            m[1] = y * x * (1 - c) + z * s;
            m[2] = x * z * (1 - c) - y * s;
            m[4] = x * y * (1 - c) - z * s;
            m[5] = y * y * (1 - c) + c;
            m[6] = y * z * (1 - c) + x * s;
            m[8] = x * z * (1 - c) + y * s;
            m[9] = y * z * (1 - c) - x * s;
            m[10] = z * z * (1 - c) + c;
            m[15] = 1;

            return new Matrix4x4f(m);

        }


        public Matrix4x4f mul(final Matrix4x4f m2) {

            final float[] o = m2.m;

            final float[] result = new float[16];

            result[0] = m[0] * o[0] + m[4] * o[1] + m[8] * o[2] + m[12] * o[3];
            result[1] = m[1] * o[0] + m[5] * o[1] + m[9] * o[2] + m[13] * o[3];
            result[2] = m[2] * o[0] + m[6] * o[1] + m[10] * o[2] + m[14] * o[3];
            result[3] = m[3] * o[0] + m[7] * o[1] + m[11] * o[2] + m[15] * o[3];
            result[4] = m[0] * o[4] + m[4] * o[5] + m[8] * o[6] + m[12] * o[7];
            result[5] = m[1] * o[4] + m[5] * o[5] + m[9] * o[6] + m[13] * o[7];
            result[6] = m[2] * o[4] + m[6] * o[5] + m[10] * o[6] + m[14] * o[7];
            result[7] = m[3] * o[4] + m[7] * o[5] + m[11] * o[6] + m[15] * o[7];
            result[8] = m[0] * o[8] + m[4] * o[9] + m[8] * o[10] + m[12] * o[11];
            result[9] = m[1] * o[8] + m[5] * o[9] + m[9] * o[10] + m[13] * o[11];
            result[10] = m[2] * o[8] + m[6] * o[9] + m[10] * o[10] + m[14] * o[11];
            result[11] = m[3] * o[8] + m[7] * o[9] + m[11] * o[10] + m[15] * o[11];
            result[12] = m[0] * o[12] + m[4] * o[13] + m[8] * o[14] + m[12] * o[15];
            result[13] = m[1] * o[12] + m[5] * o[13] + m[9] * o[14] + m[13] * o[15];
            result[14] = m[2] * o[12] + m[6] * o[13] + m[10] * o[14] + m[14] * o[15];
            result[15] = m[3] * o[12] + m[7] * o[13] + m[11] * o[14] + m[15] * o[15];

            return new Matrix4x4f(result);

        }

    }

}

(Hab mir nur die Steuerung angesehen. Beim Rest gibt es noch Verbesserungspotenzial.)

Viele Grüße
Fancy

Klar gibts verbesserungs potential - ist aber nur in kskb… danke erstmal, ich schaus mir später an …

*** Edit ***

Aber wieso eigene matrix klasse? Gibt es da vllt unterschiede zu lwjgl util?

*** Edit ***

Jedenfalls funktioniert es auch hier richtig. Ich werde mal schauen ob ich doch irgendwo nen dummen fehler hab…
oder es an deiner Matrix Klasse liegt… oder sonst was. Danke nochmal.

Böse formuliert: Not-invented-here-Syndrom :wink:

Ernsthaft: Das muss auch mit der Matrix Klasse von LWJGL funktionieren. Nur nutze ich diese zu selten als das ich immer und überall sehen würde, ob alle Parameter so sind, wie sie sein sollten.

Da das KSKB jetzt auch bei Dir funktioniert, kannst Du ja stückweise wieder zurück auf Deine ursprüngliche Version umbauen. Vermutlich findest Du dann auch den ursprünglichen Fehler.

Viele Grüße
Fancy

Hat ich grad vor, mal sehn was sich machen lässt ^^

*** Edit ***

wieso machst du eignetlich so oft so viel final?

*** Edit ***

so, es funzt jetzt, aber die maus hat tatsächlich krasse Probleme. Ich weiss dieses kskb hat sehr viele performance technische
fehler, aber man merkt trozdem das die maus einfach nur rumlaggt… versuche gerade zu verstehen warum…

package de.skysoldier.lwjgltest;

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;

import javax.imageio.ImageIO;

import org.lwjgl.BufferUtils;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.lwjgl.util.vector.Matrix4f;
import org.lwjgl.util.vector.Vector3f;

import de.skysoldier.abstractgl.AGL;
import de.skysoldier.abstractgl.AGLCaps.AGLDisplayCap;

public class Cube {
	
	private final int VERTEX_LOCATION = 0;
	private final int TEXTURE_LOCATION = 1;

	private int shaderProgramID;
    private int vertexArrayObjectID;
    private int vertexBufferObjectID;
    private int textureID;
    
    private Matrix4f projection;
    
    public Cube(){
        initDisplay();
        initTexture();
        initShaders();
        initGl();
        startGameLoop();
    }

    private void initDisplay(){
    	AGL.createLwjglContext(AGLDisplayCap.NONE);
    }

    private void initTexture(){
        BufferedImage source = null;
        try{
            source = ImageIO.read(getClass().getClassLoader().getResourceAsStream("pic.png"));
        }
        catch(Exception e){

        }
        
        IntBuffer buffer = ByteBuffer.allocateDirect(4).asIntBuffer();
        GL11.glGenTextures(buffer);
        
        final BufferedImage textureImage;

        int textureWidth = 2;
        int textureHeight = 2;

        while (textureWidth < source.getWidth())
                textureWidth *= 2;
        while (textureHeight < source.getHeight())
                textureHeight *= 2;
        
        textureID = buffer.get();

    	textureImage = new BufferedImage(textureWidth, textureHeight, BufferedImage.TYPE_4BYTE_ABGR);
        Graphics2D graphics = (Graphics2D) textureImage.getGraphics();
        graphics.drawImage(source, 0, 0, null);
        graphics.dispose();
        
        byte[] data = (byte[]) textureImage.getRaster().getDataElements(0, 0, textureWidth, textureHeight, null);

        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(textureImage.getColorModel().getPixelSize() / 8 * textureWidth * textureHeight);
        byteBuffer.put(data);
        byteBuffer.rewind();

        GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID);
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP);
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
        GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, textureWidth, textureHeight, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, byteBuffer);
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
    }

    private void initShaders(){
        String vertexShaderCode = 
        		"#version 120
"+
        		"uniform sampler2D tex;
"+
        		"attribute vec2 vertTexCoord;
"+
        		"varying vec2 fragTexCoord;
"+
        		"uniform mat4 camera;
"+
        		"uniform mat4 model;
"+
        		"attribute vec3 vert;
"+
        		"void main() {
"+
        		"	fragTexCoord = vertTexCoord;
"+
        		"    gl_Position = camera * model * vec4(vert, 1);
"+
        		"}";
        String fragmentShaderCode = 
        		"#version 120
"+
        		"uniform sampler2D fragTex;
"+
        		"varying vec2 fragTexCoord;
"+
        		"void main(void){
"+
        		"	gl_FragColor = texture2D(fragTex, fragTexCoord);
"+
        		"}";

        int vertexShaderID = GL20.glCreateShader(GL20.GL_VERTEX_SHADER);
        GL20.glShaderSource(vertexShaderID, vertexShaderCode);
        GL20.glCompileShader(vertexShaderID);

        int fragmentShaderID = GL20.glCreateShader(GL20.GL_FRAGMENT_SHADER);
        GL20.glShaderSource(fragmentShaderID, fragmentShaderCode);
        GL20.glCompileShader(fragmentShaderID);

        shaderProgramID = GL20.glCreateProgram();
        GL20.glAttachShader(shaderProgramID, vertexShaderID);
        GL20.glAttachShader(shaderProgramID, fragmentShaderID);

        GL20.glBindAttribLocation(shaderProgramID, VERTEX_LOCATION, "vert");
        GL20.glBindAttribLocation(shaderProgramID, TEXTURE_LOCATION, "vertTexCoord");
        GL20.glLinkProgram(shaderProgramID);
        
        GL20.glDetachShader(shaderProgramID, vertexShaderID);
        GL20.glDetachShader(shaderProgramID, fragmentShaderID);

        GL20.glUseProgram(shaderProgramID);
        
        float fov = 45f, aspect = 800.0f / 600.0f, zNear = 1f, zFar = 1000.0f;
        final double f = (1.0 / Math.tan(Math.toRadians(fov / 2.0)));
        
        projection = new Matrix4f();
        projection.m00 = (float) (f / aspect);
        projection.m11 = (float) f;
        projection.m22 = (zFar + zNear) / (zNear - zFar);
        projection.m23 = -1;
        projection.m32 = (2 * zFar + zNear) / (zNear - zFar);
        projection.m33 = 0;
        
//        System.out.println(projection);
//        System.exit(0);

        int compileStatus = GL20.glGetShaderi(vertexShaderID, GL20.GL_COMPILE_STATUS);
        if (compileStatus == GL11.GL_FALSE) {
            int infoLogLength = GL20.glGetShaderi(vertexShaderID, GL20.GL_INFO_LOG_LENGTH);
            String infoLog = GL20.glGetShaderInfoLog(vertexShaderID, infoLogLength);
            throw new RuntimeException(infoLog);
        }
        System.out.println("Compile Errors: " + GL20.glGetProgramInfoLog(shaderProgramID, GL20.glGetProgrami(shaderProgramID, GL20.GL_INFO_LOG_LENGTH)));
    }
    
    private void initGl(){
    	float vertices[] = new float[]{
    		1.0f, 1.0f, 1.0f,  1.0f, 1.0f,  
    		1.0f, 1.0f,-1.0f,  1.0f, 0.0f,  
    	   -1.0f, 1.0f, 1.0f,  0.0f, 1.0f,  
    	   
    	   -1.0f, 1.0f, 1.0f,  0.0f, 1.0f,  
    	    1.0f, 1.0f,-1.0f,  1.0f, 0.0f,  
    	   -1.0f, 1.0f,-1.0f,  0.0f, 0.0f,  
    	   
    	   
    	    1.0f, 1.0f,-1.0f,  1.0f, 0.0f,  
    	    0.0f, 3.0f, 0.0f,  0.5f, 1.0f,  
    	   -1.0f, 1.0f,-1.0f,  0.0f, 0.0f,  
    	    
    	   -1.0f, 1.0f,-1.0f,  0.0f, 0.0f,  
    	    0.0f, 3.0f, 0.0f,  0.5f, 1.0f,  
 	   	   -1.0f, 1.0f, 1.0f,  1.0f, 0.0f,  
	   	    
	   	    1.0f, 1.0f, 1.0f,  1.0f, 0.0f,  
	   	    0.0f, 3.0f, 0.0f,  0.5f, 1.0f,  
	   	   -1.0f, 1.0f, 1.0f,  0.0f, 0.0f,  
    	
	   	    1.0f, 1.0f,-1.0f,  0.0f, 0.0f,  
	   		0.0f, 3.0f, 0.0f,  0.5f, 1.0f,  
	   	    1.0f, 1.0f, 1.0f,  1.0f, 0.0f
    	};
        FloatBuffer verticesBuffer = BufferUtils.createFloatBuffer(vertices.length);
        verticesBuffer.put(vertices);
        verticesBuffer.flip(); 
        
        vertexArrayObjectID = GL30.glGenVertexArrays();
        GL30.glBindVertexArray(vertexArrayObjectID);

        vertexBufferObjectID = GL15.glGenBuffers();
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vertexBufferObjectID);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, verticesBuffer, GL15.GL_STATIC_DRAW);

        GL20.glEnableVertexAttribArray(VERTEX_LOCATION);
        GL20.glVertexAttribPointer(VERTEX_LOCATION, 3, GL11.GL_FLOAT, false, 5 * Float.SIZE / 8, 0);
        
        GL20.glEnableVertexAttribArray(TEXTURE_LOCATION);
        GL20.glVertexAttribPointer(TEXTURE_LOCATION, 2, GL11.GL_FLOAT, true, 5 * Float.SIZE / 8, 3 * Float.SIZE / 8);
        
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
        GL30.glBindVertexArray(0);
        
        GL11.glEnable(GL11.GL_BLEND);
        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
    
        GL11.glEnable(GL11.GL_DEPTH_TEST);
        GL11.glDepthFunc(GL11.GL_LESS);
    }

    private void startGameLoop(){
    	long lastFrame = System.nanoTime();
    	long thisFrame = System.nanoTime();
    	
    	long lastTime = System.nanoTime();
    	ArrayList<Long> fpsCollection = new ArrayList<>();
    	
    	long delta;
    	int mid = 0, min = Integer.MAX_VALUE, max = 0;   	
    	
    	try{
			Mouse.setGrabbed(true);
    	}
    	catch(Exception e){
    		e.printStackTrace();
    	}
    	
    	while(!Display.isCloseRequested()){
    		thisFrame = System.nanoTime();
    		delta = thisFrame - lastFrame;
    		lastFrame = thisFrame;
    		
    		GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
            GL11.glClearColor(0, 0, 0, 1);
            
            GL20.glUseProgram(shaderProgramID);
            GL13.glActiveTexture(GL13.GL_TEXTURE0);
    		GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID);
    		GL20.glUniform1i(GL20.glGetUniformLocation(shaderProgramID, "tex"), 0);
        	
            
            updateCamera(delta);
            
    		GL30.glBindVertexArray(vertexArrayObjectID);
            
    		for(int i = 0; i < 50; i++){
	    		for(int j = 0; j < 50; j++){
	    			GL20.glUniformMatrix4(GL20.glGetUniformLocation(shaderProgramID, "model"), false, testTranslate(2 * i + i * 0.5f, -5.0f, 2 * j + j * 0.5f, 0, delta));
		    		GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, 18);
		    		GL20.glUniformMatrix4(GL20.glGetUniformLocation(shaderProgramID, "model"), false, testTranslate(2 * i + i * 0.5f, 5.0f, 2 * j + j * 0.5f, 180, delta));
		    		GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, 18);
	    		}
	    	}
    		
            double fpsRaw = (1e9 / delta);
            int fps = (int) fpsRaw;
            if(min != 0 && fps < min){
            	min = fps;
            }
            if(fps > max){
            	max = fps;
            }
    		if(thisFrame / 1e9 - lastTime / 1e9 >= 1){
    			lastTime = thisFrame;
    			fpsCollection.add((long) fps);
    			mid = calcMid(fpsCollection);
    		}
    		Display.setTitle("mid: " + mid + " | min: " + min + " | max: " + max + " | now: " + fps + "");
            Display.update();
    	}
        destroy();
    }
    
    private float pitch;
    private float yaw;
    private float posX, posY, posZ;
    
    public void updateCamera(float delta){
            final double step = 10 * delta / 1e9;
     
            final double keySpeed = step;
            final double mouseSpeed = step * 0.04;
     
            final float rotVmax = 1;
            final float rotVMin = -1;
     
            yaw += Mouse.getDX() * mouseSpeed;
            pitch -= Mouse.getDY() * mouseSpeed;
     
            if (pitch > rotVmax)
                pitch = rotVmax;
     
            if (pitch < rotVMin)
                pitch = rotVMin;
     
            if(Keyboard.isKeyDown(Keyboard.KEY_W)){
                posX -= Math.sin(yaw) * keySpeed;
                posZ += Math.cos(yaw) * keySpeed;
            }
            if (Keyboard.isKeyDown(Keyboard.KEY_S)) {
                posX += Math.sin(yaw) * keySpeed;
                posZ -= Math.cos(yaw) * keySpeed;
            }
            if (Keyboard.isKeyDown(Keyboard.KEY_A)) {
                posX += Math.cos(yaw) * keySpeed;
                posZ += Math.sin(yaw) * keySpeed;
            }
            if (Keyboard.isKeyDown(Keyboard.KEY_D)) {
                posX -= Math.cos(yaw) * keySpeed;
                posZ -= Math.sin(yaw) * keySpeed;
            }
            
            float rotX = (float) (Math.cos(yaw) * pitch);
            float rotZ = (float) (Math.sin(yaw) * pitch);
            
            Matrix4f mv = new Matrix4f();
            
            final double sinX = Math.sin(rotX);
            final double sinY = Math.sin(yaw);
            final double sinZ = Math.sin(rotZ);
     
            final double cosX = Math.cos(rotX);
            final double cosY = Math.cos(yaw);
            final double cosZ = Math.cos(rotZ);
     
            mv.m00 = (float) (cosY * cosZ + sinY * sinX * sinZ);
            mv.m01 = (float) (cosX * sinZ);
            mv.m02 = (float) (-sinY * cosZ + cosY * sinX * sinZ);
            mv.m10 = (float) (-cosY * sinZ + sinY * sinX * cosZ);
            mv.m11 = (float) (cosX * cosZ);
            mv.m12 = (float) (sinY * sinZ + cosY * sinX * cosZ);
            mv.m20 = (float) (sinY * cosX);
            mv.m21 = (float) (-sinX);
            mv.m22 = (float) (cosY * cosX);
            
            mv.m30 = mv.m00 * posX + mv.m10 * posY + mv.m20 * posZ;
            mv.m31 = mv.m01 * posX + mv.m11 * posY + mv.m21 * posZ;
            mv.m32 = mv.m02 * posX + mv.m12 * posY + mv.m22 * posZ;
            mv.m33 = 1;
            FloatBuffer buffer = BufferUtils.createFloatBuffer(16);
            Matrix4f.mul(projection, mv, new Matrix4f()).store(buffer);
            buffer.flip();
            GL20.glUniformMatrix4(GL20.glGetUniformLocation(shaderProgramID, "camera"), false, buffer);
    }

    public FloatBuffer testTranslate(float x, float y, float z, float rot, long delta){
    	Matrix4f mat = new Matrix4f();
    	mat.translate(new Vector3f(x, y, z));
    	mat.rotate((float) Math.toRadians(rot), new Vector3f(1.0f, 0.0f, 0.0f));
    	FloatBuffer buffer = BufferUtils.createFloatBuffer(16);
    	mat.store(buffer);
    	buffer.flip();
    	return buffer;
    }
    
    
    public int calcMid(ArrayList<Long> fpsCollection){
    	long lm = 0;
    	for(long l : fpsCollection){
    		lm+=l;
    	}
    	return (int) lm / fpsCollection.size();
    }

    private void destroy(){
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
        GL15.glDeleteBuffers(vertexBufferObjectID);

        GL30.glBindVertexArray(0);
        GL30.glDeleteVertexArrays(vertexArrayObjectID);

        Display.destroy();
    }

    public static void main(String[] args) {
//    	System.setProperty("org.lwjgl.util.Debug", "true");
    	new Cube();
    }
}```

KEINE „definitive Antwort“, aber ein paar Gedanken:

Die Methode testTranslate wird für jeden Frame 2500 mal aufgerufen. Und bei 60PFS sind das schlappe 15000 Aufrufe pro Sekunde. IN dieser Methode wird mit BufferUtils.createFloatBuffer(16) ein FloatBuffer erstellt. Das ist ein direct FloatBuffer. Diese direct buffers sind ein bißchen speziell. Sie sind quasi (!) „außerhalb der VM“. Trotzdem muss sich der GC darum kümmern. Und wenn man das ganze mal mit der jVisualVM laufen läßt, sieht man schon ohne detaillierte Analyse, direkt in der „Monitor“-Ansicht, dass der GC periodisch ziemlich heftig am rödeln ist.

Wenn man das ganze ändert zu

    // HIN
    FloatBuffer buffer = BufferUtils.createFloatBuffer(16);
 
    public FloatBuffer testTranslate(float x, float y, float z, float rot, long delta){
        Matrix4f mat = new Matrix4f();
        mat.translate(new Vector3f(x, y, z));
        mat.rotate((float) Math.toRadians(rot), new Vector3f(1.0f, 0.0f, 0.0f));

        // WEG
        //FloatBuffer buffer = BufferUtils.createFloatBuffer(16);
        mat.store(buffer);
        buffer.flip();
        return buffer;
    }

sind diese „Maus-Lags“ (bei mir) zumindest schon nicht mehr feststellbar.

DASS es überhaupt zu solchen Lags kommt, ist trotzdem ein bißchen komisch. Es scheint (! mir, subjektiv !) als würde es nicht einfach „laggen“, sondern als würden größere Bewegungen detektiert als man tatsächlich macht. Aber das müßte man genauer analysieren.

Zu den direct buffers: Ich habe bei diesen direct buffers die Tendenz, sie „so selten wie möglich“ zu erstellen. Bei solchen utility-Methoden (wie hier „testTranslate“) habe ich üblicherweise dieses Muster

class Utils
{
    private static final FloatBuffer buffer = BufferUtils.createFloatBuffer(16);

    /**
     * Does some stuff and returns the buffer. 
     *
     * This buffer is only valid directly after this method call, and only
     * as long as no other method of this class has been called
     */
    static FloatBuffer doSomeStuff()
    { 
         ...
         return buffer;
    }
    static FloatBuffer doSomeOtherStuff()  {  ...  return buffer;  }
    static FloatBuffer doSomeMoreStuff()  {  ...  return buffer;  }
}

Das ist eigentlich „häßlich“ in bezug auf die API, nicht Java-Like und so, aber … da solche Methoden die Tendenz haben, SEHR oft aufgerufen zu werden, und der Buffer meistens ja wirklich nur verwendet wird, um kurz die Daten (eben in einem direct buffer) zu „parken“, damit sie nach GL rübergeshaufelt werden können, finde ich persönlich das akzeptabel (bzw. besser als wenn man den GC zumüllt - auch wenn er eigentlich genau dafür gedacht ist :smiley: ).

hm, is bin eigentlich gegen einen static buffer… Spätestens wenn man Multithreading in Betracht zieht und erst mal die ganzen Buffers berechnet und im GL-Thread dann nur mehr die Daten rüberschaufelt ist refactoring angesagt.

Ich würde einen Buffer pro Matrix erstellen, und den immer wiederverwenden…

Ja klar, in meiner lib zum Beispiel ist das auch so, aber ich hab die Kamera bisher nur im dreckigen KSKB getestet :smiley:
Aaalso, das war bei dir der Grund? Werde ich im dreckigen unaufgeäumten Kskb mal testen, danke.

Kann es eigentlich sein, das Mouse#dx und #dy einfach nur irgendwelche Probleme hat, nicht mitkommt oder sowas?
vielleicht versuche ich es mal mit den ganz normalen x y variablen der maus.

Edit: Ach ja, und ich schau mir über mcp an wie das ganze in minecraft eingebaut ist , wenn ich die entsprechenden Stellen irgendwann finde :smiley:

Edit 2: Kann man nicht theoretisch sogar für alle matrizen einen einzigen 16er buffer erstellen? Die Matrizen werden ja ohnehin nicht gleichzeitig verändert…

Bezüglich der Wiederverwendung der Buffer solltest Du Dir UBOs (ab OpenGL 3.1) ansehen. Diese leben für gewöhnlich sehr lange, sodass die Erzeugung des Buffers an die Erzeugung des UBO gekoppelt werden kann. Z.B. ein UBO für Lichtparameter:

UBO:



import static org.lwjgl.opengl.GL15.GL_STREAM_DRAW;
import static org.lwjgl.opengl.GL15.glBindBuffer;
import static org.lwjgl.opengl.GL15.glBufferData;
import static org.lwjgl.opengl.GL15.glBufferSubData;
import static org.lwjgl.opengl.GL15.glDeleteBuffers;
import static org.lwjgl.opengl.GL15.glGenBuffers;
import static org.lwjgl.opengl.GL30.glBindBufferRange;
import static org.lwjgl.opengl.GL31.GL_UNIFORM_BUFFER;

import java.nio.ByteBuffer;

import org.lwjgl.BufferUtils;


public class UBO {

    private final ByteBuffer buffer;
    private final int binding;

    private int handle = -1;
    private boolean dirty;


    public UBO(final int binding, final int size) {

        this.binding = binding;
        this.buffer = BufferUtils.createByteBuffer(size);

    }


    public final void glInit() {

        handle = glGenBuffers();

        glBindBuffer(GL_UNIFORM_BUFFER, handle);
        glBufferData(GL_UNIFORM_BUFFER, buffer.capacity(), GL_STREAM_DRAW);
        glBindBuffer(GL_UNIFORM_BUFFER, 0);

    }


    public final void glBind() {

        if (dirty) {

            glBindBuffer(GL_UNIFORM_BUFFER, handle);
            glBufferSubData(GL_UNIFORM_BUFFER, 0, buffer);

            dirty = false;

        }

        glBindBufferRange(GL_UNIFORM_BUFFER, binding, handle, 0, buffer.capacity());

    }


    public final void glDispose() {

        glDeleteBuffers(handle);

    }


    protected final void markDirty() {

        dirty = true;

    }


    protected final ByteBuffer getByteBuffer() {

        return buffer;

    }


}```

Light:
```package net.mschorn.sandbox.lwjgl.tools.light;

import java.nio.ByteBuffer;

import net.mschorn.sandbox.lwjgl.tools.buffer.UBO;


public class Light extends UBO {

    private static final int AMBIENT_RED = 0;
    private static final int AMBIENT_GREEN = 4;
    private static final int AMBIENT_BLUE = 8;
    private static final int DIFFUSE_RED = 16;
    private static final int DIFFUSE_GREEN = 20;
    private static final int DIFFUSE_BLUE = 24;
    private static final int SPECULAR_RED = 32;
    private static final int SPECULAR_GREEN = 36;
    private static final int SPECULAR_BLUE = 40;
    private static final int POSITION_X = 48;
    private static final int POSITION_Y = 52;
    private static final int POSITION_Z = 56;
    private static final int POSITION_W = 60;

    private final ByteBuffer buffer;


    public Light(final int binding) {

        super(binding, 16 * Float.SIZE / Byte.SIZE);

        buffer = getByteBuffer();

    }


    public final void setAmbient(final float r, final float g, final float b) {

        buffer.putFloat(AMBIENT_RED, r);
        buffer.putFloat(AMBIENT_GREEN, g);
        buffer.putFloat(AMBIENT_BLUE, b);

        markDirty();

    }


    public final void setDiffuse(final float r, final float g, final float b) {

        buffer.putFloat(DIFFUSE_RED, r);
        buffer.putFloat(DIFFUSE_GREEN, g);
        buffer.putFloat(DIFFUSE_BLUE, b);

        markDirty();

    }


    public final void setSpecular(final float r, final float g, final float b) {

        buffer.putFloat(SPECULAR_RED, r);
        buffer.putFloat(SPECULAR_GREEN, g);
        buffer.putFloat(SPECULAR_BLUE, b);

        markDirty();

    }


    public final void setPosition(final float x, final float y, final float z) {


        buffer.putFloat(POSITION_X, x);
        buffer.putFloat(POSITION_Y, y);
        buffer.putFloat(POSITION_Z, z);
        buffer.putFloat(POSITION_W, 1);

        markDirty();

    }


}```

Shader:

layout(std140, binding = 1) uniform Light {

vec4 ambient;
vec4 diffuse;
vec4 specular;
vec4 position;

} light;



So kann man das auch mit den MVP-Matrizen machen.

Wenn Du oft das Gleiche zeichnen lassen willst, solltest Du Dir [Instancing](https://www.opengl.org/wiki/Vertex_Rendering#Instancing) (ab OpenGL 3.1) ansehen. Die Grafikkarte ist darauf ausgelegt viele Dinge parallel zu bearbeiten. 5000*18 Vertices ist ungünstig, 1*90000 viel besser.

Außerdem solltest Du unbedingt auf Indexed Rendering (gl*Draw*Elements*) umsteigen. Nur damit funktioniert der Cache der Grafikkarte vernünftig. Lesetipp: [Vertex Specification](https://www.opengl.org/wiki/Vertex_Specification) und [Vertex Rendering](https://www.opengl.org/wiki/Vertex_Rendering).

Viele Grüße
Fancy

Hi, danke für diese Infos. Ich werde mir das zwar ansehen.
Allerdings ist Kompatibilität für mich sehr wichtig. Dabei will ich das Grafikkarten, die so schlecht sind
wie die meines Laptops, (ja ich hab auch noch einen pc aber trozdem…) mit meinem code klarkommen. Ja, man könnte
auch für verschiedene Grakas verschiedenen Code schreiben, aber ich will erstmal das ein code läuft. opengl 3.1 ist noch das maximum was mein
laptop unterstützt, glsl glaub ich 130 oder so. Ich werde mal schauen was sich in dieser version verbessern lässt…

Apropos: Ich hab auch mal was von IBO’s gelesen, also index buffer objects. Können die die performance nicht auch spürbar aufbessern?

IBOs gehören zum erwähnten Indexed Rendering und ohne die gibt es keinen Post Transform Cache. Deshalb ja, die sollte man verwenden. Wieviel das konkret bringt hängt von der jeweiligen Geometrie ab.

UBOs machen OpenGL Programme imho wesentlich sauberer (und ggf. schneller), ich würde nach Möglichkeit nicht drauf verzichten wollen.

Wie auch immer Du Dich entscheidest, Du solltest dein Programm dahin gehend optimieren, dass Du möglichst wenige glDraw*-Aufrufe hast, sondern diese stattdessen möglichst große Geometrien übermitteln. Instancing ist da halt das Einfachste.

Viele Grüße
Fancy

Hmm ich bekomms nicht hin dein UBO beispiel zu durchschauen. Wo genau erfolgt denn die Kommunikation zu den eigentlichen shader uniforms?
Oder werden einfach alle eingelesen? oder oder…? Ich lese gerade den wiki eintrag ^^

*** Edit ***

Wiki sagt:

Each active uniform block in GLSL has a corresponding active uniform block in the linked program. You can get the uniform block index (similar to a uniform location) with this function:
GLuint glGetUniformBlockIndex​( GLuint program​, const char *uniformBlockName​ );
The uniformBlockName​ is the name of the uniform block, not the name of the GLSL scope for the uniform. This function returns GL_INVALID_INDEX if the block name could not be found.
The uniform block index is used to set what uniform buffer binding location that this uniform block uses. You can call this function to associate this uniform block with a uniform buffer binding location:


Aber was genau ist jetzt ein uniform block? und woher weiss ich wo wie was.. (wwwwww...) ich einen bestimmten uniform anspreche?

zB:

//glsl
uniform float pos1;
uniform mat4 mat1;
uniform vec3 color;

normalerweise würde ich ja mit `glGetUniformLocation(programId, "pos1");` die location holen und dann mit `glUniform...()` was eintragen... 
wie schreibe ich das jetzt auf die UB's um? Sry, hab grad ein brett vorm kopf :(

*** Edit ***

Ist instancing zum beispiel bei einer Height map sinnvoll? Weil dort ist jedes Dreieck doch eigentlich das selbe objekt, nur mit einer anderen farbe, oder?