java - 了解 OpenGL 基础知识
问题描述
问候 OpenGL 爱好者!
- 首先我使用LWJGL 2,所以下面是 Java 代码。
- 第二。我想说我用谷歌搜索了我将在这篇文章中提出的每一个问题。主要问题是答案彼此不同,因此我无法对下面代码中发生的事情建立具体的理解。
- 第三。我刚开始学习 OpenGL,我也完全没有 Java 方面的经验。因此,如果您除了对我的问题的解释之外还有任何建议,请随时批评/建议。除了用 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;
}
}
注意- 此代码正在运行并输出一个蓝色窗口,中间有一个黑色四边形。问题:
glBindBuffer(GL_ARRAY_BUFFER, vboID);
我不清楚GL_Array Buffer是什么意思。据我所知,它只是向 OpenGL 当前状态显示该 VBO 将在某个时候存储数组数据。但从下面的函数中,我可以猜到它不仅仅是一种数据,它就像一个数据容器,它只能在当前状态下处于活动状态。我做对了吗?还是我错过了什么?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);
and 。最终渲染中应该没有任何变化,但实际上黑色四边形没有出现。想不通为什么。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基础知识的混乱。对于那些能够阅读甚至回答这篇文章的人 -非常感谢!
解决方案
glBindBuffer(GL_ARRAY_BUFFER, vboID);
意思是:我有几个 VBO。选择(供下次使用)由 标识的那个vboID
。该模式GL_ARRAY_BUFFER
适用于原始(字节)数据。
glBufferData(GL_ARRAY_BUFFER, size, buffer, GL_STATIC_DRAW); //Notice I added "size" for C++. LWJGL doesn't need it.
意思是:用字节填充当前绑定的array_buffer(带有“glBindBuffer”)size
;从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
的类型值(不在 [0.0, 1.0] 范围内)。该属性的下一个序列是远字节(使用 0 表示属性被紧密打包)。最后一个是 VBO 中第一个属性的偏移量。GL_FLOAT
false
stride
0.0
颜色可以被读取为另一个属性,来自相同的 VBO 或不同。此属性的“名称”可能是1
,因为0
已用于坐标。所以它需要自己的glVertexAttribPointer
调用。
属性标识符由 GPU 选择。由于 OpenGL >=3.3(我强烈建议使用),您最好选择它们(通过着色器中的“location = 0”内容)
AVAO
包含缓冲区绑定和属性绑定。每次你需要渲染来自一些 VBO 的数据时,你不需要再次使用glBindBuffer
和glVertexAttribPointer
required。改用就好glBindVertexArray
了。
“索引渲染”意味着您使用两个 VBO:一个用于坐标,另一个用于索引。(其他 VBO 也可用于其他属性)。带有索引的 VBO 告诉 GPU 来自第一个 VBO(和其他 VBO)的“序列”顺序。这些允许多次读取相同的顶点而不重复其属性。请注意,三角剖分在多个三角形之间共享相同的顶点。您可以避免向 GPU 发送重复数据。
推荐阅读
- python - 从数字中查找第 3 和第 4 位数字
- sql - Oracle SQL/PLSQL:一次性更改特定列的类型
- python - 向 QScrollArea 添加元素时滚动到底部
- java - 如何在 JAVA 中使用 com.google.zxing libraby 在二维码下方添加文本
- python - ModuleNotFoundError:没有名为“tensorflow_hub”的模块
- java - 如何打破递归函数的多个实例调用?
- mongodb - Mongoose 文本索引搜索返回空数组
- python - 如何在 sqlalchemy 中编写不同的查询?
- javascript - 按下制表符时如何操作光标跳转的位置?
- php - 关于方法的 PHP 文档