已解决:原来,我将 OpenGL 命名纹理传递给着色器而不是活动纹理编号,修复它:
GLES20.glUniform1i(sTextureHandle, 0); // 0 means GLES20.GL_TEXTURE0
更新: 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;
}
片段着色器:
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 设置,但我会尝试发布所有相关代码。