unity二叉树_Unity Shader内用八叉树实现体素化阴影!

本文介绍了如何使用Unity Shader内的八叉树技术实现体素化阴影,以解决超大场景中传统阴影技术的局限性。通过八叉树结构,实现实时阴影与静态对象阴影的高效计算,替代shadowmask和ProbesOcclusion。文章详细展示了C#和Shader的实现代码,并提供了离线阴影数据收集的方法。
摘要由CSDN通过智能技术生成

原标题:Unity Shader内用八叉树实现体素化阴影!

需求描述

unity发展之初主要是满足手游的需求,那时候的需求并未充分考虑开放大场景的技术实现。于是关于阴影的技术方案 shadowmap(实现近处动态物体+静态物体)+shadowmask(实现远处静态物体)+ProbesOcclusion(实现远处动态物体)对于超大场景并不适合。主要有几点原因

shadowmask 不能脱离lightmap独立 导致烘焙很慢

ProbesOcclusion 的数据封装太重,postions是只读的,是绑定场景的,无法方便实现随prefab加载实时修改

probe摆放工作量较大 特别是不规则阴影边界处

lod较多的反复在同一空间产生多分shadowmask较为浪费,(修改uv2 共用shadowmask可避免单个问题)

几乎所有大型mesh数据都因需要uv2而增大不少

鉴于此 unity技术内部 提供了一种 紧凑型阴影 适合越来越被需求的超大场景。论文在这,我这篇是具体的unity实现。

http://www.cse.chalmers.se/~uffe/compactPrecomputedVoxelizedShadows.pdfwww.cse.chalmers.se/~uffe/compactPrecomputedVoxelizedShadows.pdf

八叉树实现与合并

前面为了写这篇 写了二叉树和四叉树。基于我实现的四叉树只要稍改2处就可以实现八叉树了,因为八叉树与四叉树原理完全一致,只多了一倍子节点,改个数组的罢了。因为原理完全一样 不再重复解释,没看原理的请先看四叉树链接

设计一个偏移数组描述3d空间 8个象限 位置偏移

与四叉树相比 就是算索引偏移的时候 多一个维度判断 第三维度+4,8个子节点的数组 总偏移量刚好是0到7.

这样在C# 端调试实现的效果如下

可以看到这时候 实时阴影距离是0.这时候看到的静态对象阴影 和动态球体阴影 都是该体素话八叉树方案实现的。unity默认情况下 lightprobe 很难实现这样清晰的阴影过度除非摆放超密烘焙极慢。

shader内实现

因为短时间内没有像论文那样实现极大的压缩,所以我演示的是如何替换shadowmask与ProbesOcclusion,并非直接代替近处实时阴影(那样需要超高密度) shadowmask 与 ProbesOcclusion的shader实现 unity是放在UnityShadowLibrary.cginc文件 我们加入类似insert查找的8叉树查询法 只是数据存在在贴图_OTreeTex里 而非普通数组中。

uniformsampler2D_OTreeTex;

uniformint_OTreeWidth;

uniformint_unitsPerMeter;

uniformhalf4 _wposOffset;

int4 getTreeValue(uint index) {

returntex2D(_OTreeTex, half2(index %_OTreeWidth, index /_OTreeWidth)

/( half)max(_OTreeWidth, 1));

}

fixedshadowValue(float3 wpos)

{

uint x =wpos.x *_unitsPerMeter +0.5;

uint y =wpos.y *_unitsPerMeter +0.5;

uint z =wpos.z *_unitsPerMeter +0.5;

intindex =0;

intsize =1024*_unitsPerMeter;

[unroll( 30)]

while( 1) {

int4 node =getTreeValue(index);

intflag =node.w %10;

node.w =node.w /10;

if(node.w ==0) return1-flag;

if(size ==1) return1;

intchildIndex =0;

if(x >node.x +size /2)

{

childIndex ++;

}

if(y >node.y +size /2)

{

childIndex +=2;

}

if(z >node.z +size /2)

{

childIndex +=4;

}

index =node.w +childIndex;

size /=2;

}

return1;

}

延迟渲染的 这部分功能是在 这个函数

现在用官方的维京场景测试下效果(一立方米4x4x4个体素),在实时阴影距离

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值