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

Posted

技术标签:

【中文标题】JOGL/OpenGL VBO - 如何渲染顶点?【英文标题】:JOGL/OpenGL VBO - How to render vertices? 【发布时间】:2013-07-13 13:43:20 【问题描述】:

3我有以下 SceneRenderer 类,实现 GLEventListener。我想我了解创建缓冲区、存储指向这些缓冲区的指针以及用数据填充这些缓冲区的过程(参见 init 方法)。

我比较纠结的是 display() 方法。我已经尝试了几乎所有我在互联网上找到的所有东西的组合,但我仍然无法画出任何东西。谁能解释我现在该怎么做,所有缓冲区都充满了等待渲染的数据?

package cz.pscheidl.gui;

import javax.media.opengl.*;
import javax.media.opengl.glu.GLU;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;


public class SceneRenderer implements GLEventListener 

private IntBuffer buffers = IntBuffer.allocate(2);
private float[] square = 
        -1.0f, -1.0f,
        1.0f, -1.0f,
        1.0f, 1.0f,
        1.0f, 1.0f,
        -1.0f, 1.0f,
        -1.0f, -1.0f,
;

private float[] colorData = 
        255, 0, 0,
        255, 255, 0,
        0, 255, 0,
        0, 255, 0,
        0, 0, 255,
        255, 0, 0
;

FloatBuffer vertexFB = FloatBuffer.wrap(square);
FloatBuffer colorFB = FloatBuffer.wrap(colorData);


GLU glu = new GLU();

@Override
public void init(GLAutoDrawable glAutoDrawable) 
    GL3 gl = glAutoDrawable.getGL().getGL3();

    gl.glEnableClientState(GL2.GL_VERTEX_ARRAY);


    gl.glEnable(GL2.GL_DEPTH_TEST);
    gl.glClearDepthf(10.0f);
    gl.glClearColor(0.8f, 0.6f, 0.8f, 1.0f);
    gl.glDepthFunc(GL2.GL_LEQUAL);

    gl.glGenBuffers(2, buffers);

    gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, buffers.get(0));
    gl.glBufferData(GL2.GL_ARRAY_BUFFER, 4 * 6 * 2, vertexFB, GL3.GL_STATIC_DRAW);


    gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, buffers.get(1));
    gl.glBufferData(GL2.GL_ARRAY_BUFFER, 4 * 6 * 3, colorFB, GL2.GL_STREAM_DRAW);



@Override
public void dispose(GLAutoDrawable glAutoDrawable) 


@Override
public void display(GLAutoDrawable glAutoDrawable) 
    GL3 gl = glAutoDrawable.getGL().getGL3();
    gl.glClear(GL3.GL_DEPTH_BUFFER_BIT | GL3.GL_COLOR_BUFFER_BIT);


    gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, buffers.get(0));
    //After binding the buffer, now WHAT ?



@Override
public void reshape(GLAutoDrawable glAutoDrawable, int i, int i2, int i3, int i4) 
    GL3 gl = glAutoDrawable.getGL().getGL3();
    glu.gluPerspective(80.0f, 1920.0f / 1080.0f, 0.1f, 100f);



【问题讨论】:

我想你需要一些笼统的解释:Binding是告诉openGL你下次绘制时将使用什么,然后你需要告诉OpenGL实际绘制,然后你需要等待OpenGL完成在屏幕上绘制并显示框架。您已经覆盖了绑定,您可以使用opengl.org/sdk/docs/man/xhtml/glDrawElements.xml 进行绘制,并且您需要查找一些基本的 JOGL 教程以了解如何完成(我认为它称为 swapBuffers 或其他东西)绘制框架。 【参考方案1】:

您缺少一些东西:

1.着色器 着色器是在 gpu 上运行的程序。这就是您告诉 gpu 如何处理您的数据的方式。这就是您如何创建一个非常基本的程序,该程序具有顶点和片段着色器,可以显示您的网格。

把它和你的类级 var 声明放在一起:

private int program;

这将进入您的 init() 函数:

// Create program.
program = gl.glCreateProgram();

// Create vertexShader.
int vertexShader = gl.glCreateShader(GL2ES2.GL_VERTEX_SHADER);
String[] vertexShaderSource = new String[1];
vertexShaderSource[0] = "#version 330\n" +
    "layout(location=0) in vec2 position;\n" +
    "layout(location=1) in vec3 color;\n" +
    "out vec3 vColor;\n" +
    "void main(void)\n" +
    "\n" +
    "gl_Position = vec4(position, 0.0, 1.0);\n"
    "vColor = vec4(color, 1.0);\n"
    "\n";
gl.glShaderSource(vertexShader, 1, vertexShaderSource, null);
gl.glCompileShader(vertexShader);

// Create and fragment shader.
int fragmentShader = gl.glCreateShader(GL2ES2.GL_FRAGMENT_SHADER);
String[] fragmentShaderSource = new String[1];
fragmentShaderSource[0] = "#version 330\n" +
    "in vec4 vColor;\n" +
    "out vec4 fColor;\n" +
    "void main(void)\n" +
    "\n" +
    "fColor = vColor;\n" +
    "\n";
gl.glShaderSource(fragmentShader, 1, fragmentShaderSource, null);
gl.glCompileShader(fragmentShader);

// Attach shaders to program.
gl.glAttachShader(program, vertexShader);
gl.glAttachShader(program, fragmentShader);
gl.glLinkProgram(program);

2.顶点数组 绘制时需要使用两个缓冲区。顶点数组允许您存储多个缓冲区的状态并将数据发送到着色器程序中的不同位置。

把它和你的类级 var 声明放在一起:

IntBuffer vertexArray = IntBuffer.allocate(1);

在您创建缓冲区之后,这也将进入您的 init() 函数:

// Create Vertex Array.
gl.glGenVertexArrays(1, vertexArray);
gl.glBindVertexArray(vertexArray.get(0));

// Specify how data should be sent to the Program.

// VertexAttribArray 0 corresponds with location 0 in the vertex shader.
gl.glEnableVertexAttribArray(0);
gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, buffers.get(0));
gl.glVertexAttribPointer(0, 2, GL.GL_FLOAT, false, 0, 0);

// VertexAttribArray 1 corresponds with location 1 in the vertex shader.
gl.glEnableVertexAttribArray(1);
gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, buffers.get(1));
gl.glVertexAttribPointer(1, 3, GL.GL_FLOAT, false, 0, 0);

您的 display() 函数现在应该如下所示:

@Override
public void display(GLAutoDrawable glAutoDrawable) 
    GL3 gl = glAutoDrawable.getGL().getGL3();
    gl.glClear(GL3.GL_DEPTH_BUFFER_BIT | GL3.GL_COLOR_BUFFER_BIT);

    gl.glUseProgram(program)
    gl.glBindVertexArray(vertexArray.get(0));
    gl.glDrawArrays(GL.GL_TRIANGLES, 0, 6)

杂记: - 您的颜色值应介于 0 到 1 之间,而不是 0 到 255。 -您应该研究销毁您创建的 OpenGL 对象,以便在程序关闭或您不再需要它们时。 - 我强烈推荐阅读这些教程:OpenGL Book 和 Learning Modern 3D Graphics Programming。代码示例是用 C++ 编写的,但我发现它们非常有用。

【讨论】:

同时我做了一些“研究”,我并不清楚 VAO 和 VBO 之间的关系。你的帖子让我很开心。谢谢。

以上是关于JOGL/OpenGL VBO - 如何渲染顶点?的主要内容,如果未能解决你的问题,请参考以下文章

使用 glDrawArrays() 时如何获取 VBO 的长度以渲染所有顶点?

opengl vbo 纹理

使用 VBO 渲染顶点的问题 - OpenGL

如何在 ES2.0 中使用 VBO 画圆

如何有效地对齐 VBA 中的顶点以进行索引渲染?

使用 VBO 在 OpenGL 中渲染人群