1

我正在尝试使用 HLSL 中的几何着色器将单个点转换为四边形。当我不使用几何着色器并尝试显示单个像素时,它工作得很好。但是当我使用它时,四边形正在被绘制,但它们似乎每 100 帧更新或某事移动到另一个位置。

这是我的精灵类(我不完全确定那里的代码..尤其是顶点缓冲区和绘图调用):

#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 );
}

这是我的着色器:

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);
    }
}

正如您可能看到的,我正在使用相机向上和向右矢量来使四边形屏幕对齐。在这里我很不确定我的代码(这是正确的方法吗?) vertex[0].Rad 是定义四边形大小的半径或比例。

我感谢任何帮助-谢谢

4

1 回答 1

0

不幸的是,我无法发表评论,但看起来你传递的是你的地址std::vector<SpriteVertex>UpdateSubresource不是向量的内容。

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

应该读

pd3dImmediateContext->UpdateSubresource(m_pVertexBuffer, 0, &box, &sprites.front(), 0, 0);
于 2012-06-29T19:16:01.127 回答