Einfaches OpenGL 3 Beispiel zum Laufen bringen


#1

Hallo,
Marco13 könnte evtl. helfen. Ich hab den geänderten Part markiert:

#include <cstdlib>
#include <iostream>
#include <GL/glew.h>
// #include <GL/glfw.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace std;
using namespace glm;

static const struct {
    float x, y;
    float r, g, b;
} vertices[3] = {
    { -0.6f, -0.4f, 1.f, 0.f, 0.f},
    { 0.6f, -0.4f, 0.f, 1.f, 0.f},
    { 0.f, 0.6f, 0.f, 0.f, 1.f}
};
static const char* vertex_shader_text =
        "uniform mat4 MVP;
"
        "attribute vec3 vCol;
"
        "attribute vec2 vPos;
"
        "varying vec3 color;
"
        "void main()
"
        "{
"
        "    gl_Position = MVP * vec4(vPos, 0.0, 1.0);
"
        "    color = vCol;
"
        "}
";
static const char* fragment_shader_text =
        "varying vec3 color;
"
        "void main()
"
        "{
"
        "    gl_FragColor = vec4(color, 1.0);
"
        "}
";

int main(int argc, char** argv) {


    /*      init GLFW         */
    if (!glfwInit()) {

        fprintf(stderr, "failed to init GLFW");

    } else {
        fprintf(stdout, "HALLO");
        GLFWwindow * window = glfwCreateWindow(640, 480, "My Title", NULL, NULL);
        if (window) {

            GLuint vertex_buffer, vertex_shader, fragment_shader, program;
            GLint mvp_location, vpos_location, vcol_location;
            glfwMakeContextCurrent(window);
            glfwSwapInterval(1);
            // NOTE: OpenGL error checks have been omitted for brevity
            glGenBuffers(1, &vertex_buffer);
            glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
            glBufferData(GL_ARRAY_BUFFER, sizeof (vertices), vertices, GL_STATIC_DRAW);
            vertex_shader = glCreateShader(GL_VERTEX_SHADER);
            glShaderSource(vertex_shader, 1, &vertex_shader_text, NULL);
            glCompileShader(vertex_shader);
            fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
            glShaderSource(fragment_shader, 1, &fragment_shader_text, NULL);
            glCompileShader(fragment_shader);
            program = glCreateProgram();
            glAttachShader(program, vertex_shader);
            glAttachShader(program, fragment_shader);
            glLinkProgram(program);
            mvp_location = glGetUniformLocation(program, "MVP");
            vpos_location = glGetAttribLocation(program, "vPos");
            vcol_location = glGetAttribLocation(program, "vCol");
            glEnableVertexAttribArray(vpos_location);
            glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE,
                    sizeof (float) * 5, (void*) 0);
            glEnableVertexAttribArray(vcol_location);
            glVertexAttribPointer(vcol_location, 3, GL_FLOAT, GL_FALSE,
                    sizeof (float) * 5, (void*) (sizeof (float) * 2));

            while (!glfwWindowShouldClose(window)) {
                // Hier hab ich etwas geändert Start
                float ratio;
                int width, height;
                mat4x4 m, p, mvp;
                glfwGetFramebufferSize(window, &width, &height);
                ratio = width / (float) height;

                glViewport(0, 0, width, height);
                glClear(GL_COLOR_BUFFER_BIT);


                m = mat4x4(1.f);
                m = rotate(m, (float) glfwGetTime(), vec3(0.7f));
                p = ortho(-1.f, 1.f, 1.f, -1.f, -ratio, ratio);
                mvp = p * m;


                glUseProgram(program);
                glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (GLfloat *) mvp);
                glDrawArrays(GL_TRIANGLES, 0, 3);
                // Hier hab ich etwas geändert End

                glfwSwapBuffers(window);
                glfwPollEvents();
            }
        }
    }
    return 0;
}

Fehlermeldung bekomme ich:

main.cpp: In function ‘int main(int, char**)’:
main.cpp:97:75: error: invalid cast from type ‘glm::mat4x4 {aka glm::detail::tmat4x4<float, (glm::precision)0u>}’ to type ‘GLfloat* {aka float*}’
                 glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (GLfloat *) mvp);
                                                                           ^

DANKE für Hilfe


Generics gehen bei "Fix formatting post-migration: Javas, rmCRs" kaputt
#2

Nur kurz geschaut und geraten: glm::value_ptr?

glUniformMatrix4fv(mvp_location, 1, GL_FALSE, glm::value_ptr(mvp));

Wenn nicht… mal sehen.

Ansonsten vielleicht noch @Fancy


#3

Mit
#include <glm/gtc/type_ptr.hpp>
und
glUniformMatrix4fv(mvp_location, 1, GL_FALSE, value_ptr(mvp));
kann ich es mit warnungen compilieren, aber beim Ausführen:
keine Meldung und kein Fenster und/oder kurz ein Fenster und/oder Segmentation fault;
jedenfalls “nix zu sehen”

Vermutlich liegt es hieran:
m = mat4x4(1.f);
m = rotate(m, (float) glfwGetTime(), vec3(0.7f));
p = ortho(-1.f, 1.f, 1.f, -1.f, -ratio, ratio);
mvp = p * m;

Naja, muss jetzt erst mal weg


#4

Am besten, ich mach das mit LWJGL und einem Wrapper wie diesen: LWJGL Wrapper Library – Minds Eye Games
Nur ich muss auch, “halbwegs”, verstehen, was da passiert.
Gibt es andere einfache Wrapper/Libraries für LWJGL? maleDreieck(…, …) oder so? Welche könntet ihr empfehlen?

… Und dann hab ich noch allgemein eine Frage. Wie zeichnet man genau einen Pixel an der Stelle (x, y)? (2D)
Wie stellt man dazu model, view und projection ein?
Kurze Suche im Internet hat ergeben, dass diese technik des Zeichnens veraltet sei.


#5

Edit:

hier nochmal das gleiche (versuche Shader in das offizielle Beispiel zu bekommen):

 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package spielex;

/**
 * @author
 */
import org.lwjgl.*;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.*;
import org.lwjgl.system.*;

import java.nio.*;

import static org.lwjgl.glfw.Callbacks.*;
import static org.lwjgl.glfw.GLFW.*;
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 static org.lwjgl.system.MemoryStack.*;
import static org.lwjgl.system.MemoryUtil.*;

public class SpielEx {

    // The window handle
    private long window;

    // ProgramID
    int programID;
    // Vertex Shader ID
    int vertexShaderID;
    // Fragment Shader ID
    int fragmentShaderID;

    int vaoID;
    int vboID;

    public void run() {
        System.out.println("Hello LWJGL " + Version.getVersion() + "!");

        init();
        loop();

        // Free the window callbacks and destroy the window
        glfwFreeCallbacks(window);
        glfwDestroyWindow(window);

        // Terminate GLFW and free the error callback
        glfwTerminate();
        glfwSetErrorCallback(null).free();
    }

    private void init() {
        // Setup an error callback. The default implementation
        // will print the error message in System.err.
        GLFWErrorCallback.createPrint(System.err).set();

        // Initialize GLFW. Most GLFW functions will not work before doing this.
        if (!glfwInit()) {
            throw new IllegalStateException("Unable to initialize GLFW");
        }

        // Configure GLFW
        glfwDefaultWindowHints(); // optional, the current window hints are already the default
        glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // the window will stay hidden after creation
        glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); // the window will be resizable

        // Create the window
        window = glfwCreateWindow(300, 300, "Hello World!", NULL, NULL);
        if (window == NULL) {
            throw new RuntimeException("Failed to create the GLFW window");
        }

        // Setup a key callback. It will be called every time a key is pressed, repeated or released.
        glfwSetKeyCallback(window, (windo, key, scancode, action, mods) -> {
            if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE) {
                glfwSetWindowShouldClose(windo, true); // We will detect this in the rendering loop
            }
        });

        // Get the thread stack and push a new frame
        try (MemoryStack stack = stackPush()) {
            IntBuffer pWidth = stack.mallocInt(1); // int*
            IntBuffer pHeight = stack.mallocInt(1); // int*

            // Get the window size passed to glfwCreateWindow
            glfwGetWindowSize(window, pWidth, pHeight);

            // Get the resolution of the primary monitor
            GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());

            // Center the window
            glfwSetWindowPos(
                    window,
                    (vidmode.width() - pWidth.get(0)) / 2,
                    (vidmode.height() - pHeight.get(0)) / 2
            );
        } // the stack frame is popped automatically

        // Make the OpenGL context current
        glfwMakeContextCurrent(window);
        // Enable v-sync
        glfwSwapInterval(1);

        // Make the window visible
        glfwShowWindow(window);

        /* Etwas eingefügt ANFANG */
        programID = glCreateProgram();
        vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vertexShaderID, "#version 330 core
"
                + "
"
                + "layout(location = 0) in vec2 position;
"
                + "
"
                + "void main()
"
                + "{
"
                + "    gl_Position = vec4(position, 0.0, 1.0);
"
                + "}
"
                + "");
        glCompileShader(vertexShaderID);
        glAttachShader(programID, vertexShaderID);

        fragmentShaderID = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(fragmentShaderID, "#version 330 core
"
                + "
"
                + "out vec4 fragColor;
"
                + "
"
                + "void main()
"
                + "{
"
                + "    fragColor = vec4(1.0);
"
                + "}
"
                + "");
        glCompileShader(fragmentShaderID);
        glAttachShader(programID, fragmentShaderID);

        if (glGetProgrami(programID, GL_LINK_STATUS) == GL_FALSE) {
            throw new RuntimeException("Unable to link shader program:");
        }

        // Generate and bind a Vertex Array
        vaoID = glGenVertexArrays();
        glBindVertexArray(vaoID);

// The vertices of our Triangle
        float[] vertices = new float[]{
            +0.0f, +0.8f, // Top coordinate
            -0.8f, -0.8f, // Bottom-left coordinate
            +0.8f, -0.8f // Bottom-right coordinate
        };

// Create a FloatBuffer of vertices
        FloatBuffer verticesBuffer = BufferUtils.createFloatBuffer(vertices.length);
        verticesBuffer.put(vertices).flip();

// Create a Buffer Object and upload the vertices buffer
        vboID = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vboID);
        glBufferData(GL_ARRAY_BUFFER, verticesBuffer, GL_STATIC_DRAW);

// Point the buffer at location 0, the location we set
// inside the vertex shader. You can use any location
// but the locations should match
        glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
        glBindVertexArray(0);
        /* Etwas eingefügt ENDE */

    }

    private void loop() {
        // This line is critical for LWJGL's interoperation with GLFW's
        // OpenGL context, or any context that is managed externally.
        // LWJGL detects the context that is current in the current thread,
        // creates the GLCapabilities instance and makes the OpenGL
        // bindings available for use.
        GL.createCapabilities();

        // Set the clear color
        glClearColor(1.0f, 0.0f, 0.0f, 0.0f);

        // Run the rendering loop until the user has attempted to close
        // the window or has pressed the ESCAPE key.
        while (!glfwWindowShouldClose(window)) {
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer

            /* Etwas eingefügt ANFANG */
            glUseProgram(programID);

            // Bind the vertex array and enable our location
            glBindVertexArray(vaoID);
            glEnableVertexAttribArray(0);

            // Draw a triangle of 3 vertices
            glDrawArrays(GL_TRIANGLES, 0, 3);

            // Disable our location
            glDisableVertexAttribArray(0);
            glBindVertexArray(0);

            glUseProgram(0);
            /* Etwas eingefügt ENDE */

            glfwSwapBuffers(window); // swap the color buffers

            // Poll for window events. The key callback above will only be
            // invoked during this call.
            glfwPollEvents();
        }
    }

    public static void main(String[] args) {
        new SpielEx().run();
    }

}```


Hello (…)!

A fatal error has been detected by the Java Runtime Environment: (…)



Ich denke, es liegt an import static org.lwjgl.opengl.GL11.*; und MemoryStack , bin da aber nicht sicher.
Ideen?

#6

Der Wrapper dort bezieht sich hauptsächlich auf die native libraries, und mit LWJGL3 werden die in JARs mit-deployt und transparent geladen.

Ansonsten gibt’s etliche Libs, die auf LWJGL aufsetzen und “bequemere” APIs bieten.

Das mit dem “value_ptr” war nur ein erster Schuss ins Blaue. Wenn das nicht funktioniert wäre eine genauere Fehlerbeschreibung ggf. hilfreich (ansonsten probier’ ich den Code vielleicht mal aus, aber ob das hilft…?)


#7

Hm, ein Programm mit Fehlern, das nicht läuft, ist besser als ein Programm mit Fehlern, das läuft.^^
Du kannst es gerne mal ausprobieren, und noch error handler und so etwas hinzufügen.
Falls es zum Laufen bekommst, wäre ich schon 10 Schritte weiter.
:slight_smile:


#8

Der ganze eigene Initializerungs-Schlonz muss an einer Stelle stehen, wo der GL-Kontext schon “lebt”. Hab’s mal hier in eine eigene “initialize()”-Funktion reingedengelt.

Zusätzlich war das Programm fehlerhaft, weil

  • ZWEI mal glCreateShader(GL_VERTEX_SHADER) verwendet wurde
  • Das Program nicht gelinkt wurde
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package spielex;

/**
 * @author
 */
import org.lwjgl.*;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.*;
import org.lwjgl.system.*;

import java.nio.*;
import java.nio.charset.Charset;

import static org.lwjgl.glfw.Callbacks.*;
import static org.lwjgl.glfw.GLFW.*;
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 static org.lwjgl.system.MemoryStack.*;
import static org.lwjgl.system.MemoryUtil.*;

public class SpielEx {

    // The window handle
    private long window;

    // ProgramID
    int programID;
    // Vertex Shader ID
    int vertexShaderID;
    // Fragment Shader ID
    int fragmentShaderID;

    int vaoID;
    int vboID;

    public void run() {
        System.out.println("Hello LWJGL " + Version.getVersion() + "!");

        init();
        loop();

        // Free the window callbacks and destroy the window
        glfwFreeCallbacks(window);
        glfwDestroyWindow(window);

        // Terminate GLFW and free the error callback
        glfwTerminate();
        glfwSetErrorCallback(null).free();
    }

    private void init() {
        // Setup an error callback. The default implementation
        // will print the error message in System.err.
        GLFWErrorCallback.createPrint(System.err).set();

        // Initialize GLFW. Most GLFW functions will not work before doing this.
        if (!glfwInit()) {
            throw new IllegalStateException("Unable to initialize GLFW");
        }

        // Configure GLFW
        glfwDefaultWindowHints(); // optional, the current window hints are already the default
        glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // the window will stay hidden after creation
        glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); // the window will be resizable

        // Create the window
        window = glfwCreateWindow(300, 300, "Hello World!", NULL, NULL);
        if (window == NULL) {
            throw new RuntimeException("Failed to create the GLFW window");
        }

        // Setup a key callback. It will be called every time a key is pressed, repeated or released.
        glfwSetKeyCallback(window, (windo, key, scancode, action, mods) -> {
            if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE) {
                glfwSetWindowShouldClose(windo, true); // We will detect this in the rendering loop
            }
        });

        // Get the thread stack and push a new frame
        try (MemoryStack stack = stackPush()) {
            IntBuffer pWidth = stack.mallocInt(1); // int*
            IntBuffer pHeight = stack.mallocInt(1); // int*

            // Get the window size passed to glfwCreateWindow
            glfwGetWindowSize(window, pWidth, pHeight);

            // Get the resolution of the primary monitor
            GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());

            // Center the window
            glfwSetWindowPos(
                    window,
                    (vidmode.width() - pWidth.get(0)) / 2,
                    (vidmode.height() - pHeight.get(0)) / 2
            );
        } // the stack frame is popped automatically

        // Make the OpenGL context current
        glfwMakeContextCurrent(window);
        // Enable v-sync
        glfwSwapInterval(1);

        // Make the window visible
        glfwShowWindow(window);
    }
    
    boolean initialized = false;
    private void initialize()
    {
        /* Etwas eingefügt ANFANG */
        programID = glCreateProgram();
        vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vertexShaderID, "#version 330 core
"
                + "
"
                + "layout(location = 0) in vec2 position;
"
                + "
"
                + "void main()
"
                + "{
"
                + "    gl_Position = vec4(position, 0.0, 1.0);
"
                + "}
"
                + "");
        glCompileShader(vertexShaderID);
        printShaderLogInfo(vertexShaderID);
        glAttachShader(programID, vertexShaderID);

        fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); // XXX Fragment, not vertex
        glShaderSource(fragmentShaderID, "#version 330 core
"
                + "
"
                + "out vec4 fragColor;
"
                + "
"
                + "void main()
"
                + "{
"
                + "    fragColor = vec4(1.0);
"
                + "}
"
                + "");
        glCompileShader(fragmentShaderID);
        printShaderLogInfo(fragmentShaderID);
        glAttachShader(programID, fragmentShaderID);

        glLinkProgram(programID);
        if (glGetProgrami(programID, GL_LINK_STATUS) == GL_FALSE) {
            printProgramLogInfo(programID);
            throw new RuntimeException("Unable to link shader program:");
        }

        // Generate and bind a Vertex Array
        vaoID = glGenVertexArrays();
        glBindVertexArray(vaoID);

// The vertices of our Triangle
        float[] vertices = new float[]{
            +0.0f, +0.8f, // Top coordinate
            -0.8f, -0.8f, // Bottom-left coordinate
            +0.8f, -0.8f // Bottom-right coordinate
        };

// Create a FloatBuffer of vertices
        FloatBuffer verticesBuffer = BufferUtils.createFloatBuffer(vertices.length);
        verticesBuffer.put(vertices).flip();

// Create a Buffer Object and upload the vertices buffer
        vboID = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vboID);
        glBufferData(GL_ARRAY_BUFFER, verticesBuffer, GL_STATIC_DRAW);

// Point the buffer at location 0, the location we set
// inside the vertex shader. You can use any location
// but the locations should match
        glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
        glBindVertexArray(0);
        /* Etwas eingefügt ENDE */
        
    }
    
    

    private void loop() {
        // This line is critical for LWJGL's interoperation with GLFW's
        // OpenGL context, or any context that is managed externally.
        // LWJGL detects the context that is current in the current thread,
        // creates the GLCapabilities instance and makes the OpenGL
        // bindings available for use.
        GL.createCapabilities();
        
        if (!initialized)
        {
            initialize();
            initialized = true;
        }

        // Set the clear color
        glClearColor(1.0f, 0.0f, 0.0f, 0.0f);

        // Run the rendering loop until the user has attempted to close
        // the window or has pressed the ESCAPE key.
        while (!glfwWindowShouldClose(window)) {
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer

            /* Etwas eingefügt ANFANG */
            glUseProgram(programID);

            // Bind the vertex array and enable our location
            glBindVertexArray(vaoID);
            glEnableVertexAttribArray(0);

            // Draw a triangle of 3 vertices
            glDrawArrays(GL_TRIANGLES, 0, 3);

            // Disable our location
            glDisableVertexAttribArray(0);
            glBindVertexArray(0);

            glUseProgram(0);
            /* Etwas eingefügt ENDE */

            glfwSwapBuffers(window); // swap the color buffers

            // Poll for window events. The key callback above will only be
            // invoked during this call.
            glfwPollEvents();
        }
    }

    public static void main(String[] args) {
        new SpielEx().run();
    }

    
    /**
     * For debugging: Print shader log info
     * 
     * @param id shader ID
     */
    private void printShaderLogInfo(int id) 
    {
        IntBuffer infoLogLength = ByteBuffer.allocateDirect(4)
            .order(ByteOrder.nativeOrder())
            .asIntBuffer();
        glGetShaderiv(id, GL_INFO_LOG_LENGTH, infoLogLength);
        if (infoLogLength.get(0) > 0) 
        {
            infoLogLength.put(0, infoLogLength.get(0)-1);
        }

        ByteBuffer infoLog = ByteBuffer.allocateDirect(infoLogLength.get(0))
            .order(ByteOrder.nativeOrder());
        glGetShaderInfoLog(id, infoLogLength, infoLog);

        String infoLogString =
            Charset.forName("US-ASCII").decode(infoLog).toString();
        if (infoLogString.trim().length() > 0)
        {
            System.out.println("shader log:
"+infoLogString);
        }
    }    
    /**
     * For debugging: Print program log info
     * 
     * @param id program ID
     */
    private void printProgramLogInfo(int id) 
    {
        IntBuffer infoLogLength = ByteBuffer.allocateDirect(4)
            .order(ByteOrder.nativeOrder())
            .asIntBuffer();
        glGetProgramiv(id, GL_INFO_LOG_LENGTH, infoLogLength);
        if (infoLogLength.get(0) > 0) 
        {
            infoLogLength.put(0, infoLogLength.get(0)-1);
        }

        ByteBuffer infoLog = ByteBuffer.allocateDirect(infoLogLength.get(0))
            .order(ByteOrder.nativeOrder());
        glGetProgramInfoLog(id, infoLogLength, infoLog);

        String infoLogString = 
            Charset.forName("US-ASCII").decode(infoLog).toString();
        if (infoLogString.trim().length() > 0)
        {
            System.out.println("program log:
"+infoLogString);
        }
    }    
    
}

#9

Vielen Dank, jetzt läuft es bei mir.
Also muss initialize nach createCapabilities stehen, allerdings muss createCapabilities jedes Mal (main loop) aufgerufen werden?
Und ich möchte noch das Array vertices ändern. Muss dafür glBindBuffer und glBufferData in der Main loop aufgerufen werden?
Und colorsBuffer benötige ich auch^^


#10

Würde mich wundern, müßte ich aber auch erst ausprobieren. (LWJGL3 hab ich noch nicht oft verwendet, und … wenn man den Boilerplate-Code einmal hat schreibt man ihn normalerweise nicht nochmal ;-))

Und ich möchte noch das Array vertices ändern. Muss dafür glBindBuffer und glBufferData in der Main loop aufgerufen werden?

Soweit ich weiß, ja.


#11

Morgen, ich hab den Vormittag damit verbracht und jetzt bin ich frustriert…
Das gleiche Spielchen nochmal mit C++(11), GLUT (und GLEW):

#include <cstdlib>
#include <iostream>
#include <GL/glew.h>
#include <GL/glut.h>
// #include <GL/glfw.h>
// #include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
using namespace std;
using namespace glm;

// Data for triangle 1
float vertices1[] = {-3.0f, 0.0f, -5.0f, 1.0f,
    -1.0f, 0.0f, -5.0f, 1.0f,
    -2.0f, 2.0f, -5.0f, 1.0f};
float colors1[] = {0.0f, 0.0f, 1.0f, 1.0f,
    0.0f, 0.0f, 1.0f, 1.0f,
    0.0f, 0.0f, 1.0f, 1.0f};

// Data for drawing Axis
float verticesAxis[] = {-20.0f, 0.0f, 0.0f, 1.0f,
    20.0f, 0.0f, 0.0f, 1.0f,

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

    0.0f, 0.0f, -20.0f, 1.0f,
    0.0f, 0.0f, 20.0f, 1.0f};
float colorAxis[] = {0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f};

const char * vertex_shader_text =
        "#version 150 
"
        "uniform mat4 viewMatrix, projMatrix; 
"
        "in vec4 position; 
"
        "in vec3 color; 
"
        "out vec3 Color; 
"
        "void main() 
"
        "{ 
"
        "    Color = color; 
"
        "    gl_Position = projMatrix * viewMatrix * position ; 
"
        "} 
";
const char * fragment_shader_text =
        "#version 150 
"
        "in vec3 Color; 
"
        "out vec4 outputF; 
"
        "void main() 
"
        "{ 
"
        "   outputF = vec4(Color,1.0); 
"
        "} 
";

// Program and Shader Identifiers
GLuint p, v, f;

// Vertex Attribute Locations
GLuint vertexLoc, colorLoc;

// Uniform variable Locations
GLuint projMatrixLoc, viewMatrixLoc;

// Vertex Array Objects Identifiers
GLuint vao[2];

// storage for Matrices
mat4 Projection, View, Model, mvp;

void setCamera(float posX, float posY, float posZ,
        float lookAtX, float lookAtY, float lookAtZ) {
    // Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
    Projection = perspective(radians(45.0f), (float) 1 / (float) 1, 0.1f, 100.0f);

    // Or, for an ortho camera :
    // Projection = ortho(-10.0f,10.0f,-10.0f,10.0f,0.0f,100.0f); // In world coordinates

    // Camera matrix
    View = lookAt(
            vec3(posX, posY, posZ), // the position of your camera, in world space
            vec3(lookAtX, lookAtY, lookAtZ), // where you want to look at, in world space
            vec3(0, 1, 0) // probably glm::vec3(0,1,0), but (0,-1,0) would make you looking upside-down, which can be great too
            );

    // Model matrix : an identity matrix (model will be at the origin)
    Model = mat4(1.0f);
    // Our ModelViewProjection : multiplication of our 3 matrices
    mvp = Projection * View * Model; // Remember, matrix multiplication is the other way around
}

void processNormalKeys(unsigned char key, int x, int y) {
    if (key == 27) {
        glDeleteVertexArrays(2, vao);
        glDeleteProgram(p);
        glDeleteShader(v);
        glDeleteShader(f);
        exit(0);
    }
}

void changeSize(int w, int h) {
    // ?
}

void renderScene(void) {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    setCamera(10, 10, 10, 0, 0, 0); // ?

    glUseProgram(p);
    // SET UNIFORMS
    glUniformMatrix4fv(projMatrixLoc, 1, false, value_ptr( Projection ) ); // ?
    glUniformMatrix4fv(viewMatrixLoc, 1, false, value_ptr( View ) ); // ?

    glBindVertexArray(vao[0]);
    glDrawArrays(GL_TRIANGLES, 0, 3);

    glBindVertexArray(vao[1]);
    glDrawArrays(GL_LINES, 0, 6);

    glutSwapBuffers();
}

int main(int argc, char** argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(320, 320);
    glutCreateWindow("Lighthouse 3D");

    glutDisplayFunc(renderScene);
    glutIdleFunc(renderScene);
    glutReshapeFunc(changeSize);
    glutKeyboardFunc(processNormalKeys);

    glewInit();
    if (glewIsSupported("GL_VERSION_3_0"))
        printf("Ready for OpenGL 3.0
");
    else {
        printf("OpenGL 3.0 not supported
");
        exit(1);
    }

    glEnable(GL_DEPTH_TEST);
    glClearColor(1.0, 1.0, 1.0, 1.0);

    // SETUP SHADERS
    glShaderSource(v, 1, &vertex_shader_text, NULL);
    glShaderSource(f, 1, &fragment_shader_text, NULL);

    glCompileShader(v);
    glCompileShader(f);

    p = glCreateProgram();
    glAttachShader(p, v);
    glAttachShader(p, f);

    glBindFragDataLocation(p, 0, "outputF");
    glLinkProgram(p);

    vertexLoc = glGetAttribLocation(p, "position");
    colorLoc = glGetAttribLocation(p, "color");

    projMatrixLoc = glGetUniformLocation(p, "projMatrix");
    viewMatrixLoc = glGetUniformLocation(p, "viewMatrix");

    // SETUP BUFFERS
    GLuint buffers[2];

    glGenVertexArrays(2, vao);
    //
    // VAO for first triangle
    //
    glBindVertexArray(vao[0]);
    // Generate two slots for the vertex and color buffers
    glGenBuffers(2, buffers);
    // bind buffer for vertices and copy data into buffer
    glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof (vertices1), vertices1, GL_STATIC_DRAW);
    glEnableVertexAttribArray(vertexLoc);
    glVertexAttribPointer(vertexLoc, 4, GL_FLOAT, 0, 0, 0);

    // bind buffer for colors and copy data into buffer
    glBindBuffer(GL_ARRAY_BUFFER, buffers[1]);
    glBufferData(GL_ARRAY_BUFFER, sizeof (colors1), colors1, GL_STATIC_DRAW);
    glEnableVertexAttribArray(colorLoc);
    glVertexAttribPointer(colorLoc, 4, GL_FLOAT, 0, 0, 0);

    //
    // This VAO is for the Axis
    //
    glBindVertexArray(vao[1]);
    // Generate two slots for the vertex and color buffers
    glGenBuffers(2, buffers);
    // bind buffer for vertices and copy data into buffer
    glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof (verticesAxis), verticesAxis, GL_STATIC_DRAW);
    glEnableVertexAttribArray(vertexLoc);
    glVertexAttribPointer(vertexLoc, 4, GL_FLOAT, 0, 0, 0);

    // bind buffer for colors and copy data into buffer
    glBindBuffer(GL_ARRAY_BUFFER, buffers[1]);
    glBufferData(GL_ARRAY_BUFFER, sizeof (colorAxis), colorAxis, GL_STATIC_DRAW);
    glEnableVertexAttribArray(colorLoc);
    glVertexAttribPointer(colorLoc, 4, GL_FLOAT, 0, 0, 0);




    glutMainLoop();

    return (0);
}

Meine Referenzen sind:
OpenGL 3.3 + GLSL 1.5 Sample » Lighthouse3d.com
und Tutorial 3 : Matrices

Problem:
Ich seh nix, ich weiß nicht, warum ich nix sehe, ich weiß nicht mal, ob ich mit der Kamera vor oder hinter den Objekten bin,
ich weiß nicht, ob value_ptr( stimmt, ich weiß nicht, ob der Shader überhaupt geladen wird, ich weiß nicht, wieso auf einmal vec3 nach vec4 …

Das außen drumrum ist Ronz, schön Beschrieben.


#12

Warum ist changeSize leer?

Allgemein: Wenn man in GL nichts sieht, kann das tausende Gründe haben. Selbst WENN jemand hier dir deine Arbeit abnehmen soll, dein Programm zu debuggen, müßte man wissen, was im Vergleich zu einer “funktionierenden” Variante geändert ist. (Ja: Dann wüßtest du schon selbst, woran es liegt). Es macht einfach keinen Sinn, Shader-Code zu lesen und initialisierungen zu prüfen und debug-Ausgaben einzubauen, nur um dann z.B. über eine leere “changeSize”-Funktion zu stolpern.

  1. Nimm ein funktionierendes Beispiel.
  2. Mache EINE (MINIMALE) Änderung
  3. Prüfe, ob es funktioniert
    – Ja? Gehe zu 2.
    – Nein? Überlege, warum es nicht funktioniert.
    Das ist dann was, wonach man hier fragen kann: “Mit 1.2 ging es noch, aber mit 1.3 geht es nicht mehr, warum?”. Aber hier 200 Zeilen Frankencode zu posten und zu sagen “Er zeigt nix an” führt zu nichts.

#13

Ich bekomm’s nicht zum Laufen, das LWJGL-Beispiel läuft auch nicht mehr.

        try (MemoryStack stack = stackPush()) {
            IntBuffer pWidth = stack.mallocInt(1); // int*
            IntBuffer pHeight = stack.mallocInt(1); // int*
 
            // Get the window size passed to glfwCreateWindow
            glfwGetWindowSize(window, pWidth, pHeight);
 
            // Get the resolution of the primary monitor
            GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
 
            // Center the window
            glfwSetWindowPos(
                    window,
                    (vidmode.width() - pWidth.get(0)) / 2,
                    (vidmode.height() - pHeight.get(0)) / 2
            );
        } // the stack frame is popped automatically```

... verstehe ich überhaupt nicht, ist das obligatorisch?

Ich möchte einfach ein Beispiel für:
LWJGL + OpenGL 3 + JOML + GLSL + MVP + .perspective() + .lookAt() + Color buffer ...

Kannst du so ein Beispiel bringen?
Nützt es etwas, wenn ich das nicht funktionierende LWGL-Beispiel hier poste?
Welches Buch, das die obigen Themen behandelt, könntest du mir empfehlen?

#14

Ich werd’ jetzt nicht irgendein Beispiel bauen - ausgehend von https://github.com/JOML-CI/joml-lwjgl3-demos/tree/master/src/org/joml/lwjgl sollte sich ja was machen lassen…


#15

Das Objekt wird hier auch nicht angezeigt, nur der Hintergrund, keine Fehler im Programm und Shader, wieso?:

 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package spielex;

/**
 * @author
 */
import org.lwjgl.*;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.*;
import org.lwjgl.system.*;

import java.nio.*;
import java.nio.charset.Charset;
import org.joml.*;
import org.joml.Math;

import static org.lwjgl.glfw.Callbacks.*;
import static org.lwjgl.glfw.GLFW.*;
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 static org.lwjgl.system.MemoryStack.*;
import static org.lwjgl.system.MemoryUtil.*;

public class SpielEx {

    // The window handle
    private long window;

    // ProgramID
    int programID;
    // Vertex Shader ID
    int vertexShaderID;
    // Fragment Shader ID
    int fragmentShaderID;

    int vaoID;
    int vboID;
    int vcoID;

    int MLoc, VLoc, PLoc;

    public void run() {
        System.out.println("Hello LWJGL " + Version.getVersion() + "!");

        init();
        loop();

        // Free the window callbacks and destroy the window
        glfwFreeCallbacks(window);
        glfwDestroyWindow(window);

        // Terminate GLFW and free the error callback
        glfwTerminate();
        glfwSetErrorCallback(null).free();
    }

    private void init() {
        // Setup an error callback. The default implementation
        // will print the error message in System.err.
        GLFWErrorCallback.createPrint(System.err).set();

        // Initialize GLFW. Most GLFW functions will not work before doing this.
        if (!glfwInit()) {
            throw new IllegalStateException("Unable to initialize GLFW");
        }

        // Configure GLFW
        glfwDefaultWindowHints(); // optional, the current window hints are already the default
        glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // the window will stay hidden after creation
        glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); // the window will be resizable

        // Create the window
        window = glfwCreateWindow(300, 300, "Hello World!", NULL, NULL);
        if (window == NULL) {
            throw new RuntimeException("Failed to create the GLFW window");
        }

        // Setup a key callback. It will be called every time a key is pressed, repeated or released.
        glfwSetKeyCallback(window, (windo, key, scancode, action, mods) -> {
            if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE) {
                glfwSetWindowShouldClose(windo, true); // We will detect this in the rendering loop
            }
        });

        // Get the thread stack and push a new frame
        try (MemoryStack stack = stackPush()) {
            IntBuffer pWidth = stack.mallocInt(1); // int*
            IntBuffer pHeight = stack.mallocInt(1); // int*

            // Get the window size passed to glfwCreateWindow
            glfwGetWindowSize(window, pWidth, pHeight);

            // Get the resolution of the primary monitor
            GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());

            // Center the window
            glfwSetWindowPos(
                    window,
                    (vidmode.width() - pWidth.get(0)) / 2,
                    (vidmode.height() - pHeight.get(0)) / 2
            );
        } // the stack frame is popped automatically

        // Make the OpenGL context current
        glfwMakeContextCurrent(window);
        // Enable v-sync
        glfwSwapInterval(1);

        // Make the window visible
        glfwShowWindow(window);

        /* Etwas eingefügt ANFANG */
        GL.createCapabilities();

        programID = glCreateProgram();
        vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vertexShaderID, "#version 330 core
"
                + "
"
                + "layout (location = 0) in vec3 position;
"
                + "layout (location = 1) in vec3 inColour;
"
                + "uniform mat4 M;
"
                + "uniform mat4 V;
"
                + "uniform mat4 P;
"
                + "
"
                + "out vec3 exColour;
"
                + "
"
                + "void main()
"
                + "{
"
                + "    gl_Position = P * V * vec4(position, 1.0);
"
                + "    exColour = inColour;
"
                + "}
"
                + "");
        glCompileShader(vertexShaderID);
        printShaderLogInfo(vertexShaderID);
        glAttachShader(programID, vertexShaderID);
        MLoc = glGetAttribLocation(programID, "M");
        VLoc = glGetAttribLocation(programID, "V");
        PLoc = glGetAttribLocation(programID, "P");

        fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); // XXX Fragment, not vertex
        glShaderSource(fragmentShaderID, "#version 330 core
"
                + "
"
                + "in vec3 exColour;
"
                + "out vec4 fragColor;
"
                + "
"
                + "void main()
"
                + "{
"
                + "    fragColor = vec4(exColour, 1.0);
"
                + "}
"
                + "");
        glCompileShader(fragmentShaderID);
        printShaderLogInfo(fragmentShaderID);
        glAttachShader(programID, fragmentShaderID);

        glLinkProgram(programID);
        if (glGetProgrami(programID, GL_LINK_STATUS) == GL_FALSE) {
            printProgramLogInfo(programID);
            throw new RuntimeException("Unable to link shader program:");
        }

        // Generate and bind a Vertex Array
        vaoID = glGenVertexArrays();
        glBindVertexArray(vaoID);

// The vertices of our Triangle
        float[] vertices = new float[]{
            +0.0f, +5.0f, +0.0f, // Top coordinate
            -5.0f, -5.0f, +0.0f, // Bottom-left coordinate
            +5.0f, -5.0f + 0.0f // Bottom-right coordinate
        };

// Create a FloatBuffer of vertices
        FloatBuffer verticesBuffer = BufferUtils.createFloatBuffer(vertices.length);
        verticesBuffer.put(vertices).flip();

// Create a Buffer Object and upload the vertices buffer
        vboID = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vboID);
        glBufferData(GL_ARRAY_BUFFER, verticesBuffer, GL_STATIC_DRAW);

        glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);

        // Colour VBO
        vcoID = glGenBuffers();
        FloatBuffer colourBuffer = memAllocFloat(9);
        colourBuffer.put(new float[]{1f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 1f}).flip();
        glBindBuffer(GL_ARRAY_BUFFER, vcoID);
        glBufferData(GL_ARRAY_BUFFER, colourBuffer, GL_STATIC_DRAW);
        glVertexAttribPointer(1, 3, GL_FLOAT, false, 0, 0);

        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindVertexArray(0);

        /* Etwas eingefügt ENDE */
    }

    private void loop() {
        // This line is critical for LWJGL's interoperation with GLFW's
        // OpenGL context, or any context that is managed externally.
        // LWJGL detects the context that is current in the current thread,
        // creates the GLCapabilities instance and makes the OpenGL
        // bindings available for use.
        GL.createCapabilities();

        // Set the clear color
        glClearColor(0.0f, 1.0f, 0.0f, 0.0f);

        // Run the rendering loop until the user has attempted to close
        // the window or has pressed the ESCAPE key.
        while (!glfwWindowShouldClose(window)) {
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer

            /* Etwas eingefügt ANFANG */
            glUseProgram(programID);

            // Bind the vertex array and enable our location
            glBindVertexArray(vaoID);
            glEnableVertexAttribArray(0);

            // Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
            Matrix4f Projection = new Matrix4f().perspective((float) Math.toRadians(45.0f), 1.0f, 0.01f, 100.0f);

// Or, for an ortho camera :
//glm::mat4 Projection = glm::ortho(-10.0f,10.0f,-10.0f,10.0f,0.0f,100.0f); // In world coordinates
// Camera matrix
            Matrix4f View = new Matrix4f().lookAt(
                    10.0f, 10.0f, 10.0f,
                    0.0f, 0.0f, 0.0f,
                    0.0f, 1.0f, 0.0f);

// Model matrix : an identity matrix (model will be at the origin)
            Matrix4f Model = new Matrix4f();

            glUniformMatrix4fv(MLoc, false, Model.get(new float[16]));
            glUniformMatrix4fv(VLoc, false, View.get(new float[16]));
            glUniformMatrix4fv(PLoc, false, Projection.get(new float[16]));

            // Draw a triangle of 3 vertices
            glDrawArrays(GL_TRIANGLES, 0, 3);

            // Disable our location
            glDisableVertexAttribArray(0);
            glBindVertexArray(0);

            glUseProgram(0);
            /* Etwas eingefügt ENDE */

            glfwSwapBuffers(window); // swap the color buffers

            // Poll for window events. The key callback above will only be
            // invoked during this call.
            glfwPollEvents();
        }
    }

    public static void main(String[] args) {
        new SpielEx().run();
    }

    /**
     * For debugging: Print shader log info
     *
     * @param id shader ID
     */
    private void printShaderLogInfo(int id) {
        IntBuffer infoLogLength = ByteBuffer.allocateDirect(4)
                .order(ByteOrder.nativeOrder())
                .asIntBuffer();
        glGetShaderiv(id, GL_INFO_LOG_LENGTH, infoLogLength);
        if (infoLogLength.get(0) > 0) {
            infoLogLength.put(0, infoLogLength.get(0) - 1);
        }

        ByteBuffer infoLog = ByteBuffer.allocateDirect(infoLogLength.get(0))
                .order(ByteOrder.nativeOrder());
        glGetShaderInfoLog(id, infoLogLength, infoLog);

        String infoLogString
                = Charset.forName("US-ASCII").decode(infoLog).toString();
        if (infoLogString.trim().length() > 0) {
            System.out.println("shader log:
" + infoLogString);
        }
    }

    /**
     * For debugging: Print program log info
     *
     * @param id program ID
     */
    private void printProgramLogInfo(int id) {
        IntBuffer infoLogLength = ByteBuffer.allocateDirect(4)
                .order(ByteOrder.nativeOrder())
                .asIntBuffer();
        glGetProgramiv(id, GL_INFO_LOG_LENGTH, infoLogLength);
        if (infoLogLength.get(0) > 0) {
            infoLogLength.put(0, infoLogLength.get(0) - 1);
        }

        ByteBuffer infoLog = ByteBuffer.allocateDirect(infoLogLength.get(0))
                .order(ByteOrder.nativeOrder());
        glGetProgramInfoLog(id, infoLogLength, infoLog);

        String infoLogString
                = Charset.forName("US-ASCII").decode(infoLog).toString();
        if (infoLogString.trim().length() > 0) {
            System.out.println("program log:
" + infoLogString);
        }
    }
}

#16

Nochmal: Das sind 300 Zeilen code, in denen du (no offense) planlos “irgendwas” geändert hast. Wer soll sich das antun?
Funktionieren die verlinkten Beispiele?
Wenn nein: Issue aufmachen (oder hier fragen).
Wenn ja: https://github.com/JOML-CI/joml-lwjgl3-demos/blob/master/src/org/joml/lwjgl/FirstPersonCameraDemo.java und https://github.com/JOML-CI/joml-lwjgl3-demos/blob/master/src/org/joml/lwjgl/ShaderExampleLH.java nachvollziehen und los.

Aber beim Drüberscrollen:

Model.get(new float[16])

sieht SEHR stark falsch aus (ich bin nicht 100% sicher, aber ziemlich)

Siehe https://github.com/JOML-CI/JOML#using-with-lwjgl

FloatBuffer fb = BufferUtils.createFloatBuffer(16);
new Matrix4f().perspective((float) Math.toRadians(45.0f), 1.0f, 0.01f, 100.0f)
              .lookAt(0.0f, 0.0f, 10.0f,
                      0.0f, 0.0f, 0.0f,
                      0.0f, 1.0f, 0.0f).get(fb);
glUniformMatrix4fv(mat4Location, false, fb);

(Den Buffer am besten nur EINmal global allokieren, aber … das ist ein Detail)


#17

Könnte es hieran liegen (man sieht weiterhin nur den grünen Hintergrund):

            // Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
            Matrix4f Projection = new Matrix4f().perspective((float) Math.toRadians(45.0f), 1.0f, 0.01f, 100.0f);

// Or, for an ortho camera :
// glm::mat4 Projection = glm::ortho(-10.0f,10.0f,-10.0f,10.0f,0.0f,100.0f);
// Camera matrix
            Matrix4f View = new Matrix4f().lookAt(
                    0.0f, 0.0f, 10.0f,
                    0.0f, 0.0f, 0.0f,
                    0.0f, 1.0f, 0.0f);

// Model matrix : an identity matrix (model will be at the origin)
            Matrix4f Model = new Matrix4f();

            FloatBuffer fb = BufferUtils.createFloatBuffer(16);

            Model.get(fb);
            glUniformMatrix4fv(MLoc, false, fb);
            View.get(fb);
            glUniformMatrix4fv(VLoc, false, fb);
            Projection.get(fb);
            glUniformMatrix4fv(PLoc, false, fb);

Links hab ich mir alle durchgelesen. Das Problem, das sind alles keine OpenGL 3-Beispiele. :frowning:

Edit: Es ist natürlich nicht sinnvoll, das Model zu übergeben…

Und falls ich das zum Laufen bekomme, kennst du einen Algorithmus um alle Objekte gleichgroß zu machen?


Hier ist nochmal die gesamte Render-Methode:

        // Run the rendering loop until the user has attempted to close
        // the window or has pressed the ESCAPE key.
        while (!glfwWindowShouldClose(window)) {
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer

            /* Etwas eingefügt ANFANG */
            glUseProgram(programID);

            // Bind the vertex array and enable our location
            glBindVertexArray(vaoID);
            glEnableVertexAttribArray(0);

            // Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
            Matrix4f Projection = new Matrix4f().perspective((float) Math.toRadians(45.0f), 1.0f, 0.01f, 100.0f);

// Or, for an ortho camera :
// glm::mat4 Projection = glm::ortho(-10.0f,10.0f,-10.0f,10.0f,0.0f,100.0f);
// Camera matrix
            Matrix4f View = new Matrix4f().lookAt(
                    0.0f, 0.0f, 10.0f,
                    0.0f, 0.0f, 0.0f,
                    0.0f, 1.0f, 0.0f);

// Model matrix : an identity matrix (model will be at the origin)
            Matrix4f Model = new Matrix4f();

            FloatBuffer fb = BufferUtils.createFloatBuffer(16);

            Model.get(fb);
            glUniformMatrix4fv(MLoc, false, fb);
            View.get(fb);
            glUniformMatrix4fv(VLoc, false, fb);
            Projection.get(fb);
            glUniformMatrix4fv(PLoc, false, fb);

            // Draw a triangle of 3 vertices
            glDrawArrays(GL_TRIANGLES, 0, 3);

            // Disable our location
            glDisableVertexAttribArray(0);
            glBindVertexArray(0);

            glUseProgram(0);
            /* Etwas eingefügt ENDE */

            glfwSwapBuffers(window); // swap the color buffers

            // Poll for window events. The key callback above will only be
            // invoked during this call.
            glfwPollEvents();
        }

#18

Guten Morgen, @Marco13 ich hab es (mit Deiner Hilfe) hinbekommen - und möchte euch das Ergebnis nicht vorenthalten:

 /*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package spielex;

/**
 * @author
 */
import org.lwjgl.*;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.*;
import org.lwjgl.system.*;

import java.nio.*;
import java.nio.charset.Charset;
import org.joml.*;
import org.joml.Math;

import static org.lwjgl.glfw.Callbacks.*;
import static org.lwjgl.glfw.GLFW.*;
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 static org.lwjgl.system.MemoryStack.*;
import static org.lwjgl.system.MemoryUtil.*;

public class SpielEx {

    // The window handle
    private long window;

    // ProgramID
    int programID;
    // Vertex Shader ID
    int vertexShaderID;
    // Fragment Shader ID
    int fragmentShaderID;

    int vaoID;
    int vboID;
    int vcoID;

    int MLoc, VLoc, PLoc;

    public void run() {
        System.out.println("Hello LWJGL " + Version.getVersion() + "!");

        init();
        loop();

        // Free the window callbacks and destroy the window
        glfwFreeCallbacks(window);
        glfwDestroyWindow(window);

        // Terminate GLFW and free the error callback
        glfwTerminate();
        glfwSetErrorCallback(null).free();
    }

    private void init() {
        // Setup an error callback. The default implementation
        // will print the error message in System.err.
        GLFWErrorCallback.createPrint(System.err).set();

        // Initialize GLFW. Most GLFW functions will not work before doing this.
        if (!glfwInit()) {
            throw new IllegalStateException("Unable to initialize GLFW");
        }

        // Configure GLFW
        glfwDefaultWindowHints(); // optional, the current window hints are already the default
        glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // the window will stay hidden after creation
        glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); // the window will be resizable

        // Create the window
        window = glfwCreateWindow(900, 900, "Hello World!", NULL, NULL);
        if (window == NULL) {
            throw new RuntimeException("Failed to create the GLFW window");
        }

        // Setup a key callback. It will be called every time a key is pressed, repeated or released.
        glfwSetKeyCallback(window, (windo, key, scancode, action, mods) -> {
            if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE) {
                glfwSetWindowShouldClose(windo, true); // We will detect this in the rendering loop
            }
        });

        // Get the thread stack and push a new frame
        try (MemoryStack stack = stackPush()) {
            IntBuffer pWidth = stack.mallocInt(1); // int*
            IntBuffer pHeight = stack.mallocInt(1); // int*

            // Get the window size passed to glfwCreateWindow
            glfwGetWindowSize(window, pWidth, pHeight);

            // Get the resolution of the primary monitor
            GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());

            // Center the window
            glfwSetWindowPos(
                    window,
                    (vidmode.width() - pWidth.get(0)) / 2,
                    (vidmode.height() - pHeight.get(0)) / 2
            );
        } // the stack frame is popped automatically

        // Make the OpenGL context current
        glfwMakeContextCurrent(window);
        // Enable v-sync
        glfwSwapInterval(1);

        // Make the window visible
        glfwShowWindow(window);

        /* Etwas eingefügt ANFANG */
        GL.createCapabilities();

        programID = glCreateProgram();
        vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vertexShaderID, "#version 330 core\n"
                + "\n"
                + "layout (location = 0) in vec3 position;\n"
                + "layout (location = 1) in vec3 inColour;\n"
                + "uniform mat4 M;\n"
                + "uniform mat4 V;\n"
                + "uniform mat4 P;\n"
                + "\n"
                + "out vec3 exColour;\n"
                + "\n"
                + "void main()\n"
                + "{\n"
                + "    gl_Position = P * V * M * vec4(position, 1.0);\n"
                + "    exColour = inColour;\n"
                + "}\n"
                + "");
        glCompileShader(vertexShaderID);
        printShaderLogInfo(vertexShaderID);
        glAttachShader(programID, vertexShaderID);

        fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); // XXX Fragment, not vertex
        glShaderSource(fragmentShaderID, "#version 330 core\n"
                + "\n"
                + "in vec3 exColour;\n"
                + "out vec4 fragColor;\n"
                + "\n"
                + "void main()\n"
                + "{\n"
                + "    fragColor = vec4(exColour, 1.0);\n"
                + "}\n"
                + "");
        glCompileShader(fragmentShaderID);
        printShaderLogInfo(fragmentShaderID);
        glAttachShader(programID, fragmentShaderID);

        glLinkProgram(programID);
        if (glGetProgrami(programID, GL_LINK_STATUS) == GL_FALSE) {
            printProgramLogInfo(programID);
            throw new RuntimeException("Unable to link shader program:");
        }

        MLoc = glGetUniformLocation(programID, "M");
        VLoc = glGetUniformLocation(programID, "V");
        PLoc = glGetUniformLocation(programID, "P");

        // Generate and bind a Vertex Array
        vaoID = glGenVertexArrays();
        glBindVertexArray(vaoID);

        // The vertices of our Triangle
        float[] vertices = new float[]{
            +0.0f, +5.0f, +0.0f, // Top coordinate
            -5.0f, -5.0f, +0.0f, // Bottom-left coordinate
            +5.0f, -5.0f + 0.0f // Bottom-right coordinate
        };

        FloatBuffer verticesBuffer = BufferUtils.createFloatBuffer(vertices.length);
        verticesBuffer.put(vertices).flip();
        vboID = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vboID);
        glBufferData(GL_ARRAY_BUFFER, verticesBuffer, GL_STATIC_DRAW);
        glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);

        FloatBuffer colourBuffer = BufferUtils.createFloatBuffer(9);
        colourBuffer.put(new float[]{1f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 1f}).flip();
        vcoID = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vcoID);
        glBufferData(GL_ARRAY_BUFFER, colourBuffer, GL_STATIC_DRAW);
        glVertexAttribPointer(1, 3, GL_FLOAT, false, 0, 0);

        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindVertexArray(0);

        /* Etwas eingefügt ENDE */
    }

    private void loop() {
        // This line is critical for LWJGL's interoperation with GLFW's
        // OpenGL context, or any context that is managed externally.
        // LWJGL detects the context that is current in the current thread,
        // creates the GLCapabilities instance and makes the OpenGL
        // bindings available for use.
        GL.createCapabilities();

        // Set the clear color
        glClearColor(0.0f, 1.0f, 0.0f, 0.0f);

        // Run the rendering loop until the user has attempted to close
        // the window or has pressed the ESCAPE key.
        while (!glfwWindowShouldClose(window)) {
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer

            /* Etwas eingefügt ANFANG */
            glUseProgram(programID);

            // Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
            Matrix4f Projection = new Matrix4f().perspective((float) Math.toRadians(45.0f), 1.0f, 0.01f, 100.0f);

            // Or, for an ortho camera :
            // glm::mat4 Projection = glm::ortho(-10.0f,10.0f,-10.0f,10.0f,0.0f,100.0f);
            // Camera matrix
            Matrix4f View = new Matrix4f().lookAt(
                    10.0f, 10.0f, 15.0f,
                    0.0f, 0.0f, 0.0f,
                    0.0f, 1.0f, 0.0f);

            // Model matrix : an identity matrix (model will be at the origin)
            Matrix4f Model = new Matrix4f()/*.rotate(System.currentTimeMillis() % 5000 / 5000f * 2f * (float) Math.PI, new Vector3f(0, 1, 0))*/;

            FloatBuffer fb = BufferUtils.createFloatBuffer(16);

            Model.get(fb);
            glUniformMatrix4fv(MLoc, false, fb);
            View.get(fb);
            glUniformMatrix4fv(VLoc, false, fb);
            Projection.get(fb);
            glUniformMatrix4fv(PLoc, false, fb);

            glEnableVertexAttribArray(0);
            glBindBuffer(GL_ARRAY_BUFFER, vboID);
            glVertexAttribPointer(
                    0, // attribute. No particular reason for 0, but must match the layout in the shader.
                    3, // size
                    GL_FLOAT, // type
                    false, // normalized?
                    0, // stride
                    0 // array buffer offset
            );

            glEnableVertexAttribArray(1);
            glBindBuffer(GL_ARRAY_BUFFER, vcoID);
            glVertexAttribPointer(
                    1, // attribute. No particular reason for 0, but must match the layout in the shader.
                    3, // size
                    GL_FLOAT, // type
                    false, // normalized?
                    0, // stride
                    0 // array buffer offset
            );

            // Draw a triangle of 3 vertices
            glDrawArrays(GL_TRIANGLES, 0, 3);

            // Disable our location
            glDisableVertexAttribArray(0);
            glBindVertexArray(0);

            glUseProgram(0);
            /* Etwas eingefügt ENDE */

            glfwSwapBuffers(window); // swap the color buffers

            // Poll for window events. The key callback above will only be
            // invoked during this call.
            glfwPollEvents();
        }
    }

    public static void main(String[] args) {
        new SpielEx().run();
    }

    /**
     * For debugging: Print shader log info
     *
     * @param id shader ID
     */
    private void printShaderLogInfo(int id) {
        IntBuffer infoLogLength = ByteBuffer.allocateDirect(4)
                .order(ByteOrder.nativeOrder())
                .asIntBuffer();
        glGetShaderiv(id, GL_INFO_LOG_LENGTH, infoLogLength);
        if (infoLogLength.get(0) > 0) {
            infoLogLength.put(0, infoLogLength.get(0) - 1);
        }

        ByteBuffer infoLog = ByteBuffer.allocateDirect(infoLogLength.get(0))
                .order(ByteOrder.nativeOrder());
        glGetShaderInfoLog(id, infoLogLength, infoLog);

        String infoLogString
                = Charset.forName("US-ASCII").decode(infoLog).toString();
        if (infoLogString.trim().length() > 0) {
            System.out.println("shader log:\n" + infoLogString);
        }
    }

    /**
     * For debugging: Print program log info
     *
     * @param id program ID
     */
    private void printProgramLogInfo(int id) {
        IntBuffer infoLogLength = ByteBuffer.allocateDirect(4)
                .order(ByteOrder.nativeOrder())
                .asIntBuffer();
        glGetProgramiv(id, GL_INFO_LOG_LENGTH, infoLogLength);
        if (infoLogLength.get(0) > 0) {
            infoLogLength.put(0, infoLogLength.get(0) - 1);
        }

        ByteBuffer infoLog = ByteBuffer.allocateDirect(infoLogLength.get(0))
                .order(ByteOrder.nativeOrder());
        glGetProgramInfoLog(id, infoLogLength, infoLog);

        String infoLogString
                = Charset.forName("US-ASCII").decode(infoLog).toString();
        if (infoLogString.trim().length() > 0) {
            System.out.println("program log:\n" + infoLogString);
        }
    }
}

Wenn Du Zeile 230 auskommentierst, dann dreht sich das Dreieck in 5 Sek. einmal um sich selbst.

Und so schaut es momentan:

Jetzt hab ich 'ne Basis, auf der ich aufbauen kann, mit:
LWJGL + OpenGL 3 + JOML + GLSL + MVP + .perspective() + .lookAt() + Color buffer …

Ein echtes OpenGL 3-Tutorial, was mir auch geholfen hat:
https://github.com/opengl-tutorials/ogl/blob/master/tutorial04_colored_cube/tutorial04.cpp

Gern kannst Du noch Verbesserungen machen, falls etwas auffällt…

Grüße

Anmerkung: Dieses Thema kann als [gelöst] angesehen werden.

##Edit
Weitere Frage wäre, wie ich alle Objekte gleichgroß mache… Durch Skalierung? Wie funktioniert Skalierung? Und speichere ich dann das Mesh?