Licht in OpenGL

Also ein Rechteck aus zwei Dreiecken geht, aber wenn es komplizierter wird, dann gehts nicht mehr richtig, und bei einem Testwürfel ist es sogar so, dass eine Seite senkrecht in der Mitte in zwei Rechtecke(hell und dunkel) geteilt wird, obwohl es aus zwei Dreiecken gerendert wird und wenn überhaupt, dann doch schräg geteilt werden müsste, aber auch bei diesem Würfel zeigt sich, dass von 6 Normalen nur 5 errechnet wurden. Wegen dieser Teilung könnte noch jemand erklären, wie man das Problem mit der Indexreihenfolge lösen kann?

Klingt Chaotisch. Kann man mit dem Würfel ein KSKB basteln?

Ok, hier ein "K"SKB, das Licht rotiert in Y/Z Richtung um den roten Würfel, und es sieht wahrhaft bizarr aus.


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

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 java.util.ArrayList;

import javax.swing.JFrame;

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.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.util.vector.Vector3f;


public class KSKB {


	private float[] coords = {
			//Front
			-0.5f, 1.0f, 0.5f,
			-0.5f, 0.0f, 0.5f,
			0.5f, 1.0f, 0.5f,
			0.5f, 0.0f, 0.5f,
			
			//Back
			0.5f, 1.0f, -0.5f,
			0.5f, 0.0f, -0.5f,
			-0.5f, 1.0f, -0.5f,
			-0.5f, 0.0f, -0.5f,
			
			//Top
			-0.5f, 1.0f, -0.5f,
			-0.5f, 1.0f, 0.5f,
			0.5f, 1.0f, -0.5f,
			0.5f, 1.0f, 0.5f,
			
			//Bottom
			0.5f, 0.0f, 0.5f,
			0.5f, 0.0f, -0.5f,
			-0.5f, 0.0f, 0.5f,
			-0.5f, 0.0f, -0.5f,
			
			//Left
			-0.5f, 1.0f, -0.5f,
			-0.5f, 0.0f, -0.5f,
			-0.5f, 1.0f, 0.5f,
			-0.5f, 0.0f, 0.5f,
			
			//Right
			0.5f, 1.0f, 0.5f,
			0.5f, 0.0f, 0.5f,
			0.5f, 1.0f, -0.5f,
			0.5f, 0.0f, -0.5f
	};
	private int[] indecies = {
			0, 1, 2, 2, 1, 3, 
			4, 5, 6, 6, 5, 7,
			8, 9, 10, 10, 9, 11,
			12, 13, 14, 14, 13, 15,
			16, 17, 18, 18, 17, 19,
			20, 21, 22, 22, 21, 23
	};
	private FloatBuffer vertexBuffer;
	private IntBuffer indexBuffer;
	private FloatBuffer normalBuffer;
	private int vboID;
	private int nboID;
	private int vaoID;
	private JFrame f;
	private int w;
	private int h;
	private FloatBuffer modelMatrix;
	private int projectionMatrixLocation;
	private int viewMatrixLocation;
	private int modelMatrixLocation;
	private int camPosLocation;
	private int lightPosLocation;
	private int lightColorLocation;
	private int lightAmbientLocation;
	private int lightAttenuationAllowedLocation;
	private long stepTime;
	private float deltaTime;
	private float posZ;
	private float posY;
	private float posX;
	private FloatBuffer projMatrix = BufferUtils.createFloatBuffer(16);
	private FloatBuffer viewMatrix = BufferUtils.createFloatBuffer(16);
	private double rotY;
	private double rotV;
	private float rotX;
	private float rotZ;
	private float a;
	
	public KSKB(){
		f = new JFrame("KSKB");
        f.setPreferredSize(new Dimension(700, 550));
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setLocation(900, 50);
        f.pack();
        Canvas canvas = new Canvas();
        f.add(canvas);
        try {
        Display.setParent(canvas);
        f.setVisible(true);
        Display.create();
        int[] ints = {
        	0, 0, 0, 0	
        };
		Cursor invisibleCursor = new Cursor(1, 1, 0, 0, 1, toIntBuffer(ints), toIntBuffer(ints));
		Mouse.setNativeCursor(invisibleCursor);
        } catch (LWJGLException e) {
            e.printStackTrace();
        }
        w = Display.getWidth();
        h = Display.getHeight();
        Mouse.setGrabbed(true);
        
        Shader shader = null;
        try {
			shader = new Shader("vs_kskb.vertex", "fs_kskb.fragment");
		} catch (IOException e) {
			e.printStackTrace();
		}
        
		vertexBuffer = toFloatBuffer(coords);
		indexBuffer = toIntBuffer(indecies);
		normalBuffer = calcNormals();
		vboID = createVBO(vertexBuffer, vboID);
		nboID = createVBO(normalBuffer, nboID);
		initVAO();
		modelMatrix = toFloatBuffer(einheitsMatrix());
		
		shader.use();
		projectionMatrixLocation = shader.getUniformLocation("projection");
		viewMatrixLocation = shader.getUniformLocation("view");
		modelMatrixLocation = shader.getUniformLocation("model");
		camPosLocation = shader.getUniformLocation("camPos");
		lightPosLocation = shader.getUniformLocation("lightPos");
		lightColorLocation = shader.getUniformLocation("lightColor");
		lightAmbientLocation = shader.getUniformLocation("ambientLight");
		lightAttenuationAllowedLocation = shader.getUniformLocation("attenuationAllowed");
		while(!Display.isCloseRequested()){
			glEnable(GL_CULL_FACE);
			glCullFace(GL_BACK);
			deltaTime = -(stepTime - (stepTime = System.nanoTime())) / 100000000.0f;
			firstPersonControls(deltaTime, viewMatrix);
			a+=0.0001f;
			float z = (float) (Math.cos(a)*5);
			float y = (float) (Math.sin(a)*5);
			float[] lightPos = {0, y, z};
			float[] lightColor = {1, 1, 1};
			glUniform3(lightPosLocation, toFloatBuffer(lightPos));
            glUniform3(lightColorLocation, toFloatBuffer(lightColor));
            glUniform1f(lightAmbientLocation, 0.3f);
            glUniform1i(lightAttenuationAllowedLocation, 0);
            
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    		glViewport(0, 0, w, h);
            projMatrix = toFloatBuffer(projection(50.0f, w/h, 0.1f, 100.0f));
            GL20.glUniformMatrix4(viewMatrixLocation, false, viewMatrix);
            GL20.glUniformMatrix4(projectionMatrixLocation, false, projMatrix);
            GL20.glUniform3f(camPosLocation, posX, posY, posZ);
            
            modelMatrix = matrixMultiply(modelMatrix, toFloatBuffer(translate(0, -1, 0)));
            GL20.glUniformMatrix4(modelMatrixLocation, false, modelMatrix);
        	glBindVertexArray(vaoID);
            glEnableVertexAttribArray(0);
            glEnableVertexAttribArray(1);
            
            glDrawElements(GL_TRIANGLES, indexBuffer);

            glDisableVertexAttribArray(0);
            glDisableVertexAttribArray(1);
            glBindVertexArray(0);
            modelMatrix = matrixMultiply(modelMatrix, toFloatBuffer(translate(0, 1, 0)));
            
            Display.update();
		}
		
	}
	
	public static void main(String[] args){
		new KSKB();
	}

	
	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 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[] translate(float x, float y, 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 m;
	}
	
	private static float[] floatBufferToArray(FloatBuffer b) {
		float[] f = new float[b.capacity()];
		for(int i = 0; i < f.length; i++){
			f** = b.get(i);
		}
		return f;
	}

	public static FloatBuffer matrixMultiply(FloatBuffer b1, FloatBuffer b2) {
		float[] m = floatBufferToArray(b1);
		float[] o = floatBufferToArray(b2);
		
        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];
 
        FloatBuffer out = BufferUtils.createFloatBuffer(16);
        out.put(result).rewind();
        return out;
 
    }

	private void firstPersonControls(final float deltaTime, final FloatBuffer viewMatrix) {
		 
		 
        final double keySpeed = deltaTime * 0.5;
        final double mouseSpeed = 0.002;
 
        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_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;
 
        viewMatrix.position(0);
        viewMatrix.put(mv);
        viewMatrix.flip();
    }


	private void initVAO() {
		vaoID = glGenVertexArrays();
        glBindVertexArray(vaoID);

        glBindBuffer(GL_ARRAY_BUFFER, vboID);
        glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
        glEnableVertexAttribArray(0);
        
        glBindBuffer(GL_ARRAY_BUFFER, nboID);
        glVertexAttribPointer(1, 3, GL_FLOAT, false, 0, 0);
        glEnableVertexAttribArray(1);
	}


	private int createVBO(FloatBuffer b, int id) {
		GL15.glDeleteBuffers(id);
		id = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, id);
        glBufferData(GL_ARRAY_BUFFER, b, GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
		return id;
	}


	private FloatBuffer calcNormals() {
		ArrayList<Float> normals = new ArrayList<Float>(); 
		ArrayList<int[]> ipd = new ArrayList<int[]>();
		for(int i = 0; i < indexBuffer.capacity(); i += 3){
			int[] ind = {
					indexBuffer.get(i),indexBuffer.get(i+1),indexBuffer.get(i+2)
			};
			ipd.add(ind);
		}
		for(int d = 0; d < ipd.size(); d++){
			float nx = 0, ny = 0, nz = 0;
			ArrayList<Vector3f> coord_vectors = new ArrayList<Vector3f>();
			for(int i = 0; i < vertexBuffer.capacity(); i += 3){
				coord_vectors.add(new Vector3f(vertexBuffer.get(i), vertexBuffer.get(i+1), vertexBuffer.get(i+2)));
			}
			Vector3f U = new Vector3f();
			Vector3f.sub(coord_vectors.get(ipd.get(d)[1]), coord_vectors.get(ipd.get(d)[0]), U);
			Vector3f V = new Vector3f();
			Vector3f.sub(coord_vectors.get(ipd.get(d)[2]), coord_vectors.get(ipd.get(d)[0]), V);
			
			nx = U.y*V.z-U.z*V.y;
			ny = U.z*V.x-U.x*V.z;
			nz = U.x*V.y-U.y*V.x;
			
			for(int i = 0; i < 3; i++){
				normals.add(nx);
				normals.add(ny);
				normals.add(nz);
			}
			
		}
		float[] ns = new float[normals.size()];
		for(int i = 0; i < ns.length; i++){
			ns** = normals.get(i).floatValue();
		}
		return toFloatBuffer(ns);
	}


	private IntBuffer toIntBuffer(int[] ints) {
		ByteBuffer bb = ByteBuffer.allocateDirect(ints.length * 4);
	    bb.order(ByteOrder.nativeOrder());
	    IntBuffer buffer = bb.asIntBuffer();
	    buffer.put(ints);
	    buffer.position(0);
	    return buffer;
	}


	private FloatBuffer toFloatBuffer(float[]  b) {
		ByteBuffer bb = ByteBuffer.allocateDirect(b.length * 4);
	    bb.order(ByteOrder.nativeOrder());
	    FloatBuffer buffer = bb.asFloatBuffer();
	    buffer.put(b);
	    buffer.position(0);
	    return buffer;
	}
	
	
	
	public static class Shader{

		private int vertex;
		private int fragment;
		public int program;

		public Shader(String vertexDatei, String fragmentDatei) throws IOException{
			this(readFromFile(vertexDatei), readFromFile(fragmentDatei), true);
		}
		public Shader(String vertexText, String fragmentText, boolean dingenskirchen){
			vertex = glCreateShader(GL_VERTEX_SHADER);
			fragment = glCreateShader(GL_FRAGMENT_SHADER);
			
			glShaderSource(vertex, vertexText);
			glShaderSource(fragment, fragmentText);
			
			glCompileShader(vertex);
			glCompileShader(fragment);
			
			String infoLogVertex = glGetShaderInfoLog(vertex,
		            glGetShaderi(vertex, GL_INFO_LOG_LENGTH));

			String infoLogFragment = glGetShaderInfoLog(fragment,
		            glGetShaderi(fragment, GL_INFO_LOG_LENGTH));

			
		    if (glGetShaderi(vertex, GL_COMPILE_STATUS) == GL_FALSE)
				try {
					throw new LWJGLException("Failure in compiling " +"Vertex Shader"
					        + ". Error log:
" + infoLogVertex);
				} catch (LWJGLException e) {
					e.printStackTrace();
				}

		    if (glGetShaderi(fragment, GL_COMPILE_STATUS) == GL_FALSE)
				try {
					throw new LWJGLException("Failure in compiling " + "Fragment Shader"
					        + ". Error log:
" + infoLogFragment);
				} catch (LWJGLException e) {
					e.printStackTrace();
				}
		    
		    program = glCreateProgram();

		    glAttachShader(program, vertex);
		    glAttachShader(program, fragment);
		    
		    glBindAttribLocation(program, 0, "in_Position");
		    glBindAttribLocation(program, 1, "in_TextureCoord");
		    
		    glLinkProgram(program);
		    
		    String infoLog = glGetProgramInfoLog(program, glGetProgrami(program, GL_INFO_LOG_LENGTH));

		    if (glGetProgrami(program, GL_LINK_STATUS) == GL_FALSE)
				try {
					throw new LWJGLException(
					        "Failure in linking program. Error log:
" + infoLog);
				} catch (LWJGLException e) {
					e.printStackTrace();
				}
		    
		    glDetachShader(program, vertex);
		    glDetachShader(program, fragment);
		    glDeleteShader(vertex);
		    glDeleteShader(fragment);
		}

		private static String readFromFile(String datei) throws IOException{
			String text= "test";
			BufferedReader br = new BufferedReader(new InputStreamReader(Shader.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 void use() {
		    glUseProgram(program);
		}
		public void unuse() {
		    glUseProgram(0);
		}
		public void destroy() {
		    glDeleteProgram(program);
		}
		public int getUniformLocation(String str) {
		    return glGetUniformLocation(program, str);
		}
		
	}
}

Vertex Shader (vs_kskb.vertex):


#version 330

layout (location = 0) in vec3 in_Position;
layout (location = 1) in vec3 in_Normal;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
uniform vec3 camPos;

out vec3 fragNormal;
out vec3 fragVert;
out mat4 modelMat;
out vec3 cameraPosition;

void main() {
    vec4 pos = projection*view*model*vec4(in_Position, 1);
    gl_Position = pos;
	fragNormal = in_Normal;
	fragVert = in_Position;
	modelMat = model;
	cameraPosition = camPos;
}

Fragment Shader(fs_kskb.fragment):


#version 330
uniform vec3 lightPos;
uniform vec3 lightColor;
uniform float ambientLight;
uniform float materialShininess;
uniform vec3 materialSpecularColor;
uniform int attenuationAllowed;
uniform vec4 color;

in vec3 cameraPosition;
in vec2 TexCoord;
in vec3 fragNormal;
in vec3 fragVert;
in mat4 modelMat;

void main() {
    mat3 normalMatrix = transpose(inverse(mat3(modelMat)));
    vec3 normal = normalize(normalMatrix * fragNormal);
    vec3 fragPosition = vec3(modelMat *vec4(fragVert, 1));
    vec3 surfaceToLight = lightPos - fragPosition;
    float brightness = dot(normal, surfaceToLight) / (length(surfaceToLight) * length(normal));
    brightness = clamp(brightness, 0, 2);
	
	vec3 incidenceVector = -surfaceToLight; //a unit vector
	vec3 reflectionVector = reflect(incidenceVector, normal); //also a unit vector
	vec3 surfaceToCamera = normalize(cameraPosition - fragPosition); //also a unit vector
	float cosAngle = max(0.0, dot(surfaceToCamera, reflectionVector));
	float specularCoefficient = pow(cosAngle, materialShininess);
	float attenuation;
	if(attenuationAllowed == 1){
		attenuation = 1.0 / (1.0 + pow(length(surfaceToLight), 2f));
	}else{
		attenuation = 1;
	}
	vec4 surfaceColor = vec4(1, 0, 0, 1);
	vec3 diffuse = brightness * surfaceColor.rgb * lightColor;
    vec3 ambient = ambientLight * surfaceColor.rgb * lightColor;
    vec3 specular = vec3(0, 0, 0);
    vec3 linearColor = ambient + attenuation*(diffuse + specular);
    vec3 gamma = vec3(1.0/2.2, 1.0/2.2, 1.0/2.2);
	vec3 finalColor = vec3(pow(linearColor.r, gamma.r),
                  pow(linearColor.g, gamma.g),
                  pow(linearColor.b, gamma.b));
    vec4 lightSurfaceColor = vec4(finalColor*surfaceColor.rgb, surfaceColor.a);
    gl_FragColor = lightSurfaceColor;
}

Vielleicht kann mal jemand ein eigenes KSKB Posten mit dem es gut funktioniert und ich vergleiche das dann mal.

Ja, das war untergegangen. Es ist schwer, einzugrenzen, auch wenn man nicht sicher ist, wo der Fehler überhaupt liegen “kann”. Wo hast du die Würfelkoordinaten her? Wo hast du den Fragment Shader her?

Jedenfalls habe ich gerade mal die Daten von der erstbesten Seite verwendet, die bei “cube vertex buffer coordinate indices” kam ( https://developer.mozilla.org/de/docs/Web/WebGL/3D-Objekte_mit_WebGL_erstellen ), und die Normalen Händisch eingefügt:

package bytewelt.zombiepriester.light;
import static org.lwjgl.opengl.GL11.GL_BACK;
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_CULL_FACE;
import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_FALSE;
import static org.lwjgl.opengl.GL11.GL_FLOAT;
import static org.lwjgl.opengl.GL11.GL_TRIANGLES;
import static org.lwjgl.opengl.GL11.glClear;
import static org.lwjgl.opengl.GL11.glCullFace;
import static org.lwjgl.opengl.GL11.glDrawElements;
import static org.lwjgl.opengl.GL11.glEnable;
import static org.lwjgl.opengl.GL11.glViewport;
import static org.lwjgl.opengl.GL15.GL_ARRAY_BUFFER;
import static org.lwjgl.opengl.GL15.GL_STATIC_DRAW;
import static org.lwjgl.opengl.GL15.glBindBuffer;
import static org.lwjgl.opengl.GL15.glBufferData;
import static org.lwjgl.opengl.GL15.glGenBuffers;
import static org.lwjgl.opengl.GL20.GL_COMPILE_STATUS;
import static org.lwjgl.opengl.GL20.GL_FRAGMENT_SHADER;
import static org.lwjgl.opengl.GL20.GL_INFO_LOG_LENGTH;
import static org.lwjgl.opengl.GL20.GL_LINK_STATUS;
import static org.lwjgl.opengl.GL20.GL_VERTEX_SHADER;
import static org.lwjgl.opengl.GL20.glAttachShader;
import static org.lwjgl.opengl.GL20.glBindAttribLocation;
import static org.lwjgl.opengl.GL20.glCompileShader;
import static org.lwjgl.opengl.GL20.glCreateProgram;
import static org.lwjgl.opengl.GL20.glCreateShader;
import static org.lwjgl.opengl.GL20.glDeleteProgram;
import static org.lwjgl.opengl.GL20.glDeleteShader;
import static org.lwjgl.opengl.GL20.glDetachShader;
import static org.lwjgl.opengl.GL20.glDisableVertexAttribArray;
import static org.lwjgl.opengl.GL20.glEnableVertexAttribArray;
import static org.lwjgl.opengl.GL20.glGetProgramInfoLog;
import static org.lwjgl.opengl.GL20.glGetProgrami;
import static org.lwjgl.opengl.GL20.glGetShaderInfoLog;
import static org.lwjgl.opengl.GL20.glGetShaderi;
import static org.lwjgl.opengl.GL20.glGetUniformLocation;
import static org.lwjgl.opengl.GL20.glLinkProgram;
import static org.lwjgl.opengl.GL20.glShaderSource;
import static org.lwjgl.opengl.GL20.glUniform1f;
import static org.lwjgl.opengl.GL20.glUniform1i;
import static org.lwjgl.opengl.GL20.glUniform3;
import static org.lwjgl.opengl.GL20.glUseProgram;
import static org.lwjgl.opengl.GL20.glVertexAttribPointer;
import static org.lwjgl.opengl.GL30.glBindVertexArray;
import static org.lwjgl.opengl.GL30.glGenVertexArrays;

import java.awt.Canvas;
import java.awt.Dimension;
import java.io.BufferedReader;
import java.io.FileInputStream;
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 java.util.ArrayList;

import javax.swing.JFrame;

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.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.util.vector.Vector3f;


public class KSKB {

    private float coords[] = {
                    // vordere Fläche
                    -1.0f, -1.0f,  1.0f,
                     1.0f, -1.0f,  1.0f,
                     1.0f,  1.0f,  1.0f,
                    -1.0f,  1.0f,  1.0f,
                    
                    // hintere Fläche
                    -1.0f, -1.0f, -1.0f,
                    -1.0f,  1.0f, -1.0f,
                     1.0f,  1.0f, -1.0f,
                     1.0f, -1.0f, -1.0f,
                    
                    // obere Fläche
                    -1.0f,  1.0f, -1.0f,
                    -1.0f,  1.0f,  1.0f,
                     1.0f,  1.0f,  1.0f,
                     1.0f,  1.0f, -1.0f,
                    
                    // untere Fläche
                    -1.0f, -1.0f, -1.0f,
                     1.0f, -1.0f, -1.0f,
                     1.0f, -1.0f,  1.0f,
                    -1.0f, -1.0f,  1.0f,
                    
                    // rechte Fläche
                     1.0f, -1.0f, -1.0f,
                     1.0f,  1.0f, -1.0f,
                     1.0f,  1.0f,  1.0f,
                     1.0f, -1.0f,  1.0f,
                    
                    // linke Fläche
                    -1.0f, -1.0f, -1.0f,
                    -1.0f, -1.0f,  1.0f,
                    -1.0f,  1.0f,  1.0f,
                    -1.0f,  1.0f, -1.0f
    };    

	private float[] coords1 = {
			//Front
			-0.5f, 1.0f, 0.5f,
			-0.5f, 0.0f, 0.5f,
			0.5f, 1.0f, 0.5f,
			0.5f, 0.0f, 0.5f,
			
			//Back
			0.5f, 1.0f, -0.5f,
			0.5f, 0.0f, -0.5f,
			-0.5f, 1.0f, -0.5f,
			-0.5f, 0.0f, -0.5f,
			
			//Top
			-0.5f, 1.0f, -0.5f,
			-0.5f, 1.0f, 0.5f,
			0.5f, 1.0f, -0.5f,
			0.5f, 1.0f, 0.5f,
			
			//Bottom
			0.5f, 0.0f, 0.5f,
			0.5f, 0.0f, -0.5f,
			-0.5f, 0.0f, 0.5f,
			-0.5f, 0.0f, -0.5f,
			
			//Left
			-0.5f, 1.0f, -0.5f,
			-0.5f, 0.0f, -0.5f,
			-0.5f, 1.0f, 0.5f,
			-0.5f, 0.0f, 0.5f,
			
			//Right
			0.5f, 1.0f, 0.5f,
			0.5f, 0.0f, 0.5f,
			0.5f, 1.0f, -0.5f,
			0.5f, 0.0f, -0.5f
	};
    private float[] normals = {
        //Front
        0.0f, 0.0f, 1.0f,
        0.0f, 0.0f, 1.0f,
        0.0f, 0.0f, 1.0f,
        0.0f, 0.0f, 1.0f,

        //Back
        0.0f, 0.0f, -1.0f,
        0.0f, 0.0f, -1.0f,
        0.0f, 0.0f, -1.0f,
        0.0f, 0.0f, -1.0f,
        
        //Top
        0.0f, 1.0f, 0.0f,
        0.0f, 1.0f, 0.0f,
        0.0f, 1.0f, 0.0f,
        0.0f, 1.0f, 0.0f,
        
        //Bottom
        0.0f, -1.0f, 0.0f,
        0.0f, -1.0f, 0.0f,
        0.0f, -1.0f, 0.0f,
        0.0f, -1.0f, 0.0f,
        
        //Left
        -1.0f, 0.0f, 0.0f,
        -1.0f, 0.0f, 0.0f,
        -1.0f, 0.0f, 0.0f,
        -1.0f, 0.0f, 0.0f,
        
        //Right
        1.0f, 0.0f, 0.0f,
        1.0f, 0.0f, 0.0f,
        1.0f, 0.0f, 0.0f,
        1.0f, 0.0f, 0.0f,
    };
	private int[] indecies1 = {
			0, 1, 2, 2, 1, 3, 
			4, 5, 6, 6, 5, 7,
			8, 9, 10, 10, 9, 11,
			12, 13, 14, 14, 13, 15,
			16, 17, 18, 18, 17, 19,
			20, 21, 22, 22, 21, 23
	};
	
	 int [] indecies = {
	                          0,  1,  2,      0,  2,  3,    // vorne
	                          4,  5,  6,      4,  6,  7,    // hinten
	                          8,  9,  10,     8,  10, 11,   // oben
	                          12, 13, 14,     12, 14, 15,   // unten
	                          16, 17, 18,     16, 18, 19,   // rechts
	                          20, 21, 22,     20, 22, 23    // links
	 };
	private FloatBuffer vertexBuffer;
	private IntBuffer indexBuffer;
	private FloatBuffer normalBuffer;
	private int vboID;
	private int nboID;
	private int vaoID;
	private JFrame f;
	private int w;
	private int h;
	private FloatBuffer modelMatrix;
	private int projectionMatrixLocation;
	private int viewMatrixLocation;
	private int modelMatrixLocation;
	private int camPosLocation;
	private int lightPosLocation;
	private int lightColorLocation;
	private int lightAmbientLocation;
	private int lightAttenuationAllowedLocation;
	private long stepTime;
	private float deltaTime;
	private float posZ;
	private float posY;
	private float posX;
	private FloatBuffer projMatrix = BufferUtils.createFloatBuffer(16);
	private FloatBuffer viewMatrix = BufferUtils.createFloatBuffer(16);
	private double rotY;
	private double rotV;
	private float rotX;
	private float rotZ;
	private float a;
	
	public KSKB(){
		f = new JFrame("KSKB");
        f.setPreferredSize(new Dimension(700, 550));
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setLocation(900, 50);
        f.pack();
        Canvas canvas = new Canvas();
        f.add(canvas);
        try {
        Display.setParent(canvas);
        f.setVisible(true);
        Display.create();
        int[] ints = {
        	0, 0, 0, 0	
        };
		Cursor invisibleCursor = new Cursor(1, 1, 0, 0, 1, toIntBuffer(ints), toIntBuffer(ints));
		Mouse.setNativeCursor(invisibleCursor);
        } catch (LWJGLException e) {
            e.printStackTrace();
        }
        w = Display.getWidth();
        h = Display.getHeight();
        Mouse.setGrabbed(true);
        
        Shader shader = null;
        try {
			shader = new Shader("vs_kskb.vertex", "fs_kskb.fragment");
		} catch (IOException e) {
			e.printStackTrace();
		}
        
		vertexBuffer = toFloatBuffer(coords);
        indexBuffer = toIntBuffer(indecies);
		//normalBuffer = calcNormals();
        normalBuffer = toFloatBuffer(normals);
		vboID = createVBO(vertexBuffer, vboID);
		nboID = createVBO(normalBuffer, nboID);
		
		System.out.println(vertexBuffer.capacity());
		System.out.println(normalBuffer.capacity());
		
		
		initVAO();
		modelMatrix = toFloatBuffer(einheitsMatrix());
		
		shader.use();
		projectionMatrixLocation = shader.getUniformLocation("projection");
		viewMatrixLocation = shader.getUniformLocation("view");
		modelMatrixLocation = shader.getUniformLocation("model");
		camPosLocation = shader.getUniformLocation("camPos");
		lightPosLocation = shader.getUniformLocation("lightPos");
		lightColorLocation = shader.getUniformLocation("lightColor");
		lightAmbientLocation = shader.getUniformLocation("ambientLight");
		lightAttenuationAllowedLocation = shader.getUniformLocation("attenuationAllowed");
		while(!Display.isCloseRequested()){
			glEnable(GL_CULL_FACE);
			glCullFace(GL_BACK);
			deltaTime = -(stepTime - (stepTime = System.nanoTime())) / 100000000.0f;
			firstPersonControls(deltaTime, viewMatrix);
			a+=0.0001f;
			float z = (float) (Math.cos(a)*5);
			float y = (float) (Math.sin(a)*5);
			float[] lightPos = {0, y, z};
			float[] lightColor = {1, 1, 1};
			glUniform3(lightPosLocation, toFloatBuffer(lightPos));
            glUniform3(lightColorLocation, toFloatBuffer(lightColor));
            glUniform1f(lightAmbientLocation, 0.3f);
            glUniform1i(lightAttenuationAllowedLocation, 0);
            
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    		glViewport(0, 0, w, h);
            projMatrix = toFloatBuffer(projection(50.0f, w/h, 0.1f, 100.0f));
            GL20.glUniformMatrix4(viewMatrixLocation, false, viewMatrix);
            GL20.glUniformMatrix4(projectionMatrixLocation, false, projMatrix);
            GL20.glUniform3f(camPosLocation, posX, posY, posZ);
            
            modelMatrix = matrixMultiply(modelMatrix, toFloatBuffer(translate(0, -1, 0)));
            GL20.glUniformMatrix4(modelMatrixLocation, false, modelMatrix);
        	glBindVertexArray(vaoID);
            glEnableVertexAttribArray(0);
            glEnableVertexAttribArray(1);
            
            glDrawElements(GL_TRIANGLES, indexBuffer);

            glDisableVertexAttribArray(0);
            glDisableVertexAttribArray(1);
            glBindVertexArray(0);
            modelMatrix = matrixMultiply(modelMatrix, toFloatBuffer(translate(0, 1, 0)));
            
            Display.update();
		}
		
	}
	
	public static void main(String[] args){
		new KSKB();
	}

	
	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 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[] translate(float x, float y, 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 m;
	}
	
	private static float[] floatBufferToArray(FloatBuffer b) {
		float[] f = new float[b.capacity()];
		for(int i = 0; i < f.length; i++){
			f** = b.get(i);
		}
		return f;
	}

	public static FloatBuffer matrixMultiply(FloatBuffer b1, FloatBuffer b2) {
		float[] m = floatBufferToArray(b1);
		float[] o = floatBufferToArray(b2);
		
        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];
 
        FloatBuffer out = BufferUtils.createFloatBuffer(16);
        out.put(result).rewind();
        return out;
 
    }

	private void firstPersonControls(final float deltaTime, final FloatBuffer viewMatrix) {
		 
		 
        final double keySpeed = deltaTime * 0.5;
        final double mouseSpeed = 0.002;
 
        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_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;
 
        viewMatrix.position(0);
        viewMatrix.put(mv);
        viewMatrix.flip();
    }


	private void initVAO() {
		vaoID = glGenVertexArrays();
        glBindVertexArray(vaoID);

        glBindBuffer(GL_ARRAY_BUFFER, vboID);
        glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
        glEnableVertexAttribArray(0);
        
        glBindBuffer(GL_ARRAY_BUFFER, nboID);
        glVertexAttribPointer(1, 3, GL_FLOAT, false, 0, 0);
        glEnableVertexAttribArray(1);
	}


	private int createVBO(FloatBuffer b, int id) {
		GL15.glDeleteBuffers(id);
		id = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, id);
        glBufferData(GL_ARRAY_BUFFER, b, GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
		return id;
	}


	private FloatBuffer calcNormals() {
		ArrayList<Float> normals = new ArrayList<Float>(); 
		ArrayList<int[]> ipd = new ArrayList<int[]>();
		for(int i = 0; i < indexBuffer.capacity(); i += 3){
			int[] ind = {
					indexBuffer.get(i),indexBuffer.get(i+1),indexBuffer.get(i+2)
			};
			ipd.add(ind);
		}
		for(int d = 0; d < ipd.size(); d++){
			float nx = 0, ny = 0, nz = 0;
			ArrayList<Vector3f> coord_vectors = new ArrayList<Vector3f>();
			for(int i = 0; i < vertexBuffer.capacity(); i += 3){
				coord_vectors.add(new Vector3f(vertexBuffer.get(i), vertexBuffer.get(i+1), vertexBuffer.get(i+2)));
			}
			Vector3f U = new Vector3f();
			Vector3f.sub(coord_vectors.get(ipd.get(d)[1]), coord_vectors.get(ipd.get(d)[0]), U);
			Vector3f V = new Vector3f();
			Vector3f.sub(coord_vectors.get(ipd.get(d)[2]), coord_vectors.get(ipd.get(d)[0]), V);
			
			nx = U.y*V.z-U.z*V.y;
			ny = U.z*V.x-U.x*V.z;
			nz = U.x*V.y-U.y*V.x;
			
			for(int i = 0; i < 3; i++)
			{
				normals.add(nx);
				normals.add(ny);
				normals.add(nz);
			}
			
		}
		float[] ns = new float[normals.size()];
		for(int i = 0; i < ns.length; i++){
			ns** = normals.get(i).floatValue();
		}
		return toFloatBuffer(ns);
	}


	private IntBuffer toIntBuffer(int[] ints) {
		ByteBuffer bb = ByteBuffer.allocateDirect(ints.length * 4);
	    bb.order(ByteOrder.nativeOrder());
	    IntBuffer buffer = bb.asIntBuffer();
	    buffer.put(ints);
	    buffer.position(0);
	    return buffer;
	}


	private FloatBuffer toFloatBuffer(float[]  b) {
		ByteBuffer bb = ByteBuffer.allocateDirect(b.length * 4);
	    bb.order(ByteOrder.nativeOrder());
	    FloatBuffer buffer = bb.asFloatBuffer();
	    buffer.put(b);
	    buffer.position(0);
	    return buffer;
	}
	
	
	
	public static class Shader{

		private int vertex;
		private int fragment;
		public int program;

		public Shader(String vertexDatei, String fragmentDatei) throws IOException{
			this(readFromFile(vertexDatei), readFromFile(fragmentDatei), true);
		}
		public Shader(String vertexText, String fragmentText, boolean dingenskirchen){
			vertex = glCreateShader(GL_VERTEX_SHADER);
			fragment = glCreateShader(GL_FRAGMENT_SHADER);
			
			glShaderSource(vertex, vertexText);
			glShaderSource(fragment, fragmentText);
			
			glCompileShader(vertex);
			glCompileShader(fragment);
			
			String infoLogVertex = glGetShaderInfoLog(vertex,
		            glGetShaderi(vertex, GL_INFO_LOG_LENGTH));

			String infoLogFragment = glGetShaderInfoLog(fragment,
		            glGetShaderi(fragment, GL_INFO_LOG_LENGTH));

			
		    if (glGetShaderi(vertex, GL_COMPILE_STATUS) == GL_FALSE)
				try {
					throw new LWJGLException("Failure in compiling " +"Vertex Shader"
					        + ". Error log:
" + infoLogVertex);
				} catch (LWJGLException e) {
					e.printStackTrace();
				}

		    if (glGetShaderi(fragment, GL_COMPILE_STATUS) == GL_FALSE)
				try {
					throw new LWJGLException("Failure in compiling " + "Fragment Shader"
					        + ". Error log:
" + infoLogFragment);
				} catch (LWJGLException e) {
					e.printStackTrace();
				}
		    
		    program = glCreateProgram();

		    glAttachShader(program, vertex);
		    glAttachShader(program, fragment);
		    
		    glBindAttribLocation(program, 0, "in_Position");
		    glBindAttribLocation(program, 1, "in_TextureCoord");
		    
		    glLinkProgram(program);
		    
		    String infoLog = glGetProgramInfoLog(program, glGetProgrami(program, GL_INFO_LOG_LENGTH));

		    if (glGetProgrami(program, GL_LINK_STATUS) == GL_FALSE)
				try {
					throw new LWJGLException(
					        "Failure in linking program. Error log:
" + infoLog);
				} catch (LWJGLException e) {
					e.printStackTrace();
				}
		    
		    glDetachShader(program, vertex);
		    glDetachShader(program, fragment);
		    glDeleteShader(vertex);
		    glDeleteShader(fragment);
		}

		private static String readFromFile(String datei) throws IOException{
			String text= "test";
			BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(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 void use() {
		    glUseProgram(program);
		}
		public void unuse() {
		    glUseProgram(0);
		}
		public void destroy() {
		    glDeleteProgram(program);
		}
		public int getUniformLocation(String str) {
		    return glGetUniformLocation(program, str);
		}
		
	}
}

(ACHTUNG: Liest die Shader aus einer Datei, nicht mehr aus einem Stream!)

Damit sieht’s plausibel aus. Der Shader sollte also stimmen.

VERMUTLICH ist bei der Normalenberechnung was im Argen. Das liegt nahe, weil die Buffer capacity() vom Normal-Buffer und vom Coords-Buffer unterschiedlich sind.

Ich muss mir den Code nochmal genauer ansehen. Aber grob:
Es muss für jeden Vertex genau eine Normale geben (die Buffer sollten also gleich groß sein!)
Um die Normalen zu Berechnen, muss man “eigentlich” erst die Face-Normalen ausrechnen (wie du es schon machst, mit dem Kreuzprodukt)
Im einfachsten Fall wird diese Face-Normale dann den drei Vertices zugewiesen, aus denen dieses Face besteht. (Das machst du nicht. Ich VERMUTE, das sollte in diesem Loop passieren

			for(int i = 0; i < 3; i++)
			{
				normals.add(nx);
				normals.add(ny);
				normals.add(nz);
			}

aber… das macht ja so keinen Sinn: Die Normalen müssen ja den Vertices entsprechen, aus denen das Face besteht, und nicht einfach Hintereinandergehängt werden. Das könnte so gelöst werden, dass man den Normal-Buffer mit der benötigten Anzahl 0.0en auffüllt/initialisiert, und dann anstelle dieser Schleife GROB sowas macht wie

int vertexIndex0 = face.getVertexIndex(0);
int vertexIndex1 = face.getVertexIndex(1);
int vertexIndex2 = face.getVertexIndex(2);
...
Vector3f faceNormal = ... // Hast du ja schon ausgerechnet

// Und dann
normals.set(vertexIndex0*3+0, faceNormal.x);
normals.set(vertexIndex0*3+1, faceNormal.y);
normals.set(vertexIndex0*3+2, faceNormal.z);

// (genauso für vertexIndex1 und 2)

Wie gesagt, GANZ grob, wenn’s nicht klappt schau’ ich nochmal.

Es hat sich dadurch verbessert, die Meisten Flächen sind richtig beleuchtet, aber es gibt auch ein bis zwei Flächen, die der Lichtquelle genau entgegen sind, die aber auch beleuchtet sind.

Es gibt im Fragment Shader sowas wie https://www.opengl.org/sdk/docs/man/html/gl_FrontFacing.xhtml - das kann man abfragen, GROB im Sinne von

if (gl_FrontFacing) {
    // fragment receives the computed color
} else {
    // fragment is "black"
}

wobei man das “black” natürlich noch weiter ausdifferenzieren könne/sollte. Vermutlich kann @Fancy da noch genaueres dazu sagen (und zu Backface Culling allgemein)

also das hier funktioniert wie es soll:

#version 150

in vec3 fVertex;
in vec3 fNormal;

struct Light {
	vec4 position;
	vec3 color;
	vec3 ambient;
	float attenuation;
};

const int MAX_LIGHTS = 100;

uniform mat4 model;
uniform int lightCount;
uniform Light lights[MAX_LIGHTS];

vec3 calculateLight(Light light, vec3 fragmentColor, vec3 normal, vec3 fragmentPosition){
	vec3 rayDirection;
	float finalAttenuation;	
	if(light.position.w == 0.0){ //directional light
		rayDirection = normalize(light.position.xyz);
		finalAttenuation = 1.0;
	}
	else { //point light
		rayDirection = normalize(light.position.xyz - fragmentPosition);
		
		//calculate attenuation
		float distanceToLight = length(light.position.xyz - fragmentPosition);
		finalAttenuation = 1.0 / (1.0 + light.attenuation * pow(distanceToLight, 2));
	}
	
	//calculate ambient
	vec3 finalAmbient = light.ambient * light.color * fragmentColor;
	
	//diffuse
	float diffuseIntense = max(0, dot(normal, rayDirection));	
	vec3 finalDiffuse = diffuseIntense * fragmentColor * light.color;
	
	//calculate final color
	return finalAmbient + finalAttenuation * finalDiffuse;
}

vec4 getLightColor(vec4 texColor){
	vec3 colorSum = vec3(0);
	vec3 normal = normalize(transpose(inverse(mat3(model))) * fNormal);
	vec3 fragmentPosition = vec3(model * vec4(fVertex, 1));
	for(int i = 0; i < lightCount; i++){
		colorSum += calculateLight(lights**, texColor.rgb, normal, fragmentPosition);
	}
	return vec4(colorSum, texColor.a);	
}```

ich verstehe deinen shader nicht so ganz. wieso nimmst du das skalarprodukt von surface to camera und reflection vector?
du brauchst ja eigentlich, siehe shader oben, das skalar produkt von der normale und dem licht - strahl.


aber folgendes:
das hier:

if(attenuationAllowed == 1){
attenuation = 1.0 / (1.0 + pow(length(surfaceToLight), 2f));
}else{
attenuation = 1;
}


schreibst du mal besser als:

```attenuation = 1 + attenuationAllowed * (1.0 / (1.0 + pow(length(surfaceToLight), 2f)) - 1);```

einfach weil verzweigungen einen shader immer enorm verlangsamen..

@Marco13 : Zumindest oben hat er das Backface Culling an. Ich glaube er hat Dreiecke die leuchten, obwohl sie von der Lichtquelle abgewandt sind. Ich hab den Code nicht nachvollzogen, vielleicht kommt bei einigen Dreiecken die Orientierung bei der Berechnung der Normale durcheinander, so das die Normale in die falsche Richtung zeigt.

Den Shader hab ich auch nicht nachvollzogen. Ich persönlich würde mit einem einfachen Punktlicht anfangen.

KSKB, Würfel mit gegebenen Normalen:



import static org.lwjgl.glfw.Callbacks.errorCallbackPrint;
import static org.lwjgl.glfw.GLFW.GLFW_CONTEXT_VERSION_MAJOR;
import static org.lwjgl.glfw.GLFW.GLFW_CONTEXT_VERSION_MINOR;
import static org.lwjgl.glfw.GLFW.GLFW_KEY_ESCAPE;
import static org.lwjgl.glfw.GLFW.GLFW_OPENGL_CORE_PROFILE;
import static org.lwjgl.glfw.GLFW.GLFW_OPENGL_PROFILE;
import static org.lwjgl.glfw.GLFW.GLFW_RELEASE;
import static org.lwjgl.glfw.GLFW.GLFW_RESIZABLE;
import static org.lwjgl.glfw.GLFW.GLFW_VISIBLE;
import static org.lwjgl.glfw.GLFW.glfwCreateWindow;
import static org.lwjgl.glfw.GLFW.glfwDefaultWindowHints;
import static org.lwjgl.glfw.GLFW.glfwDestroyWindow;
import static org.lwjgl.glfw.GLFW.glfwGetPrimaryMonitor;
import static org.lwjgl.glfw.GLFW.glfwGetVideoMode;
import static org.lwjgl.glfw.GLFW.glfwInit;
import static org.lwjgl.glfw.GLFW.glfwMakeContextCurrent;
import static org.lwjgl.glfw.GLFW.glfwPollEvents;
import static org.lwjgl.glfw.GLFW.glfwSetErrorCallback;
import static org.lwjgl.glfw.GLFW.glfwSetKeyCallback;
import static org.lwjgl.glfw.GLFW.glfwSetWindowPos;
import static org.lwjgl.glfw.GLFW.glfwSetWindowShouldClose;
import static org.lwjgl.glfw.GLFW.glfwShowWindow;
import static org.lwjgl.glfw.GLFW.glfwSwapBuffers;
import static org.lwjgl.glfw.GLFW.glfwSwapInterval;
import static org.lwjgl.glfw.GLFW.glfwTerminate;
import static org.lwjgl.glfw.GLFW.glfwWindowHint;
import static org.lwjgl.glfw.GLFW.glfwWindowShouldClose;
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_CULL_FACE;
import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_DEPTH_TEST;
import static org.lwjgl.opengl.GL11.GL_FALSE;
import static org.lwjgl.opengl.GL11.GL_FLOAT;
import static org.lwjgl.opengl.GL11.GL_TRIANGLE_STRIP;
import static org.lwjgl.opengl.GL11.GL_TRUE;
import static org.lwjgl.opengl.GL11.GL_UNSIGNED_SHORT;
import static org.lwjgl.opengl.GL11.glClear;
import static org.lwjgl.opengl.GL11.glDrawElements;
import static org.lwjgl.opengl.GL11.glEnable;
import static org.lwjgl.opengl.GL15.GL_ARRAY_BUFFER;
import static org.lwjgl.opengl.GL15.GL_ELEMENT_ARRAY_BUFFER;
import static org.lwjgl.opengl.GL15.GL_STATIC_DRAW;
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.GL20.GL_COMPILE_STATUS;
import static org.lwjgl.opengl.GL20.GL_FRAGMENT_SHADER;
import static org.lwjgl.opengl.GL20.GL_INFO_LOG_LENGTH;
import static org.lwjgl.opengl.GL20.GL_LINK_STATUS;
import static org.lwjgl.opengl.GL20.GL_VERTEX_SHADER;
import static org.lwjgl.opengl.GL20.glAttachShader;
import static org.lwjgl.opengl.GL20.glCompileShader;
import static org.lwjgl.opengl.GL20.glCreateProgram;
import static org.lwjgl.opengl.GL20.glCreateShader;
import static org.lwjgl.opengl.GL20.glDeleteProgram;
import static org.lwjgl.opengl.GL20.glDeleteShader;
import static org.lwjgl.opengl.GL20.glEnableVertexAttribArray;
import static org.lwjgl.opengl.GL20.glGetProgramInfoLog;
import static org.lwjgl.opengl.GL20.glGetProgrami;
import static org.lwjgl.opengl.GL20.glGetShaderInfoLog;
import static org.lwjgl.opengl.GL20.glGetShaderi;
import static org.lwjgl.opengl.GL20.glLinkProgram;
import static org.lwjgl.opengl.GL20.glShaderSource;
import static org.lwjgl.opengl.GL20.glUseProgram;
import static org.lwjgl.opengl.GL20.glVertexAttribPointer;
import static org.lwjgl.opengl.GL30.glBindBufferRange;
import static org.lwjgl.opengl.GL30.glBindVertexArray;
import static org.lwjgl.opengl.GL30.glDeleteVertexArrays;
import static org.lwjgl.opengl.GL30.glGenVertexArrays;
import static org.lwjgl.opengl.GL31.GL_PRIMITIVE_RESTART;
import static org.lwjgl.opengl.GL31.GL_UNIFORM_BUFFER;
import static org.lwjgl.opengl.GL31.glGetUniformBlockIndex;
import static org.lwjgl.opengl.GL31.glPrimitiveRestartIndex;
import static org.lwjgl.opengl.GL31.glUniformBlockBinding;
import static org.lwjgl.system.MemoryUtil.NULL;

import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWKeyCallback;
import org.lwjgl.glfw.GLFWvidmode;
import org.lwjgl.opengl.GLContext;


public final class GL33Light implements Runnable {

    private static final int WIDTH = 1200;
    private static final int HEIGHT = 800;

    private static final int GL_MAJOR_VERSION = 3;
    private static final int GL_MINOR_VERSION = 3;

    private static final int VERTEX_LOCATION = 0;
    private static final int NORMAL_LOCATION = 1;
    private static final int MVP_UNIFORM_BLOCK_LOCATION = 0;
    private static final int LIGHT_UNIFORM_BLOCK_LOCATION = 1;

    private static final String VERTEX_SHADER = ""

            + "#version 330 core                                                 
"
            + "                                                                  
"
            + "layout(std140) uniform MVP {                                      
"
            + "    mat4 projection;                                              
"
            + "    mat4 modelview;                                               
"
            + "    mat3 normal;                                                  
"
            + "    mat4 mvp;                                                     
"
            + "};                                                                
"
            + "                                                                  
"
            + "layout(std140) uniform Light {                                    
"
            + "    vec4 ambient;                                                 
"
            + "    vec4 diffuse;                                                 
"
            + "    vec4 specular;                                                
"
            + "    vec4 position;                                                
"
            + "};                                                                
"
            + "                                                                  
"
            + "layout(location = " + VERTEX_LOCATION + ") in vec4 v;             
"
            + "layout(location = " + NORMAL_LOCATION + ") in vec3 vn;            
"
            + "                                                                  
"
            + "out vec3 fv;                                                      
"
            + "out vec3 fl;                                                      
"
            + "out vec3 fn;                                                      
"
            + "                                                                  
"
            + "void main() {                                                     
"
            + "                                                                  
"
            + "    fv = vec3(modelview * v);                                     
"
            + "    fl = normalize(position.xyz - fv);                            
"
            + "    fn = normalize(normal * vn);                                  
"
            + "                                                                  
"
            + "    gl_Position = mvp * v;                                        
"
            + "                                                                  
"
            + "}                                                                 
";

    private static final String FRAGMENT_SHADER = ""

            + "#version 330 core                                                 
"
            + "                                                                  
"
            + "layout(std140) uniform Light {                                    
"
            + "    vec4 ambient;                                                 
"
            + "    vec4 diffuse;                                                 
"
            + "    vec4 specular;                                                
"
            + "    vec4 position;                                                
"
            + "};                                                                
"
            + "                                                                  
"
            + "in vec3 fl;                                                       
"
            + "in vec3 fv;                                                       
"
            + "in vec3 fn;                                                       
"
            + "                                                                  
"
            + "out vec4 color;                                                   
"
            + "                                                                  
"
            + "void main() {                                                     
"
            + "                                                                  
"
            + "    vec3 l = normalize(fl);                                       
"
            + "    vec3 n = normalize(fn);                                       
"
            + "    vec3 e = normalize(-fv);                                      
"
            + "    vec3 r = normalize(reflect(-l, fn));                          
"
            + "                                                                  
"
            + "    color = ambient;                                              
"
            + "    color += diffuse * max(dot(n, l), 0.0);                       
"
            + "    color += specular * pow(max(dot(r, e), 0.0), 5);              
"
            + "                                                                  
"
            + "}                                                                 
";

    private static final float[] AMBIENT = new float[] { 0.1f, 0.1f, 0.1f, 0 };
    private static final float[] DIFFUSE = new float[] { 1.0f, 1.0f, 1.0f, 0 };
    private static final float[] SPECULAR = new float[] { 0.4f, 0.3f, 0.3f, 0 };
    private static final float[] POSITION = new float[] { 0, 2, -7, 1 };

    private static final short RESTART = (short) 0xFFFF;

    private static final short[] CUBE_IBO = new short[] {

            0, 1, 2, 3, RESTART,
            4, 5, 6, 7, RESTART,
            8, 9, 10, 11, RESTART,
            12, 13, 14, 15, RESTART,
            16, 17, 18, 19, RESTART,
            20, 21, 22, 23

    };

    // x, y, z, nx, ny, nz
    private static final float[] CUBE_VBO = new float[] {

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

            -1.0f, +1.0f, +1.0f, +0.0f, +1.0f, +0.0f,
            +1.0f, +1.0f, +1.0f, +0.0f, +1.0f, +0.0f,
            -1.0f, +1.0f, -1.0f, +0.0f, +1.0f, +0.0f,
            +1.0f, +1.0f, -1.0f, +0.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, +1.0f,
            -1.0f, -1.0f, +1.0f, +0.0f, +0.0f, +1.0f,
            -1.0f, +1.0f, +1.0f, +0.0f, +0.0f, +1.0f,

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

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

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

    };

    private final FloatBuffer mvpBuffer = BufferUtils.createFloatBuffer(16 + 16 + 12 + 16);
    private final FloatBuffer lightBuffer = BufferUtils.createFloatBuffer(4 + 4 + 4 + 4);

    private GLFWErrorCallback errorCallback;
    private GLFWKeyCallback keyCallback;

    private long windowHandle;

    private int vaoHandle;
    private int iboHandle;
    private int vboHandle;
    private int mvpHandle;
    private int lightHandle;
    private int programHandle;

    private float angle;


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

        new GL33Light().run();

    }


    @Override
    public void run() {

        try {

            initGLFW();
            initGL();

            loop();

            disposeGL();
            releaseGLFW();

        } finally {

            terminateGLFW();

        }

    }


    private void initGLFW() {

        errorCallback = errorCallbackPrint(System.err);
        glfwSetErrorCallback(errorCallback);

        if (glfwInit() != GL_TRUE)
            throw new IllegalStateException("Unable to initialize GLFW");

        glfwDefaultWindowHints();
        glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
        glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, GL_MAJOR_VERSION);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, GL_MINOR_VERSION);

        windowHandle = glfwCreateWindow(WIDTH, HEIGHT, getClass().getName(), NULL, NULL);
        if (windowHandle == NULL)
            throw new RuntimeException("Failed to create the GLFW window");

        keyCallback = new GLFWKeyCallback() {

            @Override
            public void invoke(final long window, final int key, final int scancode, final int action, final int mods) {

                if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE)
                    glfwSetWindowShouldClose(window, GL_TRUE);

            }

        };
        glfwSetKeyCallback(windowHandle, keyCallback);

        final ByteBuffer videoMode = glfwGetVideoMode(glfwGetPrimaryMonitor());
        glfwSetWindowPos(windowHandle, (GLFWvidmode.width(videoMode) - WIDTH) / 2, (GLFWvidmode.height(videoMode) - HEIGHT) / 2);

        glfwMakeContextCurrent(windowHandle);
        glfwSwapInterval(1);
        glfwShowWindow(windowHandle);

    }


    private void initGL() {

        GLContext.createFromCurrent();

        glEnable(GL_DEPTH_TEST);
        glEnable(GL_CULL_FACE);

        glEnable(GL_PRIMITIVE_RESTART);
        glPrimitiveRestartIndex(0xFFFF & RESTART);

        initVAO();
        initIBO();
        initVBO();
        initMVP();
        initLight();
        initShader();

    }


    private void initVAO() {

        vaoHandle = glGenVertexArrays();
        glBindVertexArray(vaoHandle);

    }


    private void initIBO() {

        final ShortBuffer buffer = BufferUtils.createShortBuffer(CUBE_IBO.length);
        buffer.put(CUBE_IBO);
        buffer.flip();

        iboHandle = glGenBuffers();
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboHandle);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, buffer, GL_STATIC_DRAW);

    }


    private void initVBO() {

        final FloatBuffer buffer = BufferUtils.createFloatBuffer(CUBE_VBO.length);
        buffer.put(CUBE_VBO);
        buffer.flip();

        vboHandle = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vboHandle);
        glBufferData(GL_ARRAY_BUFFER, buffer, GL_STATIC_DRAW);

        glEnableVertexAttribArray(VERTEX_LOCATION);
        glVertexAttribPointer(VERTEX_LOCATION, 3, GL_FLOAT, false, 6 * Float.BYTES, 0);

        glEnableVertexAttribArray(NORMAL_LOCATION);
        glVertexAttribPointer(NORMAL_LOCATION, 3, GL_FLOAT, false, 6 * Float.BYTES, 3 * Float.BYTES);

    }


    private void initMVP() {

        mvpHandle = glGenBuffers();
        glBindBuffer(GL_UNIFORM_BUFFER, mvpHandle);
        glBufferData(GL_UNIFORM_BUFFER, mvpBuffer.capacity() * Float.BYTES, GL_STREAM_DRAW);
        glBindBufferRange(GL_UNIFORM_BUFFER, MVP_UNIFORM_BLOCK_LOCATION, mvpHandle, 0, mvpBuffer.capacity() * Float.BYTES);

    }


    private void initLight() {

        lightHandle = glGenBuffers();
        glBindBuffer(GL_UNIFORM_BUFFER, lightHandle);
        glBufferData(GL_UNIFORM_BUFFER, lightBuffer.capacity() * Float.BYTES, GL_STREAM_DRAW);
        glBindBufferRange(GL_UNIFORM_BUFFER, LIGHT_UNIFORM_BLOCK_LOCATION, lightHandle, 0, lightBuffer.capacity() * Float.BYTES);

    }


    private void initShader() {

        final int vs = buildShader(GL_VERTEX_SHADER, VERTEX_SHADER);
        final int fs = buildShader(GL_FRAGMENT_SHADER, FRAGMENT_SHADER);

        programHandle = buildProgram(vs, fs);

        glDeleteShader(vs);
        glDeleteShader(fs);

        glUseProgram(programHandle);

        final int mvpUniformBlockIndex = glGetUniformBlockIndex(programHandle, "MVP");
        glUniformBlockBinding(programHandle, mvpUniformBlockIndex, MVP_UNIFORM_BLOCK_LOCATION);

        final int lightUniformBlockIndex = glGetUniformBlockIndex(programHandle, "Light");
        glUniformBlockBinding(programHandle, lightUniformBlockIndex, LIGHT_UNIFORM_BLOCK_LOCATION);

    }


    private int buildShader(final int type, final String source) {

        final int handle = glCreateShader(type);

        glShaderSource(handle, source);
        glCompileShader(handle);

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

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

            throw new RuntimeException(log);

        }

        return handle;

    }


    private int buildProgram(final int... shaders) {

        final int handle = glCreateProgram();

        for (final int shader : shaders)
            glAttachShader(handle, shader);

        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(log);

        }

        return handle;

    }


    private 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;

    }


    private float[] 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 m;

    }


    private float[] 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 m;

    }


    private float[] multiplication(final float[] m, final float[] o) {

        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 result;

    }


    // no non uniform scaling allowed
    private float[] normalmatrix(final float[] m) {

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

        result[0] = m[0];
        result[1] = m[1];
        result[2] = m[2];
        result[4] = m[4];
        result[5] = m[5];
        result[6] = m[6];
        result[8] = m[8];
        result[9] = m[9];
        result[10] = m[10];

        return result;

    }


    private void loop() {

        while (glfwWindowShouldClose(windowHandle) == GL_FALSE) {

            angle += 0.0005f;

            final float[] projection = projection(45, (float) WIDTH / (float) HEIGHT, 0.1f, 1000f);
            final float[] translate = translate(0, 0, -10);
            final float[] rotate = rotate(0.2f, 0.3f, -1, angle);
            final float[] modelview = multiplication(translate, rotate);
            final float[] normal = normalmatrix(modelview);
            final float[] mvp = multiplication(projection, modelview);

            mvpBuffer.put(projection);
            mvpBuffer.put(modelview);
            mvpBuffer.put(normal);
            mvpBuffer.put(mvp);
            mvpBuffer.rewind();

            glBindBuffer(GL_UNIFORM_BUFFER, mvpHandle);
            glBufferSubData(GL_UNIFORM_BUFFER, 0, mvpBuffer);

            lightBuffer.put(AMBIENT);
            lightBuffer.put(DIFFUSE);
            lightBuffer.put(SPECULAR);
            lightBuffer.put(POSITION);
            lightBuffer.rewind();

            glBindBuffer(GL_UNIFORM_BUFFER, lightHandle);
            glBufferSubData(GL_UNIFORM_BUFFER, 0, lightBuffer);

            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

            glDrawElements(GL_TRIANGLE_STRIP, CUBE_IBO.length, GL_UNSIGNED_SHORT, 0);

            glfwSwapBuffers(windowHandle);
            glfwPollEvents();

        }

    }


    private void disposeGL() {

        glDeleteProgram(programHandle);
        glDeleteBuffers(lightHandle);
        glDeleteBuffers(mvpHandle);
        glDeleteBuffers(vboHandle);
        glDeleteBuffers(iboHandle);
        glDeleteVertexArrays(vaoHandle);

    }


    private void releaseGLFW() {

        glfwDestroyWindow(windowHandle);
        keyCallback.release();

    }


    private void terminateGLFW() {

        glfwTerminate();
        errorCallback.release();

    }


}

Pffff: The text that you have entered is too long (50137 characters). Please shorten it to 35000 characters long.

Next post in 3, 2, 1, …

Hier muss was stehen, damit ich wieder Posten darf.

Gruß
Fancy

KSKB, Würfel mit berechneten Normalen:



import static org.lwjgl.glfw.Callbacks.errorCallbackPrint;
import static org.lwjgl.glfw.GLFW.GLFW_CONTEXT_VERSION_MAJOR;
import static org.lwjgl.glfw.GLFW.GLFW_CONTEXT_VERSION_MINOR;
import static org.lwjgl.glfw.GLFW.GLFW_KEY_ESCAPE;
import static org.lwjgl.glfw.GLFW.GLFW_OPENGL_CORE_PROFILE;
import static org.lwjgl.glfw.GLFW.GLFW_OPENGL_PROFILE;
import static org.lwjgl.glfw.GLFW.GLFW_RELEASE;
import static org.lwjgl.glfw.GLFW.GLFW_RESIZABLE;
import static org.lwjgl.glfw.GLFW.GLFW_VISIBLE;
import static org.lwjgl.glfw.GLFW.glfwCreateWindow;
import static org.lwjgl.glfw.GLFW.glfwDefaultWindowHints;
import static org.lwjgl.glfw.GLFW.glfwDestroyWindow;
import static org.lwjgl.glfw.GLFW.glfwGetPrimaryMonitor;
import static org.lwjgl.glfw.GLFW.glfwGetVideoMode;
import static org.lwjgl.glfw.GLFW.glfwInit;
import static org.lwjgl.glfw.GLFW.glfwMakeContextCurrent;
import static org.lwjgl.glfw.GLFW.glfwPollEvents;
import static org.lwjgl.glfw.GLFW.glfwSetErrorCallback;
import static org.lwjgl.glfw.GLFW.glfwSetKeyCallback;
import static org.lwjgl.glfw.GLFW.glfwSetWindowPos;
import static org.lwjgl.glfw.GLFW.glfwSetWindowShouldClose;
import static org.lwjgl.glfw.GLFW.glfwShowWindow;
import static org.lwjgl.glfw.GLFW.glfwSwapBuffers;
import static org.lwjgl.glfw.GLFW.glfwSwapInterval;
import static org.lwjgl.glfw.GLFW.glfwTerminate;
import static org.lwjgl.glfw.GLFW.glfwWindowHint;
import static org.lwjgl.glfw.GLFW.glfwWindowShouldClose;
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_CULL_FACE;
import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_DEPTH_TEST;
import static org.lwjgl.opengl.GL11.GL_FALSE;
import static org.lwjgl.opengl.GL11.GL_FLOAT;
import static org.lwjgl.opengl.GL11.GL_TRIANGLE_STRIP;
import static org.lwjgl.opengl.GL11.GL_TRUE;
import static org.lwjgl.opengl.GL11.GL_UNSIGNED_SHORT;
import static org.lwjgl.opengl.GL11.glClear;
import static org.lwjgl.opengl.GL11.glDrawElements;
import static org.lwjgl.opengl.GL11.glEnable;
import static org.lwjgl.opengl.GL15.GL_ARRAY_BUFFER;
import static org.lwjgl.opengl.GL15.GL_ELEMENT_ARRAY_BUFFER;
import static org.lwjgl.opengl.GL15.GL_STATIC_DRAW;
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.GL20.GL_COMPILE_STATUS;
import static org.lwjgl.opengl.GL20.GL_FRAGMENT_SHADER;
import static org.lwjgl.opengl.GL20.GL_INFO_LOG_LENGTH;
import static org.lwjgl.opengl.GL20.GL_LINK_STATUS;
import static org.lwjgl.opengl.GL20.GL_VERTEX_SHADER;
import static org.lwjgl.opengl.GL20.glAttachShader;
import static org.lwjgl.opengl.GL20.glCompileShader;
import static org.lwjgl.opengl.GL20.glCreateProgram;
import static org.lwjgl.opengl.GL20.glCreateShader;
import static org.lwjgl.opengl.GL20.glDeleteProgram;
import static org.lwjgl.opengl.GL20.glDeleteShader;
import static org.lwjgl.opengl.GL20.glEnableVertexAttribArray;
import static org.lwjgl.opengl.GL20.glGetProgramInfoLog;
import static org.lwjgl.opengl.GL20.glGetProgrami;
import static org.lwjgl.opengl.GL20.glGetShaderInfoLog;
import static org.lwjgl.opengl.GL20.glGetShaderi;
import static org.lwjgl.opengl.GL20.glLinkProgram;
import static org.lwjgl.opengl.GL20.glShaderSource;
import static org.lwjgl.opengl.GL20.glUseProgram;
import static org.lwjgl.opengl.GL20.glVertexAttribPointer;
import static org.lwjgl.opengl.GL30.glBindBufferRange;
import static org.lwjgl.opengl.GL30.glBindVertexArray;
import static org.lwjgl.opengl.GL30.glDeleteVertexArrays;
import static org.lwjgl.opengl.GL30.glGenVertexArrays;
import static org.lwjgl.opengl.GL31.GL_PRIMITIVE_RESTART;
import static org.lwjgl.opengl.GL31.GL_UNIFORM_BUFFER;
import static org.lwjgl.opengl.GL31.glGetUniformBlockIndex;
import static org.lwjgl.opengl.GL31.glPrimitiveRestartIndex;
import static org.lwjgl.opengl.GL31.glUniformBlockBinding;
import static org.lwjgl.opengl.GL32.GL_GEOMETRY_SHADER;
import static org.lwjgl.system.MemoryUtil.NULL;

import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWKeyCallback;
import org.lwjgl.glfw.GLFWvidmode;
import org.lwjgl.opengl.GLContext;


public final class GL33Normals implements Runnable {

    private static final int WIDTH = 1200;
    private static final int HEIGHT = 800;

    private static final int GL_MAJOR_VERSION = 3;
    private static final int GL_MINOR_VERSION = 3;

    private static final int VERTEX_LOCATION = 0;
    private static final int MVP_UNIFORM_BLOCK_LOCATION = 0;
    private static final int LIGHT_UNIFORM_BLOCK_LOCATION = 1;

    private static final String VERTEX_SHADER = ""

            + "#version 330 core                                                 
"
            + "                                                                  
"
            + "layout(std140) uniform MVP {                                      
"
            + "    mat4 projection;                                              
"
            + "    mat4 modelview;                                               
"
            + "    mat4 mvp;                                                     
"
            + "};                                                                
"
            + "                                                                  
"
            + "layout(std140) uniform Light {                                    
"
            + "    vec4 ambient;                                                 
"
            + "    vec4 diffuse;                                                 
"
            + "    vec4 specular;                                                
"
            + "    vec4 position;                                                
"
            + "};                                                                
"
            + "                                                                  
"
            + "layout(location = " + VERTEX_LOCATION + ") in vec4 v;             
"
            + "                                                                  
"
            + "out vec3 gv;                                                      
"
            + "out vec3 gl;                                                      
"
            + "                                                                  
"
            + "void main() {                                                     
"
            + "                                                                  
"
            + "    gv = vec3(modelview * v);                                     
"
            + "    gl = normalize(position.xyz - gv);                            
"
            + "                                                                  
"
            + "}                                                                 
";

    private static final String GEOMETRY_SHADER = ""

            + "#version 330 core                                                 
"
            + "                                                                  
"
            + "layout(std140) uniform MVP {                                      
"
            + "    mat4 projection;                                              
"
            + "    mat4 modelview;                                               
"
            + "    mat4 mvp;                                                     
"
            + "};                                                                
"
            + "                                                                  
"
            + "layout(std140) uniform Light {                                    
"
            + "    vec4 ambient;                                                 
"
            + "    vec4 diffuse;                                                 
"
            + "    vec4 specular;                                                
"
            + "    vec4 position;                                                
"
            + "};                                                                
"
            + "                                                                  
"
            + "layout(triangles) in;                                             
"
            + "layout(triangle_strip, max_vertices=3) out;                       
"
            + "                                                                  
"
            + "in vec3 gv[3];                                                    
"
            + "in vec3 gl[3];                                                    
"
            + "                                                                  
"
            + "out vec3 fv;                                                      
"
            + "out vec3 fl;                                                      
"
            + "out vec3 fn;                                                      
"
            + "                                                                  
"
            + "void main() {                                                     
"
            + "                                                                  
"
            + "    fn = normalize(cross((gv[1] - gv[0]), (gv[2] - gv[0])));      
"
            + "                                                                  
"
            + "    for(int i = 0; i < 3; i++) {                                  
"
            + "        fv = gv**;                                               
"
            + "        fl = gl**;                                               
"
            + "        gl_Position = projection * vec4(gv**, 1);                
"
            + "        EmitVertex();                                             
"
            + "     }                                                            
"
            + "                                                                  
"
            + "    EndPrimitive();                                               
"
            + "                                                                  
"
            + "}                                                                 
";

    private static final String FRAGMENT_SHADER = ""

            + "#version 330 core                                                 
"
            + "                                                                  
"
            + "layout(std140) uniform Light {                                    
"
            + "    vec4 ambient;                                                 
"
            + "    vec4 diffuse;                                                 
"
            + "    vec4 specular;                                                
"
            + "    vec4 position;                                                
"
            + "};                                                                
"
            + "                                                                  
"
            + "in vec3 fl;                                                       
"
            + "in vec3 fv;                                                       
"
            + "in vec3 fn;                                                       
"
            + "                                                                  
"
            + "out vec4 color;                                                   
"
            + "                                                                  
"
            + "void main() {                                                     
"
            + "                                                                  
"
            + "    vec3 l = normalize(fl);                                       
"
            + "    vec3 n = normalize(fn);                                       
"
            + "    vec3 e = normalize(-fv);                                      
"
            + "    vec3 r = normalize(reflect(-l, fn));                          
"
            + "                                                                  
"
            + "    color = ambient;                                              
"
            + "    color += diffuse * max(dot(n, l), 0.0);                       
"
            + "    color += specular * pow(max(dot(r, e), 0.0), 5);              
"
            + "                                                                  
"
            + "}                                                                 
";

    private static final float[] AMBIENT = new float[] { 0.1f, 0.1f, 0.1f, 0 };
    private static final float[] DIFFUSE = new float[] { 1.0f, 1.0f, 1.0f, 0 };
    private static final float[] SPECULAR = new float[] { 0.4f, 0.3f, 0.3f, 0 };
    private static final float[] POSITION = new float[] { 0, 2, -7, 1 };

    private static final short RESTART = (short) 0xFFFF;

    private static final short[] CUBE_IBO = new short[] {

            0, 1, 2, 3, RESTART,
            4, 5, 6, 7, RESTART,
            1, 5, 3, 4, RESTART,
            7, 0, 6, 2, RESTART,
            0, 7, 1, 5, RESTART,
            6, 2, 4, 3

    };

    // x, y, z,
    private static final float[] CUBE_VBO = new float[] {

            -1.0f, +1.0f, -1.0f,
            +1.0f, +1.0f, -1.0f,
            -1.0f, -1.0f, -1.0f,
            +1.0f, -1.0f, -1.0f,

            +1.0f, -1.0f, +1.0f,
            +1.0f, +1.0f, +1.0f,
            -1.0f, -1.0f, +1.0f,
            -1.0f, +1.0f, +1.0f,

    };

    private final FloatBuffer mvpBuffer = BufferUtils.createFloatBuffer(16 + 16 + 16);
    private final FloatBuffer lightBuffer = BufferUtils.createFloatBuffer(4 + 4 + 4 + 4);

    private GLFWErrorCallback errorCallback;
    private GLFWKeyCallback keyCallback;

    private long windowHandle;

    private int vaoHandle;
    private int iboHandle;
    private int vboHandle;
    private int mvpHandle;
    private int lightHandle;
    private int programHandle;

    private float angle;


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

        new GL33Normals().run();

    }


    @Override
    public void run() {

        try {

            initGLFW();
            initGL();

            loop();

            disposeGL();
            releaseGLFW();

        } finally {

            terminateGLFW();

        }

    }


    private void initGLFW() {

        errorCallback = errorCallbackPrint(System.err);
        glfwSetErrorCallback(errorCallback);

        if (glfwInit() != GL_TRUE)
            throw new IllegalStateException("Unable to initialize GLFW");

        glfwDefaultWindowHints();
        glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
        glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, GL_MAJOR_VERSION);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, GL_MINOR_VERSION);

        windowHandle = glfwCreateWindow(WIDTH, HEIGHT, getClass().getName(), NULL, NULL);
        if (windowHandle == NULL)
            throw new RuntimeException("Failed to create the GLFW window");

        keyCallback = new GLFWKeyCallback() {

            @Override
            public void invoke(final long window, final int key, final int scancode, final int action, final int mods) {

                if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE)
                    glfwSetWindowShouldClose(window, GL_TRUE);

            }

        };
        glfwSetKeyCallback(windowHandle, keyCallback);

        final ByteBuffer videoMode = glfwGetVideoMode(glfwGetPrimaryMonitor());
        glfwSetWindowPos(windowHandle, (GLFWvidmode.width(videoMode) - WIDTH) / 2, (GLFWvidmode.height(videoMode) - HEIGHT) / 2);

        glfwMakeContextCurrent(windowHandle);
        glfwSwapInterval(1);
        glfwShowWindow(windowHandle);

    }


    private void initGL() {

        GLContext.createFromCurrent();

        glEnable(GL_DEPTH_TEST);
        glEnable(GL_CULL_FACE);

        glEnable(GL_PRIMITIVE_RESTART);
        glPrimitiveRestartIndex(0xFFFF & RESTART);

        initVAO();
        initIBO();
        initVBO();
        initMVP();
        initLight();
        initShader();

    }


    private void initVAO() {

        vaoHandle = glGenVertexArrays();
        glBindVertexArray(vaoHandle);

    }


    private void initIBO() {

        final ShortBuffer buffer = BufferUtils.createShortBuffer(CUBE_IBO.length);
        buffer.put(CUBE_IBO);
        buffer.flip();

        iboHandle = glGenBuffers();
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboHandle);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, buffer, GL_STATIC_DRAW);

    }


    private void initVBO() {

        final FloatBuffer buffer = BufferUtils.createFloatBuffer(CUBE_VBO.length);
        buffer.put(CUBE_VBO);
        buffer.flip();

        vboHandle = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vboHandle);
        glBufferData(GL_ARRAY_BUFFER, buffer, GL_STATIC_DRAW);

        glEnableVertexAttribArray(VERTEX_LOCATION);
        glVertexAttribPointer(VERTEX_LOCATION, 3, GL_FLOAT, false, 3 * Float.BYTES, 0);

    }


    private void initMVP() {

        mvpHandle = glGenBuffers();
        glBindBuffer(GL_UNIFORM_BUFFER, mvpHandle);
        glBufferData(GL_UNIFORM_BUFFER, mvpBuffer.capacity() * Float.BYTES, GL_STREAM_DRAW);
        glBindBufferRange(GL_UNIFORM_BUFFER, MVP_UNIFORM_BLOCK_LOCATION, mvpHandle, 0, mvpBuffer.capacity() * Float.BYTES);

    }


    private void initLight() {

        lightHandle = glGenBuffers();
        glBindBuffer(GL_UNIFORM_BUFFER, lightHandle);
        glBufferData(GL_UNIFORM_BUFFER, lightBuffer.capacity() * Float.BYTES, GL_STREAM_DRAW);
        glBindBufferRange(GL_UNIFORM_BUFFER, LIGHT_UNIFORM_BLOCK_LOCATION, lightHandle, 0, lightBuffer.capacity() * Float.BYTES);

    }


    private void initShader() {

        final int vs = buildShader(GL_VERTEX_SHADER, VERTEX_SHADER);
        final int gs = buildShader(GL_GEOMETRY_SHADER, GEOMETRY_SHADER);
        final int fs = buildShader(GL_FRAGMENT_SHADER, FRAGMENT_SHADER);

        programHandle = buildProgram(vs, gs, fs);

        glDeleteShader(vs);
        glDeleteShader(fs);

        glUseProgram(programHandle);

        final int mvpUniformBlockIndex = glGetUniformBlockIndex(programHandle, "MVP");
        glUniformBlockBinding(programHandle, mvpUniformBlockIndex, MVP_UNIFORM_BLOCK_LOCATION);

        final int lightUniformBlockIndex = glGetUniformBlockIndex(programHandle, "Light");
        glUniformBlockBinding(programHandle, lightUniformBlockIndex, LIGHT_UNIFORM_BLOCK_LOCATION);

    }


    private int buildShader(final int type, final String source) {

        final int handle = glCreateShader(type);

        glShaderSource(handle, source);
        glCompileShader(handle);

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

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

            throw new RuntimeException(log);

        }

        return handle;

    }


    private int buildProgram(final int... shaders) {

        final int handle = glCreateProgram();

        for (final int shader : shaders)
            glAttachShader(handle, shader);

        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(log);

        }

        return handle;

    }


    private 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;

    }


    private float[] 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 m;

    }


    private float[] 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 m;

    }


    private float[] multiplication(final float[] m, final float[] o) {

        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 result;

    }


    private void loop() {

        while (glfwWindowShouldClose(windowHandle) == GL_FALSE) {

            angle += 0.0005f;

            final float[] projection = projection(45, (float) WIDTH / (float) HEIGHT, 0.1f, 1000f);
            final float[] translate = translate(0, 0, -10);
            final float[] rotate = rotate(0.2f, 0.3f, -1, angle);
            final float[] modelview = multiplication(translate, rotate);
            final float[] mvp = multiplication(projection, modelview);

            mvpBuffer.put(projection);
            mvpBuffer.put(modelview);
            mvpBuffer.put(mvp);
            mvpBuffer.rewind();

            glBindBuffer(GL_UNIFORM_BUFFER, mvpHandle);
            glBufferSubData(GL_UNIFORM_BUFFER, 0, mvpBuffer);

            lightBuffer.put(AMBIENT);
            lightBuffer.put(DIFFUSE);
            lightBuffer.put(SPECULAR);
            lightBuffer.put(POSITION);
            lightBuffer.rewind();

            glBindBuffer(GL_UNIFORM_BUFFER, lightHandle);
            glBufferSubData(GL_UNIFORM_BUFFER, 0, lightBuffer);

            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

            glDrawElements(GL_TRIANGLE_STRIP, CUBE_IBO.length, GL_UNSIGNED_SHORT, 0);

            glfwSwapBuffers(windowHandle);
            glfwPollEvents();

        }

    }


    private void disposeGL() {

        glDeleteProgram(programHandle);
        glDeleteBuffers(lightHandle);
        glDeleteBuffers(mvpHandle);
        glDeleteBuffers(vboHandle);
        glDeleteBuffers(iboHandle);
        glDeleteVertexArrays(vaoHandle);

    }


    private void releaseGLFW() {

        glfwDestroyWindow(windowHandle);
        keyCallback.release();

    }


    private void terminateGLFW() {

        glfwTerminate();
        errorCallback.release();

    }


}

Gruß
Fancy

@mymaksimus Das mit der Reflektion ist für das “Specular” Licht, das ich angefangen, aber nicht ganz implementiert habe, weil ich gemerkt habe, dass die Flächen nicht richtig beleuchtet werden.
@Fancy Was ich eigentlich schon bei deinem letzten KSKB fragen wollte: Was ist denn das mit diesem GLFW, ich wollte einfach mal Copy und Paste in Eclipse reinmachen machen, damit der Code übersichtlicher wird, aber ich bekomme fast nur Fehler an diesen Stellen angezeigt.

GLFW gehört zu LWJGL 3 und ist dort die einzige Möglichkeit ein Fenster zu öffnen. Du benutzt noch LWJGL 2, die dortige Display Klasse und die AWT Integration gibt es bei LWJGL 3 nicht mehr. Ursprünglich war angedacht LWGL 3 um zusätzliche Klassen zu ergänzen um es Abwärtskompatibel zu LWJGL 2 zu machen. Imho wird nicht mehr daran gearbeitet. Imho wird auch nicht mehr an LWJGL 2 gearbeitet.

Gruß
Fancy

@mymaksimus Ich habe deinen Shader um das ergänzt:


void main(){
	gl_FragColor = getLightColor(texture(texture, TexCoord)); //Zeile 21
}

aber bekomme diese Fehlermeldung:
ERROR: 0:21: ‘getLightColor’ : no matching overloaded function found (using implicit conversion)

die main muss ans ende, wenn du das nicht willst musst du vorher die methoden prototypen angeben (weil c++ style…)
also so:

vec4 getLightColor(vec4);

Ja also wenn ich diesen Code übertrage ändert sich nichts, außer dass das Licht irgendwie kälter wirkt(keine Ahnung warum), also zeigen die Normalen für die falsch beleuchteten Flächen wirklich in die falsche Richtung, aber wie kann man das beheben?

hm. könntest du nochmal genau den code der für die normalenberechnung zuständig ist, posten?
keine lust zu wühlen, und das meiste hast du wahrscheinlich sowieso wieder geändert


public FloatBuffer calcNormals(){
		ArrayList<Float> normals = new ArrayList<Float>(); 
		for(int i = 0; i < vertexBuffer.capacity(); i++){
			normals.add(0.0f);
		}
		ArrayList<int[]> ipd = new ArrayList<int[]>();
		for(int i = 0; i < indexBuffer.capacity(); i += 3){
			int[] ind = {
					indexBuffer.get(i),indexBuffer.get(i+1),indexBuffer.get(i+2)
			};
			ipd.add(ind);
		}
		for(int d = 0; d < ipd.size(); d++){
			float nx = 0, ny = 0, nz = 0;
			ArrayList<Vector3f> coord_vectors = new ArrayList<Vector3f>();
			for(int i = 0; i < vertexBuffer.capacity(); i += 3){
				coord_vectors.add(new Vector3f(vertexBuffer.get(i), vertexBuffer.get(i+1), vertexBuffer.get(i+2)));
			}
			Vector3f U = new Vector3f();
			Vector3f.sub(coord_vectors.get(ipd.get(d)[1]), coord_vectors.get(ipd.get(d)[0]), U);
			Vector3f V = new Vector3f();
			Vector3f.sub(coord_vectors.get(ipd.get(d)[2]), coord_vectors.get(ipd.get(d)[0]), V);
			
			nx = U.y*V.z-U.z*V.y;
			ny = U.z*V.x-U.x*V.z;
			nz = U.x*V.y-U.y*V.x;
			
			normals.set(ipd.get(d)[0]*3+0, nx);
			normals.set(ipd.get(d)[0]*3+1, ny);
			normals.set(ipd.get(d)[0]*3+2, nz);
			
			normals.set(ipd.get(d)[1]*3+0, nx);
			normals.set(ipd.get(d)[1]*3+1, ny);
			normals.set(ipd.get(d)[1]*3+2, nz);
			
			normals.set(ipd.get(d)[2]*3+0, nx);
			normals.set(ipd.get(d)[2]*3+1, ny);
			normals.set(ipd.get(d)[2]*3+2, nz);
			
		}
		float[] ns = new float[normals.size()];
		for(int i = 0; i < ns.length; i++){
			ns** = normals.get(i).floatValue();
		}
		return Main.putFloatCoords(ns);
	}

[ot]
Ich weiß, über Stil und so läßt sich streiten, aber bei Zeilen wie normals.set(ipd.get(d)[2]*3+0, nx); rollen sich mir die Fußnägel hoch.

Es gibt viele mögliche Lösungen, und EINE (wenn auch weit weg von der “besten”) könnte so aussehen…

package bytewelt;

import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Normals
{
    private FloatBuffer vertexBuffer;
    private IntBuffer indexBuffer;

    void computeThem()
    {
        FloatBuffer normalBuffer = calcNormals(indexBuffer, vertexBuffer);
    }

    static class Triangle
    {
        int v0, v1, v2;

        Triangle(int v0, int v1, int v2)
        {
            this.v0 = v0;
            this.v1 = v1;
            this.v2 = v2;
        }
    }

    private static List<Triangle> computeTriangles(IntBuffer indices)
    {
        List<Triangle> triangles = new ArrayList<Triangle>();
        for (int i = 0; i < indices.capacity(); i += 3)
        {
            int v0 = indices.get(i);
            int v1 = indices.get(i + 1);
            int v2 = indices.get(i + 2);
            triangles.add(new Triangle(v0, v1, v2));
        }
        return triangles;
    }

    private static Vector3f cross(Vector3f u, Vector3f v)
    {
        Vector3f n = new Vector3f();
        n.x = u.y * v.z - u.z * v.y;
        n.y = u.z * v.x - u.x * v.z;
        n.z = u.x * v.y - u.y * v.x;
        return n;
    }

    private static List<Vector3f> computeVectors(FloatBuffer vertices)
    {
        List<Vector3f> vectors = new ArrayList<Vector3f>();
        for (int i = 0; i < vertices.capacity(); i += 3)
        {
            float x = vertices.get(i);
            float y = vertices.get(i + 1);
            float z = vertices.get(i + 2);
            vectors.add(new Vector3f(x, y, z));
        }
        return vectors;
    }

    private static Vector3f computeNormal(
        Triangle triangle, List<Vector3f> vertices)
    {
        Vector3f v0 = vertices.get(triangle.v0);
        Vector3f v1 = vertices.get(triangle.v1);
        Vector3f v2 = vertices.get(triangle.v2);
        Vector3f u = new Vector3f();
        Vector3f.sub(v1, v0, u);
        Vector3f v = new Vector3f();
        Vector3f.sub(v2, v0, v);
        return cross(u, v);
    }

    private static void copyToBuffer(
        Iterable<? extends Vector3f> vectors, FloatBuffer buffer)
    {
        int index = 0;
        for (Vector3f v : vectors)
        {
            buffer.put(index++, v.x);
            buffer.put(index++, v.y);
            buffer.put(index++, v.z);
        }
    }

    public FloatBuffer calcNormals(IntBuffer indexBuffer,
        FloatBuffer vertexBuffer)
    {
        List<Triangle> triangles = computeTriangles(indexBuffer);
        List<Vector3f> vertices = computeVectors(vertexBuffer);
        List<Vector3f> normals =
            new ArrayList<Vector3f>(Collections.nCopies(vertices.size(), null));

        for (int t = 0; t < triangles.size(); t++)
        {
            Triangle triangle = triangles.get(t);
            Vector3f normal = computeNormal(triangle, vertices);
            normals.set(triangle.v0, normal);
            normals.set(triangle.v1, normal);
            normals.set(triangle.v2, normal);
        }

        FloatBuffer normalBuffer =
            FloatBuffer.allocate(vertexBuffer.capacity());
        copyToBuffer(normals, normalBuffer);
        return normalBuffer;
    }
}

// Dummy class
class Vector3f
{
    float x, y, z;

    public Vector3f()
    {
    }

    public Vector3f(float f, float g, float h)
    {
    }

    public static void sub(Vector3f vector3f, Vector3f vector3f2, Vector3f u)
    {
    }
}

[/ot]

Na gut das +0 ist Sinnfrei, weiß selbst nicht warum ich das geschrieben hab. Es ist schon wahr, dass das verworren ist, aber solange man durchblicken kann und es funktioniert, geht das ja. Du hast ja auch gesagt man kann sich drüber streiten.(Und wie geht das mit dem Off Topic Kasten?)