2014-07-09 51 views
2

如果在片段着色器中混合兩種不同大小的紋理,是否可以將紋理映射到不同的座標?在GLSL中混合不同大小/座標的紋理

例如,如果從下面的兩個圖像融合紋理:

black and white mask imageMatterhorn image

具有以下着色器:

 // Vertex shader 
     uniform mat4 uMVPMatrix; 
     attribute vec4 vPosition; 
     attribute vec2 aTexcoord; 
     varying vec2 vTexcoord; 
     void main() { 
     gl_Position = uMVPMatrix * vPosition; 
     vTexcoord = aTexcoord; 
     } 

     // Fragment shader 
     uniform sampler2D uContTexSampler; 
     uniform sampler2D uMaskTextSampler; 
     varying vec2 vTexcoord; 
     void main() { 
     vec4 mask = texture2D(uMaskTextSampler, vTexcoord); 
     vec4 text = texture2D(uContTexSampler, vTexcoord); 
     gl_FragColor = vec4(text.r * mask.r), text.g * mask.r, text.b * mask.r, text.a * mask.r); 
     } 

(片段着色器替換黑色的白色空間和第二紋理的白色面具)。由於兩個紋理都使用相同的gl_Position和座標(1.0f,1.0f,1.0f,0.0f,0.0f,1.0f,0.0f,0.0f),因此兩個紋理都被映射到視圖中的相同座標:

enter image description here

然而,我的目標是保持原有的質感比:

enter image description here

我想着色器內實現這一目標,而不是glBlendFuncglBlendFuncSeparate,爲了我自己的價值觀融合。

有沒有辦法在GLSL內實現這一點?我有一種感覺,我的混合不同位置座標的紋理頂點的方法被設計破壞...

回答

6

這確實是可能的,但您需要爲掩膜紋理座標獲取2D比例向量。我建議你在CPU上計算它們並通過統一方式將它們發送到着色器,另一種方法是每個頂點甚至每個片段計算它們,但是仍然需要將圖像尺寸傳遞到着色器,因此只需在CPU上執行並添加制服。

要得到那個尺度矢量,你需要一些簡單的數學。你想要做的是尊重掩碼比例,但要對其進行縮放,以便2個比例座標中的一個爲1.0,其他爲<=1.0。這意味着您將看到整個遮罩寬度或高度,而相反的維度將縮小。例如,如果您有1.0x1.0大小的圖像和2.0x1.0大小的蒙版,則縮放矢量將爲(.5,1.0)。

要使用此scaleVector你只需要乘以紋理座標:

vec4 mask = texture2D(uMaskTextSampler, vTexcoord* scaleVector); 

要計算比例矢量試試這個:

float imageWidth; 
    float imageHeight; 
    float maskWidth; 
    float maskHeight; 

    float imageRatio = imageWidth/imageHeight; 
    float maskRatio = maskWidth/maskHeight; 

    float scaleX, scaleY; 

    if(imageRatio/maskRatio > 1.0f) { 
     //x will be 1.0 
     scaleX = 1.0f; 
     scaleY = 1.0f/(imageRatio/maskRatio); 
    } 
    else { 
     //y will be 1.0 
     scaleX = imageRatio/maskRatio; 
     scaleY = 1.0f; 
    } 

注意我沒有嘗試這個代碼,所以你可能需要玩一下。

編輯:縮放的紋理座標固定

上述紋理座標的尺度使得掩模紋理使用的左上部分,而不是中心部的。座標必須圍繞中心縮放。這意味着,從中心,這是vTexcoord-vec2(.5,.5)然後擴展這個載體,並從中間加回得到原始載體:

vec2 fromCentre = vTexcoord-vec2(.5,.5); 
vec2 scaledFromCenter = fromCenter*scaleVector; 
vec2 resultCoordinate = vec2(.5,.5) + scaledFromCenter; 

你可以把它變成一條線,甚至儘量縮短一點(做對本文首先)。

+0

太棒了,謝謝!這讓我走上了正確的軌道 - 使用vec2變量進行縮放非常簡單,現在我正在管理掩碼的位置。 –

+0

哦,是的,我忘了那個部分,現在你已經在左邊了......你需要將它標準化。讓我編輯。 –

+1

試試這個編輯,我希望它是正確的......並且不要改變位置,那些應該與目標相同。另請注意,您可以在頂點着色器中進行縮放,並在片段着色器中爲掩碼添加另一個紋理座標。 –