我正在使用 ParticleGS DirectX10 示例,在 DirectX 11 中构建基于几何着色器的粒子系统。
使用示例代码并根据自己的喜好进行更改,我可以绘制一个四边形(本质上是一个不断重新创建自身的粒子)。
这是我的着色器代码:
//Single particle stream-out shader which uses ping-pong buffers.
//Based on DirectX sample ParticlesGS
struct VSParticleIn
{
float3 pos : POSITION;
float3 vel : NORMAL;
float Timer : TIMER;
uint Type : TYPE; //Only one type for the moment.
};
struct VSParticleDrawOut
{
float3 pos : POSITION;
float4 color : COLOR0;
float radius : RADIUS;
};
struct PSSceneIn
{
float4 pos : SV_Position;
float2 tex : TEXTURE0;
float4 color : COLOR0;
};
cbuffer cbRenderParticle
{
float4x4 g_mWorldViewProj;
float4x4 g_mInvView;
};
cbuffer cbAdvanceParticle
{
float g_fGlobalTime;
float g_fElapsedTime;
float4 g_vFrameGravity;
float g_fSecondsPerFirework = 1.0;
};
cbuffer cbImmutable
{
float3 g_positions[4] =
{
float3( -1, 1, 0 ),
float3( 1, 1, 0 ),
float3( -1, -1, 0 ),
float3( 1, -1, 0 ),
};
float2 g_texcoords[4] =
{
float2(0,1),
float2(1,1),
float2(0,0),
float2(1,0),
};
};
Texture2D g_txDiffuse;
SamplerState g_samLinear
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = Clamp;
AddressV = Clamp;
};
Texture1D g_txRandom;
SamplerState g_samPoint
{
Filter = MIN_MAG_MIP_POINT;
AddressU = Wrap;
};
RasterizerState mainState {
FillMode = Solid;
CullMode = None;
FrontCounterClockwise = false;
};
BlendState AdditiveBlending
{
AlphaToCoverageEnable = FALSE;
BlendEnable[0] = TRUE;
SrcBlend = SRC_ALPHA;
DestBlend = ONE;
BlendOp = ADD;
SrcBlendAlpha = ZERO;
DestBlendAlpha = ZERO;
BlendOpAlpha = ADD;
RenderTargetWriteMask[0] = 0x0F;
};
BlendState NoBlending
{
AlphaToCoverageEnable = FALSE;
BlendEnable[0] = FALSE;
};
DepthStencilState DisableDepth
{
DepthEnable = FALSE;
DepthWriteMask = ZERO;
};
DepthStencilState DSSLess
{
DepthEnable = TRUE;
DepthWriteMask = ALL;
StencilEnable = TRUE;
StencilReadMask = 0;
StencilWriteMask = 0;
FrontFaceStencilFunc = ALWAYS;
FrontFaceStencilDepthFail = INVERT;
FrontFaceStencilPass = KEEP;
FrontFaceStencilFail = KEEP;
BackFaceStencilFunc = ALWAYS;
BackFaceStencilDepthFail = INVERT;
BackFaceStencilPass = KEEP;
BackFaceStencilFail = KEEP;
DepthFunc = LESS;
};
VSParticleDrawOut RenderSceneVS(VSParticleIn input)
{
VSParticleDrawOut output = (VSParticleDrawOut)0;
output.pos = input.pos;
output.radius = 3;
output.color = float4(1,1,1,1);
return output;
}
VSParticleIn PassthroughVS(VSParticleIn input)
{
return input;
}
float3 RandomDir(float fOffset)
{
float tCoord = (g_fGlobalTime + fOffset) / 300.0;
return g_txRandom.SampleLevel( g_samPoint, tCoord, 0 );
}
[maxvertexcount(128)]
void AdvanceParticlesGS(point VSParticleIn input[1], inout PointStream<VSParticleIn> ParticleOutputStream)
{
//Just keeps emitting itself.
ParticleOutputStream.Append( input[0] );
}
[maxvertexcount(4)]
void RenderSceneGS(point VSParticleDrawOut input[1], inout TriangleStream<PSSceneIn> SpriteStream)
{
PSSceneIn output;
for(int i=0; i<4; i++)
{
float3 position = g_positions[i]*input[0].radius;
//position = mul( position, g_mInvView ) + input[0].pos;
output.pos = mul( float4(position,1.0), g_mWorldViewProj );
output.color = input[0].color;
output.tex = g_texcoords[i];
SpriteStream.Append(output);
}
SpriteStream.RestartStrip();
}
float4 RenderScenePS(PSSceneIn input) : SV_Target
{
return g_txDiffuse.Sample( g_samLinear, input.tex ) * input.color;
}
technique10 RenderParticles
{
pass p0
{
SetVertexShader( CompileShader( vs_4_0, RenderSceneVS() ) );
SetGeometryShader( CompileShader( gs_4_0, RenderSceneGS() ) );
SetPixelShader( CompileShader( ps_4_0, RenderScenePS() ) );
SetBlendState( AdditiveBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
SetRasterizerState( mainState );
SetDepthStencilState( DSSLess, 0 );
}
}
GeometryShader gsStreamOut = ConstructGSWithSO( CompileShader( gs_4_0, AdvanceParticlesGS() ), "POSITION.xyz; NORMAL.xyz; TIMER.x; TYPE.x" );
technique10 AdvanceParticles
{
pass p0
{
SetVertexShader( CompileShader( vs_4_0, PassthroughVS() ) );
SetGeometryShader( gsStreamOut );
SetPixelShader( NULL );
SetRasterizerState( mainState );
SetDepthStencilState(DisableDepth, 0);
}
}
但是,我注意到一个与我曾经遇到过的问题相似的问题:渲染的形状是扭曲的。这是一个展示正在发生的事情的视频。http://youtu.be/6NY_hxjMfwY
现在,当我意识到我需要将几何着色器显式设置为 null 以用于其他效果时,我曾经在一起使用多个效果时遇到过这个问题。正如您在视频中看到的那样,我解决了这个问题,因为场景的其余部分正在正确绘制。请注意,尽管我在主渲染状态下关闭了剔除,但某些边会以某种方式被剔除。
单独运行,着色器具有相同的行为。其他着色器似乎不会干扰它。
我的问题是,什么会导致四边形失真?我验证了我的转换矩阵,它们似乎是正确的。失真的原因可能是什么?或者常见的原因是什么?