VBO状态调用的结构

huangapple go评论91阅读模式
英文:

structure of VBO state calls

问题

我正在将我的OpenGL 2程序转换为OpenGL 3,一步一步进行。当前的步骤是摆脱即时模式,转而使用VBO。我在所有VBO状态管理调用的正确位置上遇到了困难。

假设我将有一堆对象,每个对象都有自己的顶点和元素数据的VBO。每个对象都有一个加载函数,用于设置其VBO并将数据加载到其中;它还有一个绘制函数,用于绑定其VBO并发出适当的绘制命令。为了防止对象相互干扰,我的主循环在调用绘制或加载之前应该调用PushClientAttrib(CLIENT_VERTEX_ARRAY_BIT),对吗?(当然,在之后调用PopClientAttrib()

当我推入/弹出该状态以保护我的加载函数时,对象不会被绘制。似乎有一些状态我需要在我的绘制函数中(重新)设置,但我无法弄清楚可能是什么。

这是将一个新对象e添加到场景中,让它调用其加载函数的代码:


    gl.PushClientAttrib(gl.CLIENT_VERTEX_ARRAY_BIT)
    e.SceneAdded()
    gl.PopClientAttrib()

这是如何调用每个对象的绘制函数的代码:


    gl.PushClientAttrib(gl.CLIENT_VERTEX_ARRAY_BIT)
    gl.PushMatrix()
    p.Paint()
    gl.PopMatrix()
    gl.PopClientAttrib()

这是对象的加载函数:


	// 将顶点和纹理数据告知OpenGL。
	gl.GenBuffers(1, &vboId)
	gl.BindBuffer(gl.ARRAY_BUFFER, vboId)
	gl.BufferData(gl.ARRAY_BUFFER,
		gl.Sizeiptr(unsafe.Sizeof(gldata[0])*uintptr(len(gldata))),
		gl.Pointer(&gldata[0].x), gl.STATIC_DRAW)
	gl.VertexPointer(3, gl.DOUBLE, gl.Sizei(unsafe.Sizeof(gldata[0])),
		gl.Pointer(unsafe.Offsetof(gldata[0].x)))
	gl.TexCoordPointer(2, gl.DOUBLE, gl.Sizei(unsafe.Sizeof(gldata[0])),
		gl.Pointer(unsafe.Offsetof(gldata[0].s)))

	// 将索引数据告知OpenGL。
	gl.GenBuffers(1, &iboId)
	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, iboId)
	gl.BufferData(gl.ELEMENT_ARRAY_BUFFER,
		gl.Sizeiptr(unsafe.Sizeof(sd.indices[0])*uintptr(len(sd.indices))),
		gl.Pointer(&sd.indices[0]), gl.STATIC_DRAW)

最后,这是对象的绘制函数:


func draw() {
	gl.BindBuffer(gl.ARRAY_BUFFER, vboId)
	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, iboId)
	gl.EnableClientState(gl.VERTEX_ARRAY)
	gl.EnableClientState(gl.TEXTURE_COORD_ARRAY)

	gl.DrawElements(gl.TRIANGLES, indexcount, gl.UNSIGNED_SHORT, nil)
}

只是为了明确,如果我将两个EnableClientState调用从绘制函数移动到加载函数,并且如果我不用PushClientState保护加载函数,一切都正常工作。

英文:

I'm converting my OpenGL 2 program to OpenGL 3, one small step at a time. The current step is to get rid of immediate mode in favor of VBOs. I'm stumbling on the proper placement of all the VBO state management calls.

Let's assume I'm going to have a bunch of objects, each with its own VBOs for vertex and element data. Each object has a load function that sets up its VBOs and loads data into them; and it has a draw function that binds its VBOs and issues the appropriate draw command. To keep the objects from interfering with each other, my main loop should call <code>PushClientAttrib(CLIENT_VERTEX_ARRAY_BIT)</code> before either draw <b>or</b> load is called, correct? (And of course <code>PopClientAttrib()</code> after.)

When I push/pop that state to protect my load function, the object doesn't get drawn. It seems like there's some state I need to (re)set in my draw function, but I can't figure out what it could be.

Here's code to add a new object <code>e</code> to the scene, letting it call its load function:
<pre><code>
gl.PushClientAttrib(gl.CLIENT_VERTEX_ARRAY_BIT)
e.SceneAdded()
gl.PopClientAttrib()
</code></pre>

And here's how I call each object's draw function:
<pre><code>
gl.PushClientAttrib(gl.CLIENT_VERTEX_ARRAY_BIT)
gl.PushMatrix()
p.Paint()
gl.PopMatrix()
gl.PopClientAttrib()
</code></pre>

Here's the object's load function:
<pre><code>
// Make the vertex & texture data known to GL.
gl.GenBuffers(1, &vboId)
gl.BindBuffer(gl.ARRAY_BUFFER, vboId)
gl.BufferData(gl.ARRAY_BUFFER,
gl.Sizeiptr(unsafe.Sizeof(gldata[0])*uintptr(len(gldata))),
gl.Pointer(&gldata[0].x), gl.STATIC_DRAW)
gl.VertexPointer(3, gl.DOUBLE, gl.Sizei(unsafe.Sizeof(gldata[0])),
gl.Pointer(unsafe.Offsetof(gldata[0].x)))
gl.TexCoordPointer(2, gl.DOUBLE, gl.Sizei(unsafe.Sizeof(gldata[0])),
gl.Pointer(unsafe.Offsetof(gldata[0].s)))

// Make the index data known to GL.
gl.GenBuffers(1, &amp;iboId)
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, iboId)
gl.BufferData(gl.ELEMENT_ARRAY_BUFFER,
	gl.Sizeiptr(unsafe.Sizeof(sd.indices[0])*uintptr(len(sd.indices))),
	gl.Pointer(&amp;sd.indices[0]), gl.STATIC_DRAW)

</code></pre>

Finally, here's the object's draw function:
<pre><code>
func draw() {
gl.BindBuffer(gl.ARRAY_BUFFER, vboId)
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, iboId)
gl.EnableClientState(gl.VERTEX_ARRAY)
gl.EnableClientState(gl.TEXTURE_COORD_ARRAY)

gl.DrawElements(gl.TRIANGLES, indexcount, gl.UNSIGNED_SHORT, nil)

}
</code></pre>

Just to be clear, if I move the two <code>EnableClientState</code> calls from draw to load, and if I don't protect load with <code>PushClientState</code>, everything works fine.

答案1

得分: 2

我正在将我的OpenGL 2程序转换为OpenGL 3。

那么以下内容:

为了防止对象相互干扰,我的主循环在调用绘制或加载之前应该调用PushClientAttrib(CLIENT_VERTEX_ARRAY_BIT),对吗?(当然,在之后调用PopClientAttrib()。)

这不是一个明智的方法。glPushAttrib和glPopAttrib已经被弃用,即不应该在OpenGL 3程序中使用。

此外,OpenGL顶点数组不使用glVertexPointer,而是使用glVertexAttribPointer。属性指针状态可以在顶点数组对象中管理(我建议这样做),您可以绑定/解绑。

顺便说一下:当您编写OpenGL 2时,为什么首先使用了即时模式?自从OpenGL 1.1引入顶点数组以来,即时模式的使用就不被鼓励。而且在OpenGL 2中,已经考虑移除即时模式。

英文:

> I'm converting my OpenGL 2 program to OpenGL 3

Well then the following

> To keep the objects from interfering with each other, my main loop should call PushClientAttrib(CLIENT_VERTEX_ARRAY_BIT) before either draw or load is called, correct? (And of course PopClientAttrib() after.)

is not a sane approach. glPushAttrib and glPopAttrib are deprecated, i.e. should not be used in OpenGL-3 program.

Also OpenGL vertex arrays don't use glVertexPointer the use glVertexAttribPointer. Attribute pointer state can be managed (and I recommend that) in a Vertex Array Object, which you can bind/unbind.


BTW: When you wrote for OpenGL-2, why did you use immediate mode in the first place? Use of immediate mode is discouraged ever since OpenGL-1.1, when vertex arrays had been introduced. And already with OpenGL-2 it was considered to remove immediate mode.

答案2

得分: 0

我实际提出的问题的答案是,gl.VertexPointer()和相关函数需要从对象的绘制函数中调用。我的主循环正在推送和弹出与客户端顶点相关的所有状态,所以当然会丢失。

我暗示的问题是,“如何将我的旧的GL2程序转换为新的GL3代码?” 这个问题在这里得到了非常优雅的回答:这里

英文:

The answer to the question I actually asked is that gl.VertexPointer() and friends need to be called from the object's draw function. My main loop is pushing and popping all state related to client vertices, so of course that gets lost.

The question I implied is, "How can I convert my old, GL2 program to new, GL3 code?" That's answered very elegantly <a href="https://stackoverflow.com/a/4694145/107357">here</a>.

huangapple
  • 本文由 发表于 2013年1月10日 14:04:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/14251745.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定