【问题标题】:Error when calling GL30.glGenVertexArrays();调用 GL30.glGenVertexArrays() 时出错;
【发布时间】:2020-11-18 14:26:31
【问题描述】:

我正在尝试使用 java 学习 usinf opengl 和 lwjgl,并且我有一个程序,并且正在尝试渲染一些网格,但是处理 Vaos 和 Vbos 的类是错误的。经过一些研究,我了解到这可能是原因是因为我调用该方法的位置相对于 MakecontextCurrent();方法,但我没有运气。

警告

前面有很多代码

错误的类

package renderEngine;

import java.nio.FloatBuffer;
import java.util.*;

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.*;

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);
    unbind();
    return new RawModel(vaoID,positions.length/3);
    
}
public void cleanup() {
    for(int vao : vaos) {
        GL30.glDeleteVertexArrays(vao);
    }
    for(int vbo : vbos) {
        GL30.glDeleteVertexArrays(vbo);
    }
}
public int createVAO() {
    int vaoID = GL30.glGenVertexArrays();
    vaos.add(vaoID);
    GL30.glBindVertexArray(vaoID);
    return vaoID;
}
public 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);
    GL30.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
    }
public void unbind() {
    GL30.glBindVertexArray(0);
}
private FloatBuffer storeDataInFloatBuffer(float[] data) {
    FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length);
    buffer.put(data);
    buffer.flip();
    return buffer;
}
}

这是处理游戏循环的类

package renderEngine;

import org.lwjgl.glfw.GLFW;

public class MainGameLoop implements Runnable{
public Loader loader;
public Thread gamethread;
public DisplayManager display;
public RawModel model;
Renderer renderer;
public static void main(String[] args) {
    new MainGameLoop().start();
}

private void start() {
    gamethread = new Thread(this , "game");
    gamethread.start();
}
@Override
public void run() {
    init();
    while (!display.shouldClose()) {
        update();
        render();
    }
    loader.cleanup();
}

private void render() {
    renderer.prepare();
    renderer.renderModel(model);
    display.render();
}

private void update() {
    display.update();
}

private void init() {
    float[] vertices = new float[] {
            0.5f , 0.5f , 0.0f , -0.5f , 0.5f , 0.0f , -0.5f , -0.5f , 0.0f , 0.5f , -0.5f , 0.0f
    };
    loader = new Loader();
    display = new DisplayManager(900, 500, "Our Game",GLFW.glfwGetPrimaryMonitor());
    display.createDisplay();
    model = loader.loadToVao(vertices);
    renderer = new Renderer();
    
    
}

}

处理窗口创建的类

package renderEngine;

import static org.lwjgl.glfw.GLFW.*;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengl.GL;

public class DisplayManager {

public int width , height;
public String title;
public long monitor = 0;
private long window;

public DisplayManager(int width , int height , String title , long monitor) {
    this.width = width;
    this.title = title;
    this.height = height;
    this.monitor = monitor;
}
public void createDisplay() {
    if(glfwInit()) {
        //handle initialization error
        System.err.println("Error001:FailedInitialization");
    }
    //create window
    window = glfwCreateWindow(width, height, title,monitor , 0);
    if (window == 0) {
        //handle window creation error
        System.err.println("Error002:FailedDisplayCreation");
    }
    //create vidmode
    GLFWVidMode vm = glfwGetVideoMode(glfwGetPrimaryMonitor());
    int xpos  = vm.width()/2-width/2, ypos = vm.height()/2-height/2;
    //set position to center
    glfwSetWindowPos(window, xpos, ypos);
    glfwMakeContextCurrent(ypos);
    GL.createCapabilities();
    //show window
    glfwShowWindow(window);
}
public void destroyWindow() {
    glfwDestroyWindow(window);
    glfwTerminate();
}
public void render() {
    glfwSwapBuffers(window);
}
public void update() {
    glfwPollEvents();
}
public boolean shouldClose() {
    return glfwWindowShouldClose(window);
}

}

渲染器

package renderEngine;

import org.lwjgl.opengl.*;

public class Renderer {
public void prepare() {
    GL11.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
    GL11.glClear(GL15.GL_ARRAY_BUFFER);
}
public void renderModel(RawModel model) {
    GL30.glBindVertexArray(model.getVaoID());
    GL30.glEnableVertexAttribArray(0);
    GL11.glDrawArrays(GL11.GL_TRIANGLES,0, model.getVertexCount());
    GL20.glDisableVertexAttribArray(0);
    GL30.glBindVertexArray(0);
}

}

原始模型

package renderEngine;

import org.lwjgl.opengl.*;

public class Renderer {
public void prepare() {
    GL11.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
    GL11.glClear(GL15.GL_ARRAY_BUFFER);
}
public void renderModel(RawModel model) {
    GL30.glBindVertexArray(model.getVaoID());
    GL30.glEnableVertexAttribArray(0);
    GL11.glDrawArrays(GL11.GL_TRIANGLES,0, model.getVertexCount());
    GL20.glDisableVertexAttribArray(0);
    GL30.glBindVertexArray(0);
}

}

错误

FATAL ERROR in native method: Thread[game,5,main]: No context is current or a function that is not 
available in the current context was called. The JVM will abort execution.
at org.lwjgl.opengl.GL30C.nglGenVertexArrays(Native Method)
at org.lwjgl.opengl.GL30C.glGenVertexArrays(GL30C.java:2420)
at org.lwjgl.opengl.GL30.glGenVertexArrays(GL30.java:2369)
at renderEngine.Loader.createVAO(Loader.java:28)
at renderEngine.Loader.loadToVao(Loader.java:13)
at renderEngine.MainGameLoop.init(MainGameLoop.java:47)
at renderEngine.MainGameLoop.run(MainGameLoop.java:21)
at java.lang.Thread.run(java.base@11.0.8/Thread.java:834)

【问题讨论】:

  • 在调用 glGenVertexArrays 之前,您是否将上下文设为当前(在同一个线程中)? (每个线程都有自己的当前上下文)
  • @user253751 我只在创建窗口的地方调用了 make context current 一次,我还应该在哪里调用它?
  • @user253751 老实说没有。但我确实通过消除一个更愚蠢的错误来解决问题

标签: java opengl lwjgl vertex-array vertex-array-object


【解决方案1】:

您的错误只是声明顺序上的一个简单错误。 在您的MainGameLoop class 中重新排序这些行:

loader = new Loader();
display = new DisplayManager(900, 500, "Our Game",GLFW.glfwGetPrimaryMonitor());
display.createDisplay();

像这样:

display = new DisplayManager(900, 500, "Our Game",GLFW.glfwGetPrimaryMonitor());
display.createDisplay();
loader = new Loader();

因为在您的 Loader 类中,您调用 OpenGL 函数 (GL30.glGenVertexArrays();),但如果尚未设置上下文,则无法调用 OpenGL 函数。
您使用 GL.createCapabilities(); 设置 OpenGL 上下文,此行在您的DisplayManager class.
所以GL.createCapabilities(); 在你的MainGameLoop class 中调用OpenGL 函数之后执行(实际上永远不会执行,因为JVM 之前会崩溃)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-15
    • 1970-01-01
    • 2014-08-14
    • 1970-01-01
    • 2017-07-16
    • 1970-01-01
    • 2012-06-21
    相关资源
    最近更新 更多