Проблема с рендерингом квадроцикла в LWJGL 3 с использованием VAO и VBO

(Это второй раз, когда я задаю этот вопрос. В прошлый раз я получил один ответ, который не решил его (ответ там ссылался на фрагмент кода, который случайно остался после одной из моих попыток исправить это). Я также изменил сам вопрос немного - я изменил порядок кода, чтобы поместить часть, где я считаю ошибку выше, и добавил, что я использую macOS, что может быть причиной того, что он не работает).

Итак, я только начал изучать LWJGL 3, и я использовал смесь нескольких руководств и примера кода, чтобы сделать что-то, что должно отображать прямоугольник на пурпурный экран с использованием VAO и VBO. Ошибок нет, но прямоугольник не появляется на экране (все, что я вижу, это пурпурный экран). Я попытался использовать старый конвейер LWJGL (glBegin() и glEnd()), и он действительно работает, поэтому я попытался изменить случайные вещи в коде рендеринга и загрузке в VAO и VBO. Я также пытался связать VBO, но это ничего не изменило. Я также пробовал отладку, и кажется, что созданы VAO и VBO.

Может ли кто-нибудь взглянуть на мой код и посмотреть, не выглядит ли что-то не так? Вот он (извините, если он немного запутан. Как я уже сказал, я не думаю, что проблема в классе Main или Window, но я понятия не имею о LWJGL, поэтому я все равно хотел разместить его здесь. Если у вас есть время, Пожалуйста, также посмотрите на них.В противном случае я был бы очень признателен, если бы вы могли взглянуть на классы Loader и Renderer):

(Кстати, я использую macOS, и у меня включен -XstartOnFirstThread).

Класс необработанной модели:

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

Класс загрузчика:

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

Класс рендерера:

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

Вот основной класс:

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, "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();
    }
}

Вот класс окна:

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("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(width, height, "Flappy Bird", NULL, NULL);
        if (window == NULL)
            throw new RuntimeException("Failed to create the GLFW window");
 
        // 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) -> {
            if (key == GLFW_KEY_ESCAPE && 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;
    }
}

person Nitai99    schedule 23.08.2020    source источник
comment
В вашем коде используются VAO, для которых требуется GL 3.0 или выше, и единственный способ получить GL 3.0 или выше в MacOS — это запросить базовый профиль GL3.2. Однако, поскольку ваш код не использует шейдеры, он несовместим с базовыми профилями как есть.   -  person derhass    schedule 24.08.2020


Ответы (1)


Поскольку вы используете MacOS, я рекомендую настроить профиль ядра 3.2 Контекст OpenGL. См. Разработка OpenGL для 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, "Flappy Bird", NULL, NULL);
person Rabbid76    schedule 23.08.2020
comment
Спасибо за ответ! К сожалению, у меня все еще нет квадроцикла, только пурпурный экран. Ссылки еще посмотрю, спасибо! - person Nitai99; 23.08.2020
comment
Вы можете установить обратный вызов сообщения отладки, на который драйвер может выводить сообщения журнала о предупреждениях/ошибках/информации OpenGL. В LWJGL 3 есть служебный класс org.lwjgl.opengl.GLUtil, с помощью которого можно зарегистрировать обратный вызов следующим образом: Callback debugProc = GLUtil.setupDebugMessageCallback(); (обратный вызов является org.lwjgl.system.Callback). Посмотрите, выводит ли это что-нибудь. В качестве альтернативы вы можете разбросать вызовы glGetError() и посмотреть, какой вызов GL может вызвать ошибку. - person Kai Burjack; 23.08.2020