2011-07-03 132 views
6

這很長,但我保證它很有趣。 :)在GLSL中混合多個紋理

我試圖模仿使用jMonkeyEngine的另一個應用程序的紋理的外觀。我有一個頂點列表和構成「景觀網格」的面(三角形),它應該具有7-15種不同紋理(取決於「景觀」的地形)。每個三角形都有一個與之關聯的紋理代碼,表示特定三角形應該主要由哪個紋理組成。當然,紋理應該在每張臉之間平滑融合。

所以我試圖制定一個策略,允許這(它不利用預先製作的alpha地圖png文件,紋理alphas需要在運行時完成)。現在我想象一下,如果我計算每個頂點(頂點着色器)中每個紋理的「強度」 - 通過考慮所有相鄰面的地形類型(不確定如何去做) - 我應該能夠根據像素距頂點的距離來設置alpha值。生成的'alpha map'將被frag着色器用於混合每個像素的每個紋理。

這是否可行?或者我應該看看完全不同的策略?我有我試圖模仿應用的着色器代碼(但他們是HLSL和我使用GLSL),但似乎他們正在做的其他地方這種混合步:

sampler MeshTextureSampler = sampler_state { Texture = diffuse_texture; AddressU = WRAP; AddressV = WRAP; MinFilter = LINEAR; MagFilter = LINEAR; }; 

我不知道這個HLSL「MeshTextureSampler」是什麼,但它看起來像這個應用程序可能根據需要預先混合了所有的紋理,並基於面部/地形代碼數據爲整個網格創建了單個紋理。在像素/片段着色器的所有,他們似乎真的做的是這樣的:

float4 tex_col = tex2D(MeshTextureSampler, In.Tex0); 

之後,它只是陰影,燈光,等等 - 沒有那種紋理混合在所有據我所知,這使我相信這種紋理混合工作是事先在CPU上完成的,我想。歡迎任何建議。

+0

+1爲您的第一句話。 –

回答

3

如果我理解正確的話,這裏是我的第一個鏡頭是:

你的問題是,或多或少,如何在頂點你對你的每面值分發。這實際上類似於網格上的正常生成:首先,您將爲每個三角形生成一個法線,然後根據每個頂點計算它們。谷歌「正常的一代」,你會到達那裏,但這是主要的。對於每個相鄰的三角形,找到一個加權因子(通常是使用頂點的角,或者三角形的表面積或其組合),然後將該值(不論是正常還是「強度」)相加按權重因子計算得出總計結果。正常化,你就完成了。

那麼你有你的紋理「優勢」,你可以發送到你的頂點着色器。現代的解決方案是使用字符並在像素着色器中對紋理陣列進行採樣,然後將混合值稍微混淆一點以便更好地傳輸。

所以,如果我沒有得到你的問題:

預處理:

forearch vertex in mesh 
    vertexvalue = 0 
    normalization = 0 
    foreach adjacent triangle of vertex 
     angle = calculateAngleBetween3Vertices(vertex,triangle.someothervertex,triangle.theotherothervertex) 
     vertexvalue += triangle.value * angle 
     normalization += angle 
    vertexvalue/=normalization 

渲染時間:

管每個頂點的fragmentshader的值(一個或多個),併爲此在片段着色器:

basecolour = 0; 
foreach value  
    basecolour = mix(basecolour, texture2D(textureSamplerForThisValue,uv), value) 
    //this is simple, but we could do better once we have this working 

或者,您也可以仔細觀察在你的幾何體。如果你有一個大三角形和小三角形的組合,你將有不平等的數據傳播,並且由於你的數據是每個頂點,所以你會得到更多的細節,這是更多的幾何。在這種情況下,您可能會想要做其他人正在做的事情,並使用混合貼圖將您的紋理與幾何體分離。這些可能是低分辨率,不應該增加您的內存消耗或着色器執行時間。

+0

我卡在哪裏通常是「對於每個相鄰的三角形,找到一個加權因子......」 - 我會在哪裏做到這一點,以及如何從着色器內部訪問它?仍然很難想象這一點。 – Manius

+0

你沒有。這只是預處理階段(您的值在渲染時是靜態的,對吧?)。每個三角形的權重係數應爲1,這是一件高質量的事情。否則,您可以將其作爲接觸頂點的三角形角的角度。然後,頂點處的值變成FOREACHN值+ = angle_of_triangle * value_at_triange –

+0

我只是想到了一個可能的解決方案,但是再次閱讀它我認爲它基本上與您所建議的相同(請參閱圖)。我想我會嘗試爲每個頂點傳遞'加權'alpha值(每個紋理),並將frag着色器中的值用作紋理alpha。 (這是你說的嗎?)我很難確定如何用jMonkeyEngine做到這一點,但我希望我可以將這些數據作爲頂點屬性傳遞給「texCoordX」頂點緩衝區類型。 (有點jME特定的東西那裏。)如果這個工作,使用面積/角度來計算權重,你建議只是可以做的伎倆... – Manius