2014-07-08 4 views
1

GLES20을 사용하는 GLSurfaceView에서 블렌딩 효과를 구현하려고합니다.마스크를 사용한 예기치 않은 텍스처 블렌딩 결과

보기에는 색상 (빨간색) 배경이 있으며 그 위에 마스크 텍스처와 알파 채널이있는 이미지 텍스처가 블렌드됩니다. 여기

은 예시 마스크 이미지이다 :

black and white image with shapes, picture of Android mascot with transparent background

예상 결과 : OpenGL - mask with multiple textures

: 여기 Android image with partly invisible parts on a red background

지금까지 날 안내 유사한 문제이며

불행히도 나는 비슷한 r을 얻을 수 없었다. esult. 내 onDraw() 메서드의 관련 부분은 다음과 같습니다.

// Bind default FBO and use shader program 
glBindFramebuffer(GL_FRAMEBUFFER, 0); 
glUseProgram(program); 

// Set the vertex attributes 
glVertexAttribPointer(texCoordHandle, 2, GL_FLOAT, false, 0, mTexVertices); 
glEnableVertexAttribArray(texCoordHandle); 
glVertexAttribPointer(posCoordHandle, 2, GL_FLOAT, false, 0, mPosVertices); 
glEnableVertexAttribArray(posCoordHandle); 

// Clear the buffer color - draw red color background 
glClear(GL_COLOR_BUFFER_BIT); 

// Apply transformation - irrelevant 
glUniformMatrix4fv(mvpMatrixHandle, 1, false, matrix, 0); 

// Bind the mask texture for drawing 
glUniform1i(contentTextureHandle, 0); 

glBindTexture(GL_TEXTURE_2D, textures[MASK_TEX]); 

// Write alpha value 1.0 to white regions and 0.0 to black - don't change the RGB values 
glBlendFuncSeparate(
    GL_ZERO,  // remove the source rgb colors 
    GL_ONE,  // keep the destination rgb colors 
    GL_SRC_COLOR, // !! put high alpha (1.0) where image is white 
    GL_ZERO);  // remove destination alpha 

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 

// Bind the content image 
glBindTexture(GL_TEXTURE_2D, textures[CONTENT_TEX]); 

// Change the blend function to write the regions with low alpha 
glBlendFuncSeparate(
    GL_ONE_MINUS_DST_ALPHA, // black regions (alpha 0): keep src rgb, white regions: remove src rgb 
    GL_DST_ALPHA,   // black regions: remove dst rgb, white regions: keep dst rgb 
    GL_ONE_MINUS_DST_ALPHA, // black regions: keep src alpha, white regions: remove src alpha 
    GL_DST_ALPHA);   // black regions: remove dst rgb, white regions: keep dst alpha 

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 

그러나 이러한 혼합 함수를 결합한 결과 빨간색 배경 만 생성됩니다.

나는 이틀 동안 모든 종류의 기능을 시험해 보았지만 위의 사항이 옳다고 생각한다.

test android image on top of black and white image mask

위의 블렌딩 기능의 나의 선택은 : 또한, 디버깅하는 동안 내가 대신 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);을 시도하고 두 이미지가 서로의 상단에 표시 (예 : 텍스처 또는 GL 설정에 아무 문제가 없다) 추정에 기초 funcSeparate 계산 공식 있음 :

Orgb = srgb *Srgb + drgb * Drgb 
Oa = sa * Sa + da * Da 

O : 출력이야 - 소스, D - 대상 나머지 glBlendFuncSeparate (SRGB, Drgb, SA, 다) 발 PARAMS있다

,691 363,210


예상 또는 얼마나 원하는 결과를 달성하기 위해 같은 텍스처가 조화하지 않는 이유가 뭘까요? 내가 미리 곱셈 비트 맵을 사용하고

"precision mediump float;\n" + 
    "uniform sampler2D tex_sampler;\n" + 
    "uniform sampler2D mask_sampler;\n" + 
    "varying vec2 v_texcoord;\n" + 
    "void main() {\n" + 
    " vec4 mask = texture2D(mask_sampler, v_texcoord);\n" + 
    " vec4 text = texture2D(tex_sampler, v_texcoord);\n" + 
    " gl_FragColor = vec4(text.r * (1.0 - mask.r), text.g * (1.0 - mask.r), text.b * (1.0 - mask.r), text.a * (1.0 - mask.r));\n" + 
    "}\n"; 

참고 :

내가 레토 Koradi의 조언을 따라 내 조각 쉐이더 내부의 혼합을 통합를 해결



블렌드 기능 .glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA).

반전 된 색상의 마스크 (예 : 검정색 대신 흰색 영역의 질감 표시)로 전환하여 (1.0 - mask.r) 부분을 줄이려고합니다.

정확하게 두 개의 텍스처 결합 (glActiveTexture 및 glUniform1i)을 얻는 것이 조금 까다 롭지 만 온라인에서 수행하는 방법에 대한 정보는 충분합니다.

답변

1

귀하의 해결책은 혼합 기능의 일부로 알파 성분에 어떻게 영향을 미치는지에 대한 오해에 근거한 것 같습니다. GL_SRC_COLOR은 소스 색상의 RGB에 대해 소스 색상의 (R, G, B)을 사용하고 소스의 A에 대한 소스 색상의 A을 배율로 사용합니다. 따라서 소스 부분의 경우 각 구성 요소의 사각형이됩니다.

glBlendFuncSeparate(GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ZERO); 

알파 성분에 적용되는 GL_SRC_COLOR는 승수와 소스 색상의 알파 값을 사용

그래서이 혼합 기능을 사용할 때.

glBlendFuncSeparate(GL_ZERO, GL_ONE, GL_SRC_ALPHA, GL_ZERO); 

그것은 당신의 마스크 텍스처의 알파처럼 보이는 당신이 혼합 기능을 사용하여 마스크 텍스처를 렌더링 할 때 알파 값이 모든 1.0로 설정되어 있음을 의미하는 상수 1.0입니다 :이 혼합 방정식은 동일합니다. 그런 다음, 당신의 안드로이드 텍스처를 렌더링하면 블렌드 방정식이 대상 알파가 1.0 인 모든 픽셀에 대해 기존 내용을 유지하도록 설정되어 있기 때문에 그 중 아무 것도 나타나지 않습니다.

이 문제를 해결하려면 마스크 텍스처 렌더링의 알파 출력이 적용하려는 마스크 값을 나타내는 지 확인해야합니다. 알파 자체에 마스크 값을 포함하도록 텍스처 자체를 변경하여이 작업을 수행 할 수 있습니다. 그러나 ES 2.0이 모두 쉐이더를 기반으로하므로, 조각 쉐이더에서 이것을 매우 쉽게 처리 할 수 ​​있습니다. 현재 당신의 조각 쉐이더에서이 같은 뭔가를 말 :

이 마스크 텍스처가 흑백
vec4 texVal = texture2D(...); 
gl_FragColor = texVal; 

때문에, 당신은 출력 알파로 색상 값을 사용할 수 있습니다. 이 렌더링 단계의 컬러 출력을 사용하지 않으므로 이러한 구성 요소는 무엇이든 될 수 있습니다. 우리가 0.0에 그들을 떠날 경우, 다음과 같이 수 : LibGDX texture blending with OpenGL blending function : 무슨 일을 끝낼 것이 나는 최근 관련 질문에 준 대답 유사한 것으로 밝혀

vec4 texVal = texture2D(...); 
gl_FragColor = vec4(0.0, 0.0, 0.0, texVal.r); 

. 가장 큰 차이점은 별도의 블렌드 기능을 사용하는 동안 마스크를 렌더링하는 동안 색상 출력을 억제하기 위해 컬러 마스크를 사용하는 것이 좋습니다.

+0

감사합니다. 귀하의 제안을 살펴 보겠습니다. 그러나 나는 처음 두 함수가 같지 않다고 생각한다 (내가 게시 한 다른 질문에 대한 링크 참조). 내가 이해하는 한, funcSeparate (0, 1, GL_SRC_COLOR, 0)는 흰색을 가진 영역에 대해서는 알파 1을 그리고 검은 색 영역에 대해서는 알파 0을 넣지만 (0, 1, GL_SRC_ALPHA, 0) 전체 이미지에 대해 알파 1을 넣는다 . 즉, 첫 번째 함수가 정확합니다. –

+1

레드 북에 따라 다르지 않습니다. 표 6.1을 http://www.glprogramming.com/red/chapter06.html에서 확인하십시오. 테이블의'GL_SRC_COLOR'와'GL_SRC_ALPHA' 엔트리의 경우 알파의 인수는 두 경우 모두에서 'As'입니다. 공식 OpenGL 사양도 똑같은 말을하고 있습니다. OpenGL 3.3 핵심 프로파일 사양의 표 4.2 (예 : 205 페이지)를 확인하십시오. 이것은 "Alpha Blend Factor"컬럼에서 GL_SRC_COLOR와 GL_SRC_ALPHA와 같은 값을가집니다. –

+0

대단히 고맙습니다. 조각 쉐이더를 설정하여 목표를 달성 할 수있었습니다. 두 텍스처를 함께 사용하려면 시간이 걸렸습니다. OpenGL Red Book은 훌륭한 참고 자료입니다! 나는 OpenGL에서 두 권의 책을 사서 나에게 도움이되지 않았고 유익한 반이다. –