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空間然後做縮放處理即可用來文理映射。

最後效果如下:

到這裡就重構了截面處大部分數據了,還有很多應用可以看群里大畫渣的文章 @大畫渣

zhuanlan.zhihu.com/p/72

如果想了解Unity這部分的內容可以看我的Unity渲染編程專欄。

zhuanlan.zhihu.com/p/71


SUMMARY AND OUTLOOK:

在像素著色器里對像素信息重新構建其實是一種很常用的手法,最極端的就是Raymarching演算法,對整個像素全部重定義。這種重定義的方法最大的問題就在於深度等從像素著色器傳來的信息無法使用了。

如果想要使物體之間渲染正確還需要重構深度。

Enjoy it。


NEXT:

todo..


推薦閱讀:
相关文章