运动模糊和景深

运动模糊和景深其实是很早之前的光学拍摄器材的缺陷导致的现象,后面摄影技术发达之后这些反而作为局部后期处理的手段。时至今日,实时渲染也大行其道这种技术。

 

景深:是由于光学仪器受到焦距的影响,在一个特定的距离空间内的像会比较清晰,而这个区间外的物体会出现模糊。

实现思路:其本质就是对图像进行局部模糊,而模糊的规则就是把深度分成3个区域,前后是模糊的,中间是清晰的。

 

整个过程分三个Pass:

1.将场景渲染到一个RenderTarget,做为清晰版.

2.将上一步得到的RenderTarget进行模糊处理,得到BluredRT(模糊版).

3.合成.跟据距离来判断是否应该模糊,如果不在焦点范围内则绘制BluredRT,否则就绘制RenderTarget.

sampler RenderTarget;
sampler BluredRT;
 
//焦点范围
float fNearDis;
float fFarDis;
 
float4 ps_main( float2 TexCoord : TEXCOORD0 ) : COLOR0
{  
   float4 color = tex2D( RenderTarget, TexCoord );
   if( color.a > fNearDis && color.a < fFarDis )
      return color;
   else
      return tex2D( BluredRT, TexCoord );
}

 这个做出效果并不难,难就难在如何在动态的环境中把景深用到最好。

 

运动模糊 :在拍摄快速运动的物体的时候,由于相机成像会有一小段时间的延时,导致这个区间内的像形成叠加效果。

实现原理:很多地方是用前后帧混合的方式实现运动模糊,我觉得那样子叠加少了效果不明显,多了性能不好,就采用了GPU3里面的那种方式。原理也很简单,以屏幕坐标和深度为参数,构建点的屏幕空间3D位置。然后一路逆转换,转换到世界空间,再用上一帧的转换矩阵,求出上一帧当前顶点的位置。最后,顶点屏幕空间的速度。然后进行插值采样,这种方式的好处是采样率比较高,缺点就是不能直接返回到模型空间,这样在世界空间中运动的物体就不会有运动模糊的效果。

[numthreads( 16, 16, 1 )]
void MotionBlur_CS( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex,uint3 DTid : SV_DispatchThreadID)
{
    matrix inverViewProject = mbMatrix[0]; // view和project乘积的逆
	matrix previousViewProject = mbMatrix[1]; // 前一帧的view*project矩阵

	int2 iTexCoord = DTid.xy;
	float  currentDepth = mDepthTexture[iTexCoord].x; // 当前帧的深度
	// 当前像素当前帧的view空间的位置
	float2 fTexCoord = float2(iTexCoord.x/800,iTexCoord.y/600);
	// 到透视空间
	float4 currentPosPS = float4(fTexCoord.x*2.0f - 1.0f,(1.0f - fTexCoord.y)*2.0f - 1.0f,currentDepth,1.0f);
	float4 currentPosWS = mul(currentPosPS,inverViewProject);
	currentPosWS = currentPosWS/currentPosWS.w;

	float4 previousPosPS = mul(currentPosWS,previousViewProject);
	previousPosPS = previousPosPS/previousPosPS.w;

	float2 velocity = abs((currentPosPS - previousPosPS)/2.0f); // 屏幕空间的速度 [0,1]

	float4 sceneColor = mSceneTexture[iTexCoord];
	float2 deltaVelocity = velocity/NUM_SAMPLES;
	
	for (uint i = 0; i < NUM_SAMPLES-1; i++)
	{
	    iTexCoord += uint2(deltaVelocity.x*800,deltaVelocity.y*600); 
		iTexCoord.x = clamp(iTexCoord.x,0,800-1);
		iTexCoord.y = clamp(iTexCoord.y,0,600-1);
		float4 sampleColor = mSceneTexture[iTexCoord];
		sceneColor += sampleColor;
	}
	sceneColor = sceneColor/NUM_SAMPLES;
	sceneColor.w = 1.0f;

	Result[DTid.xy] = sceneColor; 
}

 

总结:尽管效果做出来了,但是看的人晕。这两种效果本身是由拍摄过程中,器材呈现缺陷而导致的。最终,到这里却成了别人炒作的一个热点,效果本身没有错,就怕滥用,尤其是这种效果,应该建立在复杂的前提下,不经常出现才对。

你可能感兴趣的:(高级渲染)