Reduce verts or drawcalls?
by Demolishun · in Torque 3D Professional · 02/11/2013 (11:36 am) · 6 replies
From what I understand it is more important to reduce drawcalls rather than verts. So that is how I designed this continuous line drawing function. Each line would normally take 8 tris (2x2 tri end caps, 2 tri for line middle). However, because this is a triangle strip I need to combine the lines using sacrificial vertexes. So I just made it so it uses 2 per line (even though 2 on the end would be wasted).
I want to get other graphics programmers perspective on this. Is this the better way to go?
The code produces a textured line that I can adjust thickness on. The UV map is calculated elsewhere.
I want to get other graphics programmers perspective on this. Is this the better way to go?
void AudioTextureObject::drawTriLineTexN( Vector<Point2F> &points, const ColorI &color, F32 thickness, U32 uvIndex )
{
U32 lines = points.size() - 1;
if(!lines)
return;
U32 numLineVerts = 10; // each line needs 8, but we need 2 per to have linking degenerate tris
U32 numVerts = lines * numLineVerts; // calculate the number of verts
GFXVertexBufferHandle<GFXVertexPCT> verts( GFX, numVerts, GFXBufferTypeVolatile );
F32 offset = thickness/2.0f;
verts.lock();
for(U32 i=0; i < lines; i++){
F32 x1,x2,y1,y2;
x1 = points[i].x;
x2 = points[i+1].x;
y1 = points[i].y;
y2 = points[i+1].y;
F32 xdiff = x2-x1;
F32 ydiff = y2-y1;
Point3F vect(xdiff,ydiff,0.0f);
vect = mNormalize(vect);
Point2F ovect(offset*vect.x,offset*vect.y);
U32 voff = i*numLineVerts;
verts[0+voff].point.set( x1 - ovect.x*2 + ovect.y, y1 - ovect.y*2 - ovect.x, 0.0f ); // bottom
verts[1+voff].point.set( x1 - ovect.x*2 - ovect.y, y1 - ovect.y*2 + ovect.x, 0.0f ); // top
verts[2+voff].point.set( x1 + ovect.y, y1 - ovect.x, 0.0f ); // bottom r
verts[3+voff].point.set( x1 - ovect.y, y1 + ovect.x, 0.0f ); // top r
verts[4+voff].point.set( x2 + ovect.y, y2 - ovect.x, 0.0f ); // bottom r
verts[5+voff].point.set( x2 - ovect.y, y2 + ovect.x, 0.0f ); // top r
verts[6+voff].point.set( x2 + ovect.x*2 + ovect.y, y2 + ovect.y*2 - ovect.x, 0.0f ); // bottom
verts[7+voff].point.set( x2 + ovect.x*2 - ovect.y, y2 + ovect.y*2 + ovect.x, 0.0f ); // top
verts[8+voff].point.set( verts[7+voff].point ); // eat this vert, degenerate triangle
verts[9+voff].point.set( verts[7+voff].point ); // eat this vert, degenerate triangle
// grab uv coords
U32 uvoffset = uvIndex*8;
for(U32 i = 0; i < 8; i++){
verts[i+voff].texCoord.set(mUVCoords[i+uvoffset].x,mUVCoords[i+uvoffset].y);
}
verts[8+voff].texCoord.set(verts[7+voff].texCoord.x,verts[7+voff].texCoord.y); // make sure textures coords are valid
verts[9+voff].texCoord.set(verts[7+voff].texCoord.x,verts[7+voff].texCoord.y); // make sure textures coords are valid
for(U32 i = 0; i < numLineVerts; i++){
verts[i+voff].color = color;
}
if(i >= 1){
// fixup this vert
verts[-1+voff].point.set(verts[0+voff].point); // eat this vert, degenerate triangle
verts[-1+voff].texCoord.set(verts[0+voff].texCoord.x,verts[0+voff].texCoord.y); // make sure textures coords are valid
}
}
verts.unlock();
GFX->setVertexBuffer( verts );
GFX->drawPrimitive( GFXTriangleStrip, 0, numVerts-4 );
}The code produces a textured line that I can adjust thickness on. The UV map is calculated elsewhere.
About the author
I love programming, I love programming things that go click, whirr, boom. For organized T3D Links visit: http://demolishun.com/?page_id=67
#2
02/13/2013 (2:13 pm)
From what I have read, you should also use an indexed triangle list instead of a triangle strip. triangle strip is older technology and indexed triangle list is faster on modern hardware. I do not know if this is true, just something i read.
#3
Also, after reading about triangles lists they take a lot more vertices. Since my vertices are dynamic they are sent each time. So more vertices would eat up more CPU to GPU bandwidth. For fixed vertex buffers it might be faster to use indexing as only the index is sent rather than the vertex.
Here is something else I found:
msdn.microsoft.com/en-us/library/windows/desktop/bb147263%28v=vs.85%29.aspx
Edit:
What I really want to use is a geometry shader. Then I can send linestrips and have the shader create the triangles on the card. However, DX9 does not support those new shaders.
02/13/2013 (3:00 pm)
I looked at that, but was not sure how to use that. I was not able to find a simple example in the engine. Most of what I found was triangle strips being used.Also, after reading about triangles lists they take a lot more vertices. Since my vertices are dynamic they are sent each time. So more vertices would eat up more CPU to GPU bandwidth. For fixed vertex buffers it might be faster to use indexing as only the index is sent rather than the vertex.
Here is something else I found:
msdn.microsoft.com/en-us/library/windows/desktop/bb147263%28v=vs.85%29.aspx
Edit:
What I really want to use is a geometry shader. Then I can send linestrips and have the shader create the triangles on the card. However, DX9 does not support those new shaders.
#4
There is a simple solution to geometry shaders. Upgrade T3D to DX11 :)
02/14/2013 (6:55 am)
Yeah I could see that being an issue for your code.There is a simple solution to geometry shaders. Upgrade T3D to DX11 :)
#5
02/14/2013 (11:14 am)
"Simple" he says....
Torque Owner Demolishun
DemolishunConsulting Rocks!