LWJGL 3D Linien werden nicht gezeichnet

Hallo
Wahrscheinlich merk ich es nur nicht, weil ich seit Monaten nicht mehr richtig programmiert hab. Diese Sache mit dem Shader und der Weltgenerierung hat mir echt den Rest gegeben (Appropos, ich habs immer noch nicht raus, also wenn irgendwer helfen kann: Zum Thema). Aber nach diesem weiteren verzweifelten Hilferuf nun zu einem neuen Problem. Ich hab zur Ablenkung mal ein kleineres “Projektlein” angefangen. Ein 3D Funktionsplotter soll es werden. Doch irgendwie krieg ich die Basics eines GL Kontexts nicht mehr hin. Also, grundsätzlich schon, aber ich hab das Gefühl, dass irgendwas fehlt. Irgendwie funktioniert nämlich die Projektion nicht. Ich hab zu Anfang versucht 3 Linien für das Koordinatensystem zu zeichnen. Doch obwohl ich sie nur von 0 bis 1 (jeweils) zeichne, gehen sie jeweils bis zum Rand des GL Displays. Das kommt glaube ich daher, dass das nicht projeziert wird. Auch werden Linien die schräg oder ganz in Z Richtung verlaufen gar nicht angezeigt.
Das Projekt ist bisher relativ übersichtlich, ich hab mal alles in eine Datei zusammengeschrieben. Ist so ausführbar, aber ideal wär natürlich, wenn es direkt jemandem auffallen würde (Wie gesagt, ich glaub es ist ganz einfach).

import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Dimension;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

import javax.swing.*;

import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.ContextAttribs;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.PixelFormat;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL30.glBindVertexArray;
import static org.lwjgl.opengl.GL30.glGenVertexArrays;

public class Main {

	public static void main(String[] args){
		new Main();
	}

	private JFrame f;
	private JTextField formelFeld;
	private Canvas plotCanvas;
	private JLabel formelAnzeige;
	JSplitPane splitPane0;
	int shader, plotVAO, plotIBO, indexCount;
	private int modelMatrixLocation;
	private int projectionMatrixLocation;
	private FloatBuffer projectionMatrix;
	private FloatBuffer modelMatrix;
	//private Plot plot;
	private int[] vaos = new int[3];
	
	public Main(){
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (ClassNotFoundException | InstantiationException
				| IllegalAccessException | UnsupportedLookAndFeelException e) {
			e.printStackTrace();
		}
		
		f = new JFrame("Plotter");
		f.setBounds(1000, 225, 600, 450);
		f.setLayout(new BorderLayout());
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		formelFeld = new JTextField();
		plotCanvas = new Canvas(){
			private static final long serialVersionUID = 1L;
			public final void addNotify() {
                super.addNotify();
                create3DEnvironment();
            }
            public final void removeNotify() {
                Display.destroy();
                super.removeNotify();
            }
        };;
		formelAnzeige = new JLabel("Formeln");
		
		splitPane0 = new JSplitPane();
		splitPane0.setLeftComponent(formelAnzeige);
		splitPane0.setRightComponent(new JPanel().add(plotCanvas));
		
		JSplitPane splitPane = new JSplitPane();
		splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
		splitPane.setDividerLocation((int)(f.getHeight()*0.8311d));
		splitPane.setRightComponent(formelFeld);
		splitPane.setLeftComponent(splitPane0);
		
		f.add(splitPane, BorderLayout.CENTER);
		plotCanvas.setMinimumSize(new Dimension(0, 0));
		plotCanvas.setFocusable(true);
		plotCanvas.requestFocus();
		plotCanvas.setIgnoreRepaint(true);
		f.setVisible(true);
		
		try {
			shader = createDefaultShader();
		} catch (IOException e) {
			e.printStackTrace();
		}
		setUniformPositions();
		createPlot();
		
		renderLoop();
	}

	private void createPlot() {
		float[] points1 = {
				0, 0, 0,
				1, 0, 0
		};
		
		FloatBuffer b1 = BufferUtils.createFloatBuffer(6);
		b1.put(points1);
		b1.flip();
		
		int vbo1 = Main.createVBO(b1);
		
		vaos[0] = glGenVertexArrays();
		glBindVertexArray(vaos[0]);

        glBindBuffer(GL_ARRAY_BUFFER, vbo1);
        glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
        glEnableVertexAttribArray(0);
        
        float[] points2 = {
				0, 0, 0,
				0, 1, 0
		};
		
		FloatBuffer b2 = BufferUtils.createFloatBuffer(6);
		b2.put(points2);
		b2.flip();
		
		int vbo2 = Main.createVBO(b2);
		
		vaos[1] = glGenVertexArrays();
		glBindVertexArray(vaos[1]);

        glBindBuffer(GL_ARRAY_BUFFER, vbo2);
        glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
        glEnableVertexAttribArray(0);
        
        float[] points3 = {
				0, 0, 0,
				0, 0, 1
		};
		
		FloatBuffer b3 = BufferUtils.createFloatBuffer(6);
		b3.put(points3);
		b3.flip();
		
		int vbo3 = Main.createVBO(b3);
		
		vaos[2] = glGenVertexArrays();
		glBindVertexArray(vaos[2]);

        glBindBuffer(GL_ARRAY_BUFFER, vbo3);
        glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
        glEnableVertexAttribArray(0);
	}

	private void setUniformPositions() {
		modelMatrixLocation = GL20.glGetUniformLocation(shader, "model");
		projectionMatrixLocation = GL20.glGetUniformLocation(shader, "projection");
	}

	private void renderLoop() {
		matrixMultiply(modelMatrix, rotate(0, 0, 1, -45));
		while(f.isVisible()){
	        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
			glViewport(0, 0, 200, 200);
			glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
			glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
			glUseProgram(shader);
			
			GL20.glUniformMatrix4(projectionMatrixLocation, false, projectionMatrix);
			GL20.glUniformMatrix4(modelMatrixLocation, false, modelMatrix);
			
			for(int vao : vaos){
				glBindVertexArray(vao);
		        glDrawArrays(GL_LINES, 0, 2);
			}
			
			Display.update();
		}
		Display.destroy();
		System.exit(0);
	}

	private void create3DEnvironment() {
		try {
			final int GL_MAJOR_VERSION = 3;
			final int GL_MINOR_VERSION = 3;
        
			final DisplayMode displayMode = new DisplayMode(plotCanvas.getWidth(), plotCanvas.getHeight());
			final PixelFormat pixelFormat = new PixelFormat();
			final ContextAttribs contextAttribs = new ContextAttribs(GL_MAJOR_VERSION, GL_MINOR_VERSION);
        
			Display.setParent(plotCanvas);
			Display.setDisplayMode(displayMode);
			Display.create(pixelFormat, contextAttribs);
			Display.setResizable(true);
			Display.setVSyncEnabled(true);
		} catch (LWJGLException e) {
			e.printStackTrace();
		}
		projectionMatrix = createFloatBuffer(projection(75.0f, 1, 0.1f, 100.0f));
		modelMatrix = createFloatBuffer(einheitsMatrix());
	}
	
	public static float[] einheitsMatrix(){
		float[] m = new float[16];
		m[0] = 1;
		m[1] = 0;
		m[2] = 0;
		m[3] = 0;
		
		m[4] = 0;
		m[5] = 1;
		m[6] = 0;
		m[7] = 0;
		
		m[8] = 0;
		m[9] = 0;
		m[10] = 1;
		m[11] = 0;
		
		m[12] = 0;
		m[13] = 0;
		m[14] = 0;
		m[15] = 1;
		return m;
	}
	
	public static float[] 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 m;
    }
	
	public static FloatBuffer createFloatBuffer(float[] coords){
		ByteBuffer vbb = ByteBuffer.allocateDirect(coords.length * 4);
	    vbb.order(ByteOrder.nativeOrder());
	    FloatBuffer vertexBuffer = vbb.asFloatBuffer();
	    vertexBuffer.put(coords);
	    vertexBuffer.position(0);
	    return vertexBuffer;
	}

	public static int createVBO(FloatBuffer b){
		int id = glGenBuffers();
		glBindBuffer(GL_ARRAY_BUFFER, id);
		glBufferData(GL_ARRAY_BUFFER, b, GL_STATIC_DRAW);
		glBindBuffer(GL_ARRAY_BUFFER, 0);
		return id;
	}
	
	public static int createIBO(IntBuffer b){
		int id = glGenBuffers();
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id);
		glBufferData(GL_ELEMENT_ARRAY_BUFFER, b, GL_STATIC_DRAW);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
		return id;
	}
	
	public static float[] rotate(float x, float y, float z, float angle) {
		 
        final float len = (float) Math.sqrt(x * x + y * y + z * z);
        final float c = (float) Math.cos(Math.toRadians(angle));
        final float s = (float) Math.sin(Math.toRadians(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 m;
    }
	
	public static float[] scale(float x, float y, float z){
		float[] mat = new float[16];
		mat[0] = x;
		mat[1] = 0;
		mat[2] = 0;
		mat[3] = 0;
		
		mat[4] = 0;
		mat[5] = y;
		mat[6] = 0;
		mat[7] = 0;
		
		mat[8] = 0;
		mat[9] = 0;
		mat[10] = z;
		mat[11] = 0;
		
		mat[12] = 0;
		mat[13] = 0;
		mat[14] = 0;
		mat[15] = 1;
		
		return mat;
	}
	
	public static void matrixMultiply(FloatBuffer b1, float[] o) {
		float[] m = new float[b1.capacity()];
		for(int i = 0; i < m.length; i++){
			m** = b1.get(i);
		}
		
        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];
 
        b1.clear();
        b1.put(result);
        b1.flip();
    }
	
	public static String readFromFile(String datei) throws IOException{
		String text;
		BufferedReader br = new BufferedReader(new InputStreamReader(ShaderManager.class.getClassLoader().getResourceAsStream(datei)));
	    try {
	        StringBuilder sb = new StringBuilder();
	        String line = br.readLine();

	        while (line != null) {
	            sb.append(line);
	            sb.append(System.lineSeparator());
	            line = br.readLine();
	        }
	        text = sb.toString();
	    }finally {
	       br.close();
	    }
		return text;
	}
	
	public static int createDefaultShader() throws IOException{
		
		final int vs = glCreateShader(GL_VERTEX_SHADER);

	    glShaderSource(vs, readFromFile("default.vertex"));
	    glCompileShader(vs);

	    if (GL_FALSE == glGetShaderi(vs, GL_COMPILE_STATUS)) {

	        final int length = glGetShaderi(vs, GL_INFO_LOG_LENGTH);
	        final String log = glGetShaderInfoLog(vs, length);

	        throw new RuntimeException("Fehler: "+vs+" "+log);

	    }
	    
	    final int fs = glCreateShader(GL_FRAGMENT_SHADER);

	    glShaderSource(fs, readFromFile("default.fragment"));
	    glCompileShader(fs);

	    if (GL_FALSE == glGetShaderi(fs, GL_COMPILE_STATUS)) {

	        final int length = glGetShaderi(fs, GL_INFO_LOG_LENGTH);
	        final String log = glGetShaderInfoLog(fs, length);

	        throw new RuntimeException("Fehler: "+fs+" "+log);

	    }
	    
	    final int handle = glCreateProgram();

	    glAttachShader(handle, vs);
	    glAttachShader(handle, fs);

	    glLinkProgram(handle);

	    if (GL_FALSE == glGetProgrami(handle, GL_LINK_STATUS)) {

	        final int length = glGetProgrami(handle, GL_INFO_LOG_LENGTH);
	        final String log = glGetProgramInfoLog(handle, length);

	        throw new RuntimeException("Fehler beim Programm: "+handle+" "+log);

	    }
		
		return handle;
	}
}

Die einfachsten Shader:


#version 330
layout (location = 0) in vec3 in_Position;

uniform mat4 projection;
uniform mat4 model;

void main(){
	vec4 pos = projection*model*vec4(in_Position, 0);
    gl_Position = pos;
}


#version 330

out vec4 outColor;

void main(){
	outColor = vec4(1, 0, 0, 1);
}

Sollte im VertexShader nicht der Vektor mit einer 1 Angegeben sein, da es sich um eine Position handelt?

vec4 pos = projection*model*vec4(in_Position, 1.0);

Ja, stimmt. Aber dann wird gar nichts mehr angezeigt. Trotzdem danke, ich hab mich immer gefragt ob das einen unterschied macht.

Hat wirklich keiner eine Ahnung, was es sein könnte?

So sieht’s hier aus:
Wie soll es aussehen?

Schon so, aber versuch doch mal Linien in schräge Z-Richtung oder so zu zeichnen (In der Funktion createPlot()).

So?

        float[] points1 = {
                0, 0, 0,
                1, 1, 0
        };

*** Edit ***

Das was Sunshine gesagt hat stimmt. Und wenn du das geändert hast, gib’ deinen Punkten mal z-Werte von -5 oder so. Im Zweifelsfall stimmt da wohl irgendeine Transformationsmatrix nicht.

Ich meine, dass wenn man einen Vektor in den Z-Raum gehen lässt, zum Beispiel:

float[] points1 = {
                0, 0, 0,
                1, 1, 1
        };

Dass dieser dann überhaupt nicht angezeigt wird. Wie ich schon erwähnte, glaube ich es liegt an der Projektionsmatrix, aber die hab ich 1:1 aus einem anderen Projekt kopiert und da funktioniert es perfekt.

Hast du irgendwie überprüft, ob deine Matrix-Funktionen (rotate und matrixMultiply) das richtige machen? Ich meine, wer genau soll seine Zeit damit verschwenden, das ganze zu debuggen, wenn der Fehler vielleicht an irgendsoeinem Trivial-Kack liegt? Mit

        float[] points1 = {
                0, 0, -1f,
                1, 1, -2f
        };

zeichnet er was, mit

        float[] points1 = {
                0, 0, 1f,
                1, 1, 2f
        };

zeichnet er nichts, also wird da wohl händewedel irgendwo irgendwas irgendwie so berechnet, dass es nicht richtig ist…

Moin,

hab mir den Code nicht wirklich angesehen oder ausprobiert und vielleicht schlafe ich noch, aber die OpenGL “Kamera” sitzt normalerweise im Koordinatenursprung mit Blickrichtung -Z. Negative Z Werte damit ein Objekt sichtbar wird scheint erst mal nicht so verkehrt. Verwunderlicher finde ich das was bei Z=0 gezeichnet wird, wenn zNear auf 0.1 gesetzt wird.

Ansonsten scheint projection(), rotate() und matrixMultiply() von mir zu sein. Wobei zumindest letzteres modifiziert wurde.

Gruß
Fancy

Oh Gott. Danke dafür. Ich hab wirklich das Gefühl ich bin raus, wenn mir sowas total offensichtliches nicht auffällt. Danke.