了解 OpenGL 基础知识
Undestanding OpenGL fundamentals
OpenGL 爱好者们大家好!
- 首先我用的是LWJGL 2,所以是下面的Java代码。
- 其次。我想说我用谷歌搜索了我遇到的每一个问题
会在这个post中提问。主要问题是答案不同
彼此之间,所以我无法建立对事物的具体理解
这发生在我下面的代码中。
- 第三。我刚开始学习 OpenGL,而且我也完全没有 Java 的经验。因此,如果您除了对我的问题进行解释之外还有任何建议,请随时 criticize/advise。除了用 C++ 做 OpenGL :)
现在让我们开始吧。
public class Loader {
public void createVAO(int[] indices) {
int vaoID = glGenVertexArrays();
glBindVertexArray(vaoID);
createIndicesVBO(indices);
glEnableVertexAttribArray(0);
}
public void createVBO(float[] vertices) {
int vboID = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboID);
FloatBuffer buffer = makeByteBufferFromArrayOfFloats(vertices);
glBufferData(GL_ARRAY_BUFFER, buffer, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0,0);
}
public void createIndicesVBO(int[] indices) {
int vboID = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboID);
IntBuffer buffer = makeByteBufferFromArrayOfInts(indices);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, buffer, GL_STATIC_DRAW);
}
public void pleaseDraw(float[] vertices, int[] indices) {
glClearColor(0, 0, 1, 1);
glClear(GL_COLOR_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, indices.length, GL_UNSIGNED_INT,0);
}
public void cleanUp() {
glDeleteBuffers(0);
glDeleteVertexArrays(0);
}
public FloatBuffer makeByteBufferFromArrayOfFloats(float[] vertices) {
FloatBuffer FloatByteBuffer = BufferUtils.createFloatBuffer(vertices.length);
FloatByteBuffer.put(vertices);
FloatByteBuffer.flip();
return FloatByteBuffer;
}
public IntBuffer makeByteBufferFromArrayOfInts(int[] array) {
IntBuffer IntByteBuffer = BufferUtils.createIntBuffer(array.length);
IntByteBuffer.put(array);
IntByteBuffer.flip();
return IntByteBuffer;
}
}
注意 - 此代码有效并输出蓝色 window,中间有一个黑色四边形。
问题:
glBindBuffer(GL_ARRAY_BUFFER, vboID);
连 GL_Array Buffer 是什么意思我都不太明白。据我所知,它只是向 OpenGL 当前状态显示此 VBO 将在某个时候存储数组数据。但是从下面的函数我可以猜到它不仅仅是一种数据,它就像一个
数据的容器,这只是当前状态的 active。我做对了吗?或者我错过了什么?
glBufferData(GL_ARRAY_BUFFER, buffer, GL_STATIC_DRAW);
又是这个 GL_Array_Thing。似乎这个函数将数据放入 GPU 或者将当前的 VBO 放入 VAO?我不确定。
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0,0);
所以 VAO 由属性组成,这里我们向 OpenGL 展示如何读取我们的 0 属性。如果我错了请纠正我。
- 如果我知道 VAO 中的属性是如何正确工作的,我假设我可以将这行
glEnableVertexAttribArray(0);
和 glVertexAttribPointer(0, 3, GL_FLOAT, false, 0,0);
更改为 glEnableVertexAttribArray(1);
和 glVertexAttribPointer(1, 3, GL_FLOAT, false, 0,0);
。最终渲染应该没有任何变化,但实际上黑色四边形并没有出现。想不通为什么。
- 我使用索引来绘制四边形。但是 OpenGL 究竟如何理解如何读取我提供的数据,因为我没有指定如何使用它。我只是想象这条线可以帮助我做到这一点
glDrawElements(GL_TRIANGLES, indices.length, GL_UNSIGNED_INT,0);
有很多额外的问题,但它们出现是因为我对上面描述的问题缺乏理解。请帮我弄清楚我脑子里关于 OpenGL 基础知识的混乱情况。对于那些能够阅读甚至回答此问题的人 post - 非常感谢!
glBindBuffer(GL_ARRAY_BUFFER, vboID);
意思是:我有几个VBO。 Select(供下次使用)由 vboID
标识的那个。模式 GL_ARRAY_BUFFER
适用于 raw(字节)数据。
glBufferData(GL_ARRAY_BUFFER, size, buffer, GL_STATIC_DRAW); //Notice I added "size" for C++. LWJGL doesn't need it.
意思是:用size
字节填充当前绑定的array_buffer(with"glBindBuffer");从 buffer
(CPU RAM 中的地址)获取它们。我的本意(GL_STATIC_DRAW
)是GPU多次读取数据,而不是修改数据
glVertexAttribPointer(0, 3, GL_FLOAT, false, stride, 0,0); // "stride" added
GPU从一个或多个VBO读取。例如,VBO 可能由 x、y、z 坐标(3 个浮点数)和后面的 R、G、B、A 颜色分量(4 个字节)组成,并为其他顶点重复该序列。
glVertexAttribPointer 建立VBO 和所需属性之间的关系。在示例中:第一个属性 (0
) 需要 3
类型 GL_FLOAT
的值,这些值未 (false
) 归一化(不在 [0.0, 1.0] 范围内)。此属性的下一个序列是 stride
字节远(使用 0 表示属性紧密打包)。最后一个 0.0
是第一个属性在 VBO 中的偏移量。
颜色可以作为另一个属性读取,无论是否来自同一个 VBO。此属性的 "name" 可能是 1
,因为 0
已用于坐标。所以它需要自己的 glVertexAttribPointer
调用。
属性标识符由 GPU 选择。由于 OpenGL >=3.3(我强烈建议使用)你最好选择它们(通过 "location = 0" 着色器中的东西)
A VAO
包含缓冲区绑定和属性绑定。每次您需要从某些 VBO 渲染数据时,您不需要再次使用所需的 glBindBuffer
和 glVertexAttribPointer
。只需使用 glBindVertexArray
即可。
"Indexing rendering" 表示您使用两个 VBO:一个用于坐标,另一个用于索引。 (其他 VBO 也可用于其他属性)。带索引的 VBO 告诉 GPU 来自第一个 VBO(和其他 VBO)的 "sequences" 顺序。这些允许多次读取相同的顶点而不重复其属性。请注意,三角剖分在多个三角形之间共享相同的顶点。您可以避免向 GPU 发送重复数据。
OpenGL 爱好者们大家好!
- 首先我用的是LWJGL 2,所以是下面的Java代码。
- 其次。我想说我用谷歌搜索了我遇到的每一个问题 会在这个post中提问。主要问题是答案不同 彼此之间,所以我无法建立对事物的具体理解 这发生在我下面的代码中。
- 第三。我刚开始学习 OpenGL,而且我也完全没有 Java 的经验。因此,如果您除了对我的问题进行解释之外还有任何建议,请随时 criticize/advise。除了用 C++ 做 OpenGL :)
现在让我们开始吧。
public class Loader {
public void createVAO(int[] indices) {
int vaoID = glGenVertexArrays();
glBindVertexArray(vaoID);
createIndicesVBO(indices);
glEnableVertexAttribArray(0);
}
public void createVBO(float[] vertices) {
int vboID = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboID);
FloatBuffer buffer = makeByteBufferFromArrayOfFloats(vertices);
glBufferData(GL_ARRAY_BUFFER, buffer, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0,0);
}
public void createIndicesVBO(int[] indices) {
int vboID = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboID);
IntBuffer buffer = makeByteBufferFromArrayOfInts(indices);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, buffer, GL_STATIC_DRAW);
}
public void pleaseDraw(float[] vertices, int[] indices) {
glClearColor(0, 0, 1, 1);
glClear(GL_COLOR_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, indices.length, GL_UNSIGNED_INT,0);
}
public void cleanUp() {
glDeleteBuffers(0);
glDeleteVertexArrays(0);
}
public FloatBuffer makeByteBufferFromArrayOfFloats(float[] vertices) {
FloatBuffer FloatByteBuffer = BufferUtils.createFloatBuffer(vertices.length);
FloatByteBuffer.put(vertices);
FloatByteBuffer.flip();
return FloatByteBuffer;
}
public IntBuffer makeByteBufferFromArrayOfInts(int[] array) {
IntBuffer IntByteBuffer = BufferUtils.createIntBuffer(array.length);
IntByteBuffer.put(array);
IntByteBuffer.flip();
return IntByteBuffer;
}
}
注意 - 此代码有效并输出蓝色 window,中间有一个黑色四边形。 问题:
glBindBuffer(GL_ARRAY_BUFFER, vboID);
连 GL_Array Buffer 是什么意思我都不太明白。据我所知,它只是向 OpenGL 当前状态显示此 VBO 将在某个时候存储数组数据。但是从下面的函数我可以猜到它不仅仅是一种数据,它就像一个 数据的容器,这只是当前状态的 active。我做对了吗?或者我错过了什么?glBufferData(GL_ARRAY_BUFFER, buffer, GL_STATIC_DRAW);
又是这个 GL_Array_Thing。似乎这个函数将数据放入 GPU 或者将当前的 VBO 放入 VAO?我不确定。glVertexAttribPointer(0, 3, GL_FLOAT, false, 0,0);
所以 VAO 由属性组成,这里我们向 OpenGL 展示如何读取我们的 0 属性。如果我错了请纠正我。- 如果我知道 VAO 中的属性是如何正确工作的,我假设我可以将这行
glEnableVertexAttribArray(0);
和glVertexAttribPointer(0, 3, GL_FLOAT, false, 0,0);
更改为glEnableVertexAttribArray(1);
和glVertexAttribPointer(1, 3, GL_FLOAT, false, 0,0);
。最终渲染应该没有任何变化,但实际上黑色四边形并没有出现。想不通为什么。 - 我使用索引来绘制四边形。但是 OpenGL 究竟如何理解如何读取我提供的数据,因为我没有指定如何使用它。我只是想象这条线可以帮助我做到这一点
glDrawElements(GL_TRIANGLES, indices.length, GL_UNSIGNED_INT,0);
有很多额外的问题,但它们出现是因为我对上面描述的问题缺乏理解。请帮我弄清楚我脑子里关于 OpenGL 基础知识的混乱情况。对于那些能够阅读甚至回答此问题的人 post - 非常感谢!
glBindBuffer(GL_ARRAY_BUFFER, vboID);
意思是:我有几个VBO。 Select(供下次使用)由 vboID
标识的那个。模式 GL_ARRAY_BUFFER
适用于 raw(字节)数据。
glBufferData(GL_ARRAY_BUFFER, size, buffer, GL_STATIC_DRAW); //Notice I added "size" for C++. LWJGL doesn't need it.
意思是:用size
字节填充当前绑定的array_buffer(with"glBindBuffer");从 buffer
(CPU RAM 中的地址)获取它们。我的本意(GL_STATIC_DRAW
)是GPU多次读取数据,而不是修改数据
glVertexAttribPointer(0, 3, GL_FLOAT, false, stride, 0,0); // "stride" added
GPU从一个或多个VBO读取。例如,VBO 可能由 x、y、z 坐标(3 个浮点数)和后面的 R、G、B、A 颜色分量(4 个字节)组成,并为其他顶点重复该序列。
glVertexAttribPointer 建立VBO 和所需属性之间的关系。在示例中:第一个属性 (0
) 需要 3
类型 GL_FLOAT
的值,这些值未 (false
) 归一化(不在 [0.0, 1.0] 范围内)。此属性的下一个序列是 stride
字节远(使用 0 表示属性紧密打包)。最后一个 0.0
是第一个属性在 VBO 中的偏移量。
颜色可以作为另一个属性读取,无论是否来自同一个 VBO。此属性的 "name" 可能是 1
,因为 0
已用于坐标。所以它需要自己的 glVertexAttribPointer
调用。
属性标识符由 GPU 选择。由于 OpenGL >=3.3(我强烈建议使用)你最好选择它们(通过 "location = 0" 着色器中的东西)
A VAO
包含缓冲区绑定和属性绑定。每次您需要从某些 VBO 渲染数据时,您不需要再次使用所需的 glBindBuffer
和 glVertexAttribPointer
。只需使用 glBindVertexArray
即可。
"Indexing rendering" 表示您使用两个 VBO:一个用于坐标,另一个用于索引。 (其他 VBO 也可用于其他属性)。带索引的 VBO 告诉 GPU 来自第一个 VBO(和其他 VBO)的 "sequences" 顺序。这些允许多次读取相同的顶点而不重复其属性。请注意,三角剖分在多个三角形之间共享相同的顶点。您可以避免向 GPU 发送重复数据。