`

体积光

 
阅读更多

体积光是透射的一种,次表面散射也是,所不同的是次表面散射是在模型里面,而体积光一般都是在模型外面。

 

伪体积光散射:

基于延迟渲染的体积光散射,简单说就是2D模拟3D效果,过程:

1.在屏幕中渲染光源

2.在屏幕中渲染遮蔽

3.屏幕中某点的颜色,是这个点到光源的这个线段上采样点的光的颜色的累积 (- -)。

#define NUM_SAMPLES 200 // 采样数
[numthreads( 16, 16, 1 )] //SV_GroupID 线程组的3D编号 最大只能是32X32
void VLS_CS( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex,uint3 DTid : SV_DispatchThreadID) //横
{
    // 全局固定参数
	float density = 1.0f;
	float weight = 1.0f;
    float decay = 0.995f;//0.98f;
	float exposure = 1.0f/200;

	matrix viewProject = mbMatrix[1];

    float4 lightPos = float4(lbParam[0].xyz,1.0f);

    float4 color = float4(0.0f,0.0f,0.0f,1.0f);

	lightPos = mul(lightPos, viewProject); // pos 是对的
	lightPos = lightPos / lightPos.w;
	lightPos = (lightPos + 1.0f) / 2.0f;
	lightPos.y = 1.0f - lightPos.y;

	float2 texCoord = float2(DTid.x/800.0f,DTid.y/600.0f); 

	float2 deltaTexCoord = (texCoord - lightPos.xy);
	deltaTexCoord *= 1.0f / NUM_SAMPLES * density;

	float illuminationDecay = 5.0f;
	for (uint i = 0; i < NUM_SAMPLES; i++)
	{
	    texCoord -= deltaTexCoord;
		uint2 tex = uint2(texCoord.x*800,texCoord.y*600);
		float4 sampleColor = mTexture[tex];
		sampleColor *= illuminationDecay * weight;
		color += sampleColor;
		illuminationDecay *= decay;
	}

	color *= exposure;
	color.w = 1.0f;

	Result[DTid.xy] = color;
}

 这种方式渲染出的结果有一种光芒万丈的感觉,但是,缺点很明显光源必须在屏幕中。因为光不在屏幕中就采样不到光的颜色,这样是不行的。

 

体积光散射:

1.在NVIDIA SDK里面有一个体积光的例子,看起来应该具备通用的能力,但是巨复杂,而且从代码量看来看,效率肯定也不会太高。

2.intel的体积光的例子,貌似是用shadow map 不停的拍照,然后累积一张张切片,最终混合成体积光的样子。这种方式感觉比N卡的更废,尤其是在光源比较远的时候。

3.我自己的实现思路,与下面这张图类似,以eye到屏幕射出一条射线,然后在这个射线上进行采样,来判断是否被遮蔽。

 



 这里的原理就是沿着深度的方向进行采样,看看有多少点在阴影里面,然后计算这个像素点最终的颜色。但是,这里有个问题,深度一般是[-1,1]这个采样应该如何把握呢?间隙太大,有些障碍物直接被忽略掉了。采样点太多肯定也是不行的。

 

演示:


 


 


 




 

  • 大小: 17.7 KB
  • 大小: 18.4 KB
  • 大小: 39.2 KB
  • 大小: 47.3 KB
  • 大小: 46.3 KB
  • 大小: 45.5 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics