Android OpenGL ES 2.0 - 某些设备上的黑色纹理

时间:2013-12-20 18:41:17

标签: android opengl-es textures galaxy-nexus

已解决:原来,我将OpenGL命名纹理传递给着色器而不是活动纹理编号,修复它:

GLES20.glUniform1i(sTextureHandle, 0); // 0 means GLES20.GL_TEXTURE0

UPDATE: glGetError()在调用glTexImage2D()后返回0。所以没有OpenGL标记错误......

我一直在使用OpenGL 2.0进行渲染。

我一直在三星Galaxy Nexus上测试它,并且没有任何纹理错误。我的所有纹理都是2的幂,格式为.png,并存储在No -DPI文件夹中。所有纹理都加载,并使用或不使用alpha完美渲染。

我尝试了三星Galaxy S4和Droid Bionic上的游戏,两者都产生了黑色纹理(有和没有alpha混合)。

我已经在互联网上搜索了同样问题的人,但他们的所有修复都已反映在我的代码中。

我认为它必须与我创建纹理的方式或我的OpenGL设置有关,因为为什么它只适用于Galaxy Nexus?

OpenGL设置:

GLES20.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);    //Black Background
GLES20.glClearDepthf(1.0f);                     //Depth Buffer Setup
GLES20.glEnable(GLES20.GL_DEPTH_TEST);          //Enables Depth Testing
GLES20.glDepthFunc(GLES20.GL_LEQUAL);           //The Type Of Depth Testing To Do
GLES20.glDisable(GLES20.GL_BLEND);
Matrix.orthoM(sProjectionMatrix, 0, 0.0f, width, height, 0.0f, 0.0f, MAX_DEPTH);
Matrix.setLookAtM(sViewMatrix, 0, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f);

// Get the texturing handles
GLES20.glBindAttribLocation(sShaderProgram, 2, "a_tex_coords");
sTexCoordsHandle = GLES20.glGetAttribLocation(sShaderProgram, "a_tex_coords");
sTextureHandle = GLES20.glGetUniformLocation(sShaderProgram, "u_texture");
GLES20.glUseProgram(sShaderProgram);

GLES20.glEnableVertexAttribArray(sPositionHandle);
GLES20.glEnableVertexAttribArray(sColorHandle);
GLES20.glEnableVertexAttribArray(sTexCoordsHandle);

纹理加载代码:

Bitmap bitmap = BitmapFactory.decodeStream(sGame.CONTEXT.getResources().openRawResource(R.drawable.circle));

LAST_TEXTURE_INDEX++;
GLES20.glGenTextures(1, Texture.IDS, LAST_TEXTURE_INDEX);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, IDS[LAST_TEXTURE_INDEX]);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); 
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();

其他纹理尝试(替换GLUtils.texImage2D和位图):

int width = 128;
int height = 128;
ByteBuffer pixelBuffer = ByteBuffer.allocateDirect(width * height * 3).order(ByteOrder.nativeOrder());

for (int y = 0; y < height; y++)
{
    for (int x = 0; x < width; x++)
    {
        pixelBuffer.put((byte) 0x00);
        pixelBuffer.put((byte) 0xFF);
        pixelBuffer.put((byte) 0xFF);
    }
}

pixelBuffer.position(0);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGB, width, height, 0, GLES20.GL_RGB, GLES20.GL_UNSIGNED_BYTE, pixelBuffer);

在渲染之前我称之为:

GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, sTextureIndex);
GLES20.glUniform1i(sTextureHandle, sTextureIndex);

顶点着色器:

attribute vec4 a_position;
attribute vec4 a_color;
attribute vec2 a_tex_coords;
uniform mat4 u_model_view_projection;
varying vec4 v_color;
varying vec2 v_tex_coords;

void main() {
    v_color = a_color;
    v_tex_coords = a_tex_coords;
    gl_Position = u_model_view_projection * a_position;
}

Fragment Shader:

varying vec2 v_tex_coords;
uniform sampler2D u_texture;
void main() {
    vec4 color = texture2D(u_texture, v_tex_coords);
    gl_FragColor = color;
}

为了解决这个问题,我禁用了混合,因为我知道alpha也经常引起头痛。

两种类型的纹理(使用图像或使用像素数据)都适用于我的Galaxy Nexus,但不适用于S4。我不知道这是我的纹理代码是否破碎,或者其他一些OpenGL设置,但我会尝试发布所有相关代码。

1 个答案:

答案 0 :(得分:0)

原来,我将OpenGL命名纹理传递给着色器而不是活动纹理编号,修复它:

GLES20.glUniform1i(sTextureHandle, 0); // 0 means GLES20.GL_TEXTURE0

而不是:

GLES20.glUniform1i(sTextureHandle, sTextureIndex); // sTextureIndex = generated texture ID