体积光逻辑(1)

——体积光,在物理层面来说是丁达尔效应. 主要实现使用的是RayMarch
一、 What is RayMarch?
一根ray一步一步向前走(marching),一直到与物体相交
二、RayMarch 元素:
每一个采样点计算都要把所有因素的数值进行相乘处理,得到该采样点上的最终结果
因素
公式
代码
备注
1 光强度的衰减计算
//世界坐标转到灯光坐标系下
float3 lightCoord = mul (_MyLightMatrix0, float4 (wpos, 1 )).xyz;
/ /使用点到光源中心距离的平方dot(lightCoord, lightCoord)构成二维采样坐标,
//对衰减纹理_LightTexture0采样。
// UNITY_ATTEN_CHANNEL是衰减值所在的纹理通道,可以在内置的HLSLSupport.cginc文件中查看
//一般PC和主机平台的话 UNITY_ATTEN_CHANNEL 是r通道,移动平台的话是a通道
atten = tex2D (_LightTexture0, dot (lightCoord, lightCoord).rr). UNITY_ATTEN_CHANNEL ;
 _LightTexture0 包含了光源衰减信息的衰减纹理
2 散射函数  
HG公式
【常量配置】散射因子g
rd 视角方向
lightDir 光线的方向
float ScatterHG(float3 rd, float3 lightDir, float g){
      float cosTheta = dot(lightDir,-rd);
      float result = 1/(4*3.14)* (1 - pow(g,2))/ pow(1 + pow(g,2) -2*g* cosTheta, 1.5);
      return result;          
 }
3 透光比
Beer–Lambert法则
Out = In*exp(-c*d)
c是物质密度,d是距离, In是入射光
float ExtingctionFunc(float In, float d, float c)
{
    return In* exp(-c*d);
}
  透光强度随着介质的密度光传播的距离的增加成指数下降。
4 阴影
#if defined(SHADOWS_DEPTH)
// 世界坐标转化到阴影坐标下
         float4 shadowCoord = mul(_MyWorld2Shadow, float4(wpos, 1));
         atten *= saturate(UnitySampleShadowmap(shadowCoord));
#endif
采样点和光源做一条线段,检测场景中这条线段有没有和别的可见物体相交, 如果有就说明该采样点被遮挡
UnitySampleShadowMap函数:
根据给定的而阴影坐标,在阴影深度贴图中进行采样,获得阴影坐标对应的贴图文素的深度值
从起点开始, 沿着射线,采样每个点的亮度,所有经过的采样点上的亮度求和就是像素的最终颜色。
三、项目中使用的变量以及计算方式:
解释
代码
_WorldViewProj
MVP矩阵。
用于把坐标转化成屏幕空间坐标
//平台差异化兼容 理 构建 p
//GetGPUProjectionMatrix 由于 DX 和 GL的坐 差异, 一化 理。 当使用DX渲染的 候, 吧DX的z 从(-1,1) 映射到(0,1)。 y 轴进 行反 操作
Matrix4x4 proj = GL.GetGPUProjectionMatrix(_camera.projectionMatrix, true); //平台差异化兼容
_viewProj = proj * _camera.worldToCameraMatrix;
// VP
_viewProj = proj * _camera.worldToCameraMatrix; 
//构建world 矩阵
float scale = _light.range;
float angleScale = Mathf.Tan((_light.spotAngle + 1) * 0.5f * Mathf. Deg2Rad) * _light.range;
Matrix4x4 world = Matrix4x4.TRS(_light.transform.position, _light.transform.rotation, new Vector3(angleScale, angleScale, scale));
_WorldViewProj = _viewProj * world;
_MyLightMatrix0
灯光的矩阵
用于把坐标转化到灯光的坐标系下
_viewMatrix = Matrix4x4.TRS(_light.transform.position, _light.transform.rotation, Vector3.one).inverse;
Matrix4x4 clip = Matrix4x4.TRS(new Vector3(0.5f, 0.5f, 0.0f), Quaternion.identity, new Vector3(-0.5f, -0.5f, 1.0f));
Matrix4x4 proj = Matrix4x4.Perspective(_light.spotAngle, 1, 0, 1);
_MyLightMatrix0 = clip * proj * _viewMatrix
_MyWorld2Shadow
把世界坐标转化到阴影坐标系下
Matrix4x4 m = light_clip * light_proj;
m[0, 2] *= -1;
m[1, 2] *= -1;
m[2, 2] *= -1;
m[3, 2] *= -1;
// m 公式
_MyWorld2Shadow = m*_viewMatrix
四: 参考
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值