Game Development Community

Line Shader? (or how the heck do I draw thick line primitives in T3D?)

by Demolishun · in Torque 3D Professional · 01/17/2013 (6:26 am) · 5 replies

This is really frustrating. All I want to do is draw lines. Now I search and find I cannot draw "thick" lines because modern graphics cards do not support line drawing. They fake it with quads internally. Okay, so why can't I tell the card to draw thicker quads? Apparently there is a way, but I cannot find a way to adjust the line primitive thickness in T3D. So it either is not there or I have not found it.

Anyway, what the heck does this have to do with shaders? Apparently you can theoretically create a shader that will draw quads for you. I am not currently sure how to do this, but hey, someday, maybe. I did figure out how to load and apply a shader to a primitive, but I am not necessarily looking forward to learning to write a shader to just draw thicker lines.

So my question is: Is there already a shader that comes with T3D that modifies line primitives so we can draw thicker lines? Is there someone in the groove on shaders that could spin one up? I will be more than happy to write a resource on how to use such shader, if that makes a difference.

Sincerely,
Brain Fried

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


#1
01/17/2013 (9:50 am)
How the heck did I miss this documentation?!:
www.garagegames.com/products/torque-3d/guides

There are 3 guides explicitly for writing shaders!

Can we get a link somewhere on the top bar (if it is not already there) linking to these guides?
#2
01/17/2013 (1:14 pm)
Frank,

Was just going to point you there....but you beat me to it.

Ron
#3
01/18/2013 (1:57 am)
Create a vertex buffer with two vertices, the gpu rasterizer should prepare a line for you.
Draw thicker lines with thicker meshes.
The graphics cards draw what you tell them to draw.
#4
01/18/2013 (11:26 am)
@Ivan,
I am really confused. Here is what I am doing now:
GFX->getDrawUtil()->drawLine(0,0,1.0,1.0,ColorI(255,255,255));
This is defined as:
void GFXDrawUtil::drawLine( F32 x1, F32 y1, F32 x2, F32 y2, const ColorI &color )
{
   drawLine( x1, y1, 0.0f, x2, y2, 0.0f, color );
}

void GFXDrawUtil::drawLine( F32 x1, F32 y1, F32 z1, F32 x2, F32 y2, F32 z2, const ColorI &color )
{
   GFXVertexBufferHandle<GFXVertexPC> verts( mDevice, 2, GFXBufferTypeVolatile );
   verts.lock();

   verts[0].point.set( x1, y1, z1 );
   verts[1].point.set( x2, y2, z2 );

   verts[0].color = color;
   verts[1].color = color;

   verts.unlock();

   mDevice->setVertexBuffer( verts );
   mDevice->setStateBlock( mRectFillSB );
   mDevice->drawPrimitive( GFXLineList, 0, 1 );
}

I created my own version so I can texture:
void AudioTextureObject::drawLine( F32 x1, F32 y1, F32 x2, F32 y2, const ColorI &color )
{
   drawLine( x1, y1, 0.0f, x2, y2, 0.0f, color );
}
void AudioTextureObject::drawLine( F32 x1, F32 y1, F32 z1, F32 x2, F32 y2, F32 z2, const ColorI &color )
{
   GFXVertexBufferHandle<GFXVertexPC> verts( GFX, 2, GFXBufferTypeVolatile );
   verts.lock();

   verts[0].point.set( x1, y1, z1 );
   verts[1].point.set( x2, y2, z2 );

   verts[0].color = color;
   verts[1].color = color;

   verts.unlock();

   GFX->setVertexBuffer( verts );
   GFX->drawPrimitive( GFXLineList, 0, 1 );
}

So what do you mean by "the gpu rasterizer should prepare a line for you"? The way I see it I either need to use the GFXLineList and modify with a shader, or figure out the geometry before hand and then send that mesh. The reason the shader option is on the table is because it potentially can be faster because there is less data sent to the GFX card. Otherwise I am going to figure out how to create a triangle strip and texture it. Did you have something else in mind? Is there another trick I am not aware of? (Probably yes because it has been years since I have tried GFX programming on GPUs). I was just frustrated there is not an easier way to manipulate line widths, that was my main gripe.
#5
01/18/2013 (1:41 pm)
Well, here is my first stab at this using just tris:
void AudioTextureObject::drawTriLine( F32 x1, F32 y1, F32 x2, F32 y2, const ColorI &color, F32 thickness )
{
   GFXVertexBufferHandle<GFXVertexPC> verts( GFX, 12, GFXBufferTypeVolatile );

   verts.lock();

   F32 offset = thickness/2.0f;

   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);
   
   verts[0].point.set( x1 - ovect.x, y1 - ovect.y, 0.0f );
   verts[1].point.set( x1 - ovect.x, y1 + ovect.y, 0.0f );
   verts[2].point.set( x1 + ovect.x, y1 - ovect.y, 0.0f );   

   verts[3].point.set( x2 + ovect.x, y2 + ovect.y, 0.0f );
   verts[4].point.set( x2 + ovect.x, y2 - ovect.y, 0.0f );
   verts[5].point.set( x2 - ovect.x, y2 + ovect.y, 0.0f );   

   verts[6].point.set( x1 - ovect.x, y1 + ovect.y, 0.0f );
   verts[7].point.set( x2 - ovect.x, y2 + ovect.y, 0.0f );
   verts[8].point.set( x2 + ovect.x, y2 - ovect.y, 0.0f );

   verts[9].point.set( x2 + ovect.x, y2 - ovect.y, 0.0f );
   verts[10].point.set( x1 + ovect.x, y1 - ovect.y, 0.0f );
   verts[11].point.set( x1 - ovect.x, y1 + ovect.y, 0.0f );

   verts[0].color = color;
   verts[1].color = color;
   verts[2].color = color;
   verts[3].color = color;
   verts[4].color = color;
   verts[5].color = color;
   verts[6].color = color;
   verts[7].color = color;
   verts[8].color = color;
   verts[9].color = color;
   verts[10].color = color;
   verts[11].color = color;

   verts.unlock();

   GFX->setVertexBuffer( verts );
   GFX->drawPrimitive( GFXTriangleList, 0, 4 );   
}
Now I will have to figure out how to reduce the number of points by using GFXTriangleStrip. I still need to texture this though. Right now it does well for just drawing lines of a color. I need to figure out how to antialias to make it look better.