【问题标题】:XNA - Using Dynamic Vertex Buffer and only four(4) verticesXNA - 使用动态顶点缓冲区和只有四 (4) 个顶点
【发布时间】:2010-07-07 15:03:21
【问题描述】:

只是一个关于绘制四边形的快速问题。我目前正在使用:

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);

现在,还有更多内容,因为我使用了循环队列和其他一些东西,但这足以理解。

【问题讨论】:

  • 我不明白编辑后的部分。为什么是“nQuads * 6”。你说的6倍是什么意思?还有什么不好的?
  • 如果我想绘制 10 个四边形,这意味着 60 个顶点,因为我每个四边形有 6 个顶点。从技术上讲,我的 60 个顶点是 20 个三角形。因此,我可以想象我的四边形由六个顶点组成,而实际上它是由三个顶点组成的两个三角形。如果我突然只使用四个顶点而不是六个,一个四边形将由 4/3 个三角形组成,因此彼此重叠。
  • 你的四边形是相互连接的还是你想画一个四边形?
  • 它们在视觉上没有连接,但它们是同一个缓冲区的一部分,是的。据我了解,GPU 正在使用该缓冲区并使用顶点 1-3、4-6、7-9 等来绘制三角形。如果可以解决问题,我编辑了一些代码:\

标签: c# xna vertex-buffer vertices


【解决方案1】:

是的,这是可能的。您需要使用 TriangleStrip 作为 PrimitiveType。在您的 VertexBuffer 中,您按以下顺序定义您的顶点:

1---3
|\  |
| \ |
|  \|
0---2
编辑以解决您修改后的问题

我不知道您的代码是什么样的,但一般来说,有关原始计数的信息用于以下位置:

  • 缓冲区创建:public VertexBuffer ( GraphicsDevice graphicsDevice, int sizeInBytes, BufferUsage usage ) //sizeInBytes 取决于原始计数。
  • 绘图调用:public void DrawPrimitives ( PrimitiveType primitiveType, int startVertex, int primitiveCount )

请注意,您的顶点格式的 size 信息在更多地方需要,但应该不是问题,因为尺寸不应该改变。

更新

感谢您的澄清,现在我知道您想要实现什么。处理您的问题的正确方法是将顶点缓冲区与索引缓冲区结合使用。顶点缓冲区保存顶点,索引缓冲区保存连接顶点以形成三角形的顺序。想象一下,您想在屏幕上绘制以下四边形:

 (0,1)________(1,1)
     |        |
     |        |
     |________|
 (0,0)        (1,0)

你之前做的是这样的:

Vector3 v0, v1, v2, v3;
v0 = new Vector3(0, 0, 0);
v1 = new Vector3(1, 0, 0);
v2 = new Vector3(0, 1, 0);
v3 = new Vector3(1, 1, 0);

List vertices = new List();
//first triangle
vertices.add(v0);
vertices.add(v2);
vertices.add(v1);

//second triangle
vertices.add(v2);
vertices.add(v1);
vertices.add(v3);

VertexBuffer vb = new VertexBuffer(...);
vb.setData(verticesToDraw);

//draw the scene using PrimitiveType.TriangleList and primitive count 2

你现在要做的是:

//vertices stay the same as in the example above!
List vertices = new List();
vertices.add(v0);
vertices.add(v1);
vertices.add(v2);
vertices.add(v3);

int[] indices = new int[6];
//first triangle
indices[0] = 0;
indices[1] = 2; 
indices[2] = 1;

//second triangle
indices[3] = 2;
indices[4] = 1;
indices[5] = 3;

VertexBuffer vb = new VertexBuffer(...);
IndexBuffer ib = new IndexBuffer(...);

vb.setData(vertices);
ib.setData(indices);

/*draw using the DrawIndexedPrimitives() method rather than the
DrawPrimitives() method and use PrimitiveType.TriangleList and
primitive count 2.*/

您会看到,每个四边形保存 2 个顶点,但必须使用 6 个索引来指定从顶点构建三角形的顺序。因此,此方法仅在您的顶点很大(包含许多信息,如法线、纹理坐标等)并且由许多三角形共享时才有用。

Riemers.net 有一个关于顶点和索引缓冲区的非常好的、简短且易于理解的教程。

【讨论】:

  • 这是否意味着,只需更改我当前的: - 原始类型。 - 顶点从 6 到 4(使用您的订单) - 根据 nVertices 更改计算。因为如果是这样,我到处都是线路。好像我的 GPU 不知道我想要 4 个顶点是两个三角形:/
  • 您之前使用过哪种 PrimitiveType?我猜三角形列表?然后您需要更改 PrimitiveType 和 Vertex 定义(/创建)。我知道 XNA 想知道原始计数的唯一地方是缓冲区创建和绘图调用 - 你说的全部是什么意思?
  • 非常感谢您对我的包容!正是我正在寻找的答案!我自己的自定义顶点非常大,所以这完全是我优化所需要的。再次感谢你! :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多