2017-04-22 70 views
2

我目前正在關注使用VAO和VBOS進行渲染的ThinMatrix OpenGL教程。我幾乎完全複製了代碼(唯一的區別是我使工廠類成爲靜態的,而不是僅僅通過它)。唯一的區別技術可以讓我在版本的程序之間,看他是我使用LWJGL 3代替LWJGL 2.Java lwjgl使用VAOs的現代OpenGL訪問衝突異常

下面是我的源代碼:

/************* 
    MAIN 
*************/ 
import Render.ModelLoader; 
import Render.Render; 
import Render.RawModel; 
import org.lwjgl.Version; 
import org.lwjgl.glfw.Callbacks; 
import org.lwjgl.glfw.GLFWErrorCallback; 
import org.lwjgl.glfw.GLFWVidMode; 
import org.lwjgl.opengl.GL; 

import static org.lwjgl.opengl.GL11.*; 
import static org.lwjgl.glfw.GLFW.*; 
import static org.lwjgl.system.MemoryUtil.NULL; 

public class Main { 

    private static long window; 
    private static ModelLoader modelLoader; 
    private static Render renderer; 


    private static final int WIDTH = 1280; 
    private static final int HEIGHT = 720; 

    public static void main(String[] args) { 

     float[] vertices = { 
       //Bottom left triangle 
       -.5f,.5f,0f, 
       -.5f,-.5f,0f, 
       .5f,-.5f,0f, 
       //Top right triangle 
       .5f,-.5f,0f, 
       .5f,.5f,0f, 
       -.5f,.5f,0f 
     }; 

     RawModel model = modelLoader.loadToVAO(vertices); 

     initApp(); 

     //Main Loop 
     while (!glfwWindowShouldClose(window)){ 
      glfwPollEvents(); 
      renderer.prepare(); 
      renderer.render(model); 
      glfwSwapBuffers(window); 
     } 

     cleanUp(); 
    } 

    public static void initApp(){ 
     System.out.println("LWJGL " + Version.getVersion()); 
     //Set the error callback routine to use System.err 
     GLFWErrorCallback.createPrint(System.err).set(); 

     //Init GLFW 
     if (!glfwInit()){ 
      throw new IllegalStateException("Could not initialise GLFW."); 
     } 

     //Create the window 
     glfwDefaultWindowHints(); 
     glfwWindowHint(GLFW_RESIZABLE,GLFW_FALSE); 
     window = glfwCreateWindow(WIDTH, HEIGHT, "My Display", NULL, NULL); 
     if (window == NULL){ 
      throw new IllegalStateException("Could not create window"); 
     } 

     //Center the window 
     GLFWVidMode vidMode = glfwGetVideoMode(glfwGetPrimaryMonitor()); 
     glfwSetWindowPos(window, (vidMode.width()-WIDTH)/2, (vidMode.height()-HEIGHT)/2); 

     //Link window's context to current thread 
     glfwMakeContextCurrent(window); 
     //VSync 
     glfwSwapInterval(1); 
     glfwShowWindow(window); 

     GL.createCapabilities(); 
     System.out.println("OpenGL " + glGetString(GL_VERSION)); 
    } 

    public static void cleanUp(){ 
     modelLoader.cleanUp(); 
     Callbacks.glfwFreeCallbacks(window); //Release callbacks 
     glfwDestroyWindow(window); //Destroy the window 
     glfwTerminate(); //Terminate GLFW 
     glfwSetErrorCallback(null).set(); 
    } 

} 
/************* 
    RAWMODEL 
*************/ 
package Render; 

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; 
    } 
} 
/************* 
    MODELLOADER 
*************/ 
package Render; 

import org.lwjgl.BufferUtils; 
import java.nio.FloatBuffer; 
import java.util.ArrayList; 
import java.util.List; 

import static org.lwjgl.opengl.GL11.GL_FLOAT; 
import static org.lwjgl.opengl.GL15.*; 
import static org.lwjgl.opengl.GL20.*; 
import static org.lwjgl.opengl.GL30.*; 

public class ModelLoader { 

    private static List<Integer> vaos = new ArrayList<>(); 
    private static List<Integer> vbos = new ArrayList<>(); 

    public static RawModel loadToVAO(float[] positions){ 
     int vaoID = createVAO(); 
     vaos.add(vaoID); 
     storeDataInAttribList(0,positions); 
     unbindVAO(); 
     return new RawModel(vaoID, positions.length/3); 
    } 

    private static int createVAO(){ 
     int vaoID = glGenVertexArrays(); 
     glBindVertexArray(vaoID); 
     return vaoID; 
    } 

    private static void storeDataInAttribList(int attribNum, float[] data){ 
     int vboID = glGenBuffers(); 
     vbos.add(vboID); 
     glBindBuffer(GL_ARRAY_BUFFER,vboID); 
     FloatBuffer buffer = storeDataInFB(data); 
     glBufferData(GL_ARRAY_BUFFER,buffer,GL_STATIC_DRAW); 
     glVertexAttribPointer(attribNum,3,GL_FLOAT,false,0,0); 
     glBindBuffer(GL_ARRAY_BUFFER,0); 
    } 

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

    private static void unbindVAO(){ 
     glBindVertexArray(0); 
    } 

    public static void cleanUp(){ 
     for (int vao:vaos) { 
      glDeleteVertexArrays(vao); 
     } 
     for (int vbo:vbos) { 
      glDeleteBuffers(vbo); 
     } 
    } 
} 
/************* 
    RENDER 
*************/ 
package Render; 

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

public class Render { 

    public static void prepare(){ 
     glClearColor(0.0f,0.4f,0.6f,1.0f); 
     glClear(GL_COLOR_BUFFER_BIT); 
    } 

    public static void render(RawModel model){ 
     glEnableClientState(GL_VERTEX_ARRAY); 
     glBindVertexArray(model.getVaoID()); 
     glEnableVertexAttribArray(0); 
     glDrawArrays(GL_TRIANGLES,0,model.getVertexCount()); 
     glDisableVertexAttribArray(0); 
     glBindVertexArray(0); 
     glDisableClientState(GL_VERTEX_ARRAY); 
    } 
} 

我有問題是,每當我嘗試運行它只是與此錯誤消息崩潰項目:

Connected to the target VM, address: '127.0.0.1:49390', transport: 'socket' 

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

    EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffffa09862d, pid=12556, tid=0x00000000000020ac 

JRE version: Java(TM) SE Runtime Environment (8.0_121-b13) (build 1.8.0_121-b13) 
Java VM: Java HotSpot(TM) 64-Bit Server VM (25.121-b13 mixed mode windows-amd64 compressed oops) 
Problematic frame: 
C [lwjgl_opengl.dll+0x862d] 

Failed to write core dump. Minidumps are not enabled by default on client versions of Windows 

An error report file with more information is saved as: 
C:\Users\TokenGuard\IdeaProjects\ModernOpenGLTutorial\hs_err_pid12556.log 

If you would like to submit a bug report, please visit: 
    http://bugreport.java.com/bugreport/crash.jsp 
The crash happened outside the Java Virtual Machine in native code. 
See problematic frame for where to report the bug. 

Disconnected from the target VM, address: '127.0.0.1:49390', transport: 'socket' 

Process finished with exit code 1 

在環顧四周,我發現這個計算器帖子:Java OpenGL EXCEPTION_ACCESS_VIOLATION on glDrawArrays only on NVIDIA,這似乎有同樣的問題,這個問題的OP實際上發佈瞭解決方案

我正在使用AMD圖形卡,但我仍試圖查看它是否解決了我的問題,但它什麼都沒做,因爲它仍然出現相同的錯誤消息。

放入一些斷點我發現問題在於createVAO()方法,更具體地說,由於某種原因,致電glGenVertexArrays()失敗。我曾嘗試明確告訴glfw使用OpenGL 3.0,但它仍然沒有幫助。

在這一點上我完全沒有想法。 任何指導我應該做什麼?

+0

除了OpenGL版本1.1(你的代碼看起來是3.x)之外,你需要一些東西來獲得函數指針。這個工作的一個典型的,好的圖書館是GLEW。 – Ripi2

+0

@ Ripi2不使用GLEW它是舊的和破碎的,而是使用GLAD。另外LWJGL自動加載函數指針。 – Vallentin

回答

2

問題是這樣的:

RawModel model = modelLoader.loadToVAO(vertices); 
initApp(); 

你需要圍繞翻轉:

initApp(); 
RawModel model = modelLoader.loadToVAO(vertices) 

但問題是,當你調用modelLoader.loadToVAO(vertices)它調用glGenVertexArrays()(如你觀察到的) 。此時,您沒有設置當前上下文。你在initApp()glfwMakeContextCurrent()做什麼。

在調用任何OpenGL函數之前,您必須先設置當前上下文。

+0

非常感謝。我最終通過在主循環中完成所有這些工作來完成「硬連線」,並且它像魅力一樣工作。這解釋了另一種方法導致它崩潰......再次感謝! –