Metall-Material

Das Bild ist beim Posten irgendwie kaputt gegangen. Und nur zur Sicherheit: Das hier

fragColor = vec4(0, 0, 0, 1);           //           texture(u_cubemapTexture, v_reflect);

steht nicht wirklich so im Code, oder?

doch, aber nur um zu testen, ob es schwarz angezeigt werden würde. Das habe ich gemacht, weil ich rausfinden wollte, ob es an der Cubemap oder an was Anderem liegt, dass nichts angezeigt wird. Aber auch so wurde nichts angezeigt, also kann man das getrost wieder löschen und “texture(u_cubemapTexture, v_reflect);” reinschreiben.

Ich habs jetzt mal auf das Minimalste reduziert um herauszufinden, warum es nicht gezeichnet wird, und ich glaube, dass entweder die Matrizen, oder die Vertices nicht richtig übergeben werden.Die Locations für die Matrizen in der Reihenfolge wie im Code sind 1, 2 und 0(heißt 0, dass die Loction nicht richtig existiert? Das wär dann der Fehler).Ein KSKB ist leider nicht möglich, da es bei weitem nicht mehr kurz ist, und mit einem Fehler außerhalb von Java crasht, bei dem ich keine Ahnung hab, woher er kommt.

activity.mappingShader.use();
	    System.out.println(activity.mappingProjectionLocation+" "+activity.mappingViewLocation+" "+activity.mappingModelLocation);
	    glUniformMatrix4(activity.mappingProjectionLocation, false, activity.projMatrix);
	    glUniformMatrix4(activity.mappingViewLocation, false, activity.viewMatrix);
	    glUniformMatrix4(activity.mappingModelLocation, false, activity.modelMatrix);
	    
		glBindVertexArray(vaoID);
        glEnableVertexAttribArray(0);      
        glDrawElements(GL_TRIANGLES, indexBuffer);
        glDisableVertexAttribArray(0);
        glBindVertexArray(0);
        
        activity.mappingShader.unuse();

Inzwischen weiß ich echt nicht mehr was ich tun kann.

Eine location von 0 ist OK. Wie Hilfe hier konkret aussehen sollte weiß ich aber jetzt auch nicht. Eigentlich fände ich es ganz interessant, mal (“einfach so”) auszuprobieren, ob man das mit so einer EnviromentMap hinkriegt, aber … erstens liegen im Moment andere Sachen weiter oben in der Queue, und zweitens hätte das im besten oder schlechtesten (!?) Fall zur Folge, dass ICH dann ein KSKB posten würde, und du suchen dürftest, wo denn der Unterschied ist…

EDIT: Habe gerade mal angefangen, zu versuchen, so ein KSKB zu basteln, aber das ist eben absurd aufwändig. Alleine die Möglichkeit zu bieten, das ganze mit der Maus zu rotieren (und Sachen wie gluLookAt) kann man kaum in ein KSKB bringen, das nicht wirklich NUR ein fixes Bild rendert.

Sowas wie OpenGL Mathematics für Java-OpenGL zu basteln liegt zwar “eigentlich” auch schon lange in meiner Queue, aber … ich befürchte, da wird es auch noch eine ganze Weile liegenbleiben. Schade, eigentlich. @Fancy hast du irgendwas, was du da immer verwendest? Ich meine, alleine eine Matrixmultiplikation auf float[]-Arrays (oder ja eigentlich FloatBuffern!!!) jedes mal auszuimplementieren ist ja ein Krampf. Für meine “Rendering-Library” hatte ich mir da ein paar Utilities gebaut, auf https://java.net/projects/vecmath/ aufsetzend, aber … ich hätte auch kein Problem damit, letztere zu ersetzen…

Ich hab das gerade auch mal runter geschrieben und es lief auch nicht auf Anhieb. Kurzes testen ergab dann aber das bei mir das

wohl wichtig genommen wird. Beim Zombiepriester scheint das aber nicht das Problem zu sein. Wenn man den Base64 String aus dem Link zu seinem Bild zu einem Jpeg umbaut und die Koordinaten nachrechnet, kommt da überall 64x64 raus. Was zwar viel zu wenig ist, aber gehen sollte.

Sei es drum, sein Bild:

Mein KSKB:
Imho ist da aber noch (mindestens) ein Fehler drin, die Reflexionen erscheinen mir an den Kanten zu glatt.



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_LINEAR;
import static org.lwjgl.opengl.GL11.GL_RGBA8;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_MAG_FILTER;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_MIN_FILTER;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_WRAP_S;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_WRAP_T;
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_BYTE;
import static org.lwjgl.opengl.GL11.GL_UNSIGNED_SHORT;
import static org.lwjgl.opengl.GL11.glBindTexture;
import static org.lwjgl.opengl.GL11.glClear;
import static org.lwjgl.opengl.GL11.glDeleteTextures;
import static org.lwjgl.opengl.GL11.glDrawElements;
import static org.lwjgl.opengl.GL11.glEnable;
import static org.lwjgl.opengl.GL11.glGenTextures;
import static org.lwjgl.opengl.GL11.glTexImage2D;
import static org.lwjgl.opengl.GL12.GL_BGRA;
import static org.lwjgl.opengl.GL12.GL_CLAMP_TO_EDGE;
import static org.lwjgl.opengl.GL12.GL_TEXTURE_WRAP_R;
import static org.lwjgl.opengl.GL13.GL_TEXTURE0;
import static org.lwjgl.opengl.GL13.GL_TEXTURE_CUBE_MAP;
import static org.lwjgl.opengl.GL13.GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
import static org.lwjgl.opengl.GL13.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
import static org.lwjgl.opengl.GL13.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
import static org.lwjgl.opengl.GL13.GL_TEXTURE_CUBE_MAP_POSITIVE_X;
import static org.lwjgl.opengl.GL13.GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
import static org.lwjgl.opengl.GL13.GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
import static org.lwjgl.opengl.GL13.glActiveTexture;
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.glGetUniformLocation;
import static org.lwjgl.opengl.GL20.glLinkProgram;
import static org.lwjgl.opengl.GL20.glShaderSource;
import static org.lwjgl.opengl.GL20.glUniform1i;
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.GL33.glBindSampler;
import static org.lwjgl.opengl.GL33.glDeleteSamplers;
import static org.lwjgl.opengl.GL33.glGenSamplers;
import static org.lwjgl.opengl.GL33.glSamplerParameteri;
import static org.lwjgl.system.MemoryUtil.NULL;

import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

import javax.imageio.ImageIO;

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 GL33Cubemap 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 int TEXTURE_UNIT = 0;

    private static final String IMAGE = "blub.jpg";

    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;                                                      
"
            + "out vec3 freflect;                                                
"
            + "                                                                  
"
            + "void main() {                                                     
"
            + "                                                                  
"
            + "    fv = vec3(modelview * v);                                     
"
            + "    fl = normalize(position.xyz - fv);                            
"
            + "    fn = normalize(normal * vn);                                  
"
            + "                                                                  
"
            + "    vec3  reflectView = reflect(fv, fn);                          
"
            + "    freflect = mat3(inverse(modelview)) * reflectView;            
" // FIXME
            + "                                                                  
"
            + "    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;                                                
"
            + "};                                                                
"
            + "                                                                  
"
            + "uniform samplerCube cube;                                         
"
            + "                                                                  
"
            + "in vec3 fl;                                                       
"
            + "in vec3 fv;                                                       
"
            + "in vec3 fn;                                                       
"
            + "in vec3 freflect;                                                 
"
            + "                                                                  
"
            + "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), 2);              
"
            + "    color *= texture(cube, freflect);                             
"
            + "                                                                  
"
            + "}                                                                 
";

    private static final float[] AMBIENT = new float[] { 0.1f, 0.1f, 0.1f, 0 };
    private static final float[] DIFFUSE = new float[] { 0.8f, 0.8f, 0.8f, 0 };
    private static final float[] SPECULAR = new float[] { 0.9f, 0.8f, 0.8f, 0 };
    private static final float[] POSITION = new float[] { 0, 1, -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 int handleSampler;
    private int handleTexture;

    private float angle;


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

        new GL33Cubemap().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();
        initSampler();
        initTexture();

    }


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

        final int cubeUniformIndex = glGetUniformLocation(programHandle, "cube");
        glUniform1i(cubeUniformIndex, TEXTURE_UNIT);

    }


    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 void initSampler() {

        handleSampler = glGenSamplers();
        glSamplerParameteri(handleSampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glSamplerParameteri(handleSampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glSamplerParameteri(handleSampler, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
        glSamplerParameteri(handleSampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glSamplerParameteri(handleSampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

        glBindSampler(TEXTURE_UNIT, handleSampler);

    }


    private void initTexture() {

        BufferedImage image = loadImage();
        image = flipImage(image);

        handleTexture = glGenTextures();
        glActiveTexture(GL_TEXTURE0 + TEXTURE_UNIT);
        glBindTexture(GL_TEXTURE_CUBE_MAP, handleTexture);

        // FIXME ?
        final int w = image.getWidth(), h = image.getHeight();
        initSite(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, image.getSubimage(w / 4, h / 3, w / 4, h / 3));
        initSite(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, image.getSubimage(3 * w / 4, h / 3, w / 4, h / 3));
        initSite(GL_TEXTURE_CUBE_MAP_POSITIVE_X, image.getSubimage(2 * w / 4, h / 3, w / 4, h / 3));
        initSite(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, image.getSubimage(0, h / 3, w / 4, h / 3));
        initSite(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, image.getSubimage(w / 4, 0, w / 4, h / 3));
        initSite(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, image.getSubimage(w / 4, 2 * (h / 3), w / 4, h / 3));

    }


    private void initSite(final int target, final BufferedImage image) {

        final int[] pixels = image.getRGB(0, 0, image.getWidth(), image.getHeight(), null, 0, image.getWidth());

        final ByteBuffer buffer = BufferUtils.createByteBuffer(pixels.length * Integer.SIZE / Byte.SIZE);
        buffer.asIntBuffer().put(pixels);
        buffer.rewind();

        glTexImage2D(target, 0, GL_RGBA8, image.getWidth(), image.getHeight(), 0, GL_BGRA, GL_UNSIGNED_BYTE, buffer);


    }


    private BufferedImage loadImage() {

        BufferedImage image;

        try (InputStream is = getClass().getClassLoader().getResourceAsStream(IMAGE)) {

            if (is == null)
                throw new RuntimeException("Image not found!");

            image = ImageIO.read(is);

            is.close();

        } catch (final IOException e) {

            throw new RuntimeException(e);

        }

        return image;

    }


    private BufferedImage flipImage(final BufferedImage image) {

        final AffineTransform tx = AffineTransform.getScaleInstance(1, -1);
        tx.translate(0, -image.getHeight());

        final AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
        final BufferedImage result = op.filter(image, null);

        return result;

    }


    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.toRadians(angle));
        final float s = (float) Math.sin(Math.toRadians(angle));

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

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

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

        return m;

    }


    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.5f;

            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() {

        glDeleteTextures(handleTexture);
        glDeleteSamplers(handleSampler);
        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();

    }


}

@Marco13 : Eine saubere OpenGL Mathe Bibliothek steht auch auf meiner ToDo Liste, für KSKBs kopier ich derzeit einfach die Methoden aus einem der anderen KSKBs.

Gruß
Fancy

@Fancy Viel irritierender als die Auflösung oder „zu glatte Reflexion“ (?) finde ich, dass die Reflexion zu „springen“ scheint: Es gibt einen Punkt, wo die Reflexion schlagartig etwas komplett anderes zeigt. Irgendwas passt da wohl mit den Normalen oder der NormalMatrix nicht…? Hab’s aber nicht im Dreil nachvollzogen (ob die „sides“ die richtigen Bildausschnitte verwenden, bin ich mir auch nicht sicher, aber das könnte auch stimmen…)

Das schwierige bei solchen KSKBs ist der Impuls, es statt Copy&Paste DOCH wieder allgemeiner zu machen. Gestern hatte ich gedacht: „Gut, ich bastel’ da jetzt mal ein KSKB, das aus NUR genau EINER Klasse besteht…“ … aber nach ein paar Minuten hatte ich dann schon wieder Klassen wie „RenderedObject“, „Geometry“, „BufferUtils“… und bevor ich dann mit der „MatrixUtils“ angefangen habe, dachte ich mir: Frag’ ich mal nach :wink:

Bezüglich einer vernünftigen Mathe-Bibliothek für OpenGL: Hast du da schon konkrete Ansätze oder Überlegungen? Also, nicht dass mir langeweilig wäre, aber vielleicht könnte man da ja zumindest mal anfangen zu überlegen und was zu basteln…

Welche Probleme treten denn in diesem Zusammenhang außerhalb von Java auf?

Das war ein “EXCEPTION_ACCESS_VIOLATION” in einem C++ Programm, wahrscheinlich die java.exe, oder irgendein OpenGL-helfendes Programm, falls so was überhaupt existiert.
Ich schau mir das KSKB mal an(kanns wegen diesem GLFW leider nicht starten, aber es ist ja klar was es macht) und hoffentlich wird es dann bei mir auch bald funktionieren.

Es funktioniert endlich, echt super! Nur ein bisschen komisch, wie Marco13 schon sagte. Leider weiß ich nicht was ich dagegen tun kann.

Ok, hab mir das gerade nochmal angesehen. Bei den Seiten war die Z-Achse vertauscht. Warum die Spiegelung kopfüber steht ist mir nicht klar, macht man das bei OpenGL eigentlich obligatorische flipImage raus, stimmt es.

Ich hab mal eine Variante angepasst die den Shader aus dem Tutorial verwendet und in der man (ruckelig) um den Würfel herum gehen kann. Das vom Zombieprister verwendete Bild gibt es hier in der original Auflösung (sonst erkennt man nicht viel).



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_CURSOR;
import static org.lwjgl.glfw.GLFW.GLFW_CURSOR_DISABLED;
import static org.lwjgl.glfw.GLFW.GLFW_KEY_A;
import static org.lwjgl.glfw.GLFW.GLFW_KEY_D;
import static org.lwjgl.glfw.GLFW.GLFW_KEY_ESCAPE;
import static org.lwjgl.glfw.GLFW.GLFW_KEY_S;
import static org.lwjgl.glfw.GLFW.GLFW_KEY_W;
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.glfwSetCursorPos;
import static org.lwjgl.glfw.GLFW.glfwSetCursorPosCallback;
import static org.lwjgl.glfw.GLFW.glfwSetErrorCallback;
import static org.lwjgl.glfw.GLFW.glfwSetInputMode;
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_LINEAR;
import static org.lwjgl.opengl.GL11.GL_RGBA8;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_MAG_FILTER;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_MIN_FILTER;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_WRAP_S;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_WRAP_T;
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_BYTE;
import static org.lwjgl.opengl.GL11.GL_UNSIGNED_SHORT;
import static org.lwjgl.opengl.GL11.glBindTexture;
import static org.lwjgl.opengl.GL11.glClear;
import static org.lwjgl.opengl.GL11.glDeleteTextures;
import static org.lwjgl.opengl.GL11.glDrawElements;
import static org.lwjgl.opengl.GL11.glEnable;
import static org.lwjgl.opengl.GL11.glGenTextures;
import static org.lwjgl.opengl.GL11.glTexImage2D;
import static org.lwjgl.opengl.GL12.GL_BGRA;
import static org.lwjgl.opengl.GL12.GL_CLAMP_TO_EDGE;
import static org.lwjgl.opengl.GL12.GL_TEXTURE_WRAP_R;
import static org.lwjgl.opengl.GL13.GL_TEXTURE0;
import static org.lwjgl.opengl.GL13.GL_TEXTURE_CUBE_MAP;
import static org.lwjgl.opengl.GL13.GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
import static org.lwjgl.opengl.GL13.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
import static org.lwjgl.opengl.GL13.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
import static org.lwjgl.opengl.GL13.GL_TEXTURE_CUBE_MAP_POSITIVE_X;
import static org.lwjgl.opengl.GL13.GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
import static org.lwjgl.opengl.GL13.GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
import static org.lwjgl.opengl.GL13.glActiveTexture;
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.glGetUniformLocation;
import static org.lwjgl.opengl.GL20.glLinkProgram;
import static org.lwjgl.opengl.GL20.glShaderSource;
import static org.lwjgl.opengl.GL20.glUniform1i;
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.GL33.glBindSampler;
import static org.lwjgl.opengl.GL33.glDeleteSamplers;
import static org.lwjgl.opengl.GL33.glGenSamplers;
import static org.lwjgl.opengl.GL33.glSamplerParameteri;
import static org.lwjgl.system.MemoryUtil.NULL;

import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

import javax.imageio.ImageIO;

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


public final class GL33FpsCubemap 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 TEXTURE_UNIT = 0;

    private static final String IMAGE = "cubemap.jpg";

    private static final String VERTEX_SHADER = ""

            + "#version 330 core                                                 
"
            + "                                                                  
"
            + "layout(std140) uniform MVP {                                      
"
            + "    mat4 projection;                                              
"
            + "    mat4 view;                                                    
"
            + "    mat4 model;                                                   
"
            + "};                                                                
"
            + "                                                                  
"
            + "layout(location = " + VERTEX_LOCATION + ") in vec3 v;             
"
            + "layout(location = " + NORMAL_LOCATION + ") in vec3 vn;            
"
            + "                                                                  
"
            + "out vec3 pos_eye;                                                 
"
            + "out vec3 n_eye;                                                   
"
            + "                                                                  
"
            + "void main() {                                                     
"
            + "                                                                  
"
            + "   pos_eye = vec3 (view * model * vec4 (v, 1.0));                 
"
            + "   n_eye = vec3 (view * model * vec4 (vn, 0.0));                  
"
            + "   gl_Position = projection * view * model * vec4 (v, 1.0);       
"
            + "                                                                  
"
            + "}                                                                 
";

    private static final String FRAGMENT_SHADER = ""

            + "#version 330 core                                                 
"
            + "                                                                  
"
            + "layout(std140) uniform MVP {                                      
"
            + "    mat4 projection;                                              
"
            + "    mat4 view;                                                    
"
            + "    mat4 model;                                                   
"
            + "};                                                                
"
            + "                                                                  
"
            + "uniform samplerCube cube;                                         
"
            + "                                                                  
"
            + "in vec3 pos_eye;                                                  
"
            + "in vec3 n_eye;                                                    
"
            + "                                                                  
"
            + "out vec4 color;                                                   
"
            + "                                                                  
"
            + "void main() {                                                     
"
            + "                                                                  
"
            + "    vec3 incident_eye = normalize (pos_eye);                      
"
            + "    vec3 normal = normalize (n_eye);                              
"
            + "    vec3 reflected = reflect (incident_eye, normal);              
"
            + "    reflected = vec3 (inverse (view) * vec4 (reflected, 0.0));    
"
            + "                                                                  
"
            + "    color = texture(cube, reflected);                             
"
            + "                                                                  
"
            + "}                                                                 
";

    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 + 16);

    private GLFWErrorCallback errorCallback;
    private GLFWKeyCallback keyCallback;
    private GLFWCursorPosCallback cursorCallback;

    private long windowHandle;

    private int vaoHandle;
    private int iboHandle;
    private int vboHandle;
    private int mvpHandle;
    private int programHandle;
    private int handleSampler;
    private int handleTexture;

    private float rotY, rotV;
    private float posX, posY, posZ;


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

        new GL33FpsCubemap().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) {

                final double keySpeed = 0.1;

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

                if (key == GLFW_KEY_W) {

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

                }

                if (key == GLFW_KEY_S) {

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

                }

                if (key == GLFW_KEY_A) {

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

                }

                if (key == GLFW_KEY_D) {

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

                }

            }

        };
        glfwSetKeyCallback(windowHandle, keyCallback);

        cursorCallback = new GLFWCursorPosCallback() {

            @Override
            public void invoke(final long window, final double xpos, final double ypos) {

                final float deltaX = (float) (xpos - WIDTH / 2);
                final float deltaY = (float) (ypos - HEIGHT / 2);

                final double mouseSpeed = 0.001;

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

                rotY += deltaX * mouseSpeed;
                rotV += deltaY * mouseSpeed;

                if (rotV > rotVmax)
                    rotV = rotVmax;

                if (rotV < rotVMin)
                    rotV = rotVMin;

                glfwSetCursorPos(window, WIDTH / 2, HEIGHT / 2);

            }

        };
        glfwSetCursorPosCallback(windowHandle, cursorCallback);
        glfwSetInputMode(windowHandle, GLFW_CURSOR, GLFW_CURSOR_DISABLED);

        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();
        initShader();
        initSampler();
        initTexture();

    }


    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 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 cubeUniformIndex = glGetUniformLocation(programHandle, "cube");
        glUniform1i(cubeUniformIndex, TEXTURE_UNIT);

    }


    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 void initSampler() {

        handleSampler = glGenSamplers();
        glSamplerParameteri(handleSampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glSamplerParameteri(handleSampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glSamplerParameteri(handleSampler, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
        glSamplerParameteri(handleSampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glSamplerParameteri(handleSampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

        glBindSampler(TEXTURE_UNIT, handleSampler);

    }


    private void initTexture() {

        final BufferedImage image = loadImage();
        // image = flipImage(image); // WTF?

        handleTexture = glGenTextures();
        glActiveTexture(GL_TEXTURE0 + TEXTURE_UNIT);
        glBindTexture(GL_TEXTURE_CUBE_MAP, handleTexture);

        final int w = image.getWidth(), h = image.getHeight();
        initSide(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, image.getSubimage(0, h / 3, w / 4, h / 3));
        initSide(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, image.getSubimage(w / 4, h / 3, w / 4, h / 3));
        initSide(GL_TEXTURE_CUBE_MAP_POSITIVE_X, image.getSubimage(2 * w / 4, h / 3, w / 4, h / 3));
        initSide(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, image.getSubimage(3 * w / 4, h / 3, w / 4, h / 3));
        initSide(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, image.getSubimage(w / 4, 0, w / 4, h / 3));
        initSide(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, image.getSubimage(w / 4, 2 * (h / 3), w / 4, h / 3));

    }


    private void initSide(final int target, final BufferedImage image) {

        final int[] pixels = image.getRGB(0, 0, image.getWidth(), image.getHeight(), null, 0, image.getWidth());

        final ByteBuffer buffer = BufferUtils.createByteBuffer(pixels.length * Integer.SIZE / Byte.SIZE);
        buffer.asIntBuffer().put(pixels);
        buffer.rewind();

        glTexImage2D(target, 0, GL_RGBA8, image.getWidth(), image.getHeight(), 0, GL_BGRA, GL_UNSIGNED_BYTE, buffer);


    }


    private BufferedImage loadImage() {

        BufferedImage image;

        try (InputStream is = getClass().getClassLoader().getResourceAsStream(IMAGE)) {

            if (is == null)
                throw new RuntimeException("Image not found!");

            image = ImageIO.read(is);

            is.close();

        } catch (final IOException e) {

            throw new RuntimeException(e);

        }

        return image;

    }


    private BufferedImage flipImage(final BufferedImage image) {

        final AffineTransform tx = AffineTransform.getScaleInstance(1, -1);
        tx.translate(0, -image.getHeight());

        final AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
        final BufferedImage result = op.filter(image, null);

        return result;

    }


    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.toRadians(angle));
        final float s = (float) Math.sin(Math.toRadians(angle));

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

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

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

        return m;

    }


    private float[] fpsControl() {

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

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

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

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

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

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

        return mv;

    }


    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) {

            final float[] projection = projection(45, (float) WIDTH / (float) HEIGHT, 0.1f, 1000f);
            final float[] view = fpsControl();
            final float[] rotate = rotate(0, 0, 1, 20);
            final float[] translate = translate(0, 0, -10);
            final float[] model = multiplication(translate, rotate);

            mvpBuffer.put(projection);
            mvpBuffer.put(view);
            mvpBuffer.put(model);
            mvpBuffer.rewind();

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

            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() {

        glDeleteTextures(handleTexture);
        glDeleteSamplers(handleSampler);
        glDeleteProgram(programHandle);
        glDeleteBuffers(mvpHandle);
        glDeleteBuffers(vboHandle);
        glDeleteBuffers(iboHandle);
        glDeleteVertexArrays(vaoHandle);

    }


    private void releaseGLFW() {

        glfwDestroyWindow(windowHandle);
        keyCallback.release();
        cursorCallback.release();

    }


    private void terminateGLFW() {

        glfwTerminate();
        errorCallback.release();

    }


}

@Marco13 : Ne, hab da noch nix konkretes angedacht.

Gruß
Fancy

Gut, danke jetzt funktioniert es besser. Nun möchte ich dennoch einmal ausprobieren, wie es aussehen würde, wenn man die Cubemap aus der Umgebung erstellt. Mit Framebuffern bekomme ich die 6 Seiten als Texturen, ich weiß nur nicht, wie ich diese auf die Seiten der Cubemap bekomme, denn bei:

glTexImage2D(target, 0, GL11.GL_RGBA, bi.getWidth(), bi.getHeight(), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, image);

Kann man ja nur ein Bild als ByteBuffer übergeben, und keine Textur-ID. Ich bin mir sicher, es gibt dafür etwas analoges, nur hab ich im Internet nichts dazu gefunden.

Nein, das ist die falsche Stelle. Dritter Parameter von glFramebufferTexture2D.

Gruß
Fancy

Ich habe jetzt erst mal eine FrameBuffer Klasse erstellt und um es zu testen will ich nun die Framebuffer-Textur auf eine Fläche mappen. Nur ist diese Textur nicht vorhanden/durchsichtig. Die Klasse basiert hierauf Die Klasse sieht folgendermaßen aus:

import static org.lwjgl.opengl.EXTFramebufferObject.GL_COLOR_ATTACHMENT0_EXT;
import static org.lwjgl.opengl.EXTFramebufferObject.GL_DEPTH_ATTACHMENT_EXT;
import static org.lwjgl.opengl.EXTFramebufferObject.GL_FRAMEBUFFER_EXT;
import static org.lwjgl.opengl.EXTFramebufferObject.GL_RENDERBUFFER_EXT;
import static org.lwjgl.opengl.EXTFramebufferObject.glBindFramebufferEXT;
import static org.lwjgl.opengl.EXTFramebufferObject.glBindRenderbufferEXT;
import static org.lwjgl.opengl.EXTFramebufferObject.glFramebufferRenderbufferEXT;
import static org.lwjgl.opengl.EXTFramebufferObject.glFramebufferTexture2DEXT;
import static org.lwjgl.opengl.EXTFramebufferObject.glGenFramebuffersEXT;
import static org.lwjgl.opengl.EXTFramebufferObject.glGenRenderbuffersEXT;
import static org.lwjgl.opengl.EXTFramebufferObject.glRenderbufferStorageEXT;
import static org.lwjgl.opengl.GL11.GL_INT;
import static org.lwjgl.opengl.GL11.GL_LINEAR;
import static org.lwjgl.opengl.GL11.GL_RGBA;
import static org.lwjgl.opengl.GL11.GL_RGBA8;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_MIN_FILTER;
import static org.lwjgl.opengl.GL11.glBindTexture;
import static org.lwjgl.opengl.GL11.glGenTextures;
import static org.lwjgl.opengl.GL11.glTexImage2D;
import static org.lwjgl.opengl.GL11.glTexParameterf;

import org.lwjgl.opengl.GL14;

public class Framebuffer {

	private int fboID;
	private int textureID;
	private int depthRenderBufferID;

	public Framebuffer(){
		fboID = glGenFramebuffersEXT();                                         // create a new framebuffer
        textureID = glGenTextures();                                               // and a new texture used as a color buffer
        depthRenderBufferID = glGenRenderbuffersEXT();                                  // And finally a new depthbuffer
 
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboID);                        // switch to the new framebuffer
        
        glBindTexture(GL_TEXTURE_2D, textureID);                                   // Bind the colorbuffer texture
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);               // make it linear filterd
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 512, 512, 0,GL_RGBA, GL_INT, (java.nio.ByteBuffer) null);  // Create the texture data
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT0_EXT,GL_TEXTURE_2D, textureID, 0); // attach it to the framebuffer
        
        glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthRenderBufferID);                // bind the depth renderbuffer
        glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL14.GL_DEPTH_COMPONENT24, 512, 512); // get the data space for it
        glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,GL_DEPTH_ATTACHMENT_EXT,GL_RENDERBUFFER_EXT, depthRenderBufferID); // bind it to the renderbuffer
        
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);  
	}
	
	public void bind(){
		glBindTexture(GL_TEXTURE_2D, 0);
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboID);    
	}
	public void unbind(){
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
	}
	public int texture(){
		return textureID;
	}
}

Und so rendere ich das:

frameBuffer.bind();
        world.render();
        frameBuffer.unbind();
        texMesh.setTextur(frameBuffer.texture());
        world.render();
        texMesh.draw();

Die dort verwendeten *EXT Methoden stammen aus einer Zeit als es noch kein FBO im OpenGL Standard gab und sollten heute nicht mehr verwendet werden. Meine Klassen verwenden die aktuellen Methoden: FBO, RBO, Texture, Sampler.

Der Ablauf sieht dann etwa so aus:

        
        sampler = new Sampler(binding);
        sampler.addParameter(GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        sampler.addParameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        sampler.addParameter(GL_TEXTURE_WRAP_S, GL_REPEAT);
        sampler.addParameter(GL_TEXTURE_WRAP_T, GL_REPEAT);
        
        texture = new Texture(binding, width, height, GL_RGBA8);   
        
        fbo = new FBO();
        rbo = new RBO(width, height);
        
    }
    
    void init() {
          
        sampler.glInit();
        texture.glInit();
        
        fbo.glInit();
        rbo.glInit();
        fbo.glBind();
        rbo.glBind();
        texture.glAttachToFBO(GL_COLOR_ATTACHMENT0);
        fbo.glUnbind();
        
    }
    
    void loop() {
        
        fbo.glBind();
        //draw to fbo
        fbo.glUnbind();
        
        sampler.glBind();
        texture.glBind();
        //draw normal
        
    }
    
    void dispose() {
        
        fbo.glDispose();
        rbo.glDispose();    
        texture.glDispose();
        sampler.glDispose();     
        
    }

Gruß
Fancy

Ich habs jetzt ohne Sampler gemacht, der ist ja nur für die Textur-Parameter zuständig. Ich hoffe, das das nicht so schlimm ist. Die neue Klasse folgt, es wird noch nichts angezeigt, obwohl ich (vermutlich) alles richtig gemacht haben müsste.

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

import org.lwjgl.opengl.GL14;

public class Framebuffer {

	private int fboID;
	private int textureID;
	private int depthRenderBufferID;

	public Framebuffer(int w, int h){
		fboID = glGenFramebuffers();            
        textureID = glGenTextures();                                               
        depthRenderBufferID = glGenRenderbuffers();                                 
 
        glBindFramebuffer(GL_FRAMEBUFFER, fboID);                      
        
        glBindTexture(GL_TEXTURE_2D, textureID);                               
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);           
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0,GL_RGBA, GL_INT, (java.nio.ByteBuffer) null);
        glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D, textureID, 0);
        
        glBindRenderbuffer(GL_RENDERBUFFER, depthRenderBufferID);
        glRenderbufferStorage(GL_RENDERBUFFER, GL14.GL_DEPTH_COMPONENT24, w, h);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderBufferID);
        glBindRenderbuffer(GL_RENDERBUFFER, 0);
        glBindFramebuffer(GL_FRAMEBUFFER, 0);  
	}
	
	public void bind(){
        glBindFramebuffer(GL_FRAMEBUFFER, fboID);
        glBindRenderbuffer(GL_RENDERBUFFER, depthRenderBufferID);
	}
	public void unbind(){
		glBindFramebuffer(GL_FRAMEBUFFER, 0);
	}
	public int texture(){
		return textureID;
	}
}

Ich hab jetzt mal danach gegoogelt und ein paar Sachen ausprobiert, wie im Fragment Shader

layout(location=0) out vec4 outColor;

. Auch habe ich den Viewport vor dem Rendern neu gesetzt, aber die Textur ist irgendwie immer noch nicht vorhanden. Braucht man vielleicht eine Minimum Shader Version dafür?

glGenerateMipmap vergessen?

GL30.glGenerateMipmap(GL_TEXTURE_2D); ändert leider nichts.

*** Edit ***

Ahh, ich hab jetzt die Textur-Parameter geändert, und jetzt sieht man was, aber es sieht so aus, als wäre es irgendwie sehr oft drauf:

Das sind meine Textur Parameter:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
       
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 10);
        glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
        glPixelStorei(GL_UNPACK_ALIGNMENT, 4);

rumrat Hängt der beobachtete Effekt dort nicht einfach an den Texturkoordinaten? Wie sieht das aus, wenn man es auf einen Würfel anwendet, bei dem alle Texturkoordinaten einfach von (0,0) bis (1,1) gehen?