Jump to content
  • Advertisement
Sign in to follow this  
MedRamBO

Primitive thickness

This topic is 3031 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello,

i recently stepped into primitive rendering in directX10. The lines are being rendered fine on the positions i want. My actual problem is that they doesnt appear as thick as in directX9. They seem to be more thick than a pixel. I've read some around and found some info that its possible to fix that with some kind of geometry shader. Does anybody know how that would work and how it would look code wise? I am not into it that deep.

Attached is the drawLine method (initialization isnt needed i belive, if so i'll post it immediliantly)

void drawLine(int x1, int y1, int x2, int y2, D3DCOLOR lineColor) {
VERTEX Vertices[] = {
/*p1*/{getScreenPercentage(x1, y1), lineColor}, //getScreenPercentage puts the given screencoords into the rasterized state
/*p2*/{getScreenPercentage(x2, y2), lineColor}
};

pDevice->IASetInputLayout(pVertexLayout);
UINT stride = sizeof(VERTEX);
UINT offset = 0;
pDevice->IASetVertexBuffers(0, 1, &p2pBuffer, &stride, &offset);

VERTEX* pVoid;
p2pBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&pVoid);
pVoid[0] = Vertices[0];
pVoid[1] = Vertices[1];
p2pBuffer->Unmap();

pDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_LINELIST);
pPass->Apply(0);
pDevice->Draw(2, 0);
}




And my effect

char szEffect[] =
"struct DATA"
"{"
" float4 Pos : SV_POSITION;"
" float4 Color : COLOR;"
"};"

"DATA VS(float4 Pos : POSITION, float4 Col : COLOR)"
"{"
" DATA Data;"
" Data.Pos = Pos;"
" Data.Color = Col;"
" return Data;"
"}"

"float4 PS(DATA Data) : SV_TARGET"
"{"
" return Data.Color;"
"}"

"technique10 T0"
"{"
" pass P0"
" {"
" SetVertexShader(CompileShader(vs_4_0, VS()));"
" SetGeometryShader(NULL);"
" SetPixelShader(CompileShader(ps_4_0, PS()));"
" }"
"}";


Share this post


Link to post
Share on other sites
Advertisement
Mh, if nobody has an idea on that. How would i make lines more thick. Maybe that drops me in the right direction to accomblish the minimizing stuff aswell.

Btw, thats a quote on the topic i mentioned:
Quote:

You can use a geometry shader that will take as an input a segment of your line and output a quad (a triangle strip made of two triangles) so that the width of the quad is constant in screen space and matches the desire line thickness. It works perfectly well (for having implemented it in a CAD 3D engine).

If geometry shader is not an option, a workaround could be to use a vertex shader, but it will require some re-work of your VB. Keep in mind that the VS must then have knowledge of the line segment in its whole so you will end up storing p and p+1 for each of your VB elements, plus the cost of duplication of indices/vertices (depending the topology used and if you render your line as an indexed primitive or not).

If performance is not an issue, doing the expand on the CPU is maybe the way to go.

EDIT:

About dash patterns: you can use a geometry shader too in order to emulate glLineStipple behavior. If you have a GL_LINES topology, that is to say isolated lines, the pattern restarts at each new line segment. So you just have to compute in the geometry shader the screen-space horizontal start (or vertical start, depending the orientation) of your line segment and pass this extra infos to the pixel shader. The pixel shader will then be responsible of discarding fragments according to the factor and pattern values (DirectX 10/11 Integer and Bitwise instructions make it easy).

Again this works well, and you can combine it with emulated width lines (with the first technique above mentioned).

Now if you have GL_LINE_STRIP topology, the pattern restarts at each new primitive (so for each new draw call). The situation becomes a bit more complicated since you need to have the knowledge of the number of pixels that have been rendered before, and this for each line segment.

You can achieve that with rendering your line strip in a temporary VB using DirectX 10 stream-out functionality (each element of this VB corresponds to the screen-space length of each segment). Then you have to do a Parallel Prefix Sum (aka Scan) of this VB (for accumulating each line segment length values).

Lastly, you render your line strip like for GL_LINES but use this extra Scan VB informations in the PS.


I havnt got a clue how to accomblish such a thing :S

Share this post


Link to post
Share on other sites
Sadly, we don't have geometry shades in DX9, they were introduced in DX10. So we don't have DX9 shaders that can generate new vertices, just shaders that work on existing vertices or shaders that work on pixels.

I think to do this in DX9, you would have to construct each line yourself as a quad where each pair of vertices were in the same position. You could then cross the vector formed by the two ends, normalise it then use a scaled version of this vector to move out two of the end points by the required amount. Doing this vector maths would ensure they moved out at a right angle to the original line, which should produce the results you want.

I guess it would be possible to do this in a vertex shader by passing in state, but I wouldn't have thought it was worth it since in a VS you can only work on one vertex in isolation.

Share this post


Link to post
Share on other sites
Oh, i am working in DirectX10. Else i wouldnt have to set the Inputlayout and so on. So geometry shades are an option but i dont know how to set them up to modify the line width in a linelist

[Edited by - MedRamBO on August 26, 2010 4:24:59 AM]

Share this post


Link to post
Share on other sites
May it be that?


[maxvertexcount(3)]
void GSSolidWire( triangle GS_INPUT input[3],
inout TriangleStream<PS_INPUT_WIRE> outStream )
{
PS_INPUT_WIRE output;

// Shade and colour face.
output.Col = shadeFace(input[0].PosV, input[1].PosV, input[2].PosV);

// Emit the 3 vertices
// The Height attribute is based on the constant
output.Pos = input[0].Pos;
output.Heights = float3( 1, 0, 0 );
outStream.Append( output );

output.Pos = input[1].Pos;
output.Heights = float3( 0, 1, 0 );
outStream.Append( output );

output.Pos = input[2].Pos;
output.Heights = float3( 0, 0, 1 );
outStream.Append( output );

outStream.RestartStrip();
}

//in technique:
SetGeometryShader( CompileShader( gs_4_0, GSSolidWire() ) );



To be honest, i havnt got a clue how to set this up correctly to work with my linelist and vertex definition

Share this post


Link to post
Share on other sites
I wonder that nobody got any ideas. I've implemented the drawing functions into a game running the targeted directx version. The goal is to convert my graphics adapter from my ingame irc chat from directx9 to directx10. Therefore i need to convert basic functions such as sprites, image drawing, drawline, text etc.

Thats how it looks in comperison:

DX9:
lolwf.png<br>


DX10:
screenshotvg.png<br>

See the difference?

Share this post


Link to post
Share on other sites
Can't say if this helps, I just realized your text is not at the same position either. In DirectX 9 you do a half-pixel offset to align properly to pixels. Never used DX10/11 but AFAIR this problem has been made transparent or solved through a render state. For a long shot: Try a half-pixel offset.

Share this post


Link to post
Share on other sites
The text is at the same position. Its drawn through the IDX11Font class which takes screen positions. Its jsut about the lines, they are at the correct positions thoe.. prolly just looks like cuz i cut some of the picture while saving it with paint :) Thanks for the comment thoe.

To align from screenpos into the weird screenMapping i use following code:


D3DXVECTOR3 getScreenPercentage(float iScreenX, float iScreenY) {
float iCenterX = getScreenWidth() / 2.f;
float iCenterY = getScreenHeight() / 2.f;

float iOffsetX = iScreenX / iCenterX;
float iOffsetY = iScreenY / iCenterY;

if(iOffsetX < 1.0f)
iOffsetX = -1.0f + iOffsetX;
else
iOffsetX = iOffsetX - 1.0f;

if(iOffsetY < 1.0f)
iOffsetY = 1.0f - iOffsetY;
else
iOffsetY = 1.0f - iOffsetY;

D3DXVECTOR3 d3dVector(iOffsetX, iOffsetY, 0);

return d3dVector;
}


Share this post


Link to post
Share on other sites
I've ran the code in some test window i've created by myself. That runs fine. The lines are as big as i want them to be. It seems that some renderState or something else is set incorrectly to render it correctly.

I need that because i want to convert my ingame irc chat from directx9 to 10 due my huge performance lag being forced by the games weak dx9 support.

I dont really know what it could be. Its not the drawing code itself thoe. Must be some mis - setting of the game.

Any ideas?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!