PerPixel

Does anyone can point me to right place for information on rendering my game when multiple textures are involve. I'm currently rewriting Quake 1 in XNA and I got he levels to load fine but its deadly slow. I do not use the vis yet so I render everything but its still should be pretty fast.

If i render the level using only a single texture2d its pretty damn fast but for using multiple texture what I did is take all the triangles using the same textures and collecting them on startup. When im done loading and start to draw I loop in each of those triangles list, set the texture in my effect, fill the vertexbuffer and draw the primitives.

thx

for (i = 0; i < r_bsp.polygoneCollections.Length; i++)
{
if (r_bsp.polygoneCollectionsIdea.numtris < 1)
continue;

texture = Bitmap.texturesIdea;
Quake.effect.Parameters["UserTexture"].SetValue(texture);

Quake.effect.Begin();
foreach (EffectPass pass in Quake.effect.CurrentTechnique.Passes)
{
pass.Begin();

int numvertexes = r_bsp.polygoneCollectionsIdea.Vertexes.Length;

vertexBuffer = new VertexBuffer(
Quake.graphics.GraphicsDevice,
VertexPositionTexture.SizeInBytes * numvertexes,
ResourceUsage.None,
ResourceManagementMode.Automatic);

vertexBuffer.SetData<VertexPositionTexture>(r_bsp.polygoneCollectionsIdea.Vertexes);
graphics.GraphicsDevice.Vertices[0].SetSource(vertexBuffer, 0, VertexPositionTexture.SizeInBytes);

graphics.GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, r_bsp.polygoneCollectionsIdea.numtris);

vertexBuffer.Dispose(); // If i dont do this the memory fill like mad and drop, repeat.....

pass.End();
}
Quake.effect.End();
}


Re: XNA Game Studio Express Best Draw method for game level (Quake 1 in XNA)

Joel Martinez

are you attempting to draw the whole level (even if you can't see a given piece)





Re: XNA Game Studio Express Best Draw method for game level (Quake 1 in XNA)

Hlubocky

He states that he is drawing the entire level in his post.




Re: XNA Game Studio Express Best Draw method for game level (Quake 1 in XNA)

Joel Martinez

ahh yes, well, I didn't see that :-)

"... but its still should be pretty fast."

Seems like a pretty bold statement to make without profiling ... how many FPS are you getting try rendering a subset of the level and see if the performance improves and by how much.





Re: XNA Game Studio Express Best Draw method for game level (Quake 1 in XNA)

PerPixel

With a map that as alot of different textures (27) but still low poly count (start.bsp first level, the portal map) it get very slow at 2 fps on a an NVIDIA 7950 GTX. But with a map like those for deathmatch with around 10 different textures I get 20 fps. I improved the draw code like this,

cl_camera.UpdateCameraFirstPerson();
graphics.GraphicsDevice.Clear(Color.Gray);

graphics.GraphicsDevice.VertexDeclaration = vertexDeclaration;
graphics.GraphicsDevice.RenderState.CullMode = CullMode.CullCounterClockwiseFace;

graphics.GraphicsDevice.Vertices[0].SetSource(vertexBuffer, 0, VertexPositionTexture.SizeInBytes);

int i;


for (i = 0; i < r_bsp.polygoneCollections.Length; i++)
{
if (r_bsp.polygoneCollectionsIdea.numtris < 1)
continue;

texture = Bitmap.texturesIdea;
Quake.effect.Parameters["UserTexture"].SetValue(texture);

Quake.effect.Begin();

foreach (EffectPass pass in Quake.effect.CurrentTechnique.Passes)
{
pass.Begin();

vertexBuffer.SetData<VertexPositionTexture>(r_bsp.polygoneCollectionsIdea.Vertexes);
graphics.GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, r_bsp.polygoneCollectionsIdea.numtris);

pass.End();
}
Quake.effect.End();
}

Console.WriteLine(DateTime.Now.ToLongTimeString());

I also did try not changing the texture and use the same one on all the tri with no improuvement. Im sure there is a smart way to do this and I wish it was some how possible and efficient to draw 1 triangle at a time by setting the vertex buffer first outside the loop and then in the draw I just set the texture and draw the each triangle in a loop. I think i'll try that now.





Re: XNA Game Studio Express Best Draw method for game level (Quake 1 in XNA)

KIWIDOGGIE

may i have a release beta of your game. I can see if it will run on my POWERHOUSE pc




Re: XNA Game Studio Express Best Draw method for game level (Quake 1 in XNA)

gmcbay

This code is much better than the one that was constantly creating a new vertex buffer! It is difficult to tell from just this inner loop, but would it be possible for you to reduce the shader state changes by putting the Quake.effect.Begin() / End() *outside* of the "for (i = 0; i < r_bsp.polygoneCollections.Length; i++)" loop.

eg:

Quake.effect.Begin();

foreach (EffectPass pass in Quake.effect.CurrentTechnique.Passes
 { 
      pass.Begin();

      for (i = 0; i < r_bsp.polygoneCollections.Length; i++)      
      {        
        if (r_bsp.polygoneCollections [ i ].numtris < 1)          
          continue;        
    
        texture = Bitmap.textures [ i ];        
    
        Quake.effect.Parameters["UserTexture"].SetValue(texture);        
        Quake.effect.CommitChanges();                  
    
        vertexBuffer.SetData(r_bsp.polygoneCollections.Vertexes);          
        graphics.GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, r_bsp.polygoneCollections.numtris);}          
      }
  
  
      pass.End();        
 }        
    
 Quake.effect.End();      
 
I'd also recommend sorting the collections by texture so you can minimize the amount of times you have to set the UserTexture parameter (unless all collections are already sorted that way, I don't recall how Quake 1 level storage works anymore), but that is probably a smaller win than reducing the amount of times you begin/end on the shader.




Re: XNA Game Studio Express Best Draw method for game level (Quake 1 in XNA)

PerPixel

I'll try that and quake didn't short by texture but
i did =)

The FPS is getting better!




Re: XNA Game Studio Express Best Draw method for game level (Quake 1 in XNA)

PerPixel

Ok, I managed to clean it up and make it run freely.

What I did,

1 - Load the BSP file
2 - Get all the surface and put them in my class called polygon with texture name, vertexes, number of triangles.
3 - Go trough all the poly and sort them by textures, add offset position of each type
4 - Create a vertex buffer with all the polygones vertexes ordered by texture
5 - In the draw code set the first textures, draw from offset, number of triangle

This run fast but I end up with way too much duplicated vertex.... Not a problem for this game but could get some improvement. Next step is to fix the textures UV and load the lightmaps.

http://perpixel.dyndns.org/~guillaume/quakexna_01.jpg






Re: XNA Game Studio Express Best Draw method for game level (Quake 1 in XNA)

Jon Watte

Polycount doesn't matter these days, until you get into millions of vertices.

State changes matter. You want to minimize those. What I would do would be the following:

1) Load all vertices into one big vertex buffer.
2) Load all triangles (indices) into one big index buffer.
3) Sort triangles by texture, so that you have one index buffer subset contiguous of a single texture. Sort the vertices in that same order, too. (Yes, this requires re-numbering in the index buffer, and is a step that can go horribly wrong if you don't do it right :-)
4) Draw as follows:

Device.VertexDeclaration = myVertexDeclaration;
Device.Vertices[0].SetStreamSource(myVertexBuffer, 0, myVertexSize);
Device.Indices = myIndexBuffer;
myEffect.Begin();
EffectParameter tex = myEffect.Parameter["Texture"];
EffectParameter lm = myEffect.Parameter["Lightmap"];
foreach (EffectPass e in myEffect.CurrentTechnique.Passes) {
e.Begin();
foreach (MySubset ms in myMeshSubsets) {
tex.SetValue(textureArray[ms.index]);
lm.SetValue(lightmapArray[ms.index]);
e.ApplyChanges();
Device.DrawIndexedPrimitives(ms.offset, count, etc ...);
}
e.End();
}
myEffect.End();


This should get good performance on most hardware. The biggest problem should be overdraw, because you might end up filling the screen several times over (even with Z buffer testing), which would be slow on systems such as laptops and low-end desktops, but should be fast on high-end cards like GeForce 7800, 7900, etc.