使用 JOGL 使用 VBO 渲染随机引发异常

Posted

技术标签:

【中文标题】使用 JOGL 使用 VBO 渲染随机引发异常【英文标题】:Rendering with VBO using JOGL trows exception at random 【发布时间】:2014-09-12 09:28:33 【问题描述】:

我一直在尝试使用 JOGL 编写我的渲染应用程序。但我遇到了 VBO 的问题。在linux下它每次都运行良好,但在windows下它总是崩溃。我不知道我错过了什么。我编写了为 VBO 提供服务的代码,结合了各种教程,因为 Java 很少,而不是谈论 JOGL。

我已阅读:

http://www.java-gaming.org/index.php?topic=25672.0 我修改了我的代码,所以我从我的类的 init 函数传递 GL2 实例,它从 GLEventListener 作为函数参数一直派生到我的 VBOClass 函数。 (我不将 GL2 实例存储为类属性) 但这并没有帮助

所以我的班级:

public class VBOMesh 
private int vertexVBOId;
private int normalVBOId;
private int texCoordVBOId;

public VBOMesh(GL2 gl) 
    IntBuffer ib = IntBuffer.allocate(4);

    gl.glGenBuffers(4, ib);

    vertexVBOId = ib.get(0);
    normalVBOId = ib.get(1);
    texCoordVBOId = ib.get(2);


public void setVetices(GL2 gl, List<Vector3> vetices)

    gl.glBindBuffer( GL.GL_ARRAY_BUFFER, vertexVBOId);
    gl.glBufferData( GL.GL_ARRAY_BUFFER, vetices.size()*3*Float.SIZE, VectorListToFloatBuffer(vetices,3), GL.GL_STATIC_DRAW);
    gl.glBindBuffer( GL.GL_ARRAY_BUFFER, 0);


public void setTexCoords(GL2 gl, List<Vector3> texCoords)

    gl.glBindBuffer( GL.GL_ARRAY_BUFFER, texCoordVBOId);
    gl.glBufferData( GL.GL_ARRAY_BUFFER, texCoords.size()*2*Float.SIZE, VectorListToFloatBuffer(texCoords,2), GL.GL_STATIC_DRAW);
    gl.glBindBuffer( GL.GL_ARRAY_BUFFER, 0);


public void setNormals( GL2 gl, List<Vector3> normals)

    gl.glBindBuffer( GL.GL_ARRAY_BUFFER, normalVBOId);
    gl.glBufferData( GL.GL_ARRAY_BUFFER, normals.size()*3*Float.SIZE, VectorListToFloatBuffer(normals,3), GL.GL_STATIC_DRAW);
    gl.glBindBuffer( GL.GL_ARRAY_BUFFER, 0);


public void Draw( GL2 gl, List<Integer> indices)
      
    IntBuffer indiceBuffer = Buffers.newDirectIntBuffer( indices.size() );

    for (int ind : indices) 
        indiceBuffer.put(ind);
    

    gl.glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
    gl.glEnableClientState(GLPointerFunc.GL_NORMAL_ARRAY);
    gl.glEnableClientState(GLPointerFunc.GL_TEXTURE_COORD_ARRAY);

    gl.glBindBuffer( GL.GL_ARRAY_BUFFER, normalVBOId);
    gl.glNormalPointer( GL.GL_FLOAT, 0, 0);
    gl.glBindBuffer( GL.GL_ARRAY_BUFFER, texCoordVBOId);
    gl.glTexCoordPointer(2, GL.GL_FLOAT, 0, 0);
    gl.glBindBuffer( GL.GL_ARRAY_BUFFER, vertexVBOId);
    gl.glVertexPointer(3, GL.GL_FLOAT, 0, 0);

    gl.glDrawElements(GL.GL_TRIANGLES, indiceBuffer.capacity(), GL.GL_UNSIGNED_INT, indiceBuffer.rewind());
    //gl.glDrawArrays(GL.GL_LINES, 0, 24);

    gl.glBindBuffer( GL.GL_ARRAY_BUFFER, 0);
    gl.glDisableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
    gl.glDisableClientState(GLPointerFunc.GL_NORMAL_ARRAY);
    gl.glDisableClientState(GLPointerFunc.GL_TEXTURE_COORD_ARRAY);


private Buffer VectorListToFloatBuffer(List<Vector3> vectors, int floatsToTake)

    if(floatsToTake > 4)
    
        throw new InvalidParameterException("floats to take greater than 4");
    

    FloatBuffer buffer = Buffers.newDirectFloatBuffer(vectors.size()*3);

    for (Vector3 vector : vectors) 
    
        float [] arr = 0.f,0.f,0.f;

        if(vector != null)
        
            arr = vector.getVector3AsGLArray();
        

        for (int i = 0; i < floatsToTake; i++) 
        
            buffer.put(arr[i]);
        
    

    return buffer.rewind();

异常发生在glBufferData。

我没有想法,所以我问。

【问题讨论】:

这是来自生成的输出文件:# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x697c851e, pid=6476, tid=7160 来自堆栈跟踪:j jogamp.opengl.gl4.GL4bcImpl.glBufferData(IJLjava/nio/Buffer;I)V+67 j SceneTools.VBOMesh.setNormals (Ljavax/media/opengl/GL2;Ljava/util/List;)V+35 end 如果你debug step through,参数check out? normalVBOId 大约是 3,看起来是正确的,然后我正在测试的模型的缓冲区容量是 942,它是包含向量的列表大小的 3 倍,所以看起来还可以。但是由于 Float.SIZE,我作为大小传递给 glBufferData 的是一个很大的数字,我不确定它是否应该存在。 指责 JOGL 而不是假设问题可能来自您的代码不是很聪明。如果您使用通过 com.jogamp.common.nio.Buffers 创建的直接 NIO 浮点缓冲区,那么它从一开始就可以在任何地方工作。如果您阅读了该方法的文档,您会发现自己的错误。 【参考方案1】:

Float.SIZE 返回单个浮点数 (32) 中的 bits 数,而您想要浮点数中的 bytes 数。

Float.SIZE 的每个实例替换为(Float.SIZE/Byte.SIZE) 或只是4,或自定义常量BYTES_IN_FLOAT

【讨论】:

非常感谢!有效。我相信,我读过的那些 Java VBO 教程完全错过了这一点。

以上是关于使用 JOGL 使用 VBO 渲染随机引发异常的主要内容,如果未能解决你的问题,请参考以下文章

JOGL/OpenGL VBO - 如何渲染顶点?

在 netbeans 7.4 上运行 jogl VBO

JOGL:用新的细节级别替换 VBO 数据

在 JOGL 中跨多个 QWidget 共享 VBO

随机“CALayerInvalidGeometry 原因:CALayer 位置包含 NaN”异常

JOGL 没有渲染任何东西