前言


jackie:unity 实现超精简版VirturalTexturezhuanlan.zhihu.com


unity 默认管线如何录制透明底图片 unity透明通道_unity透明通道加颜色


之前实现了 基础版功能,没看过的先看下上面这链接。但和市面上常见的做法一样 有个很大限制,就是只能混合2层。如果用这种方式去混合三层是会出各种问题的原因还是因为 跨id 插值了权重。既然当初专栏名称就是造轮子,又有公司的项目真实需求(路在泥土上,路的边缘上刷细节一定会横跨路面和泥土实现3层或以上混合)。同时又没查到这种做法。于是忍不住半夜研究了起来。

效果图


unity 默认管线如何录制透明底图片 unity透明通道_图层_02

常见2图层混合 或跨id插值3层混合 会出现的 3层过渡区错乱问题


unity 默认管线如何录制透明底图片 unity透明通道_unity透明通道加颜色_03

该方案只多采样一次的情况下很好的解决了3层混合效果

思路分析

要测底解决跨id 插值权重问题,最好类似unity terrain自带的 alphamapTextures 一样组织,每个id的权重独立一个颜色通道,所以 16图层需要4张权重图,合并成图集的代码很简单,同样能用数组的这里建议也用数组


unity 默认管线如何录制透明底图片 unity透明通道_unity透明通道加颜色_04

把unity的 alphamap 合并成图集

unity 默认管线如何录制透明底图片 unity透明通道_unity透明通道加颜色_05

alphamap合并图集后效果

这样每个id的权重占一个颜色通道 这是符合默认bilinear插值采样的。 下面来获得 3层权重。我们r通道混合的最多 所以 我们不通过贴图获得具体数值,而通过 1-g-b计算获得r的权重。这样做有2个好处 1少采样一次性能更好,2 有些地方实际混合了3层以上 这样计算就会把丢失的一小部分算作混合最重的层 这样对画面改动较小。核心代码如下


float


getChannelValue 就是一个 根据下标动态获取 rgba 分量的函数封装。我不明白为什么 不能像c语言一样 对一个 float4的struct 可以直接用[0] 取R,[1]取G,当然常量是可以这样获取的 编译器不能确定的变量 他就会报错,其实我想了下 这个数学逻辑很好实现 但默认没封装。我就自己写了一个。

法线的混合 就取最重要的2层够了 3种半透明区域内法线已经减弱了。

所以只比基础2层混合 多2次采样就实现了3层混合(3层满足绝大部分高要求的游戏了)性能依然可接受,如果你策划可妥协 或mmo手游 建议采样基础版方案