當游戲中地面的紋理都是重復的時候,會看起來很假,而且影響沉浸感。
很明顯地可以看出來有固定的pattern。這主要是因為每個0~1的tile內的紋理都是完全一樣的,iq提出了兩種方法來改良,使得看起來不會這么有重復感。當然,這兩種技術都會成倍增大采樣的次數,同時也有一些額外的計算,但效果還是不錯的,在能夠承受這種cost的時候還是很值得一用的。
對每個tile使用的紋理進行隨機的翻轉和平移
- 消除每個tile的重復感。這是通過判斷當前所處的tile(這可以利用floor(uv)輕松得到),然后給每個tile一個四維的偽隨機數,xy表示該tile的翻轉方向(即水平和豎直方向上是否要進行mirror),zw表示該tile的平移方向,至此就可以保證每個tile都是不同的了。
上一步的結果有兩個問題,首先是在tile和tile相交處有明顯的接縫問題。這個可以通過算該tile旁邊的三個tiles的采樣結果,然后靠uv的小數部分判斷距離接縫處的距離,并據此來混合四個采樣結果,模糊接縫處使得結果看起來比較自然。何時開始混合邊界可以當成一個參數來調節。
即便模糊了接縫處,還是會有一些殘留的接縫。這些接縫產生的原因是因為我們這種方法會使得uv在tile的邊界處產生很大的跳躍,導致mipmaping的時候也會出現跳躍。解決方法就是傳遞正確的ddx和ddy給tex2D函數,避免uv跳躍即可。
fixed4 texNoTileTech1(sampler2D tex, float2 uv) {float2 iuv = floor(uv)float2 fuv = frac(uv)// Generate per-tile transformation
#if defined (USE_HASH)float4 ofa = hash4(iuv + float2(
0,
0))float4 ofb = hash4(iuv + float2(
1,
0))float4 ofc = hash4(iuv + float2(
0,
1))float4 ofd = hash4(iuv + float2(
1,
1))
#elsefloat4 ofa = tex2D(_NoiseTex, (iuv + float2(
0.5,
0.5))/
256.0)float4 ofb = tex2D(_NoiseTex, (iuv + float2(
1.5,
0.5))/
256.0)float4 ofc = tex2D(_NoiseTex, (iuv + float2(
0.5,
1.5))/
256.0)float4 ofd = tex2D(_NoiseTex, (iuv + float2(
1.5,
1.5))/
256.0)
#endif// Compute the correct derivativesfloat2 dx = ddx(uv)float2 dy = ddy(uv)// Mirror per-tile uvsofa
.zw = sign(ofa
.zw -
0.5)ofb
.zw = sign(ofb
.zw -
0.5)ofc
.zw = sign(ofc
.zw -
0.5)ofd
.zw = sign(ofd
.zw -
0.5)float2 uva = uv * ofa
.zw + ofa
.xy, dxa = dx * ofa
.zw, dya = dy * ofa
.zwfloat2 uvb = uv * ofb
.zw + ofb
.xy, dxb = dx * ofb
.zw, dyb = dy * ofb
.zwfloat2 uvc = uv * ofc
.zw + ofc
.xy, dxc = dx * ofc
.zw, dyc = dy * ofc
.zwfloat2 uvd = uv * ofd
.zw + ofd
.xy, dxd = dx * ofd
.zw, dyd = dy * ofd
.zw// Fetch
and blendfloat2 b = smoothstep(_BlendRatio,
1.0 - _BlendRatio, fuv)return lerp( lerp(tex2D(tex, uva, dxa, dya), tex2D(tex, uvb, dxb, dyb), b
.x),lerp(tex2D(tex, uvc, dxc, dyc), tex2D(tex, uvd, dxd, dyd), b
.x), b
.y)
}
Voronoi分布來劃分和混合空間
這種劃分的好處是混合是發生在Voronoi圖上的,而不是整整齊齊的方格上,看起來可能更加自然。
- 空間劃分。整個空間還是會有若干的tile,但是會在每個tile內隨機生成一個Voronoi點,每個點對應了一個紋理樣式(靠隨機平移來區分)。
- 混合。計算每個像素所在的周圍9個Voronoi點,采樣得到它們的紋理顏色,混合的時候依靠該像素到每個Voronoi點的距離的高斯衰減值作為混合權重,也就是說,距離Voronoi點越近權重越高。與方法一不同,這種方法其實隨時隨地都在混合(方法一的混合只發生在邊界處),因此采用高斯衰減的好處就在于越靠近高斯衰減權重會迅速升高,使得混合不會造成整體非常模糊。最后,還需要對總體混合權重進行一次歸一化,防止顏色失真。
shader代碼——
fixed4 texNoTileTech2(
sampler2D tex, float2 uv) {float2 iuv =
floor(uv);float2 fuv = frac(uv);float2 dx = ddx(uv);float2 dy = ddy(uv);float4 va =
0.0;
float wt =
0.0;
float blur = -(_BlendRatio +
0.5) *
30.0;
for (
int j = -
1; j <=
1; j++) {
for (
int i = -
1; i <=
1; i++) {float2 g = float2((
float)i, (
float)j);
#if defined (USE_HASH)float4 o = hash4(iuv + g);
#elsefloat4 o = tex2D(_NoiseTex, (iuv + g + float2(
0.5,
0.5))/
256.0);
#endiffloat2 r = g - fuv + o.xy;
float d =
dot(r, r);
float w =
exp(blur * d);float4 c = tex2D(tex, uv + o.zw, dx, dy);va += w * c;wt += w;}}
return va/wt;
}
總結
以上是生活随笔為你收集整理的#游戏unity-VR场景漫游#shader之消除纹理重复感的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。