我正在尝试使用 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 是定义四边形大小的半径或比例。
我感谢任何帮助-谢谢