Android 来自 png 文件的 OpenGL ES 2.0 纹理是黑色的

Android OpenGL ES 2.0 textures from png file are black

我的 OpenGL 实现遇到了一个我不明白的问题。 我正在显示一个在 FragmentShader 中组合了三个纹理的 Sprite。如果我使用来自 android 资源的位图作为纹理,一切正常,但如果我使用下载的 png 等价物并从文件系统加载它们,我的纹理只显示黑色。

纹理不是 2 的幂,也不是正方形,但正如我所说,如果我将图像复制到 android 资源,则实现有效,但在现实世界中我需要下载它们。

这是我的代码: 精灵构造函数:

final float[] spriteTextureCoordinates =
{                                               
        1f,  0f,
        1f, 1f,
         0f, 1f,
         0f,  0f
};

mCubeTextureCoordinates = ByteBuffer.allocateDirect(spriteTextureCoordinates.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
mCubeTextureCoordinates.put(spriteTextureCoordinates).position(0);

ByteBuffer dlb = ByteBuffer.allocateDirect(spriteCoords.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);

int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);

shaderProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(shaderProgram, vertexShader);
GLES20.glAttachShader(shaderProgram, fragmentShader);

GLES20.glBindAttribLocation(shaderProgram, 0, "a_TexCoordinate");

GLES20.glLinkProgram(shaderProgram);
mTextureManager.loadDefaultTextures(mActivityContext, true);

开画:

GLES20.glUseProgram(shaderProgram);

mPositionHandle = GLES20.glGetAttribLocation(shaderProgram, "vPosition");

GLES20.glEnableVertexAttribArray(mPositionHandle);

GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);

mTextureUniformHandle0 = GLES20.glGetUniformLocation(shaderProgram, "u_Texture0");
mTextureUniformHandle1 = GLES20.glGetUniformLocation(shaderProgram, "u_Texture1");
mTextureUniformHandle2 = GLES20.glGetUniformLocation(shaderProgram, "u_Texture2");
mTextureCoordinateHandle = GLES20.glGetAttribLocation(shaderProgram, "a_TexCoordinate");

GLES20.glUniform1i(mTextureUniformHandle0, 0);
GLES20.glUniform1i(mTextureUniformHandle1, 2);
GLES20.glUniform1i(mTextureUniformHandle2, 4);

GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureManager.getMapLayerTexture());

GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + 2);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureManager.getRadarTexture(currentImageIndex));

GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + 4);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureManager.getGeoLayerTextureForZoomLevel(zoomStep));

mCubeTextureCoordinates.position(0);
GLES20.glVertexAttribPointer(mTextureCoordinateHandle, mTextureCoordinateDataSize, GLES20.GL_FLOAT, false, 0, mCubeTextureCoordinates);
GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);

mMVPMatrixHandle = GLES20.glGetUniformLocation(shaderProgram, "uMVPMatrix");

GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);

GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);

GLES20.glDisableVertexAttribArray(mPositionHandle);

着色器:

private final String vertexShaderCode =
"attribute vec2 a_TexCoordinate;" +
"varying vec2 v_TexCoordinate;" +
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"void main() {" +
"  gl_Position = uMVPMatrix * vPosition;" +
    "v_TexCoordinate = a_TexCoordinate;" +
"}";

private final String fragmentShaderCode =
"precision mediump float;" +
"uniform sampler2D u_Texture0;" +
"uniform sampler2D u_Texture1;" +
"uniform sampler2D u_Texture2;" +
"varying vec2 v_TexCoordinate;" +
"void main() {" +
"vec4 texel0 = texture2D(u_Texture0, v_TexCoordinate);" +
"vec4 texel1 = texture2D(u_Texture1, v_TexCoordinate);" +
"vec4 texel2 = texture2D(u_Texture2, v_TexCoordinate);" +
"gl_FragColor = mix(mix(texel0, texel1, texel1.a),texel2,texel2.a);"+
"}";

工作纹理加载:

 public  int[] loadTextures(final Context context, int... resIDs)
{
    final int[] textureHandle = new int[resIDs.length];

    GLES20.glGenTextures(resIDs.length, textureHandle, 0);

    for(int i=0; i<textureHandle.length; i++){
        if (textureHandle[i] != 0)
        {
            final BitmapFactory.Options options = new BitmapFactory.Options();
            options.inScaled = false;   // No pre-scaling

            final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resIDs[i], options);

            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[i]);

            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
            GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);

            bitmap.recycle();
        }
        if (textureHandle[i] == 0)
        {
            throw new RuntimeException("Error loading texture.");
        }
    }


    return textureHandle;
}

一个不工作的:

public synchronized int loadNewRadarLayerTexture(Context context, ImageData data) throws IOException {
    int textureID = data.getTextureID();
    if(textureID == 0) {
        final int[] textureHandle = new int[1];
        GLES20.glGenTextures(textureHandle.length, textureHandle, 0);
        textureID = textureHandle[0];
        if (textureID != 0) {
            final BitmapFactory.Options options = new BitmapFactory.Options();
            options.inScaled = false; // No pre-scaling

            File directory = context.getDir(RRD.DIR,
                    Context.MODE_PRIVATE);
            File image = new File(directory, data.getFile());

            Bitmap bitmap = BitmapFactory.decodeFile(image.getPath(),options);

            // Bind to the texture in OpenGL
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);

            // Set filtering
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
            GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
            Log.d("OpenGL","Error:"+GLES20.glGetError());
            bitmap.recycle();
        }
        if(textureID == 0){
            throw new RuntimeException("Error loading texture.");
        }

        data.setTextureID(textureID);

    }
    return textureID;
}

如果我使用第一种方法生成的纹理,一切正常。如果我使用第二种方法,我的整个纹理似乎都是黑色的

阅读本主题时发现错误:Threading textures load process for android opengl game 下载完成后我正在加载纹理。我在正确的线程中,但不是在 onSurfaceChanged 或 onDrawFrame 方法期间,原因是纹理未正确上传。

第一个解决方案是在加载纹理时检查 onDrawFrame,如果没有加载则加载纹理。