rain简析(待改)

rain简析(待改)

rain简析(待改)_第1张图片
概要:雨粒子每刻的动画使用输出流,在每一帧都使用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
渲染雾
运行范例:
范例显示两个点光源和一条直射光下的桥。
左键控制直射光。

你可能感兴趣的:(rain简析(待改))