在LWJGL 3中使用VAOs和VBOs渲染四边形时出现问题。

huangapple go评论75阅读模式
英文:

Problem with rendering a quad in LWJGL 3 using VAOs and VBOs

问题

以下是您提供的代码的翻译部分:

public class RawModel {
    private int vaoID;
    private int vertexCount;
     
    public RawModel(int vaoID, int vertexCount) {
        this.vaoID = vaoID;
        this.vertexCount = vertexCount;
    }
 
    public int getVaoID() {
        return vaoID;
    }
 
    public int getVertexCount() {
        return vertexCount;
    }
}

public class Loader {
        
    private List<Integer> vaos = new ArrayList<Integer>();
    private List<Integer> vbos = new ArrayList<Integer>();
     
    public RawModel loadToVAO(float[] positions) {
        int vaoID = createVAO();
        storeDataInAttributeList(0, positions);
        unbindVAO();
        return new RawModel(vaoID, positions.length/3);
    }
     
    private int createVAO() {
        int vaoID = GL30.glGenVertexArrays();
        vaos.add(vaoID);
        GL30.glBindVertexArray(vaoID);
        return vaoID;
    }
     
    private void storeDataInAttributeList(int attributeNumber, float[] data) {
        int vboID = GL15.glGenBuffers();
        vbos.add(vboID);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboID);
        FloatBuffer buffer = storeDataInFloatBuffer(data);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
        GL20.glVertexAttribPointer(attributeNumber, 3, GL11.GL_FLOAT, false, 0, 0);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
    }
     
    private void unbindVAO() {
        GL30.glBindVertexArray(0);
    }
     
    private FloatBuffer storeDataInFloatBuffer(float[] data) {
        FloatBuffer buffer = MemoryUtil.memAllocFloat(data.length);
        buffer.put(data);
        buffer.flip();
        return buffer;
    }
     
    public void cleanUp() {
        for (int vao : vaos) {
            GL30.glDeleteVertexArrays(vao);
        }
        for (int vbo : vbos) {
            GL15.glDeleteBuffers(vbo);
        }
    }
}

public class Renderer {

    public void prepare() {
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
        GL11.glClearColor(1f, 0f, 1f, 1f);
    }
     
    public void render(RawModel model) {
        GL30.glBindVertexArray(model.getVaoID());
        GL20.glEnableVertexAttribArray(0);
        GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, model.getVertexCount());
        GL20.glDisableVertexAttribArray(0);
        GL30.glBindVertexArray(0);
    }
}

public class Window {
    private int width, height;
    private String title;
    private long window;
 
    public Window(int width, int height, String title) {
        this.width = width;
        this.height = height;
        this.title = title;
    }
 
    public void create() {
        GLFWErrorCallback.createPrint(System.err).set();
 
        if (!glfwInit())
            throw new IllegalStateException("Unable to initialize GLFW");
 
        glfwDefaultWindowHints();
        glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
        glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
 
        window = glfwCreateWindow(width, height, "Flappy Bird", NULL, NULL);
        if (window == NULL)
            throw new RuntimeException("Failed to create the GLFW window");
 
        try (MemoryStack stack = stackPush()) {
            IntBuffer pWidth = stack.mallocInt(1);
            IntBuffer pHeight = stack.mallocInt(1);
 
            glfwGetWindowSize(window, pWidth, pHeight);
 
            GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
 
            glfwSetWindowPos(window, (vidmode.width() - pWidth.get(0)) / 2, (vidmode.height() - pHeight.get(0)) / 2);
        }
         
        glfwSetKeyCallback(window, (window, key, scancode, action, mods) -> {
            if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE)
                glfwSetWindowShouldClose(window, true);
        });
 
        glfwMakeContextCurrent(window);
        glfwSwapInterval(1);
 
        glfwShowWindow(window);
    }
 
    public long getWindowNum() {
        return window;
    }
}

public class Main {
 
    private Window window;
     
    Loader loader = new Loader();
    Renderer renderer = new Renderer();
     
    float[] vertices = {
        -0.5f, 0.5f, 0f,
        -0.5f, -0.5f, 0f,
        0.5f, -0.5f, 0f,
        0.5f, -0.5f, 0f,
        0.5f, 0.5f, 0f,
        -0.5f, 0.5f, 0f
    };
     
    RawModel model;
     
    public void run() {
        setup();
        loop();
         
        loader.cleanUp();
 
        glfwFreeCallbacks(window.getWindowNum());
        glfwDestroyWindow(window.getWindowNum());
         
        glfwTerminate();
        glfwSetErrorCallback(null).free();
    }
 
    private void loop() {
        while (!glfwWindowShouldClose(window.getWindowNum())) {
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
             
            renderer.render(model);
             
            glfwSwapBuffers(window.getWindowNum());
             
            glfwPollEvents();
        }
    }
 
    public void setup() {
        window = new Window(900, 300, "Flappy Bird");
        window.create();
         
        GL.createCapabilities();
        GLFW.glfwMakeContextCurrent(window.getWindowNum());
 
        model = loader.loadToVAO(vertices);
        renderer.prepare();
         
        GL11.glViewport(0, 0, 900, 300);
    }
     
    public static void main(String[] args) {
        new Main().run();
    }
}
英文:

(This is the second time I am asking this question. Last time I got one answer that didn't solve it (the answer there referred a bit of code that was left accidentally from one of my attempts at fixing this). I also changed the question itself slightly - I changed the order of code to put the part where I believe the mistake higher is and added that I am using macOS, which might be the reason that it doesn't work).

So, I just started learning LWJGL 3 and I used a mixture of a couple of tutorials and example code to make something that should render a rectangle to a magenta screen using VAOs and VBOs. There are no errors but the rectangle doesn't appear on screen (all I can see is a magenta screen). I tried using the old LWJGL pipeline (glBegin() and glEnd()) and it does work so I tried changing random things in the rendering code and the loading to VAOs and VBOs. I also tried to bind the VBO too but it didn't change anything. I also tried debugging and it seems like there is a VAO and a VBO that is created.

Can someone take a look at my code and see if something looks wrong? Here it is (sorry if its a bit messy. Like I said, I don't think the problem is in the Main or Window class but I have no idea about LWJGL so I wanted to put it here anyways. If you have time, please also look at them. Otherwise I would really appreciate it if you could look at the Loader and Renderer classes):

(Btw, I am using macOS, and I do have -XstartOnFirstThread on).

The Raw Model class:

package engine.io;
 
public class RawModel {
    private int vaoID;
    private int vertexCount;
     
    public RawModel(int vaoID, int vertexCount) {
        this.vaoID = vaoID;
        this.vertexCount = vertexCount;
    }
 
    public int getVaoID() {
        return vaoID;
    }
 
    public int getVertexCount() {
        return vertexCount;
    }
}

The loader class:

package engine.io;
 
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.List;

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.lwjgl.system.MemoryUtil;

public class Loader {
        
    private List&lt;Integer&gt; vaos = new ArrayList&lt;Integer&gt;();
    private List&lt;Integer&gt; vbos = new ArrayList&lt;Integer&gt;();
     
    public RawModel loadToVAO(float[] positions) {
        int vaoID = createVAO();
        storeDataInAttributeList(0, positions);
        unbindVAO();
        return new RawModel(vaoID, positions.length/3);
    }
     
    private int createVAO() {
        int vaoID = GL30.glGenVertexArrays();
        vaos.add(vaoID);
        GL30.glBindVertexArray(vaoID);
        return vaoID;
    }
     
    private void storeDataInAttributeList(int attributeNumber, float[] data) {
        int vboID = GL15.glGenBuffers();
        vbos.add(vboID);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboID);
        FloatBuffer buffer = storeDataInFloatBuffer(data);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
        GL20.glVertexAttribPointer(attributeNumber, 3, GL11.GL_FLOAT, false, 0, 0);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
    }
     
    private void unbindVAO() {
        GL30.glBindVertexArray(0);
    }
     
    private FloatBuffer storeDataInFloatBuffer(float[] data) {
        FloatBuffer buffer = MemoryUtil.memAllocFloat(data.length);
        buffer.put(data);
        buffer.flip();
        return buffer;
    }
     
    public void cleanUp() {
        for (int vao : vaos) {
            GL30.glDeleteVertexArrays(vao);
        }
        for (int vbo : vbos) {
            GL15.glDeleteBuffers(vbo);
        }
    }
}

The renderer class:

package engine.io;
    
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;

public class Renderer {

    public void prepare() {
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
        GL11.glClearColor(1f, 0f, 1f, 1f);
    }
     
    public void render(RawModel model) {
        GL30.glBindVertexArray(model.getVaoID());
        GL20.glEnableVertexAttribArray(0);
        GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, model.getVertexCount());
        GL20.glDisableVertexAttribArray(0);
        GL30.glBindVertexArray(0);
    }
}

Here is the Main class:

import org.lwjgl.*;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.*;
import org.lwjgl.system.*;

import engine.io.Loader;
import engine.io.RawModel;
import engine.io.Renderer;
import engine.io.Window;

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

public class Main {
 
    private Window window;
     
    Loader loader = new Loader();
    Renderer renderer = new Renderer();
     
    float[] vertices = {
            // Left bottom triangle
            -0.5f, 0.5f, 0f,
            -0.5f, -0.5f, 0f,
            0.5f, -0.5f, 0f,
            // Right top triangle
            0.5f, -0.5f, 0f,
            0.5f, 0.5f, 0f,
            -0.5f, 0.5f, 0f
    };
     
    RawModel model;
     
    public void run() {
        setup();
        loop();
         
        loader.cleanUp();
 
        glfwFreeCallbacks(window.getWindowNum());
        glfwDestroyWindow(window.getWindowNum());
         
        glfwTerminate();
        glfwSetErrorCallback(null).free();
    }
 
    private void loop() {
        while ( !glfwWindowShouldClose(window.getWindowNum()) ) {
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer
             
            renderer.render(model);
             
            glfwSwapBuffers(window.getWindowNum()); // swap the color buffers
             
            glfwPollEvents();
        }
    }
 
    public void setup() {
        window = new Window(900, 300, &quot;Flappy Bird&quot;);
        window.create();
         
        GL.createCapabilities();
        GLFW.glfwMakeContextCurrent(window.getWindowNum());
 
        model = loader.loadToVAO(vertices);
        renderer.prepare();
         
        GL11.glViewport(0, 0, 900, 300);
        
    }
     
    public static void main(String[] args) {
        new Main().run();
    }
}

Here is the window class:

package engine.io;
 
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryStack.stackPush;
import static org.lwjgl.system.MemoryUtil.*;

import java.nio.IntBuffer;

//import static org.lwjgl.glfw.GLFW.*;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.system.MemoryStack;

public class Window {
    private int width, height;
    private String title;
    private long window;
 
    public Window(int width, int height, String title) {
        this.width = width;
        this.height = height;
        this.title = title;
    }
 
    public void create() {
        GLFWErrorCallback.createPrint(System.err).set();
 
        if (!glfwInit())
            throw new IllegalStateException(&quot;Unable to initialize GLFW&quot;);
 
        // 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(width, height, &quot;Flappy Bird&quot;, NULL, NULL);
        if (window == NULL)
            throw new RuntimeException(&quot;Failed to create the GLFW window&quot;);
 
        // 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
            // Setup a key callback. It will be called every time a key is pressed, repeated
            // or released.
        glfwSetKeyCallback(window, (window, key, scancode, action, mods) -&gt; {
            if (key == GLFW_KEY_ESCAPE &amp;&amp; action == GLFW_RELEASE)
                glfwSetWindowShouldClose(window, true); // We will detect this in the rendering loop
        });
 
        // Make the OpenGL context current
        glfwMakeContextCurrent(window);
        // Enable v-sync
        glfwSwapInterval(1);
 
        // Make the window visible
        glfwShowWindow(window);
 
    }
         
    public long getWindowNum() {
        return window;
    }
}

答案1

得分: 2

由于您使用的是MacOS,我建议您设置一个3.2核心配置OpenGL上下文。请参阅在OS X上进行OpenGL开发

glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, true);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

// 创建窗口
window = glfwCreateWindow(width, height, "Flappy Bird", NULL, NULL);
英文:

Since you are on MacOS, I recommend to set up a 3.2 core profile OpenGL Context. See OpenGL Development on OS X:

glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, true);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

// Create the window
window = glfwCreateWindow(width, height, &quot;Flappy Bird&quot;, NULL, NULL);

huangapple
  • 本文由 发表于 2020年8月23日 17:40:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/63545503.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定