4
\$\begingroup\$

I've a class that creates a cube using VertexPositionColor and these vertices are stored in a VertexBuffer. Now i would like to dynamically change the color of my vertices. In my class i have a reference to a VertexPositionColor array wich contain all my vertices. I've wrote a SetColor function wich accept a Color in parameter and update each Color property of my vertices. But when i call it, it doesn't work. This is normal because vertices are stored in VertexBuffer and is not updated.

So, how can i update vertices property and keep using VertexBuffer?

\$\endgroup\$
3
  • \$\begingroup\$ Post some code, please! \$\endgroup\$
    – r2d2rigo
    Oct 7, 2011 at 10:40
  • \$\begingroup\$ You need to call SetData(vertices) on the vertex buffer after you have modified the data. It's best to do this only once a frame, IF the data has been modified. \$\endgroup\$ Oct 9, 2011 at 11:19
  • \$\begingroup\$ Also, investigate DynamicVertexBuffer - you shouldn't be using a regular VertexBuffer for dynamic data. \$\endgroup\$ Oct 9, 2011 at 11:20

4 Answers 4

3
\$\begingroup\$

To change a vertex buffer it can't be active:

   GraphicsDevice.SetVertexBuffer(null);

To transfer vertex data to the gpu memory:

   VertexBuffer.SetData<VertexPositionColor>(VertexData);

To active the vertex buffer again:

   GraphicsDevice.SetVertexBuffer( VertexBuffer );

Note that if your color change affects every vertex with one unique color, you may consider to pass to a shader a single color as a parameter, and do not modify vertex.

\$\endgroup\$
6
  • \$\begingroup\$ Call GraphicsDevice.SetVertexBuffer with null parameter works fine. As you say, i can use a shader for changing color. But i would like to change also the position of my vertices. So i need to update the vertex buffer. A question comes to my mind. Call too many times SetVertexBuffer and VertexBuffer.SetData<> function will drop performance? For exemple if i create 1000 cubes and i update theirs position each frame, SetVertexBuffer and VertexBuffer.SetData<> will be called 1000 times. Do you think there's a better solution? \$\endgroup\$ Oct 9, 2011 at 22:18
  • \$\begingroup\$ Use only one vertexbuffer \$\endgroup\$
    – Blau
    Oct 9, 2011 at 22:43
  • \$\begingroup\$ You mean to share one instance of VertexBuffer between all my Cube class instance and not create one VertexBuffer per instance? \$\endgroup\$ Oct 10, 2011 at 7:31
  • \$\begingroup\$ One big vertex buffer is usually better than multiple small vertexbuffer. \$\endgroup\$
    – Blau
    Oct 10, 2011 at 8:48
  • \$\begingroup\$ I will use one buffer for all my cubes. But i don't know how to do it with my Cube class. Currently one instance haves an array of vertices and an array of indices (so i use only 4 vertices to create a face of the cube), and in my draw method i call GraphicsDevice.indices to set the indices array then GraphicsDevice.SetVertexBuffer and finally DrawIndexedPrimitives. Now if i use only one vertex buffer, i think i need to call SetVertexBuffer one time but how do i set indices and draw my cube? If all my vertices are in the same buffer how the Draw method will know from which vertex to begin? \$\endgroup\$ Oct 10, 2011 at 9:48
1
\$\begingroup\$

The only way to change the contents of a VertexBuffer in XNA is by calling VertexBuffer.SetData().

When you need to update your vertex data often, it is recommended you use a DynamicVertexBuffer which streams vertices to the GPU.

Your best bet is to do some profiling using either:

  • a DynamicVertexBuffer (stored in VRAM) and DrawPrimitives()
  • a simple array (stored in RAM) and DrawUserPrimitives()

And see which one is faster for your specific use case.

\$\endgroup\$
3
  • \$\begingroup\$ So, each time i want to update the Color or Position of my vertices i have to call SetData of the buffer. This will not decrease performance if i have to update these informations many time? \$\endgroup\$ Oct 7, 2011 at 12:05
  • \$\begingroup\$ When i try to call SetData an InvalidOperationException is throw : You can not call SetData on a resource while it is actively involved in GraphicsDevice. Cancel its association with the device before calling SetData. \$\endgroup\$ Oct 7, 2011 at 12:33
  • \$\begingroup\$ See Blau's answer: to change a vertex buffer, you have to do it while it's not bound to the GPU. Call GraphicsDevice.SetVertexBuffer(null); \$\endgroup\$
    – Elisée
    Oct 9, 2011 at 10:38
0
\$\begingroup\$

I would do this using two vertex buffers. The first is static and contains the data that won't change, the second dynamic and containing the data that will change. That way you get to minimize the impact of data transfers. I'm not certain what the XNA equivalent of the relevant D3D terminology is, but GraphicsDevice.SetVertexBuffers looks to be what you need.

\$\endgroup\$
0
\$\begingroup\$

Like above suggestion made...

"Note that if your color change affects every vertex with one unique color, you may consider to pass to a shader a single color as a parameter, and do not modify vertex."

...if you do need to pass more than one color, I would suggest adding a texture parameter and then assigning the color in the effect file using something like...

pixelcolor=tex2D(samplerTexture,psIn.Coordinates);

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .