LWJGL OpenGL glGenVertexArrays()错误:此函数不可用

时间:2016-05-22 17:04:47

标签: java opengl lwjgl vao

全部,glGenVertexArrays()遇到困难。我收到以下错误:

  

线程“main”中的异常java.lang.IllegalStateException:此功能不可用。       在org.lwjgl.system.Checks.checkFunctionality(Checks.java:57)       在org.lwjgl.opengl.GL30.getInstance(GL30.java:667)       在org.lwjgl.opengl.GL30.getInstance(GL30.java:662)       在org.lwjgl.opengl.GL30.nglGenVertexArrays(GL30.java:2789)       在org.lwjgl.opengl.GL30.glGenVertexArrays(GL30.java:2816)       在renderEngine.Loader.createVAO(Loader.java:26)       在renderEngine.Loader.loadToVAO(Loader.java:19)       在renderEngine.MainGameLoop.main(MainGameLoop.java:27)

这是我的主游戏循环(我从createDisplay()方法调用GL.createCapabilities()。)

package renderEngine;

import static org.lwjgl.glfw.GLFW.*;

public class MainGameLoop {

public static DisplayManager dm = new DisplayManager();

public static void main(String[] args) {

    //Create Display
    dm.createDisplay();

    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 = loader.loadToVAO(vertices);
    //Game Loop
    while (glfwWindowShouldClose(dm.getWindowID()) != GLFW_TRUE) {
        renderer.prepare();
        renderer.render(model);
        dm.updateDisplay();
    }

    //Destroy Display
    dm.destroyWindow();
    loader.cleanUp();
}
}

如上所述,这是Display Manager类:

package renderEngine;

import static org.lwjgl.glfw.GLFW.*;

import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWKeyCallback;
import org.lwjgl.opengl.GL;

public class DisplayManager {

private GLFWErrorCallback errorCallback;
private GLFWKeyCallback keyCallback;

private long windowID; 

//Constructor
public DisplayManager(){
    init();
}

private void init(){
    if(glfwInit() != GLFW_TRUE){
        throw new IllegalStateException("Unable to initiate GLFW");
    }
}

public long createDisplay(){
    windowID = glfwCreateWindow(640,480,"Hello World!", 0, 0);
    if(windowID == 0){
        glfwTerminate();
        throw new RuntimeException("Failed to create the GLFW window");
    }

    GLFW.glfwSetWindowTitle(windowID, "GLFW Window");

    setErrorCallback();
    setKeyCallback();

    glfwMakeContextCurrent(windowID);
    GL.createCapabilities();

    return windowID;
}

public long getWindowID(){
    return this.windowID;
}

private void setErrorCallback(){
    errorCallback = GLFWErrorCallback.createPrint(System.err);
    glfwSetErrorCallback(errorCallback);
}

private void setKeyCallback(){

    keyCallback = new GLFWKeyCallback(){
        @Override
        public void invoke(long window, int key, int scancode, int action, int mods) {
            if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS){
                glfwSetWindowShouldClose(window, GLFW_TRUE);
            }
        }
    };
    glfwSetKeyCallback(windowID, keyCallback);
}

public void updateDisplay(){
    GLFW.glfwSwapInterval(1);
    glfwSwapBuffers(windowID);
    glfwPollEvents();
}

public void destroyWindow(){
    glfwDestroyWindow(windowID);
    keyCallback.release();
    glfwTerminate();
    errorCallback.release();
}

}

如果看起来上面提到的错误与loader类有关:

package renderEngine;

import java.util.List;
import java.nio.FloatBuffer;
import java.util.ArrayList;

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

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); //0 un-binds currently bound VAO
}

public void cleanUp(){
    for(int vao:vaos){
        GL30.glDeleteVertexArrays(vao);
    }

    for(int vbo:vbos){
        GL15.glDeleteBuffers(vbo);
    }
}

private FloatBuffer storeDataInFloatBuffer(float[] data){
    FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length);
    buffer.put(data);
    buffer.flip();
    return buffer;
}

}

特别是这行代码:

GL30.glBindVertexArray(vaoID);

据我所知,这是正确的方法,并且已经从主线程设置/调用GL功能/上下文(主游戏循环主方法,利用显示管理器)

为了完整性,这里是RawModel和Renderer类,不要怀疑这些问题:

package renderEngine;

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

import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;

public class Renderer {

public void prepare(){
    GL11.glClearColor(1, 0, 0, 1);
    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
}

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

}

非常感谢您对我实施“glGenVertexArrays”所给予的任何帮助。

我现在添加了以下内容

    GLFW.glfwDefaultWindowHints();
    GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 3);
    GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 2);

但是,我现在收到以下错误:

  

线程“main”中的异常java.lang.RuntimeException:无法创建GLFW窗口       at renderEngine.DisplayManager.createDisplay(DisplayManager.java:37)       在renderEngine.MainGameLoop.main(MainGameLoop.java:12)

我的createDisplay()的具体实现如下:

    public long createDisplay(){
    GLFW.glfwDefaultWindowHints();
    GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 3);
    GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 2);


    windowID = glfwCreateWindow(640,480,"Hello World!", 0, 0);
    if(windowID == 0){
        glfwTerminate();
        throw new RuntimeException("Failed to create the GLFW window");
    }



    GLFW.glfwSetWindowTitle(windowID, "GLFW Window");

    setErrorCallback();
    setKeyCallback();

    glfwMakeContextCurrent(windowID);
    GL.createCapabilities();

    return windowID;
}

更新

如果已删除错误回调,则认为它们可能导致问题。产生的错误是:

  

线程“main”中的异常java.lang.RuntimeException:无法创建GLFW窗口       at renderEngine.DisplayManager.createDisplay(DisplayManager.java:40)       在renderEngine.MainGameLoop.main(MainGameLoop.java:12)

似乎抛出了RuntimeException,并且如果无法创建glfw窗口,则显示我的自定义错误消息。这可能与我运行此命令的顺序相关吗?我已经玩过使用noluck放置'init'方法。必须要有一些我忽视的东西?...谢谢。

更新了显示管理器的代码:

package renderEngine;

import static org.lwjgl.glfw.GLFW。*;

import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWKeyCallback;
import org.lwjgl.opengl.GL;

public class DisplayManager {

private GLFWErrorCallback errorCallback;
private GLFWKeyCallback keyCallback;

private long windowID; 

//Constructor
public DisplayManager(){

    init();
}

private void init(){

    if(glfwInit() != GLFW_TRUE){
        throw new IllegalStateException("Unable to initiate GLFW");
    }
}

public long createDisplay(){
    GLFW.glfwDefaultWindowHints();
    GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 3);
    GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 2);


    windowID = glfwCreateWindow(640,480,"Hello World!", 0, 0);
    System.out.println(windowID);
    if(windowID == 0){
        glfwTerminate();
        throw new RuntimeException("Failed to create the GLFW window");
    }

    glfwMakeContextCurrent(windowID);
    GL.createCapabilities();


    GLFW.glfwSetWindowTitle(windowID, "GLFW Window");

    //setErrorCallback();
    //setKeyCallback();


    return windowID;
}

public long getWindowID(){
    return this.windowID;
}

private void setErrorCallback(){
    errorCallback = GLFWErrorCallback.createPrint(System.err);
    glfwSetErrorCallback(errorCallback);
}

private void setKeyCallback(){

    keyCallback = new GLFWKeyCallback(){
        @Override
        public void invoke(long window, int key, int scancode, int action, int mods) {
            if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS){
                glfwSetWindowShouldClose(window, GLFW_TRUE);
            }
        }
    };
    glfwSetKeyCallback(windowID, keyCallback);
}

public void updateDisplay(){
    GLFW.glfwSwapInterval(1);
    glfwSwapBuffers(windowID);
    glfwPollEvents();
}

public void destroyWindow(){
    glfwDestroyWindow(windowID);
    keyCallback.release();
    glfwTerminate();
    errorCallback.release();
}

}

非常感谢和亲切的问候, 杰克

1 个答案:

答案 0 :(得分:3)

glGenVertexArrays函数需要OpenGL 3.0或更高版本。你必须明确地告诉GLFW。在致电glfwCreateWindow之前:

GLFW.glfwDefaultWindowHints();
GLFW.glfwWindowHint(GLFW.CONTEXT_VERSION_MAJOR, 3);
GLFW.glfwWindowHint(GLFW.CONTEXT_VERSION_MINOR, 0);

您可以通过调用GL11.glGetString(GL11.GL_VERSION)或查看GL.getCapabilities().OpenGL30标记来检查您是否拥有OpenGL 3.0或更高版本。