【问题标题】:glDrawArrays specify different offsetsglDrawArrays 指定不同的偏移量
【发布时间】:2016-01-29 08:45:35
【问题描述】:

考虑以下情况:

A,B 成为 VBO 使得size(A)=N*size(B)。将执行 N 个glDrawArrays 调用。顶点着色器可以计算以下输入之一。

in VA: a1 a2 a3 a4 a5 ...
in VB: b1 b2 b3 b4 b5 ...

in VA: a1 a2 a3 a4 a5  ...
in VB: b6 b7 b8 b9 b10 ...

 ...

在此示例中,将具有以下 VBO

A  = (a1,a2,a3,a4,a5,...)
B1 = (b1,b2,b3,b4,b5,...)
B2 = (b6,b7,b8,b9,b10,...)

  ...

BN = ( ... , B_(size(A)*N-1)), B_(size(A)*N))

与 VAO 的

V1 = (VA->A,VB->B1)
V2 = (VA->A,VB->B2)
  ...
VN = (VA->A,VB->BN)

VA->A 表示顶点属性VA 指向VBO A

情况是我使用互操作性在 OpenCL 中计算了数据。从 OpenCL 计算的角度来看,使用将输出写入 single buffer 的内核非常优雅,这也是我的 VBO。

所以 B 看起来像这样:

B = (b1, b2, b3, ..., B_(size(A)*N))

现在我知道每个数据块对应的 x 轴如下所示:

A = (a1, a2, a3, ... x_size(A))

为了绘制数据,我的第一次尝试是创建一个 VBO X,基本上是

X = (A, A, ...) = (a1, a2, a3, ... x_size(A), a1, a2, a3, ...)

然后使用glDrawArraysposition, length 参数从其中渲染每个图形。

如果我有可能只使用A,B 而不是将B 拆分为多个VBO 或将X 复制为一个大VBO A,这对我来说将是一个不错的功能。那么这可能吗?如果不是:什么是好的策略?

【问题讨论】:

  • 我对这里的内存布局感到困惑。 VBO 是一个连续 内存段,就像您从malloc() 获得的一样。如果 A 是 VBO,它怎么可能在两个地方?你的意思是A和B是不同的顶点属性吗?能不能把你想要的内存布局画成一条直线,而不是这个有点模棱两可的二维布局?
  • 或者换句话说,我不确定这是指a1 a2 ... aN b1 b2 ... bN a1 a2 ... aN bN+1 bN+2 ... b2N,还是指a1 b1 a2 b2 ... aN bN ...
  • 抱歉我的第一个问题不准确,我更新了问题。希望现在情况变得更清楚
  • @keksnicoh: "如果我有可能只使用所描述的 A、B 而不是将 B 拆分为几个 VBO 或将 X 复制到一个大 VBO 中,这对我来说将是一个不错的功能A.”谁说你不能这样做?
  • @Nicol Bolas:没有人,但我不知道怎么做。

标签: opengl opencl


【解决方案1】:

使用 OpenGL >=4.3 或 ARB_vertex_attrib_binding,您可以使用glBindVertexBuffer() 快速将 B 属性重新绑定到不同的缓冲区或同一缓冲区中的不同位置。您仍然会遇到多个绘图调用,并且这些绘图调用之间的状态更改,但这是一个相当便宜的状态更改(就状态更改而言,它是最便宜的):

// Note: assuming A and B are just regular float, not vec2 or anything
// Omitted: VAO binding, enabling attributes, uniforms...

// Attribute locations
const int ATTRIB_A = 0, ATTRIB_B = 1;
// VBOs for A and B
GLuint buf_a, buf_b;
// Size of A = n, size of B = n * m
int n, m;

// Set the format for A and B
// Note: You can bind multiple attributes to each binding point,
// so hypothetical attribute C could share with A or B.
glVertexAttribFormat(ATTRIB_A, 1, GL_FLOAT, GL_FALSE, 0);
glVertexAttribFormat(ATTRIB_A, 1, GL_FLOAT, GL_FALSE, 0);

// Set the VBO binding points for A and B
glVertexAttribBinding(ATTRIB_A, 0);
glVertexAttribBinding(ATTRIB_B, 1);

// Bind your buffer for A
glBindVertexBuffer(0, buf_a, 0, sizeof(float));
for (int i = 0; i < m; i++) {
    // Bind part of the buffer for B
    glBindVertexBuffer(1, buf_b, i * n * sizeof(float), sizeof(float));
    // Draw...
    glDrawArrays(GL_POINTS, 0, n);
}

对于旧版本的 OpenGL,并且没有 ARB_vertex_attrib_binding,您可以在循环中调用 glVertexAttribPointer() 而不是 glBindVertexBuffer()

【讨论】:

  • glBindVertexBuffer 是我的东西!糟糕的是,我在我的 Mac 上坚持使用核心配置文件 4.1。 glVertexAttribPointer 在这里对我有帮助吗?我无法使用此命令定义偏移量。
  • 啊,是的,我分担你的痛苦。偏移量实际上是glVertexAttribPointer 的最后一个参数。它只是看起来像一个指针,但它实际上是一个偏移量。
  • 是的,我刚刚在这里读到:opengl.org/wiki/…。感谢您对此的提示,看起来我可以像我希望的那样解决我的问题 - 即使在 OpenGL4.1CoreProfile 中也是如此。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-06
  • 2011-08-05
相关资源
最近更新 更多