【问题标题】:Problems drawing VBO with glDrawArrays using OpenGL/LWJGL使用 OpenGL/LWJGL 使用 glDrawArrays 绘制 VBO 的问题
【发布时间】:2014-06-05 00:58:38
【问题描述】:

我在让 VBO 参与我的游戏时遇到了一些困难。我环顾四周,检查了所有常见的错误,但似乎没有什么能让他们画出来。

以下是按执行顺序排列的相关代码:

运行一次:

public void startLWJGL() {
    try {
        Display.setParent(game.getCanvas());
        Display.create();
    } catch (LWJGLException ex) {
        System.err.print("LWJGL failed to initialize.");
        System.exit(-1);
    }

    // Initialize
    GL11.glMatrixMode(GL11.GL_PROJECTION_MATRIX);
    GL11.glLoadIdentity();
    GL11.glOrtho(0, 800, 0, 600, 1, -1); // L, R, B, T, Near, Far
    GL11.glMatrixMode(GL11.GL_MODELVIEW);
    GL11.glClearColor(0.01f,0.05f,0.1f,1f);

    GL11.glDisable(GL11.GL_DEPTH_TEST);
    //GL11.glDisable(GL11.GL_BLEND);

    GL11.glViewport(0, 0, 800, 600);

    Renderer.init();
}

public static void init() {
    BALL_GEO = GL15.glGenBuffers();
    GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, BALL_GEO);
    GL15.glBufferData(GL15.GL_ARRAY_BUFFER, makeBallGeometry(), GL15.GL_STATIC_DRAW);

    COLOR_BUF = GL15.glGenBuffers();
    GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, COLOR_BUF);
    GL15.glBufferData(GL15.GL_ARRAY_BUFFER, makeSolidColBuffer(1f, 0f, 1f, 1f, (CIRCLE_SEGMENTS + 2)), GL15.GL_STATIC_DRAW);
}

运行每一帧:

private void tick(long delta) {
    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
    Renderer.testRender();
}

    public static void testRender() {

    drawBall(new Ball(new Vector(200, 200), null, 50.0));

    // This is just test stuff that DOES work
    GL11.glColor4f(1f, 1f, 1f, 1f);
    GL11.glBegin(GL11.GL_QUADS);
    GL11.glVertex2f(100, 100);
    GL11.glVertex2f(100, 400);
    GL11.glVertex2f(200, 400);
    GL11.glVertex2f(200, 100);
    GL11.glEnd();

    GL11.glMatrixMode(GL11.GL_MODELVIEW);
    GL11.glPushMatrix();
    //GL11.glLoadIdentity();
    GL11.glTranslatef(400f, 200f, 1f);
    GL11.glScalef(0.5f, 0.5f, 0.5f);

    GL11.glColor4f(0f, 1f, 1f, 1f);
    GL11.glBegin(GL11.GL_QUADS);
    GL11.glVertex2f(100, 100);
    GL11.glVertex2f(100, 400);
    GL11.glVertex2f(200, 400);
    GL11.glVertex2f(200, 100);
    GL11.glEnd();

    GL11.glPopMatrix();

}

public static void drawBall(Ball o) {
    GL11.glMatrixMode(GL11.GL_MODELVIEW);
    float x = (float) o.getPos().x;
    float y = (float) o.getPos().y;
    float s = (float) o.getRadius();

    GL11.glEnableClientState(GL11.GL_COLOR_ARRAY);
    GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);

    GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, BALL_GEO);
    GL11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0);
    GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);

    GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, COLOR_BUF);
    GL11.glColorPointer(4, GL11.GL_FLOAT, 0, 0);
    GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);

    GL11.glPushMatrix();
    //GL11.glLoadIdentity();
    GL11.glTranslatef(x, y, 0f);
    GL11.glScalef(s, s, s);

    GL11.glDrawArrays(GL11.GL_TRIANGLE_FAN, 0, (CIRCLE_SEGMENTS + 2));

    GL11.glDisableClientState(GL11.GL_COLOR_ARRAY);
    GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
    GL11.glPopMatrix();
}

用英文术语来说,我在 2D 中渲染不同大小和位置的纯色圆圈。我用即时模式测试了几何,它工作得很好。这可能是非常愚蠢的事情,但我无法弄清楚我的生活是什么。我在另一台计算机上运行此代码,它吐出 0x05 错误硬崩溃,但在这台计算机上它根本不渲染。 Ball 对象的构造函数接受一个向量作为它的位置、一个速度向量和一个半径作为双精度数。

编辑:以下是供提问者使用的几何图形和颜色缓冲区代码:

private static FloatBuffer makeBallGeometry() {
    FloatBuffer buffer = BufferUtils.createFloatBuffer((CIRCLE_SEGMENTS + 2) * 3);

    float theta = 2f * (float) Math.PI / CIRCLE_SEGMENTS; // Divisions in Radians
    float tanFac = (float) Math.tan(theta); // Scalar for tangenial line
    float radFac = (float) Math.cos(theta); // Scalar for radial line
    float x = 50f;
    float y = 0f;
    float tx, ty;

    buffer.put(0f);
    buffer.put(0f);
    buffer.put(0f);
    for (int i = 0; i <= CIRCLE_SEGMENTS; i++) {
        buffer.put(x);
        buffer.put(y);
        buffer.put(0f);

        tx = -y; // Tangent
        ty = x;

        x += tx * tanFac; // Adjust over by tanFac
        y += ty * tanFac;

        x *= radFac; // Shrink by radFac
        y *= radFac;
    }

    return buffer;
}

private static FloatBuffer makeSolidColBuffer(float r, float g, float b, float a, int size) {
    FloatBuffer buffer = BufferUtils.createFloatBuffer(size * 4);
    for (int i = 0; i < size; i++) {
        buffer.put(r);
        buffer.put(g);
        buffer.put(b);
        buffer.put(a);
    }
    return buffer;
}

【问题讨论】:

  • 你的几何图形是什么样的?你能发布Ball构造函数的代码吗?
  • @user1118321:我读代码的方式,Ball 对象只包含球的位置和半径。这是我们需要看到的makeBallGeometry() 函数。
  • glBufferData 没有 size 参数总是以错误的方式摩擦我。 Java 语言绑定使用java.nio.Buffer 中的当前位置计算数据的大小,但这意味着如果您忘记回退 (flip) 缓冲区,您基本上会传递 GL 0 字节的数据。你这样做了吗? -- 更重要的是,你能把makeBallGeometry()makeSolidColBuffer()的实现添加到你的问题中吗?
  • @RetoKoradi 是的,当然。我的意思是makeBallGeometry() 方法。很好的收获。
  • 我添加了生成缓冲区的代码。这是什么翻转方法?我没有使用 java.nio 包的经验,所以我可能在那里做错了。

标签: java opengl lwjgl vbo gldrawarrays


【解决方案1】:

正如Andon M. Coleman 所指出的,我的问题是我忽略了在缓冲区上调用flip(),并且实际上并没有传递任何信息字节。我在返回之前将 buffer.flip() 添加到颜色和顶点缓冲区,现在一切似乎都正常工作了。

【讨论】:

  • 是的,这是必要的,因为put (...) 每次调用时都会增加缓冲区中的 current 位置。基本上它会调整缓冲区的大小并将当前位置移动到末尾。 LWJGL 使用 当前 位置和缓冲区末尾之间的长度来确定要发送到 GL 的数据量(以及从缓冲区开始复制数据的位置)。 flip (...)current 位置设置为缓冲区的开头,这允许 LWJGL 将整个缓冲区发送到 GL(如果当前位置是结尾,则完全不发送任何内容)。跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多