0
\$\begingroup\$

Good afternoon,

I have been toying with the VertexBuffer in XNA just to see what it is capable of. I have done some very minor 3D work in the past, so the concepts are not completely foreign to me; however, my knowledge and experience leave a lot to be desired.

I have run a few tests in release mode with a static vertex buffer, using VertexPositionNormalTexture, and performance has been bugging me. My initial tests involved a rotating view of 40,000 (give or take) randomly generated cubes, with vertices for edges obscured by adjacent opaque cubes not added to the buffer. The view worked fine, but performance was notably choppy, expecially when the corner of the randomized area rotated into view.

My first idea to optimize was to combine adjacent, parallel faces into single, continuous faces, and adjust the Vector2 texture coordinates to appropriately draw the repeating texture; however, when I tested a single rotating cube (36 total vertices) with each side showing 100x100 tiled repetitions of the texture, I experienced pretty much the exact same stuttering problem.

So I have to ask, what might I be doing wrong? Should I render my own pre-tiled RenderTarget2D textures to use with the static vertex buffer, so the GPU does not have to "tile" it so many times? Or does the GPU do that already on its own?

My vertex buffer is generated only once and sent to the GPU only once. My texture is loaded only once, and the same texture/effect is used for the entire vertex buffer.

I do not understand why a GTX 275 would have such a hard time drawing 12 textured triangles.

What am I missing?

From my custom Chunk class:

let construct() =
    _vertices <- _blocks.Values |> Seq.collect Block.vertices |> Seq.toArray

    let vertexCount = _vertices.Length
    if vertexCount > 0 then
        _buffer <- new VertexBuffer(device, VertexPositionNormalTexture.VertexDeclaration, vertexCount, BufferUsage.None)
        _buffer.SetData(_vertices)
        device.SetVertexBuffer(_buffer)


    _requiresConstruction <- false

member public m.DrawToDevice(device : GraphicsDevice) =
    if _requiresConstruction then construct()

    let vertexCount = _vertices.Length

    if vertexCount > 0 then
        let triangleCount = vertexCount / 3
        device.DrawPrimitives(PrimitiveType.TriangleList, 0, triangleCount)

From the Game-derived class:

override game.Draw gameTime = 
    let skyColor = Color.CornflowerBlue

    game.GraphicsDevice.Clear(skyColor)
    let fogColor = skyColor.ToVector3()

    let effect = new BasicEffect(device)
    let cameraPosition = Vector3(0.0f, 0.0f, 125.0f)

    effect.World <- Matrix.CreateTranslation(chunk.ChunkPosition);
    effect.View <-
        Matrix.CreateRotationY(MathHelper.ToRadians(rotation)) *
        Matrix.CreateRotationX(MathHelper.ToRadians(rotation)) *
        Matrix.CreateLookAt(cameraPosition, chunk.ChunkPosition, Vector3.Up);

    let viewDistance = 250.0f
    effect.Projection <- Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, device.Viewport.AspectRatio, 1.0f, viewDistance);
    effect.FogEnabled <- true
    effect.FogColor <- fogColor
    effect.FogStart <- viewDistance / 3.0f
    effect.FogEnd <- viewDistance

    effect.TextureEnabled <- true
    effect.Texture <- sprite
    effect.EnableDefaultLighting()

    for pass in effect.CurrentTechnique.Passes do
        pass.Apply()
        chunk.DrawToDevice(device)

    base.Draw(gameTime)

sprite is a 20x20 Texture2D loaded from content

UPDATE: I tried the massive, single cube again, two ways:

  • With a single, non-tiled, pre-stretched texture
  • With a single, non-tiled, texture, stretched using Vector2 texture positions.

Both of them exhibit the exact same stuttering behavior I had before. Something must be wrong here. 36 vertices. Non-tiled 20x20 texture. Static vertex buffer. How on earth could this be stuttering on a machine that runs modern 3D games without issue?

Does XNA simply not play well with F#?

UPDATE: RESOLVED

The problem seems to have been recreating effect each frame.

I moved all effect code except for the following into m.LoadContent:

// Set the World matrix which defines the position of the cube
effect.World <- Matrix.CreateTranslation(chunk.ChunkPosition);

// Set the View matrix which defines the camera and what it's looking at
effect.View <-
    Matrix.CreateRotationY(MathHelper.ToRadians(rotation)) *
    Matrix.CreateRotationX(MathHelper.ToRadians(rotation)) *
    Matrix.CreateLookAt(cameraPosition, chunk.ChunkPosition, Vector3.Up);

effect.FogColor <- fogColor

CPU use dropped from 13% while corners rotating into/out of view, to 0-4%. No more stuttering.

Thanks anyway, though I would still certainly appreciate any tips.

\$\endgroup\$

migrated from programmers.stackexchange.com Sep 8 '13 at 23:17

This question came from our site for professionals, academics, and students working within the systems development life cycle.

  • 2
    \$\begingroup\$ Creating any object that uses underlying GPU resources every frame will definitely kill your performance. \$\endgroup\$ – dadoo Games Sep 8 '13 at 23:53
  • \$\begingroup\$ You should post your solution as an answer, instead of an update to your question. \$\endgroup\$ – MichaelHouse Sep 9 '13 at 5:28
  • \$\begingroup\$ Hi Byte56. I completely agree with you, but the site owners do not. If stack exchange would have allowed me to answer, and thus resolve, my own question, I would have. They enforce a waiting period, which I believe is now over... so here I am to take care of it. \$\endgroup\$ – dpaz Sep 18 '13 at 21:30
1
\$\begingroup\$

The problem seems to have been recreating effect each frame.

I moved all effect code except for the following into m.LoadContent:

// Set the World matrix which defines the position of the cube effect.World <- Matrix.CreateTranslation(chunk.ChunkPosition);

// Set the View matrix which defines the camera and what it's looking at effect.View <- Matrix.CreateRotationY(MathHelper.ToRadians(rotation)) * Matrix.CreateRotationX(MathHelper.ToRadians(rotation)) * Matrix.CreateLookAt(cameraPosition, chunk.ChunkPosition, Vector3.Up);

effect.FogColor <- fogColor CPU use dropped from 13% while corners rotating into/out of view, to 0-4%. No more stuttering.

(answered after mandatory waiting period)

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.