2011-08-17 9 views
8

저는 Android 용 OpenGL ES 2.0을 사용하는 법을 배우고 있습니다. 화면의 중간에 텍스처를 단순히 표시하려고 시도했지만 충분하지는 않지만 PNG 알파가 제대로 작동하는 것처럼 보일 수 없습니다. 이미지는 검은 색 배경으로 표시되거나 내가 사용하는 설정에 따라 전체 이미지가 배경색으로 약간 혼합됩니다.OpenGL ES 2.0 PNG 알파 채널

실제로이 튜토리얼은 투명성으로 작업 한 적이 없으므로 주변을 검색하여 찾은 코드에서 작업하려고 시도했으며 한 가지 중요한 단계를 놓쳤을 가능성이 큽니다. 그래도이 문제를 파악하기 위해 많은 노력을 기울였으며 설치 프로그램에없는 답변을 보지 못했습니다. 나는 glBlendFunc의 모든 조합을 시도했지만 행운을 얻지 못했습니다.

내가 관련이있을 수있는 모든 코드를 붙여 넣으려고하면 질문이 너무 부풀어 오르는 것처럼 보였으므로 여러분이 요청하는 코드를 게시하게되어 기쁩니다. 나는 다음에 시도해야 할 것에 대한 어떤 아이디어라도 크게 감사 할 것입니다.

EDIT :: 여기 내 조각 쉐이더가 원인이라고 생각합니다. 이 부분 만 제가 투명성을 다루기위한 훌륭한 예를 찾지 못했고 다른 모든 것들은 제가 다른 곳에서 본 것과 일치합니다.

 final String fragmentShader =   
     "precision mediump float;  \n" 
     + "varying vec2 v_Color;   \n"  
     + "uniform sampler2D s_baseMap; \n" 
     + "void main()     \n"  
     + "{        \n" 
     + " vec4 baseColor;    \n" 
     + " baseColor = texture2D(s_baseMap, v_Color); \n" 
     + " gl_FragColor = baseColor;  \n"  
     + "}        \n"; 

그것은 명시 적으로 알파 무엇이든, 그것은 결국 그것을 사용하지 않는 예에서입니다하지 않을하지만 보였다 때문에 난 아직도 조각 쉐이더에 대해 많이 알고하지 않습니다에 "일종의" 배경으로 이미지를 혼합 할 때 작동합니다. 알파와 함께 작동하고있는 것으로 보았습니다. 잘못된 설정이있었습니다.

EDIT :: 다음은 "loadTexture"방법입니다. OpenGL ES 2.0 책의 예제에서 배우려는 내용과 거의 비슷합니다. 이미지를 올바르게 작동시키는 몇 가지 변경 사항이 있습니다.

private int loadTexture (InputStream is) 
{ 
    int[] textureId = new int[1]; 
    Bitmap bitmap; 
    bitmap = BitmapFactory.decodeStream(is); 
    byte[] buffer = new byte[bitmap.getWidth() * bitmap.getHeight() * 4]; 

    for (int y = 0; y < bitmap.getHeight(); y++) 
     for (int x = 0; x < bitmap.getWidth(); x++) 
     { 
      int pixel = bitmap.getPixel(x, y); 
      buffer[(y * bitmap.getWidth() + x) * 4 + 0] = (byte)((pixel >> 16) & 0xFF); 
      buffer[(y * bitmap.getWidth() + x) * 4 + 1] = (byte)((pixel >> 8) & 0xFF); 
      buffer[(y * bitmap.getWidth() + x) * 4 + 2] = (byte)((pixel >> 0) & 0xFF); 
     } 

    ByteBuffer byteBuffer = ByteBuffer.allocateDirect(bitmap.getWidth() * bitmap.getHeight() * 4); 
    byteBuffer.put(buffer).position(0); 

    GLES20.glGenTextures (1, textureId, 0); 
    GLES20.glBindTexture (GLES20.GL_TEXTURE_2D, textureId[0]); 

    GLES20.glTexImage2D (GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, bitmap.getWidth(), bitmap.getHeight(), 0, 
          GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, byteBuffer); 

    GLES20.glTexParameteri (GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); 
    GLES20.glTexParameteri (GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); 
    GLES20.glTexParameteri (GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); 
    GLES20.glTexParameteri (GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); 

    return textureId[0]; 
} 

나는 코드가 무엇을하고 있는지 이해하지만 틀림없이 여전히 때문에 내 지식의 부족으로 나에게 그래서 난 그냥 뭔가를 분명 누락 될 수 있습니다 약간의 혼란.

나는 내가 가지고있는 문제의 원인이 될 수있는 것처럼 보이는 내 코드의 다른 부분을 보지 못한다. 그러나 프로그래밍은 항상 예기치 못한 (특히 OpenGL의 세계에서는) 것으로 보인다. 뭔가 다른 것이 내가 당신을 위해서도 게시 할 수있는 원인이라고 생각하십시오. 모든 문제에 대한 유감!

+0

RGB 이미지를로드하거나 RGB 텍스처를 만드는 대신 이미지를 텍스처에로드 할 때 PNG의 알파 채널이 유지되는지 확인하십시오. 물론 올바른'glBlendFunc'를 설정하는 것 외에도'glEnable (GL_BLEND)'를 호출해야합니다. 그러나 일부 코드는 반드시 도움이 될 것입니다. 어쩌면 이미지로드 및 텍스처 생성 코드와 블렌딩 상태를 설정하는 코드 일 수 있습니다. 물론 여기에 새로 온 사람이라면 수락 및 상향 투표 기능에 대해 자신에게 알리는 것을 잊지 마십시오. –

+0

프래그먼트 쉐이더는 텍스처의 알파를 프래그먼트 색상에 올바르게 위임하므로 유효합니다. 따라서 로딩 및 텍스처 생성 코드를 게시하지 않아도됩니다. –

+0

블렌딩이 비활성화 된 상태에서'gl_FragColor = vec4 (baseColor.aaa, 1.0)'을 시도해 볼 수 있습니다. 이렇게하면 알파 채널의 회색 음영 이미지가 나타납니다. – trenki

답변

3

블렌딩 함수로 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)을 사용하고 질감의 알파 값을 gl_FragColor 조각 쉐이더 출력 변수에 쓰는 것이 가장 좋습니다.

업로드 된 모든 텍스처 데이터에는 알파 값이 있어야하며 알파 채널 (RGBA, RGBA8 등)을 지원하는 텍스처 형식을 사용해야합니다.

알파 값을 RGB 색상 구성 요소로 라우팅하고 얻은 이미지를 검사하여이를 확인할 수 있습니다.

편집 : 이미지 로딩 코드에서

당신은 알파 채널을 통해 복사하는 것을 잊지! davebytes이주는 제안을 시도하십시오.

+0

glBlendFunc에서 해당 설정을 사용하면 이미지가 전혀 표시되지 않습니다. glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA)는 나에게 가장 잘 맞거나, 최소한 작업에 가장 가깝다. 이미지가 배경에 혼합되면 이미지의 투명한 부분도 제거되는 것처럼 보일 것입니다. 나는 아직 그것에 대해 많이 알지 못하고 대부분 투명도를 사용하지 않는 예제의 코드 사본이므로 조각 문제 셰이더에 내 문제가 있다고 생각합니다. 나는 그것을 메인 포스트에 게시 할 것이다. – DaeKo

1

초기 쉐이더가 정상입니다. 알파는 컬러 연산에 내재되어 있기 때문에 블렌드/모드/등에 따라 적용되지 않을 수 있습니다.

fragcolor = base.aaa하면 텍스처가 검은 색으로 표시되어 텍스처 데이터가 '불량'임을 의미합니다.

텍스처로드를 보면 예, 잘못되었습니다. 당신은 alpha, rgb를 복사하지 않습니다. java가 바이트 배열을 0으로 초기화한다고 가정하면 모든 알파는 0이 될 것이고, 알파 블렌딩을 활성화하면 이미지가 '사라질'수있는 블랙 박스가 생깁니다.

은 당신의 인생을 단순화하기 위해 대신 모든 손 복사 및 물건, 당신은 단순히 일반적으로 비트 맵을로드하고 대신 직접 glTexImage2d를 사용하는 업로드 할 GLUtils 도우미를 사용할 수 있습니다 그런

bitmap = BitmapFactory.decodeStream(is); 
    GLES20.glGenTextures (1, textureId, 0); 
    GLES20.glBindTexture (GLES20.GL_TEXTURE_2D, textureId[0]); 
    GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0); 

뭔가. 그런 다음 블렌딩을 사용하고 미리 곱셈되지 않은 경우 src + invsrc 블렌드 모드를 사용하고 렌더링하면 원하는 결과가 얻어야합니다.

9

for (int y = 0; y < bitmap.getHeight(); y++) 
    for (int x = 0; x < bitmap.getWidth(); x++) 
    { 
     int pixel = bitmap.getPixel(x, y); 
     buffer[(y * bitmap.getWidth() + x) * 4 + 0] = (byte)((pixel >> 16) & 0xFF); 
     buffer[(y * bitmap.getWidth() + x) * 4 + 1] = (byte)((pixel >> 8) & 0xFF); 
     buffer[(y * bitmap.getWidth() + x) * 4 + 2] = (byte)((pixel >> 0) & 0xFF); 
     buffer[(y * bitmap.getWidth() + x) * 4 + 3] = (byte)((pixel >> 24) & 0xFF); 
    } 

로 변경

for (int y = 0; y < bitmap.getHeight(); y++) 
    for (int x = 0; x < bitmap.getWidth(); x++) 
    { 
     int pixel = bitmap.getPixel(x, y); 
     buffer[(y * bitmap.getWidth() + x) * 4 + 0] = (byte)((pixel >> 16) & 0xFF); 
     buffer[(y * bitmap.getWidth() + x) * 4 + 1] = (byte)((pixel >> 8) & 0xFF); 
     buffer[(y * bitmap.getWidth() + x) * 4 + 2] = (byte)((pixel >> 0) & 0xFF); 
    } 

당신은 텍스처를 그릴 직전 단순히

GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA); 
GLES20.glEnable(GLES20.GL_BLEND); 

를 추가 알파 정보를 포함합니다. 완료되면 GL_BLEND를 비활성화하는 것을 잊지 마십시오.