LWJGL - Matrizen (OpenGL 3+)

Hi, ich bin’s wieder und es geht mal wieder um modernes OpenGL :wink:

Um nun die ganzen Funktionen wie glTranslate(), glRotate, glScale, glLookAt und glPerspective() etc auch in OpenGL 3+ zur Verfügung zu haben wollte ich nun Matrizen hinzufügen.
Seit ich sie hinzugefügt habe ist das Bild schwarz (mal wieder -_- ).
Ich habe eine ModelView und eine ProjectionMatrix erstellt. Grundlage war zwar dieses Tutorial aber auch viele andere Seiten nachdem nur dieses Tutorial nicht so ganz funktioniert hatte.

Zusätzlich habe ich noch eine kleine MatrixHelper Klassen erstellt um Funktionen, die nicht in Matrix4f enthalten sind (z.B. lookAt) zur Verfügung zu haben.

Hier ist mein Code:

Main.java
[spoiler]```

package oneric.level.main;

import java.io.File;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.Random;

import oneric.gl.shader.Shader;
import oneric.gl.shader.ShaderProgramm;
import oneric.importer.obj.Model;
import oneric.importer.obj.OBJLoader;
import oneric.util.GLHelper;
import oneric.util.MathHelper;
import oneric.util.MatrixHelper;

import org.lwjgl.BufferUtils;
//import org.lwjgl.opengl.GL11;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;

import org.lwjgl.util.vector.Matrix4f;
import org.lwjgl.util.vector.Vector3f;

import static org.lwjgl.opengl.GL11.;
import static org.lwjgl.opengl.GL15.
;
import static org.lwjgl.opengl.GL20.;
import static org.lwjgl.opengl.GL30.
;

public class Main {

//TODO private static Level level;

public static Random rand = new Random();

private static Matrix4f m_ModelView;


//static int modelID;
static int length;
static int textureID;
static IntBuffer vboIDs;
static int vaoID;
static int shProID;
static int projectionMatrixID;
static int modelViewnMatrixID;

public static void main(String[] args) {
	
	setUpDisplay();
	setUpOpenGL();		
	
	FloatBuffer vertexPy = BufferUtils.createFloatBuffer(54);
	
	vertexPy.put(-5F); vertexPy.put(0F); vertexPy.put(3F);//Grundfläche 1
	vertexPy.put(5F); vertexPy.put(0F); vertexPy.put(-3F);
	vertexPy.put(-5F); vertexPy.put(0F); vertexPy.put(-3F);
	
	vertexPy.put(-5F); vertexPy.put(0F); vertexPy.put(3F);//Grundfläche 2
	vertexPy.put(5F); vertexPy.put(0F); vertexPy.put(3F);
	vertexPy.put(5F); vertexPy.put(0F); vertexPy.put(-3F);
	
	vertexPy.put(0F); vertexPy.put(5F); vertexPy.put(0F);//Seite 1
	vertexPy.put(-3F); vertexPy.put(0F); vertexPy.put(3F);
	vertexPy.put(3F); vertexPy.put(0F); vertexPy.put(3F);
	
	vertexPy.put(0F); vertexPy.put(5F); vertexPy.put(0F);//Seite 2
	vertexPy.put(3F); vertexPy.put(0F); vertexPy.put(-3F);
	vertexPy.put(-3F); vertexPy.put(0F); vertexPy.put(-3F);
	
	vertexPy.put(0F); vertexPy.put(5F); vertexPy.put(0F);//Seite 3
	vertexPy.put(-3F); vertexPy.put(0F); vertexPy.put(-3F);
	vertexPy.put(-3F); vertexPy.put(0F); vertexPy.put(3F);
	
	vertexPy.put(0F); vertexPy.put(5F); vertexPy.put(0F);//Seite 4
	vertexPy.put(3F); vertexPy.put(0F); vertexPy.put(3F);
	vertexPy.put(3F); vertexPy.put(0F); vertexPy.put(-3F);
	
	vertexPy.flip();
	
	FloatBuffer colourPy = BufferUtils.createFloatBuffer(54);
	
	for(int i = 0; i < 18; i++)
	{
		switch(rand.nextInt(3))
		{
		case 0:
			colourPy.put(0F); colourPy.put(0F); colourPy.put(1F);
			break;
			
		case 1:
			colourPy.put(0F); colourPy.put(1F); colourPy.put(0F);
			break;
			
		case 2:
			colourPy.put(1F); colourPy.put(0F); colourPy.put(0F);
			break;
			
		default:
			colourPy.put(1F); colourPy.put(0F); colourPy.put(1F);	
			break;
		}
	}
	
	colourPy.flip();
	 
	
	vaoID = glGenVertexArrays();
	vboIDs = BufferUtils.createIntBuffer(2);
	glGenBuffers(vboIDs);
	
	
	glBindVertexArray(vaoID);
	
	glBindBuffer(GL_ARRAY_BUFFER, vboIDs.get(0));
	glBufferData(GL_ARRAY_BUFFER, vertexPy, GL_STATIC_DRAW);
	glEnableVertexAttribArray(0); 
	glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0); 
	
	glBindBuffer(GL_ARRAY_BUFFER, vboIDs.get(1)); 
	glBufferData(GL_ARRAY_BUFFER, colourPy, GL_STATIC_DRAW); 
	glEnableVertexAttribArray(1); 
	glVertexAttribPointer(1, 3, GL_FLOAT, false, 0, 0); 
	
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindVertexArray(0);
	
	Shader shVertex = new Shader();
	Shader shFragment = new Shader();
	
	try {
		shVertex.loadShader("res/shaders/shader.vert", GL_VERTEX_SHADER);
		shFragment.loadShader("res/shaders/shader.frag", GL_FRAGMENT_SHADER);
	} catch (IOException e1) {
		e1.printStackTrace();
	}
	
	ShaderProgramm spMain = new ShaderProgramm();
	
	spMain.createProgramm();
	spMain.addShaderToProgramm(shVertex);
	spMain.addShaderToProgramm(shFragment);
	
	spMain.linkProgramm();
	spMain.useProgramm();
	shProID = spMain.getProgrammID();
	
	
	projectionMatrixID = glGetUniformLocation(shProID, "projectionMatrix");
	modelViewnMatrixID = glGetUniformLocation(shProID, "modelViewMatrix");
	
	///////////////////
	
	Matrix4f m_Projection = MatrixHelper.mgluPerspetive(100, Display.getWidth()/Display.getHeight(), 1F, 200F);
	
	///////////////////
	m_ModelView = MatrixHelper.lookAt(new Vector3f(0F, 15F, 40F), new Vector3f(0F, 0F, 0F), new Vector3f(0F, 1F, 0F));
	
	
	
	
	FloatBuffer mBuffer = BufferUtils.createFloatBuffer(16); 
	
	m_Projection.store(mBuffer); mBuffer.flip();
	glUniformMatrix4(projectionMatrixID, false, mBuffer);
	
	m_ModelView.store(mBuffer); mBuffer.flip();
	glUniformMatrix4(modelViewnMatrixID, false, mBuffer);

	   
	
	
	
	
	while(!Display.isCloseRequested())
	{
		render();
		
		Display.update();
		Display.sync(120);
	}

}








/**
 * Sets up the basic Display
 * */
private static void setUpDisplay() {
	
    try {
    	
        Display.setDisplayMode(/*Display.getDesktopDisplayMode()*/new DisplayMode(900, 900));
        Display.setVSyncEnabled(true);
        Display.setTitle("Level: ");
        Display.setResizable(false);
        //Display.setFullscreen(true);
        Display.create();
    } catch (LWJGLException e) {
        System.err.println("The display wasn't initialized correctly. :(");
        Display.destroy();
        System.exit(1);
    }
}

/**
 * Sets up OpenGl so it's ready to use
 * */
private static void setUpOpenGL()
{
	
	GL11.glShadeModel(GL11.GL_SMOOTH);
	GL11.glEnable(GL11.GL_DEPTH_TEST);
	GL11.glEnable(GL11.GL_LIGHTING);
	GL11.glEnable(GL11.GL_LIGHT0);
	
	//GL11.glLightModel(GL11.GL_LIGHT_MODEL_AMBIENT, asFlippedFloatBuffer(new float[]{0.05f, 0.05f, 0.05f, 1f}));
	//GL11.glLight(GL11.GL_LIGHT0, GL11.GL_DIFFUSE, asFlippedFloatBuffer(new float[]{1.0F, 1.0F, 1.0F,1F}));
	GL11.glEnable(GL11.GL_CULL_FACE);
	GL11.glCullFace(GL11.GL_BACK);
	
	GL11.glEnable(GL11.GL_COLOR_MATERIAL);
	GL11.glColorMaterial(GL11.GL_FRONT, GL11.GL_DIFFUSE);
	
	glEnable(GL_TEXTURE_2D);
	
}



static int rAngle = 0;
private static void render()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   
	
	
    
	 glUseProgram(shProID);
    glBindVertexArray(vaoID);  
    
    Matrix4f m_Current = m_ModelView.rotate(rAngle, new Vector3f(0F, 1F, 0F));
    MatrixHelper.mglUniformMatrix4(modelViewnMatrixID, m_Current);
    
    glDrawArrays(GL_TRIANGLES, 0, 18);
    
     
    m_Current = new Matrix4f(m_ModelView);
    m_Current.scale(new Vector3f(0.5F, 0.5F, 0.5F));
    m_Current.translate(new Vector3f(1F, 1F, 1F));
    
    MatrixHelper.mglUniformMatrix4(modelViewnMatrixID, m_Current);
    
    glDrawArrays(GL_TRIANGLES, 0, 18);
    
    

    rAngle++;	
	
    
    
}

}




MatrixHelper.java
[spoiler]```
package oneric.util;

import static org.lwjgl.opengl.GL20.glUniformMatrix4;

import java.nio.FloatBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.util.vector.Matrix4f;
import org.lwjgl.util.vector.Vector3f;

public class MatrixHelper {

	//Den Code für die Matrixmanipulationene habe ich ehrlich gesagt einfach nur vom DGL-Wiki übernommen


	public static Matrix4f lookAt(Vector3f eye, Vector3f center, Vector3f up)
	{
		Vector3f f = (Vector3f.sub(center, eye, null)).normalise(null);
		Vector3f u = up.normalise(null);
		Vector3f s = (Vector3f.sub(f, u, null)).normalise(null);
		
		Matrix4f result = new Matrix4f();
		result.setZero();
		
		result.m00 = s.x;
		result.m10 = s.y;
		result.m20 = s.z;
		
		result.m01 = u.x;
		result.m11 = u.y;
		result.m21 = u.z;
		
		result.m02 = -f.x;
		result.m12 = -f.y;
		result.m22 = -f.z;
		
		return (result.translate(new Vector3f(-eye.x, -eye.y, -eye.z)));
	}
	
	/**
	 * @param fovy: Betrachtungswinkel in Grad entlang der Y-Achse (FOV)
	 * @param aspect: Verhältnis von Breite zu Höhe
	 * @param zNear: Entfernung zur Nahen Z-Schnittfläche. Muss POSITIV sein (Wie nah kann man etawas sehen)
	 * @param zFar: Entfernung zur fernen Z-Schnittfläche. Muss POSITIV sein (Wie weit kann man sehen) 
	 * 
	 * */
	public static Matrix4f perspetiveMatrix(float fovy, float aspect, float zNear, float zFar)
	{
		
		float f = MathHelper.coTangent(MathHelper.degreesToRadians( fovy )/2);
		
		Matrix4f matrix = new Matrix4f();
		matrix.setZero();
		
		// 1. die spalte 2. die zeile
		
		matrix.m00 = (f/aspect);
		
		matrix.m11 = f;
		
		matrix.m22 = ((zFar+zNear)/(zNear-zFar));
		matrix.m23 = -1;
		
		matrix.m32 = ((2*zFar*zNear)/(zNear-zFar));
		
		return matrix;
		
	}
	
	/**
	 * Creates an Perspective matrix like glLoadIdentity() and gluPerspective(...)
	 * 
	 * @param fovy: Betrachtungswinkel in Grad entlang der Y-Achse (FOV)
	 * @param aspect: Verhältnis von Breite zu Höhe
	 * @param zNear: Entfernung zur Nahen Z-Schnittfläche. Muss POSITIV sein (Wie nah kann man etawas sehen)
	 * @param zFar: Entfernung zur fernen Z-Schnittfläche. Muss POSITIV sein (Wie weit kann man sehen) 
	 * 
	 * */
	public static Matrix4f mgluPerspetive(float fovy, float aspect, float zNear, float zFar)
	{
		
		/*TODO ??*/float f = MathHelper.coTangent(MathHelper.degreesToRadians( fovy )/2);
		
		Matrix4f matrix = new Matrix4f();
		matrix.setZero();
		
		// 1. die spalte 2. die zeile
		
		matrix.m00 = (f/aspect);
		
		matrix.m11 = f;
		
		matrix.m22 = ((zFar+zNear)/(zNear-zFar));
		matrix.m23 = -1;
		
		matrix.m32 = ((2*zFar*zNear)/(zNear-zFar));
		
		Matrix4f idMatrix = new Matrix4f();
		idMatrix.setIdentity();
		
		
		
		return Matrix4f.mul(idMatrix, matrix, null);
		
	}
	
	public static void mglUniformMatrix4(int id, boolean transpose, Matrix4f matrix)
	{
		FloatBuffer mBuffer = BufferUtils.createFloatBuffer(16); 
		
		matrix.store(mBuffer); mBuffer.flip();
		glUniformMatrix4(id, false, mBuffer);
	}
	
	public static void mglUniformMatrix4(int id, Matrix4f matrix)
	{
		mglUniformMatrix4(id, false, matrix);
	}
	
	
}

```[/spoiler]



MathHelper.java
[spoiler]```
package oneric.util;

public class MathHelper {
	
	
	public static float coTangent(float angle) 
	{
		return (float)(1f / Math.tan(angle));
	}
		
		
	public static float degreesToRadians(float degrees) {
		return degrees * (float) (Math.PI / 180d);
	}

}

```[/spoiler]



shader.vert
[spoiler]```
#version 330 

uniform mat4 projectionMatrix; 
uniform mat4 modelViewMatrix; 

layout (location = 0) in vec3 inPosition; 
layout (location = 1) in vec3 inColor; 

smooth out vec3 theColor; 

void main() 
{ 
   gl_Position = projectionMatrix*modelViewMatrix*vec4(inPosition, 1.0); 
   theColor = inColor; 
}
```[/spoiler]



shader.frag
[spoiler]```
#version 330 

smooth in vec3 theColor; 
out vec4 outputColor; 

void main() 
{ 
   outputColor = vec4(theColor, 1.0); 
}
```[/spoiler]


Ich habe keine Ahnung mehr was falsch sein könnte. Vielleicht übersehe ich aber auch einfach irgendetwas ganz banales :D

Mfg
~Oneric

Bezüglich konkreter Hilfe vertrau’ ich da mal wieder voll auf Fancy, aber … allgemein wäre es gut, wenn man genauer wüßte, wo vielleicht etwas falsch ist. Also, dass „nichts gerendert wird“ kann nahezu an jeder einzelnen Zeile des Codes liegen. Von einem fehlenden ‚flip()‘ beim Buffer-Füllen, über versehentlich transponierten Matrizen (heißer Kandidat…) und einen falschen Parameter beim glVertexAttribPointer, bis hin zu einem outputColor = vec4(0,0,0,0); :smiley: Also, wenn klarer wäre, durch welche Änderung es „kaputt“ gegangen ist, könnte man sich diesen Teil genauer anschauen.

Es wurde geändert:
– im vertex Shader die Definition der Position
– neues VAO/VBO für die Pyramide. Vorher hatte ich nur ein 2dimensionales Dreieck, aber für rotation etc wollte ich etw dreidimensionales. (EDIT: Wenn ich das alte DreiecksObjekt verwende wird auch nichts gerendert)
– alles was mit Matrix4f and glUniform[…] zu tun hat
– die Klassen MatrixHelper und MathHelper

Mfg
~Oneric

Hmja, falls Fancy den Fehler nicht durch Draufschauen findet, probier’ ich das morgen ggf. mal aus.

Moin,

ich hab es zwar gerad mal laufen lassen, aber so auf die schnelle kein sinnvolles Ergebnis bekommen. Falls Marco den Fehler nicht schon findet, werd ich später auch noch mal einen Blick drauf werfen. Ggf. poste ich dann auch eine aufgeräumte Version davon, so wie ich das Programm oben schreiben würde.

Viele Grüße
Fancy

So, hab nun noch mal draufgesehen:

Main.java:


        final Matrix4f m_Projection = MatrixHelper.mgluPerspetive(100, (float) Display.getWidth() / (float) Display.getHeight(), 1F, 200F); // <--

        ///////////////////```


MatrixHelper.java:
```    public static Matrix4f lookAt(final Vector3f eye, final Vector3f center, final Vector3f up)
    {
        final Vector3f f = (Vector3f.sub(center, eye, null)).normalise(null);
        final Vector3f upn = up.normalise(null); // <--
        final Vector3f s = (Vector3f.cross(f, upn, null)).normalise(null); // <--
        final Vector3f u = Vector3f.cross(s, f, null); // <--

        final Matrix4f result = new Matrix4f();
        result.setZero();

        result.m00 = s.x;
        result.m10 = s.y;
        result.m20 = s.z;

        result.m01 = u.x;
        result.m11 = u.y;
        result.m21 = u.z;

        result.m02 = -f.x;
        result.m12 = -f.y;
        result.m22 = -f.z;

        result.m33 = 1; // <--

        return (result.translate(new Vector3f(-eye.x, -eye.y, -eye.z)));
    }```

```    public static Matrix4f perspetiveMatrix(final float fovy, final float aspect, final float zNear, final float zFar)
    {

        final float f = MathHelper.coTangent(MathHelper.degreesToRadians( fovy )/2);

        final Matrix4f matrix = new Matrix4f();
        matrix.setZero();

        // 1. die spalte 2. die zeile

        matrix.m00 = (f/aspect);

        matrix.m11 = f;

        matrix.m22 = ((zFar+zNear)/(zNear-zFar));
        matrix.m23 = -1;

        matrix.m32 = ((2*zFar*zNear)/(zNear-zFar));

        matrix.m33 = 1; // <--

        return matrix;

    }```

Dann sieht man auf jeden Fall schon mal ein sich Drehendes etwas.

Edit: Und etwa [so](https://gist.github.com/mschorn/a68006910aeea9f8aa95) würde ich das Programm von oben schreiben. Vermutlich ist das aber auf Anhieb schwer verständlich. Weitere OpenGL Beispiele von mir gibt es [hier](http://sandbox.mschorn.net/).

Viele Grüße
Fancy

[QUOTE=Fancy]So, hab nun noch mal draufgesehen:
[spoiler]
Main.java:


        final Matrix4f m_Projection = MatrixHelper.mgluPerspetive(100, (float) Display.getWidth() / (float) Display.getHeight(), 1F, 200F); // <--

        ///////////////////```


MatrixHelper.java:
```    public static Matrix4f lookAt(final Vector3f eye, final Vector3f center, final Vector3f up)
    {
        final Vector3f f = (Vector3f.sub(center, eye, null)).normalise(null);
        final Vector3f upn = up.normalise(null); // <--
        final Vector3f s = (Vector3f.cross(f, upn, null)).normalise(null); // <--
        final Vector3f u = Vector3f.cross(s, f, null); // <--

        final Matrix4f result = new Matrix4f();
        result.setZero();

        result.m00 = s.x;
        result.m10 = s.y;
        result.m20 = s.z;

        result.m01 = u.x;
        result.m11 = u.y;
        result.m21 = u.z;

        result.m02 = -f.x;
        result.m12 = -f.y;
        result.m22 = -f.z;

        result.m33 = 1; // <--

        return (result.translate(new Vector3f(-eye.x, -eye.y, -eye.z)));
    }```

```    public static Matrix4f perspetiveMatrix(final float fovy, final float aspect, final float zNear, final float zFar)
    {

        final float f = MathHelper.coTangent(MathHelper.degreesToRadians( fovy )/2);

        final Matrix4f matrix = new Matrix4f();
        matrix.setZero();

        // 1. die spalte 2. die zeile

        matrix.m00 = (f/aspect);

        matrix.m11 = f;

        matrix.m22 = ((zFar+zNear)/(zNear-zFar));
        matrix.m23 = -1;

        matrix.m32 = ((2*zFar*zNear)/(zNear-zFar));

        matrix.m33 = 1; // <--

        return matrix;

    }```

Dann sieht man auf jeden Fall schon mal ein sich Drehendes etwas.

Edit: Und etwa [so](https://gist.github.com/mschorn/a68006910aeea9f8aa95) würde ich das Programm von oben schreiben. Vermutlich ist das aber auf Anhieb schwer verständlich. Weitere OpenGL Beispiele von mir gibt es [hier](http://sandbox.mschorn.net/).
[/spoiler]
Viele Grüße
Fancy[/QUOTE]

Hey Danke :) 
Es funktioniert super und die Beispiele werden mir bestimmt auch noch öfters helfen ;)

Mfg
~Oneric