2016-03-07 42 views
0

我寫了這個簡單的着色器紋理覆蓋在另一個(基地)的質感 -如何疊加紋理而不裁剪基礎紋理?

varying highp vec2 textureCoordinate; 
varying highp vec2 textureCoordinate2; 

uniform sampler2D inputImageTexture; 
uniform sampler2D inputImageTexture2; 

void main() 
{ 
    mediump vec4 base = texture2D(inputImageTexture, textureCoordinate); 
    mediump vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2); 

    mediump float ra = (overlay.a) * overlay.r + (1.0 - overlay.a) * base.r; 
    mediump float ga = (overlay.a) * overlay.g + (1.0 - overlay.a) * base.g; 
    mediump float ba = (overlay.a) * overlay.b + (1.0 - overlay.a) * base.b; 

    gl_FragColor = vec4(ra, ga, ba, 1.0); 
} 

問題 - 這個工程除了一個問題。如果重疊圖像小於基本圖像,則重疊圖像的外部區域給出α值爲1.0,即overlay.a == 1.0。由於這個原因,基礎圖像被覆蓋圖像剪切。覆蓋圖之外的區域顯示爲黑色。

我是新來的opengl,並期待它的邊界外,紋理的alpha應該顯示爲0.0?如何修復我的着色器代碼以實現所需的行爲?或者我需要修改我的圖形管道?

編輯頂點着色器如下─

attribute vec4 inputTextureCoordinate2; 

varying vec2 textureCoordinate; 
varying vec2 textureCoordinate2; 

void main() 
{ 
    gl_Position = pos; 
    textureCoordinate = uv; 
    textureCoordinate2 = inputTextureCoordinate2.xy; 
} 
+0

你可以發佈你的頂點着色器代碼嗎? – Swifter

+0

@Swifter:添加了頂點着色器 –

回答

0

我在我的代碼中發現了這個問題。我有

GLES20.glClearColor(0, 0, 0, 1); 

在我的代碼。更改爲 -

GLES20.glClearColor(0, 0, 0, 0); 

修復了這個問題。

也正如@Reet提到的,我改變了我的片段着色器以使用矢量操作進行優化。

void main() 
{ 
    mediump vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2); 

    mediump vec3 col = texture2D(inputImageTexture, textureCoordinate).xyz; 
    col = mix(col, overlay.xyz, overlay.a); 

    gl_FragColor = vec4(col, 1.0); 
} 
1

我期待它的邊界之外,紋理的alpha應顯示爲0.0

你是如何取樣紋理之外其界限?當採樣紋理,UV座標的範圍從0到1,如果座標在該範圍之外,那麼兩件事情之一會發生:

  • 如果GL_CLAMP_TO_EDGE設置,那麼cooridnate會固定(0,1)範圍內,並且您將採樣邊緣像素
  • 如果設置了GL_REPEAT,則將採用座標的小數部分,並且您將在紋理中間的某個位置採樣

有關glTexParameter的更多詳細信息,請參閱the docs

如果您的用例僅僅是覆蓋圖像,也許您應該嘗試編寫一個pixel shader

  • 將視口設置爲基本圖像尺寸並從(-1,1)中繪製一個四邊形。
  • 您的片段着色器現在將在每個像素上操作,稱爲紋素。獲取紋理與gl_FragCoord
  • 樣本的基礎和覆蓋texel例如使用texelFetch
  • 如果紋理像素的覆蓋之外,將疊加層的RGBA值設置爲0

例如

//fragment shader 
uniform ivec2 overlayDim; 
uniform sampler2D baseTexture; 
uniform sampler2D overlayTexture; 

void main() { 
    vec2 texelf = floor(gl_FragCoord.xy); 
    ivec2 texel = (int(texelf.x), int(texelf.y)); 

    vec4 base = texelFetch(baseTexture, texel, 0); 
    vec4 overlay = texelFetch(overlayTexture, texel, 0); 

    float overlayIsValid = float(texel.x < overlayDim.x && texel.y < overlayDim.y); 

    overlay *= overlayIsValid; 

    //rest of code 
} 
1

,如果你品嚐紋理的範圍之外被控制,會發生什麼您使用glTexParameteri()GL_TEXTURE_WRAP_SGL_TEXTURE_WRAP_T設置的值。

在完整的OpenGL中,您可以將值設置爲GL_CLAMP_TO_BORDER,將邊框顏色設置爲alpha值爲0.0的值,然後完成。但是紋理邊框在OpenGL ES 2.0中不可用(該選項在ES 3.2中引入,但不在早期版本中引入)。

做不到這一點,我能想到的兩個選項:

  • 如果你有過的紋理數據的控制,你可以一個一個像素的邊框設置爲透明值。 GL_CLAMP_TO_EDGE然後在範圍之外採樣時爲您提供透明值。
  • 檢查片段着色器中的範圍。

第二種選擇可能看起來像這樣(未經測試),片段着色器代碼:

mediump vec3 col = texture2D(inputImageTexture, textureCoordinate).xyz; 

if (all(greaterThan(textureCoordinate2, vec2(0.0))) && 
    all(lessThan(textureCoordinate2, vec2(1.0)))) 
{ 
    mediump vec3 overlay = texture2D(inputImageTexture2, textureCoordinate2).xyz; 
    col = mix(col, overlay, overlay.a); 
} 

gl_FragColor = vec4(col, 1.0); 

相比於原來的代碼,還要注意使用矢量操作。每當有一種對矢量進行操作的好方法時,它會使代碼更簡單。這也將使GPU的矢量操作更容易優化器的工作。