
概要:雨粒子每刻的動畫使用輸出流,在每一幀都使用geometry Shader擴成billboard.
最后,雨粒子的渲染使用的紋理庫存儲在一個紋理陣列。使用DX10和GeForce8 系列GPU。
1.應用風和重力使粒子一直在作動畫。
2.把粒子擴成要在每一幀渲染的精靈。
3.渲染精靈
1.(1)C++使用輸出流
//設立渲染點列表,每個粒子存一個頂點。
pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_POINTLIST);
pd3dDevice->IASetInputLayout(g_pVertexLayoutRainVertex);
//決定哪個頂點緩沖我們既將要渲染
假如這是第一幀我們渲染一個預產生的頂點幀g_pParticleStart
static bool firstFrame=true;
ID3D10Buffer* pBuffers[1];
if(firstFrame)
pBuffers[0]=g_pParticleStart;
else
pBuffers[0]=g_pParticleDrawFrom;
pDevice->IASetVertexBuffers(0,1,pBuffers,stride,offset);
//指向正確的輸出緩沖
pBuffers[0] = g_pParticleStreamTo;
pd3dDevice->SOSetTargets( 1, pBuffers, offset );
// 畫圖,使粒子動畫
D3D10_TECHNIQUE_DESC techDesc;
g_pTechniqueAdvanceRain->GetDesc( &techDesc );
g_pTechniqueAdvanceRain->GetPassByIndex(0)->Apply(0);
pd3dDevice->Draw(g_numRainVertices , 0 );
// Get back to normal
pBuffers[0] = NULL;
pd3dDevice->SOSetTargets( 1, pBuffers, offset );
// Swap buffers交換緩沖區
ID3D10Buffer* pTemp = g_pParticleDrawFrom;
g_pParticleDrawFrom = g_pParticleStreamTo;
g_pParticleStreamTo = pTemp;
firstFrame = false;
2.(2)HLSL--使用Geometry shader Expanding
GeometryShader gsStreamOut = ConstructGSWithSO( CompileShader( vs_4_0, VSAdvanceRain() ), "POSITION.xyz; SEED.xyz; SPEED.xyz; RAND.x; TYPE.x" );
technique10 AdvanceParticles
{
pass p0
{
SetVertexShader( CompileShader( vs_4_0, VSAdvanceRain() ) );
SetGeometryShader( gsStreamOut );
SetPixelShader( NULL );
SetDepthStencilState( DisableDepth, 0 );
}
}
(3)HLSL--使用Geometry shader Extruding
// GS for rendering rain as point sprites. Takes a point and turns it into 2 tris.
[maxvertexcount(4)]
void GSRenderRain(point VSParticleIn input[1], inout TriangleStream<PSSceneIn> SpriteStream)
{
float totalIntensity = g_PointLightIntensity*g_ResponsePointLight + dirLightIntensity*g_ResponseDirLight;
if(!cullSprite(input[0].pos,2*g_SpriteSize) && totalIntensity > 0)
{
PSSceneIn output = (PSSceneIn)0;
output.type = input[0].Type;
output.random = input[0].random;
float3 pos[4];
GenRainSpriteVertices(input[0].pos.xyz, input[0].speed.xyz/g_FrameRate + g_TotalVel, g_eyePos, pos);
float3 closestPointLight = g_PointLightPos;
float closestDistance = length(g_PointLightPos - pos[0]);
if( length(g_PointLightPos2 - pos[0]) < closestDistance )
closestPointLight = g_PointLightPos2;
output.pos = mul( float4(pos[0],1.0), g_mWorldViewProj );
output.lightDir = g_lightPos - pos[0];
output.pointLightDir = closestPointLight - pos[0];
output.eyeVec = g_eyePos - pos[0];
output.tex = g_texcoords[0];
SpriteStream.Append(output);
output.pos = mul( float4(pos[1],1.0), g_mWorldViewProj );
output.lightDir = g_lightPos - pos[1];
output.pointLightDir = closestPointLight - pos[1];
output.eyeVec = g_eyePos - pos[1];
output.tex = g_texcoords[1];
SpriteStream.Append(output);
output.pos = mul( float4(pos[2],1.0), g_mWorldViewProj );
output.lightDir = g_lightPos - pos[2];
output.pointLightDir = closestPointLight - pos[2];
output.eyeVec = g_eyePos - pos[2];
output.tex = g_texcoords[2];
SpriteStream.Append(output);
output.pos = mul( float4(pos[3],1.0), g_mWorldViewProj );
output.lightDir = g_lightPos - pos[3];
output.pointLightDir = closestPointLight - pos[3];
output.eyeVec = g_eyePos - pos[3];
output.tex = g_texcoords[3];
SpriteStream.Append(output);
SpriteStream.RestartStrip();
}
}
3.
渲染點精靈
使用DX10新特性Texture Array
渲染霧
運行范例:
范例顯示兩個點光源和一條直射光下的橋。
左鍵控制直射光。