我不明白GL_ARRAY_BUFFEROpenGL 中绑定点(例如)的目的是什么.据我所知,glGenBuffers()创建了一种指向位于GPU内存中某处的顶点缓冲区对象的指针.
所以:
glGenBuffers(1, &bufferID)
Run Code Online (Sandbox Code Playgroud)
意味着我现在有一个句柄,bufferID,到图形卡上的1个顶点对象.现在我知道下一步是将bufferID绑定到绑定点
glBindBuffer(GL_ARRAY_BUFFER, bufferID)
Run Code Online (Sandbox Code Playgroud)
这样我就可以使用该绑定点使用如下glBufferData()函数发送数据:
glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW)
Run Code Online (Sandbox Code Playgroud)
但为什么我不能只使用bufferID来指定我想要发送数据的位置呢?就像是:
glBufferData(bufferID, sizeof(data), data, GL_STATIC_DRAW)
Run Code Online (Sandbox Code Playgroud)
然后当调用绘图函数时,我也只是将任何ID放入我想要绘制绘图函数的VBO中.就像是:
glDrawArrays(bufferID, GL_TRIANGLES, 0, 3)
Run Code Online (Sandbox Code Playgroud)
为什么我们需要额外的间接步骤glBindBuffers?
在顶点数组缓冲区的典型构建中,我尝试将 unsigned int 属性与其他经典属性(顶点、法线、纹理坐标...)一起传递。然而,该属性的值最终以某种方式错误:我不确定该值是否错误或该属性根本没有设置。
从一个简单的例子开始,假设我定义了以下 C++ 输入结构:
struct buffer_data_t
{
glm::vec3 vertex;
glm::vec3 normal;
glm::vec2 texCoords;
};
Run Code Online (Sandbox Code Playgroud)
准备我的顶点数组如下所示:
// Assume this 'shader.attribute(..)' is working and returns the attribute's position
unsigned int shadInputs[] = {
(unsigned int)shader.attribute("VS_Vertex"),
(unsigned int)shader.attribute("VS_Normal"),
(unsigned int)shader.attribute("VS_TexCoords"),
};
glGenBuffers(1, &glBuffer);
glBindBuffer(GL_ARRAY_BUFFER, glBuffer);
glBufferData(GL_ARRAY_BUFFER, vertice.size() * sizeof(buffer_data_t), &vertice[0], GL_STATIC_DRAW);
glGenVertexArrays(1, &glArray);
glBindVertexArray(glArray);
{
glBindBuffer(GL_ARRAY_BUFFER, glBuffer);
glVertexAttribPointer(shadInputs[0], 3, GL_FLOAT, GL_FALSE, sizeof(buffer_data_t), (void*)(sizeof(glm::vec3) * 0));
glVertexAttribPointer(shadInputs[1], 3, GL_FLOAT, GL_FALSE, sizeof(buffer_data_t), (void*)(sizeof(glm::vec3) * 1));
glVertexAttribPointer(shadInputs[2], 2, GL_FLOAT, GL_FALSE, sizeof(buffer_data_t), (void*)(sizeof(glm::vec3) * …Run Code Online (Sandbox Code Playgroud) 因此,在OpenGL渲染应用程序中,通常最好在应用程序的整个生命周期中创建和维护顶点缓冲区,并且只使用glBufferData每帧交换数据,或者更好的方法是删除VBO并在每一帧重新创建它?
Intuition告诉我交换数据更好,但是我见过的一些示例程序是后者,所以我有点困惑.
我读过Nvidia关于VBO的白皮书,但由于我是opengl的新手,所以它没有多大意义.
在此先感谢您的建议
对于一点背景:我正在使用 C++ 开发一个项目,在该项目中我试图根据实时配置文件数据绘制对象的 3D 表示。分析数据是从外部分析硬件收集的。该系统沿着一个物体以每秒 300 次的速度为我的软件提供一个剖面切片。每个切片由约 8000 个 XY 点的列表组成。轮廓仪的运动由编码器记录。编码器信息提供扫描的第三维。
另一个需要注意的重要事项是探查器可能会在对象上来回移动。发生这种情况时,我想用新的切片替换以前读取/绘制的切片(基于编码器位置)。到目前为止,我正在使用我按编码器计数存储的切片的循环缓冲区来实现这一点。这也意味着当缓冲区填满并开始覆盖旧切片时,我会想要丢弃切片。为了在屏幕上显示适当数量的主题片断 - 我需要一次绘制 1000 个切片数据。现在我将对象渲染为点云。将来我们可能会尝试附加相邻的切片并渲染为三角形列表。
我是 DirectX 的新手,但使用书籍和在线示例,我已经达到了在 3D 中绘制对象的程度,但我确信我没有有效/正确地使用顶点缓冲区。我发现的大多数示例都适用于非常静态的模型。因此,他们倾向于用他们的点列表创建一个单一的顶点缓冲区,然后只是通过矩阵变换来操作。另一方面,当我从硬件中检索配置文件数据时,我将非常快速地更新场景。
目前,我正在为我读入的每个切片创建一个新的顶点缓冲区。当我绘制场景时,我会遍历最多 1000 个缓冲区的列表,并为每个缓冲区调用 Draw()。我注意到,如果我将一次绘制的顶点缓冲区数量减少一半,我的 FPS 会显着增加,而将每个缓冲区的顶点点数量减半时几乎没有改进 - 所以我认为这表明多个顶点缓冲区不是解决这个问题的正确方法。
所以对于我的问题的胆量......我想知道当顶点变化如此频繁时我是否可以将所有这些顶点放在一个顶点缓冲区中。我可以更新现有顶点缓冲区中的点吗?或者我应该在每次更新场景时重新创建一个全新的缓冲区?要记住的最后一件事是,硬件中每个切片的点数会有所不同 - 因此,在覆盖之前的切片时,新切片可能比被替换的切片具有更多或更少的点。
谢谢你的时间。任何建议将不胜感激!
我有一个调用glDrawArrays的OpenGL渲染代码,当OpenGL上下文(自动/隐式获取)时,它可以完美地运行4.2但是在显式请求的OpenGL核心上下文3.2中一致地失败(GL_INVALID_OPERATION).(在两种情况下,着色器始终设置为#version 150,但这与我怀疑的点不同.)
根据规范,glDrawArrays()在GL_INVALID_OPERATION失败时只有两个实例:
"如果非零缓冲区对象名称绑定到已启用的数组,并且缓冲区对象的数据存储当前已映射" - 此时我没有进行任何缓冲区映射
"如果几何着色器处于活动状态且模式与[...]不兼容" - nope,则截至目前没有几何着色器.
此外:
我已经验证并仔细检查了它只是glDrawArrays()调用失败了.还要仔细检查传递给glDrawArrays()的所有参数在GL版本,缓冲区绑定下是否相同.
这发生在3个不同的nvidia GPU和2个不同的操作系统(Win7和OSX,都是64位 - 当然,在OSX中我们只有 3.2上下文,无论如何都不是4.2).
使用集成的"Intel HD"GPU不会发生这种情况,但对于那个,我只获得一个自动的隐式3.3上下文(试图通过GLFW明确强制使用此GPU的3.2核心配置文件在这里无法创建窗口,但这是一个完全不同的问题...)
对于它的价值,这里是在Golang中从渲染循环中摘录的相关例程:
func (me *TMesh) render () {
curMesh = me
curTechnique.OnRenderMesh()
gl.BindBuffer(gl.ARRAY_BUFFER, me.glVertBuf)
if me.glElemBuf > 0 {
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, me.glElemBuf)
gl.VertexAttribPointer(curProg.AttrLocs["aPos"], 3, gl.FLOAT, gl.FALSE, 0, gl.Pointer(nil))
gl.DrawElements(me.glMode, me.glNumIndices, gl.UNSIGNED_INT, gl.Pointer(nil))
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, 0)
} else {
gl.VertexAttribPointer(curProg.AttrLocs["aPos"], 3, gl.FLOAT, gl.FALSE, 0, gl.Pointer(nil))
/* BOOM! */
gl.DrawArrays(me.glMode, 0, me.glNumVerts)
}
gl.BindBuffer(gl.ARRAY_BUFFER, 0)
}
Run Code Online (Sandbox Code Playgroud)
所以当然这是更大的渲染循环的一部分,尽管现在整个"*TMesh"构造只是两个实例,一个是简单的立方体,另一个是简单的金字塔.重要的是整个绘图循环完美无缺,在3.3和4.2下查询GL时没有报告错误,但是3个具有显式3.2核心配置文件的nvidia GPU失败并且错误代码根据规范只调用了两个具体情况,据我所知,这里没有一个适用.
这可能有什么问题?你碰到过这个吗?我缺少什么想法?
在我的跨平台OpenGL应用程序中,我想使用顶点缓冲区对象进行绘制.但是我遇到了调用glDrawRangeElements的问题.
glDrawRangeElements(GL_TRIANGLES, start, start + count, count,
GL_UNSIGNED_INT, static_cast<GLvoid *> (start * sizeof(unsigned int)));
Run Code Online (Sandbox Code Playgroud)
编译器(Mac OS X上的CLang)不喜欢最后一个参数"错误:无法从类型'unsigned long'转换为指针类型'GLvoid*'(又名'void*')".OpenGL API将最后一个参数的类型定义为const GLvoid*,并且当此api与顶点数组一起使用时需要一个指针.但是我知道当使用顶点缓冲区对象而不是指针时,应该将一个表示偏移量的整数值传递给缓冲区数据.这就是我想要做的事情,因此我必须施展.如何协调api要求与编译器进行严格的检查?
我是 OpenGL 的新手,正在学习 VBO 和 VAO。我试图了解如何在 VAO 中处理/释放/分离 VBO,当我不再有单个 VBO id,只有 VAO 时。
我是否必须单独获取所有glDeleteBuffersVBO ,然后调用每个 VBO?或者是否有一种方法可以使用 VAO 并自动处理所有 VBO?
有人可以展示如何从 VAO 获取 VBO 吗?
不知道问这个问题的最佳方式是什么......但我有一个带有皮肤人体模型的场景套件场景(它由几个皮肤网格组成,有些具有混合形状(变形)、骨骼层次和> 60种不同的材料) . 一些网格分配了 3-8 种材料。所有这些网格都分为 8 组。
当我在设备(iPhone 5s、iPad Pro)上运行项目时,出现此错误:
validateFunctionArguments:2800: 失败的断言 `(length - offset)(11088) 在 scn_node[0] 的索引 1 处的缓冲区绑定必须 >= 12368。'
如果我隐藏前两组网格,那么项目运行得很好。如果我取消隐藏前两组并隐藏其他所有内容,则应用程序也可以在设备上正常运行。但是,如果我显示所有 8 个组应用程序崩溃并给出该错误。如果我删除 3D 包中的所有材料,然后使用单一材料导出模型,那么所有显示的 8 个组都运行良好。
我们正在使用金属。最新的 Xcode 8,最新的 iOS 10
什么可能导致这种情况?场景只有那个模型,没有别的。非常感谢任何帮助或建议。谢谢!
我一直在寻找将属性与任意组的顶点相关联的方法,起初,实例化似乎是实现此目的的唯一方法,但是后来我迷迷糊糊地问了这个问题,这个答案指出:
但是,使用较新版本的OpenGL可能会设置某个顶点属性的缓冲区偏移增加的速率。有效地,这意味着给定顶点数组的数据在属性的缓冲区偏移量增加之前被复制到n个顶点。设置该除数的函数是glVertexBindingDivisor。
(强调我的)
在我看来,这似乎是答案在断言,我可以划分顶点数而不是实例数。但是,当我查看glVertexBindingDivisor的文档并将其与进行比较时,glVertexAttribDivisor它们似乎都指发生在实例而非顶点上的划分。例如,在glVertexBindingDivisor的文档中指出:
glVertexBindingDivisor和glVertexArrayBindingDivisor修改在单个draw命令中渲染图元的多个实例时通用顶点属性前进的速率。如果除数为零,则使用绑定到bindingindex的缓冲区的属性每个顶点前进一次。如果除数不为零,则属性在每个要渲染的顶点集的除数实例中前进一次。如果相应的除数值不为零,则将该属性称为实例。
(强调我的)
那么这两个功能之间的实际区别是什么?
我想绘制多个不同长度的线条。所有顶点都在一个公共缓冲区中。
订单如下所示:
v_1_1,v_1_2,v_1_3,v_2_1,v_2_2,v_3_1,..对于每个顶点v_i_j,其中i是条带j的索引和条带中顶点的索引。
是否可以使用索引缓冲区来指定该缓冲区中每个条带的开始和结束索引?
或者有什么其他方法可以解决这个问题?
vertex-buffer ×10
opengl ×8
c++ ×3
vertex ×2
c++11 ×1
directx ×1
directx-10 ×1
glm-math ×1
glsl ×1
go ×1
index-buffer ×1
ios ×1
metal ×1
opengl-3 ×1
opengl-4 ×1
opengl-es ×1
sigabrt ×1
vertex-array ×1
xcode ×1