MY BLOG DIRECTORY:
YivanLee:专题概述及目录zhuanlan.zhihu.com
INTRODUCTION:
我们有时候需要对模型的数据进行重建来完成一些需求,比如在模型上挖洞,做瓶子中的水,在模型面数很低的情况下对模型的结构进行改变,这时就需要在像素着色器中重建模型数据。
MAIN CONTENT:
【1】对像素数据进行切割
模型像素数据重建这个事情可以分为很多方法,对像素数据进行切割就是最基础的方法。对像素切割其实非常简单,就是控制是否clip掉像素,所以使用mask模式控制OpacityMask就能控制clip的阈值从而对模型进行切割。
下面是使用一个球形的SDF函数进行切割。
之前做Ray marching的时候就有接触过SDF,因此我们可以组合多个球形场来切割,不仅仅是一个。
平面切割:
其实还有很多种切割方式,我这里只抛砖引玉。下面演示下在Unreal中组合切割模型的SDF
效果如下:
材质节点:
CustomNode的代码:
#define LEN(X) length(SphereArray[X].xyz-WorldPos)-SphereArray[X].w
float CalcSDF(in float4 LocA, in float4 LocB, in float4 LocC, in float4 LocD, in float3 WorldPos)
{
float Ret = 0;
float4 SphereArray[4] = { LocA, LocB, LocC, LocD };
Ret = min(min(min(LEN(0), LEN(1)), LEN(2)), LEN(3));
return Ret;
}
//Retrun code
//return CalcSDF(LocA, LocB, LocC, LocD, WorldPos);
这个CustomNode被我魔改过,魔改方法在材质编辑器篇里有讲解。
【2】重构像素法线数据
我们切割好了模型,下面需要对切割过的模型进行数据重建,在重建前,我们还能从像素着色器里挖信息出来。
TwoSideSign可以得到像素在TwoSide模式下是正向还是反向的,由此就可以区分切割剩下的像素的正反信息。
用这个信息就可以重构法线数据了
但是TwoSideSign对Shader Modle的版本有严格限制。不是所有版本都能用的。
重构了法线之后就可以对切割截面进行正常的光照计算了
【3】重构像素位置坐标和UV数据
上面只是重构的法线数据,现在我们需要重构位置数据
位置数据的重构方法也非常简单,就是找一个规则重构其顶点位置信息,这里我假设一个横截面截断了这个模型,所以我需要把背面像素的位置信息全部沿视角方向投射到截面位置。
float2 InteractPane(in float PaneHeight, in float3 V, in float3 WorldPos)
{
float2 Ret = float2(0, 0);
float t = 0;
float3 ro = WorldPos;
float3 rd = V;
float3 P0 = float3(0, 0, PaneHeight);
float3 N = float3(0, 0, 1);
t = max(dot((P0 - ro), -N) / dot(rd, -N), 0);
Ret = (ro + rd * t).xy;
return Ret;
}
//return InteractPane(PaneHeight, V, WorldPos);
用摄像机到像素的射线和平面求交即可得到新的像素位置。
因为这时平面截面,所以只需要把位置数据做空间转换到local空间然后做缩放处理即可用来文理映射。
最后效果如下:
到这里就重构了截面处大部分数据了,还有很多应用可以看群里大画渣的文章 @大画渣
https://zhuanlan.zhihu.com/p/72821343
如果想了解Unity这部分的内容可以看我的Unity渲染编程专栏。
https://zhuanlan.zhihu.com/p/71986075
SUMMARY AND OUTLOOK:
在像素着色器里对像素信息重新构建其实是一种很常用的手法,最极端的就是Raymarching算法,对整个像素全部重定义。这种重定义的方法最大的问题就在于深度等从像素着色器传来的信息无法使用了。
如果想要使物体之间渲染正确还需要重构深度。
Enjoy it。
NEXT: