体积光逻辑(1)

本文详细介绍了Unity中体积光的实现方法,包括RayMarching技术在体积光渲染中的应用,以及光强度衰减、散射函数、透光比和阴影计算等关键步骤。通过示例代码展示了如何计算每个采样点的亮度,并最终合成像素的最终颜色。同时,还提到了在项目中使用的矩阵转换及其作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

——体积光,在物理层面来说是丁达尔效应. 主要实现使用的是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
四: 参考
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值