1
\$\begingroup\$

I'm using DirectX 11 and c++ and I've been trying to make a ribbon trail renderer. I was hoping to be able to not have to build every vertex on the CPU side, just keeping the, uuh, "keyframes", or corners of the ribbon and build the quads between them on the GPU side. My current setup is:

  1. Have an array of vertices (float3 pos, float size, float4 color). For my testing example, I'm having 5 vertices in the array.
  2. Send the array to a vertex buffer. (code bellow).
  3. Set topology to a linestrip.
  4. Call on context and draw.
  5. Vertex shader just doing its thing.
  6. Geometry shader; I use the current vertex and the next vertex to build a quad between the two. (guessing my problem is here maybe).

My results are iffy. Having a list of positions as following:

  • ( 1, 0, 0)
  • ( 0, 0, 1)
  • (-1, 0, 0)
  • (-2, 0, 1)
  • (-3, 0, 0)

Aaaand it looks like this:

Vertices n stuff

I was hoping to be able to build a zig-zag line with the 5 CPU vertices. Also, the black side of a line is the first index of input[] in the geometry shader, vice versa the white side being the second index of input[]. From the looks of it, every second triangle have a different order for its vertices which probably causes the straight wrong lines.


Code
First, the input layout

const D3D11_INPUT_ELEMENT_DESC LineRendererLayout[] =
{
    { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "SIZE", 0, DXGI_FORMAT_R32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};

Since the data struct for each corner is a vector3, a float and a vector4, I don't see how the input layout is wrong.

Next, the updating of the vertex buffer right before rendering:

if (myParticles.Size() > 0)
{
    D3D11_MAPPED_SUBRESOURCE mappedResource;
    ID3D11DeviceContext* d3dContext = Engine::GetInstance()->GetContext();
    d3dContext->Map(myVertexBuffer.myVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);

    if (mappedResource.pData != nullptr)
    {
        LineRendererData* data = (LineRendererData*)mappedResource.pData;
        memcpy(data, &myParticles[0], sizeof(LineRendererData) * myParticles.Size());
    }
    d3dContext->Unmap(myVertexBuffer.myVertexBuffer, 0);
}

So the vertices are right next to each other in the buffer; 0, 1, 2, 3, 4. This is the second place I suspect my error might be.

Next up, rendering. Should not be any problems I think:

myEffect->GetShaderResourceVariable("AlbedoTexture")->SetResource(myTexture->GetShaderView());
myEffect->SetView(aCamera->GetOrientation());
myEffect->SetProjection(aCamera->GetProjectionMatrix());

ID3D11DeviceContext* context = Engine::GetInstance()->GetContext();

context->IASetInputLayout(myInputLayout);
context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
context->IASetVertexBuffers(myVertexBuffer.myStartSlot, 1, &(myVertexBuffer.myVertexBuffer), &myVertexBuffer.myStride, &myVertexBuffer.myByteOffset);

D3DX11_TECHNIQUE_DESC techDesc;
myEffect->GetTechnique()->GetDesc(&techDesc);   // GetTechnique() returns a ID3D11EffectTechnique*

for (UINT p = 0; p < techDesc.Passes; ++p)
{
    myEffect->GetTechnique()->GetPassByIndex(p)->Apply(0, context);
    context->Draw(myParticles.Count(), 0);
}

Finally, the geometry shader!

struct VS_INPUT
{
    float3 Pos : POSITION;
    float Size : SIZE;
    float4 Color : COLOR;
};

struct GS_INPUT
{
    float4 Pos : POSITION;
    float Size : SIZE;
    float4 Color : COLOR;
};

[maxvertexcount(6)]
void GS(triangle GS_INPUT input[3], inout TriangleStream<PS_INPUT> TriStream)
{
    PS_INPUT output = (PS_INPUT)0;

    output.Pos = input[0].Pos + float4(0, -input[0].Size, 0, 0);
    output.Pos = mul(output.Pos, View);
    output.Pos = mul(output.Pos, Projection);
    output.Uv = texCoords[0];
    output.Color = 0;
    TriStream.Append(output);

    output.Pos = input[0].Pos + float4(0, input[0].Size, 0, 0);
    output.Pos = mul(output.Pos, View);
    output.Pos = mul(output.Pos, Projection);
    output.Uv = texCoords[0];
    output.Color = 0;
    TriStream.Append(output);

    output.Pos = input[1].Pos + float4(0, -input[0].Size, 0, 0);
    output.Pos = mul(output.Pos, View);
    output.Pos = mul(output.Pos, Projection);
    output.Uv = texCoords[0];
    output.Color = 1;
    TriStream.Append(output);

    output.Pos = input[0].Pos + float4(0, input[0].Size, 0, 0);
    output.Pos = mul(output.Pos, View);
    output.Pos = mul(output.Pos, Projection);
    output.Uv = texCoords[0];
    output.Color = 0;
    TriStream.Append(output);

    output.Pos = input[1].Pos + float4(0, -input[0].Size, 0, 0);
    output.Pos = mul(output.Pos, View);
    output.Pos = mul(output.Pos, Projection);
    output.Uv = texCoords[0];
    output.Color = 1;
    TriStream.Append(output);

    output.Pos = input[1].Pos + float4(0, input[0].Size, 0, 0);
    output.Pos = mul(output.Pos, View);
    output.Pos = mul(output.Pos, Projection);
    output.Uv = texCoords[0];
    output.Color = 1;
    TriStream.Append(output);

    TriStream.RestartStrip();
} 

Not fancy, but easier for debug purposes.


As of right now I'm pretty lost on this issue. The fix might be very simpe, I don't know. I've stared myself blind at this stage.

I hope this post isn't too much of a mess, and thanks in advance!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.