DirectX9 SDK Samples(26) PixelMotionBlur Sample
動態模糊,一看到這個詞我就想到了極品飛車和MineCraft的光影MOD。DX11貌似可以很好地支持動態模糊,但這個例子是基于DX9的,那DX9是怎么實現MotionBlur的呢?
SDK文檔里面提到,實現動態模糊的其中一種方法是將場景用不同的Alpha通道渲染多遍。這個例子用的是另外一個方法,模仿現實中動態模糊出現的條件,記錄像素的速度來實現動態模糊。
既然是Post-Process,那么多個RenderTarget一般都是需要的。RenderTarget需要三個紋理,一個用來渲染原來的場景,另外兩個是浮點紋理,提供給PS來渲染每個像素的速度,其中一個記錄上一幀的速度,另外一個記錄當前幀的速度。也需要一個QUAD用來顯示最后的紋理。
在Render函數主要完成了兩件事:1.渲染場景和記錄當前幀每個像素的速度,假如設備不支持同時渲染多個RenderTarget,那么就需要在兩個Pass內完成上述渲染;2.完成Post-Process,對一個全屏的矩形(就是上面提到的QUAD)每個像素執行MB的PS。
那么該怎么計算速度呢?可以確定的是,這個計算必須在VS上進行。那么是不是保存所有點的上一次的坐標呢?明顯不用,只需要保存上一次的WVP矩陣就可以了。
// Transform from object space to homogeneous projection spacevPosProjSpaceCurrent = mul(vPos, mWorldViewProjection);vPosProjSpaceLast = mul(vPos, mWorldViewProjectionLast);// Output the vetrex position in projection spaceOutput.Position = vPosProjSpaceCurrent;// Convert to non-homogeneous points [-1,1] by dividing by w vPosProjSpaceCurrent /= vPosProjSpaceCurrent.w;vPosProjSpaceLast /= vPosProjSpaceLast.w;// Vertex's velocity (in non-homogeneous projection space) is the position this frame minus // its position last frame. This information is stored in a texture coord. The pixel shader // will read the texture coordinate with a sampler and use it to output each pixel's velocity.float2 velocity = vPosProjSpaceCurrent - vPosProjSpaceLast; // The velocity is now between (-2,2) so divide by 2 to get it to (-1,1)velocity /= 2.0f; // Store the velocity in a texture coordOutput.VelocityUV = velocity; 這一段HLSL代碼正是完成了計算速度的工作。注意,在計算速度前需要先除以w值,具體我也不清楚為什么。 PS_OUTPUT WorldPixelShader( VS_OUTPUT In ) { PS_OUTPUT Output;Output.RGBColor = tex2D(MeshTextureSampler, In.TextureUV) * In.Diffuse;Output.PixelVelocity = float4(In.VelocityUV,1.0f,1.0f);// Using MRT, output 2 values in the pixel shader. return Output; }PS不需要做什么,基本上輸出值就好了。接下來就是怎么樣利用記錄好的值來進行MotionBlur了。
float curVelocitySqMag = curFramePixelVelocity.r * curFramePixelVelocity.r +curFramePixelVelocity.g * curFramePixelVelocity.g;float lastVelocitySqMag = lastFramePixelVelocity.r * lastFramePixelVelocity.r +lastFramePixelVelocity.g * lastFramePixelVelocity.g;if( lastVelocitySqMag > curVelocitySqMag ){pixelVelocity.x = lastFramePixelVelocity.r * PixelBlurConst; pixelVelocity.y = -lastFramePixelVelocity.g * PixelBlurConst;}else{pixelVelocity.x = curFramePixelVelocity.r * PixelBlurConst; pixelVelocity.y = -curFramePixelVelocity.g * PixelBlurConst; }// For each sample, sum up each sample's color in "Blurred" and then divide// to average the color after all the samples are added.float3 Blurred = 0; for(float i = 0; i < NumberOfPostProcessSamples; i++){ // Sample texture in a new spot based on pixelVelocity vector // and average it with the other samples float2 lookup = pixelVelocity * i / NumberOfPostProcessSamples + OriginalUV;// Lookup the color at this new spotfloat4 Current = tex2D(RenderTargetSampler, lookup);// Add it with the other samplesBlurred += Current.rgb;}// Return the average color of all the samplesreturn float4(Blurred / NumberOfPostProcessSamples, 1.0f); 以上就是MB的HLSL代碼,簡單來說就是首先確定使用哪一個速度值,然后就是根據速度方向來進行采樣,這樣就產生了模糊效果。使用這樣的方法來模擬動態模糊有兩個缺點,一個是在邊緣會出現漏洞,第二個是當物體移動過快時模糊效果不對,后一個可以通過提高幀數解決。前一個如果對每一個像素周圍的像素也進行采用的話,估計改善情況。
總結
以上是生活随笔為你收集整理的DirectX9 SDK Samples(26) PixelMotionBlur Sample的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: git pull远程master_git
- 下一篇: 等了好久终于到今天--姐拿到驾照了(考试