【问题标题】:2D rendering with VBO in lwjgl won't draw在 lwjgl 中使用 VBO 进行 2D 渲染不会绘制
【发布时间】:2011-05-23 01:18:56
【问题描述】:

我正在使用 LWJGL 开发一款 2D 游戏。我已经使用 glBegin 成功地渲染了带有纹理的 QUADS,但迁移到 VBO 被证明是一项艰巨的任务。目前,我可以使用布尔值在 vbo 和非 vbo 渲染之间切换,两者都使用相同的顶点和纹理坐标。 VBO 实现不会在屏幕上绘制任何内容。谁能指出我正确的方向?

这是我的初始化:

public void init() {
    VBOID = VBOHandler.createVBOID();
    TBOID = VBOHandler.createVBOID();
    float[] vdata = {0, 0, 
                    width, 0,
                    width, height,
                    0, height};
    float[] tdata = {sx, sy, 
                     ex, sy, 
                     ex, ey, 
                     sx, ey};

    //Texture coordinates: (0,0)(1,0)(1,1) and (0,1)

    FloatBuffer fb = BufferUtils.createFloatBuffer(8);
    fb.put(vdata);
    VBOHandler.bufferData(VBOID, fb);
    fb = BufferUtils.createFloatBuffer(8);
    fb.put(tdata);
    VBOHandler.bufferData(TBOID, fb);
}

这是我的渲染代码:

private void render() {
    texture.bind();
    if(vbo) {
        GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
        GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);

        VBOHandler.bindBuffer(VBOID);
        GL11.glVertexPointer(2, GL11.GL_FLOAT, 0, 0);

        VBOHandler.bindBuffer(TBOID);
        GL11.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 0);

        VBOHandler.bindElementBuffer(VBOHandler.getDefaultIBOID());
    // I figured why not use a standard IBO for all my sprite drawing
    // The default IBO ID is initialized earlier in the program, not shown in this code
        GL12.glDrawRangeElements(GL11.GL_TRIANGLE_FAN, 0, 3, 4, GL11.GL_UNSIGNED_SHORT, 0);

        GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
        GL11.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
    } else {
        GL11.glBegin(GL11.GL_TRIANGLE_FAN);
        GL11.glTexCoord2f(sx, sy);
        GL11.glVertex2f(0, 0);
        GL11.glTexCoord2f(ex, sy);
        GL11.glVertex2f(width,0);
        GL11.glTexCoord2f(ex, ey);
        GL11.glVertex2f(width, height);
        GL11.glTexCoord2f(sx, ey);
        GL11.glVertex2f(0, height);
        GL11.glEnd();
    }

}

还有 VBOHandler 类,对于那些感兴趣的人

public class VBOHandler {

    private static int IBOID;

public static void initDefaultIBO() {
    IBOID = createVBOID();
    short[] indexdata = {0, 1, 2, 3};
    ShortBuffer shortBuffer = BufferUtils.createShortBuffer(4);
    shortBuffer.put(indexdata);
    VBOHandler.bufferElementData(IBOID, shortBuffer);
}

public static int getDefaultIBOID() {
    return IBOID;
}

public static int createVBOID() {
    if(GLContext.getCapabilities().GL_ARB_vertex_buffer_object) {
        return ARBVertexBufferObject.glGenBuffersARB();
    }
    return 0;
}

public static void bufferData(int id, FloatBuffer buffer) {
    if (GLContext.getCapabilities().GL_ARB_vertex_buffer_object) {
        ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, id);
        ARBVertexBufferObject.glBufferDataARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, buffer, ARBVertexBufferObject.GL_STATIC_DRAW_ARB);
    }
}

public static void bufferElementData(int id, ShortBuffer buffer) {
    if (GLContext.getCapabilities().GL_ARB_vertex_buffer_object) {
        ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB, id);
        ARBVertexBufferObject.glBufferDataARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB, buffer, ARBVertexBufferObject.GL_STATIC_DRAW_ARB);
    }
}

public static void bindBuffer(int id) {
    ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, id);
}

public static void bindElementBuffer(int id) {
    ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB, id);
}
 }

上面的渲染函数位于我的 Sprite 类中。我的 GameView 每帧都会调用它:

public void renderGame() {
    GL11.glMatrixMode(GL11.GL_MODELVIEW);
    GL11.glLoadIdentity();
    sprite.render();
}

GameView 使用以下代码初始化:

Display.setDisplayMode(new DisplayMode(1024, 768));
GL11.glEnable(GL11.GL_TEXTURE_2D);  
GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);         
GL11.glEnable(GL11.GL_BLEND); // enable alpha blending
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glOrtho(x - width/2, x + width/2, y + height / 2, y - height / 2, -1, 1);
GL11.glMatrixMode(GL11.GL_MODELVIEW);

【问题讨论】:

  • 完全不相关的评论:你实际上可以放弃你的默认 IBO 并使用 glDrawArrays,因为你的 IBO 所做的不仅仅是按顺序遍历你的数组。
  • 您是否检查过缓冲区对象是否受支持以及您的缓冲区 ID 是否具有有效值 (!=0)?
  • 感谢大家的回复。我所有的缓冲区都有有效的 ID(准确地说是 1,2 和 3)并且 GLContext.getCapabilities().GL_ARB_vertex_buffer_object 返回 true。
  • 我找不到任何东西。也许你的问题更深一些。您能否发布更多代码(也许是一个最小的工作示例)?
  • 我添加了一些代码块。看看你能不能从中做出明智的选择

标签: java opengl 2d vbo lwjgl


【解决方案1】:

在将 FloatBuffers 传递给 OpenGL 之前,您没有在 FloatBuffers 上调用“flip”。 需要在将 FloatBuffers 传递给 OpenGL 之前调用它们的“flip()”,否则它将无法读取它们。值得注意的是,您自己调用 'flip()' 后无法读取 FloatBuffers。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-12
    • 1970-01-01
    • 2014-03-24
    • 2020-12-12
    • 1970-01-01
    相关资源
    最近更新 更多