1
votes

i am trying to convert a single point into a quad using the geometry shader in HLSL. When i am not using the geometry shader and try to display the single pixel it works just fine. But when i use it, the quads are getting drawn but they seem to move to another location every 100th frame update or something.

Here is my sprite class (i am not entirely sure about my code there..especially the vertex buffer and the draw call):

#include "SpriteRenderer.h"

#include "debug.h"
SpriteRenderer::SpriteRenderer(const std::vector<std::string>& textureFilenames) 
                                                :m_textureFilenames (textureFilenames),
                                                 m_pEffect (NULL),
                                                 m_spriteTex (NULL),
                                                 m_spriteSRV (NULL),
                                                 m_spriteCountMax (0),
                                                 m_pVertexBuffer (NULL),
                                                 m_pInputLayout (NULL),
                                                 pd3dImmediateContext(NULL)
{

}

SpriteRenderer::~SpriteRenderer(){

}

HRESULT SpriteRenderer::ReloadShader(ID3D11Device* pDevice){

    HRESULT hr;

    ReleaseShader();

    WCHAR path[MAX_PATH];
    stringstream ss;
    wstringstream wss;

    V_RETURN(DXUTFindDXSDKMediaFileCch(path, MAX_PATH, L"SpriteRenderer.fxo"));
    ifstream is(path, ios_base::binary);
    is.seekg(0, ios_base::end);
    streampos pos = is.tellg();
    is.seekg(0, ios_base::beg);
    vector<char> effectBuffer((unsigned int)pos);
    is.read(&effectBuffer[0], pos);
    is.close();
    V_RETURN(D3DX11CreateEffectFromMemory((const void*)&effectBuffer[0],effectBuffer.size(), 0, pDevice, &m_pEffect));

    return S_OK;
}

void SpriteRenderer::ReleaseShader(){
    SAFE_RELEASE( m_pEffect );
}

HRESULT SpriteRenderer::CreateResources(ID3D11Device* pDevice){
    HRESULT hr;
    // Fill in the subresource data.
    D3D11_SUBRESOURCE_DATA InitData;
    InitData.pSysMem = NULL;
    InitData.SysMemPitch = sizeof(SpriteVertex);
    InitData.SysMemSlicePitch = 0;

    D3D11_BUFFER_DESC bufferDesc;
    bufferDesc.Usage            = D3D11_USAGE_DEFAULT;
    bufferDesc.ByteWidth        = 1024 * InitData.SysMemPitch;
    bufferDesc.BindFlags        = D3D11_BIND_VERTEX_BUFFER;
    bufferDesc.CPUAccessFlags   = 0;
    bufferDesc.MiscFlags        = 0;

    V_RETURN(pDevice->CreateBuffer( &bufferDesc, NULL, &m_pVertexBuffer ));

    const D3D11_INPUT_ELEMENT_DESC layout[] = // http://msdn.microsoft.com/en-us/library/bb205117%28v=vs.85%29.aspx
    {
        { "POSITION",          0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
        { "RADIUS",            0, DXGI_FORMAT_R32_FLOAT,       0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
        { "TEXTUREINDEX",      0, DXGI_FORMAT_R32_SINT,        0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    };
    UINT numElements = sizeof( layout ) / sizeof( layout[0] );
    D3DX11_PASS_DESC passDesc;
    m_pEffect->GetTechniqueByName("Render")->GetPassByName("P0_Sprite")->GetDesc(&passDesc);

    V_RETURN( pDevice->CreateInputLayout( layout, numElements, passDesc.pIAInputSignature,
              passDesc.IAInputSignatureSize, &m_pInputLayout ) );

    return S_OK;
}

void SpriteRenderer::ReleaseResources(){
    SAFE_RELEASE( m_pInputLayout );
    SAFE_RELEASE( m_pVertexBuffer );
}

void SpriteRenderer::RenderSprites(ID3D11Device* pDevice, const std::vector<SpriteVertex>& sprites, const CFirstPersonCamera& camera){
    pDevice->GetImmediateContext(&pd3dImmediateContext);
    m_spriteCountMax = sprites.size();
    D3D11_BOX box;
    box.left  = 0; box.right = m_spriteCountMax * sizeof(SpriteVertex);
    box.top  = 0; box.bottom = 1;
    box.front = 0; box.back  = 1;

    pd3dImmediateContext->UpdateSubresource(m_pVertexBuffer, 0, &box, &sprites, 0, 0);

    ID3D11Buffer* vbs[] = { m_pVertexBuffer, };
    unsigned int strides[] = { sizeof(SpriteVertex), }, offsets[] = { 0, };

    pd3dImmediateContext->IASetVertexBuffers(0,1, vbs, strides, offsets);
    pd3dImmediateContext->IASetInputLayout(m_pInputLayout);
    pd3dImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);

    //TODO: Move to header file.
    ID3DX11EffectMatrixVariable* g_ViewProjectionEV;
    ID3DX11EffectVectorVariable* g_WorldUpEV;
    ID3DX11EffectVectorVariable* g_WorldRightEV;

    g_WorldUpEV = m_pEffect->GetVariableByName("g_WorldUp")->AsVector();
    g_WorldRightEV = m_pEffect->GetVariableByName("g_WorldRight")->AsVector();
    g_ViewProjectionEV = m_pEffect->GetVariableByName("g_ViewProjection")->AsMatrix();

    g_WorldUpEV->SetFloatVector(( float * )camera.GetWorldUp());
    g_WorldRightEV->SetFloatVector(( float * )camera.GetWorldRight());

    for(auto it = sprites.begin(); it != sprites.end(); it++){
        D3DXMATRIX worldView, mRotx, mRoty, mRotz, mTrans, mScale;
        D3DXMatrixTranslation(&mTrans, it->Position.x, it->Position.y, it->Position.z);
        D3DXMatrixRotationX(&mRotx, 0);
        D3DXMatrixRotationY(&mRoty, 0);
        D3DXMatrixRotationZ(&mRotz, 0);
        D3DXMatrixScaling(&mScale, 1.0f, 1.0f, 1.0f);
        worldView = mScale * mRotx * mRotz * mRotz * mTrans * (*camera.GetViewMatrix());
        D3DXMATRIX worldViewProj = worldView * (*camera.GetProjMatrix());
        g_ViewProjectionEV->SetMatrix(( float* )worldViewProj);
        m_pEffect->GetTechniqueByName("Render")->GetPassByName("P0_Sprite")->Apply(0, pd3dImmediateContext);
        pd3dImmediateContext->Draw(1, 0);   
    }


    SAFE_RELEASE( pd3dImmediateContext );
}

And here is my shader:

matrix g_ViewProjection;
//--------------------------------------------------------------------------------------
// Constant buffers
//--------------------------------------------------------------------------------------

cbuffer cbPerFrame
{
    float3 g_WorldUp;
    float3 g_WorldRight;
}

//--------------------------------------------------------------------------------------
// Structs
//--------------------------------------------------------------------------------------

struct PSVertex {
    float4 Position : SV_POSITION;
};

struct SpriteVertex
{
    float3 Position : POSITION;
    float Rad : RADIUS;
    int TexIndex: TEXTUREINDEX;
};

//--------------------------------------------------------------------------------------
// Rasterizer states
//--------------------------------------------------------------------------------------

RasterizerState rsCullNone {
    CullMode = None; 
};

//--------------------------------------------------------------------------------------
// DepthStates
//--------------------------------------------------------------------------------------
DepthStencilState EnableDepth
{
    DepthEnable = TRUE;
    DepthWriteMask = ALL;
    DepthFunc = LESS_EQUAL;
};

BlendState NoBlending
{
    AlphaToCoverageEnable = FALSE;
    BlendEnable[0] = FALSE;
};

//--------------------------------------------------------------------------------------
// Shaders
//--------------------------------------------------------------------------------------
SpriteVertex DummyVS(SpriteVertex Input) {
    SpriteVertex vs;
    vs.Position = Input.Position;
    vs.Rad = Input.Rad;
    vs.TexIndex = Input.TexIndex;

    return vs;
}
float4 DummyPS(PSVertex input) : SV_Target0 {
    return float4(1, 1, 0, 1);
}

/*
SpriteVertex DummyVS(VSInput Input) {
    SpriteVertex output;

    output.Position = Input.Pos;
    output.Rad = Input.Rad;
    output.TexIndex = Input.TexIndex;
    //stream = mul(float4(Input.Pos.xyz, 1), g_ViewProjection);
    return output;
}

float4 DummyPS(PSVertex input) : SV_Target0 {
    return float4(1, 1, 0, 1);
}
*/
[maxvertexcount(4)]
void SpriteGS(point SpriteVertex vertex[1], inout TriangleStream<PSVertex> stream){
    PSVertex v;

    v.Position = float4(vertex[0].Position + mul(vertex[0].Rad,g_WorldRight) + mul(vertex[0].Rad,g_WorldUp), 1.f);
    v.Position = mul(v.Position, g_ViewProjection);
    stream.Append(v);
    v.Position = float4(vertex[0].Position - mul(vertex[0].Rad,g_WorldRight) + mul(vertex[0].Rad,g_WorldUp), 1.f);
    v.Position = mul(v.Position, g_ViewProjection);
    stream.Append(v);
    v.Position = float4(vertex[0].Position + mul(vertex[0].Rad,g_WorldRight) - mul(vertex[0].Rad,g_WorldUp), 1.f);
    v.Position = mul(v.Position, g_ViewProjection);
    stream.Append(v);
    v.Position = float4(vertex[0].Position - mul(vertex[0].Rad,g_WorldRight) - mul(vertex[0].Rad,g_WorldUp), 1.f);
    v.Position = mul(v.Position, g_ViewProjection);
    stream.Append(v);
    stream.RestartStrip();
}
//--------------------------------------------------------------------------------------
// Techniques
//--------------------------------------------------------------------------------------
technique11 Render
{
    pass P0_Sprite
    {
        SetVertexShader(CompileShader(vs_4_0, DummyVS()));
        SetGeometryShader(CompileShader(gs_4_0, SpriteGS()));
        SetPixelShader(CompileShader(ps_4_0, DummyPS()));

        SetRasterizerState(rsCullNone);
        SetDepthStencilState(EnableDepth, 0);
        SetBlendState(NoBlending, float4(0.0f, 0.0f, 0.0f, 0.0f), 0xFFFFFFFF);
    }
}

As you might see i am using the camera up and right vector to make the quads screen aligned. Here i am pretty unsure about my code (is this the right way to do this?) The vertex[0].Rad is a Radius or scale to define the size of the quad.

I appreciate any help- Thanks

1

1 Answers

0
votes

Unfortunately I cannot comment, but it looks like you are passing the address of your std::vector<SpriteVertex> to UpdateSubresource instead of the contents of the vector.

pd3dImmediateContext->UpdateSubresource(m_pVertexBuffer, 0, &box, &sprites, 0, 0);

should read

pd3dImmediateContext->UpdateSubresource(m_pVertexBuffer, 0, &box, &sprites.front(), 0, 0);