   Best practices for rendering terrain for an rts game
  I need to render a grid of 128*128 squares, with textures, but my fps is below 20fps!!!Let me explain what i'm doing...I'm rendering 128*128 quads. i call drawIndexedPrimitives() for each quad (i first check if it's in the viewing frustrum, to avoid unnecessary draw calls). Each square is surrounded by 8 squares, and those squares can have different textures. To blend the textures, i apply 10 textures per squad (i multitexture them: 1.base texture, 2.detail texture, 3-10 blending in with other quads). so before every squad is drawn, i set the effect parameters (i have about 6 effect.setparameters per squad). all the effect.setparameters instructions takes off about 30-40 fps from my performance.this is not a good performance, but i can't find any other way to do it. i can't use prerendered blended squads because there's a HUGE number of combinations that a squad can take, and that would use up alot of memory.so how should i render the terrain? there must be a better way, because other games can render 512*512 squads, with alot of textures, at an high fps.any help pls?   
  You really need to render multiple quads in a single draw call. You should not be making more than 300-500 DrawIndexedPrimitive() calls per frame, and preferably as few as possible.Normally this is done by creating a texture sheet or atlas, so you can pack multiple textures onto one sheet. That will allow you to reduce your entire terrain to a single draw call (in the best case).Also, 10 textures per quad is extremely excessive, especially given that a lot of hardware can't use more than 8 textures at once, and some older hardware (Ge Force 4 era) can't render more than 4...   ;  Ahm... i call drawindexedp() about 100 times / frame (the quads that are not in the viewing frustrum are not even processed).All the textures are in one file... I just change the texture coordinates before i lerp them....this is how it looks in the shader:originaltexture = lerp(originaltexture, texcoord1, alpha1)texcoord1 = ........ (i change the value)originaltexture = lerp(originaltexture, texcoord1, alpha2)texcoord1 = ........ (i change the value)..........texcoord1 = ........originaltexture = lerp(originaltexture coord, texcoord1, alpha10)i can't find any other better way to do it :(. any suggestions?   ;  I would recommend doing the following:Setup:1. Put all 128x128 quads into a single vertex buffer that has a vertex declaration containing (x, y, z) position and texture coordinates for a base texture and blendmap (google texture splatting to see how to do this without using 10 textures per vertex). Create an index buffer for this vertex buffer. Never lock this vertex/index buffer again.2. Create a second vertex stream that has 1 texture coord and a normal. The texture coord is the heightmap data for 128x128 quads.Render:1. Lock the second vertex stream and memcpy heightmap/normal data as the player moves around the world. Bind the second stream and then call DrawIndexedPrimitive *ONCE* only to render the entire 128x128 terrain mesh. Don't concern yourself with frustum culling at the grid square level as its not worth it (though culling entire 128x128 patches is worthwhile).2. In the vertex shader, generate the tex coords for the detail map and the texture blends (only use 4, 10 is excessively wasteful IMHO) using the RGBA of the blend texture (again google texture splatting for how to do this).Here's a small example from my application (which doesn't use texture splatting BTW)://// Multi-stream vertex declaration for dynamic terrain exploration//IDirect3DVertexDeclaration9* VertexTerrain::Decl = 0;D3DVERTEXELEMENT9 VertexTerrainElements[] = {{0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},{0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},{1, 0,  D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},{1, 4,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,   0},D3DDECL_END()};HR(gd3dDevice->CreateVertexDeclaration(VertexTerrainElements, &VertexTerrain::Decl));struct OutputVS{    float4 posH    : POSITION0;    float2 nonTiledTexC : TEXCOORD0;    float  shade   : TEXCOORD1;float  fogLerpParam : TEXCOORD2;};//// Low quality (per-vertex) versions//OutputVS TerrainVS( float3 posW    : POSITION0,    // Stream 1float2 tex0    : TEXCOORD0,    // Stream 1float1 height  : TEXCOORD1,    // Stream 2float3 normalW : NORMAL0  // Stream 2    ){    // Zero out our output.    OutputVS outVS = (OutputVS)0;    //    // Just compute a grayscale diffuse and ambient lighting    // term: terrain has no specular reflectance.  The color    // comes from the texture.    //    outVS.shade = saturate(max(0.0f, dot(normalW, -gLight.dirW)) + 0.3f);   // Adjust the vertex position    float4 posT = mul(float4(posW, 1.0f), gWorld);    posT.y += height;   // Transform to homogeneous clip space.    outVS.posH = mul(posT, gViewProj);    // Pass on texture coordinates to be interpolated in rasterization.    outVS.nonTiledTexC = tex0;    // Compute vertex distance from camera in world space for fog calculation.    float dist = distance(float3(posT.xyz), gEyePosW);    outVS.fogLerpParam = saturate((dist - gFogStart) / gFogRange);    // Done--return the output.    return outVS;}float4 TerrainPS( float2 nonTiledTexC : TEXCOORD0,   float  shade   : TEXCOORD1,   float  fogLerpParam : TEXCOORD2) : COLOR{    float3 c0 = tex2D(TexS, nonTiledTexC).rgb;   // Combine the color from lighting with the texture color.    return (lerp(float4( shade * c0, 1.0f ), gFogColor, fogLerpParam));};  First of all, when discussing performance it's a good idea to either compare it to something (like when you tested it with fewer textures) or give some information about the hardware and drawing process. If you're using integrated graphics at a resolution of 1920x1200 we could tell you that you're getting good performance.Also, giving such info will mean that you're aware of what might affect performance. This means you can test it. You can reduce resolution, and see what effect it has. You can remove multitexturing, and see what effect it has. You can reduce texture size, and see if this helps. Also, if we know you have an NVIDIA card, we could tell you that NVPerfHUD could help. The basic idea is to realise where your bottleneck is.People have given you pretty good advice here, especially that you're doing quite extensive multitexturing. I imagine that most of the quads don't overlap, and therefore only need 2 textures. You might want to consider rendering these parts separately. It will also reduce the amount of blending for the others. This would add more draw calls, but reduce multitexturing on most of the map, so if that's the bottleneck, it could help.Depending on the number of textures, you could also pre-blend their relevant parts (which are probably small) into a texture, and use just that additional texture.   