XNA - 使用动态顶点缓冲区且仅使用四 (4) 个顶点
只是一个关于绘制四边形的快速问题。我目前正在使用:
GraphicsDevice.DrawPrimitives(PrimitiveType primitiveType,
int startVertex, int primitiveCount);
这可以完美地绘制我的四边形,但我可以使其工作的唯一方法是为我的四边形使用六(6)个顶点(将它们绘制为两个三角形)。我只是想知道是否可以为 GPU 提供四 (4) 个顶点,同时仍然保留我的动态顶点缓冲区。
我知道我可以使用 DrawUserIndexedPrimitives() 来做到这一点,但我想要我的缓冲区! ;)
编辑:我需要吗?如果需要,我在哪里告诉我的 GPU 我正在为每两个三角形提供四个顶点?我目前将我的四边形作为 nQuads * 6 顶点存储在顶点缓冲区中,并且我的 GPU 使用每三个顶点作为一个三角形。因此,仅仅切换到四个顶点意味着:
Quads: {v1,v2,v3,v4} {v5,v6,v7,v8} ...
Triangles: {v1,v2,v3} {v4,v5,v6} {v7,v8 ...}
这不是一件好事,因为第二个三角形使用第一个四边形中的一个顶点,第三个三角形使用第二个四边形中的两个顶点,依此类推。
编辑2:抱歉,我实际上正在使用动态顶点缓冲区。
发布一些关于如何使用六个顶点制作四边形的代码:
// ## CONSTRUCTION
// Setting up buffer and vertex holder.
particleVertexBuffer = new DynamicVertexBuffer(graphicsDevice,
ParticleQuad.VerticesSizeInBytes * nMaxParticles,
BufferUsage.WriteOnly);
particleVertices = new ParticleVertex[nMaxParticles * 6];
// ## ADD VERTICES
particleVertices[i].Set();
particleVertices[i+1].Set();
particleVertices[i+2].Set();
particleVertices[i+3].Set();
particleVertices[i+4].Set();
particleVertices[i+5].Set();
// ## SET BUFFER
particleVertexBuffer.SetData(particleVertices, 0, nMaxParticles * 6, SetDataOptions.NoOverwrite);
graphicsDevice.Vertices[0].SetSource(particleVertexBuffer, 0, ParticleVertex.SizeInBytes);
// ## DRAW
graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList,
FirstUsedParticle * 6, ((LastUsedParticle - FirstUsedParticle)+1)* 2);
现在,还有更多内容,因为我使用循环队列和其他一些东西,但这足以理解。
Just a quick question on drawing quads. I'm currently using:
GraphicsDevice.DrawPrimitives(PrimitiveType primitiveType,
int startVertex, int primitiveCount);
This draws my quads perfectly fine but the only way I can make it work is to use six (6) vertices for my quads (drawing them as two triangles). I'm just wondering if it is possible to feed the GPU with four (4) vertices and still retain my dynamic vertex buffer.
I know that I can do so with DrawUserIndexedPrimitives() but I want my buffer! ;)
Edit: Do I need, and if so where do I tell my GPU that I'm feeding it four vertices per two triangles? I'm currently storing my quads as nQuads * 6 vertices in a vertex buffer and my GPU uses every three vertices as a triangle. So just switching to four vertices means:
Quads: {v1,v2,v3,v4} {v5,v6,v7,v8} ...
Triangles: {v1,v2,v3} {v4,v5,v6} {v7,v8 ...}
Which is not a good thing since triangle number two uses one vertex from the first quad, number three uses two from the second quad, and so on and so forth.
Edit 2: I'm sorry, I'm actually using a dynamic vertex buffer.
Posting some code on how I do my quads with six vertices:
// ## CONSTRUCTION
// Setting up buffer and vertex holder.
particleVertexBuffer = new DynamicVertexBuffer(graphicsDevice,
ParticleQuad.VerticesSizeInBytes * nMaxParticles,
BufferUsage.WriteOnly);
particleVertices = new ParticleVertex[nMaxParticles * 6];
// ## ADD VERTICES
particleVertices[i].Set();
particleVertices[i+1].Set();
particleVertices[i+2].Set();
particleVertices[i+3].Set();
particleVertices[i+4].Set();
particleVertices[i+5].Set();
// ## SET BUFFER
particleVertexBuffer.SetData(particleVertices, 0, nMaxParticles * 6, SetDataOptions.NoOverwrite);
graphicsDevice.Vertices[0].SetSource(particleVertexBuffer, 0, ParticleVertex.SizeInBytes);
// ## DRAW
graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList,
FirstUsedParticle * 6, ((LastUsedParticle - FirstUsedParticle)+1)* 2);
Now, there are a bit more to it because I use a circular queue and a bit other stuff, but this would be enough for understandability.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
是的,这是可能的。您需要使用 TriangleStrip 作为 PrimitiveType。在您的 VertexBuffer 中,您按以下顺序定义顶点:
EDIT to adress Your modified question
我不知道您的代码是什么样子,但一般来说,有关基元计数的信息在以下位置使用:
public VertexBuffer (
//sizeInBytes 取决于基元计数。GraphicsDevice 图形设备,
int 大小(以字节为单位),
BufferUsage 使用情况
)
public void DrawPrimitives (
PrimitiveType 原始类型,
int 起始顶点,
int 原始计数
)
请注意,更多地方需要有关顶点格式的大小的信息,但这应该不是问题,因为大小不应改变。
更新
谢谢澄清,现在我知道你想要实现什么。处理您的问题的正确方法是将顶点缓冲区与索引缓冲区结合使用。顶点缓冲区保存顶点,索引缓冲区保存连接顶点形成三角形的顺序。想象一下,您想在屏幕上绘制以下四边形:
您之前所做的是:
您现在所做的是:
您看,每个四边形保存 2 个顶点,但必须使用 6 个索引来指定构建顺序从顶点开始的三角形。因此,只有当您的顶点很大(带有法线、纹理坐标等许多信息)并且由许多三角形共享时,此方法才有用。
Riemers.net 有一个非常好的、简短的关于顶点和索引缓冲区的易于理解的教程。
Yes that's possible. You'll need to use TriangleStrip as the PrimitiveType. In Your VertexBuffer, You define Your vertices in the following order:
EDIT to adress Your modified question
I don't know, how Your code looks like, but in general the information about the primitve count is used in the following places:
public VertexBuffer (
//sizeInBytes depends on the primitive count.GraphicsDevice graphicsDevice,
int sizeInBytes,
BufferUsage usage
)
public void DrawPrimitives (
PrimitiveType primitiveType,
int startVertex,
int primitiveCount
)
Note, the information about the size of Your vertex format is needed in a couple more places but shouldn't be a problem as the size shouldn't change.
Update
Thx for the clarification, now I know, what You want to achieve. The correct way to handle Your problem is to use a vertex buffer in conjunction with a index buffer. The vertex buffer holds the vertices, the index buffer holds the order in which to connect the vertices to form triangles. Imagine You want to draw the following quad on Your screen:
What You did earlier was this:
What You do now is this:
You see, You save 2 vertices per quad but have instead to use 6 indices which specify the order in which to build triangle from the vertices. So this method is only useful if Your vertices are big (cary many information like normals, texture coordinates etc) and are shared by many triangles.
Riemers.net has a really nice, short and easy to understand tutorial on vertex and index buffers.