2

我正在 OpenGL ES 3 中尝试使用数组纹理。我正在尝试将不同的纹理渲染到我已经批量渲染的不同立方体上。但立方体只显示为黑色。

我查看了 Logcat 消息并将问题范围缩小到我调用 glTexStorage3D 的时间。这是我收到的消息:

08-14 10:24:00.332 17416-17429/? W/Adreno-ES20: core_glTexStorage3D:265: GL_INVALID_OPERATION

根据文档,错误发生在

如果默认纹理对象当前绑定到目标,则会生成 GL_INVALID_OPERATION。

如果当前绑定到目标的纹理对象已经将 GL_TEXTURE_IMMUTABLE_FORMAT 设置为 GL_TRUE,则会生成 GL_INVALID_OPERATION。

如果目标是 GL_TEXTURE_2D_ARRAY 并且级别大于 ⌊log2(max(width, height))⌋+1,则生成 GL_INVALID_OPERATION。

我检查了这些条件并打印到 logcat:

08-14 10:24:00.332 17416-17429/? D/a﹕immutable is gl false

08-14 10:24:00.332 17416-17429/? D/a:纹理绑定二维数组:0

08-14 10:24:00.332 17416-17429/? D/a:绑定方法后的纹理绑定二维数组:1

08-14 10:24:00.332 17416-17429/? D/a:绑定后不可变是gl false

08-14 10:24:00.332 17416-17429/? W/Adreno-ES20::GL_INVALID_OPERATION

根据日志,前两个条件不匹配。我传递的宽度、高度和级别都是 1,所以第三个条件也不应该匹配。

是什么导致了无效操作错误?另外,无效操作错误是我的黑色纹理的原因,还是不相关?

这是我加载数组纹理的方式:

int width = 1;
int height = 1;
public int generateTextureArray(int res[]) {
    int texArray[] = new int[1];
    int params[] = new int[2];

    GLES30.glGetTexParameteriv(GLES30.GL_TEXTURE_2D_ARRAY, GLES30.GL_TEXTURE_IMMUTABLE_FORMAT, params, 0);
    if (params[0] == GLES30.GL_TRUE)
        Log.d("a", "immutable is gl true");
    else
        Log.d("a", "immutable is gl false");

    GLES30.glGetIntegerv(GLES30.GL_TEXTURE_BINDING_2D_ARRAY, params, 1);
    Log.d("a", "texture binding 2d array: " + params[1]);

    GLES30.glGenTextures(1, texArray, 0);
    GLES30.glBindTexture(GLES30.GL_TEXTURE_2D_ARRAY, texArray[0]);

    if (texArray[0] != 0) {

        GLES30.glGetIntegerv(GLES30.GL_TEXTURE_BINDING_2D_ARRAY, params, 1);
        Log.d("a", "texture binding 2d array after bind method: " + params[1]);

        GLES30.glGetTexParameteriv(GLES30.GL_TEXTURE_2D_ARRAY, GLES30.GL_TEXTURE_IMMUTABLE_FORMAT, params, 0);
        if (params[0] == GLES30.GL_TRUE)
            Log.d("a", "immutable after binding is gl true");
        else
            Log.d("a", "immutable after binding is gl false");

        GLES30.glTexStorage3D(GLES30.GL_TEXTURE_2D_ARRAY, 1, GLES30.GL_RGBA, width, height, res.length);

        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inScaled = false;   // No pre-scaling

        for (int i = 0; i < res.length; i++) {
            Bitmap bitmap = BitmapFactory.decodeResource(surfaceView.getResources(), res[i], options);
            ByteBuffer texBuffer = ByteBuffer.allocateDirect(bitmap.getHeight() * bitmap.getWidth() * 4);
            bitmap.copyPixelsToBuffer(texBuffer);
            texBuffer.position(0);

            GLES30.glTexSubImage3D(GLES30.GL_TEXTURE_2D_ARRAY, 0, 0, 0, i, width, height, 1,
                    GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, texBuffer);

            bitmap.recycle();
        }

        GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D_ARRAY, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);
        GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D_ARRAY, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR);
        GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D_ARRAY, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE);
        GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D_ARRAY, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE);
    } else {
        throw new RuntimeException("Error loading texture");
    }

    return texArray[0];
}
4

1 回答 1

0

可能还有其他事情发生,但您实际上应该从您的呼叫中得到一个GL_INVALID_ENUM错误:glTexStorage3D()

GLES30.glTexStorage3D(GLES30.GL_TEXTURE_2D_ARRAY, 1, GLES30.GL_RGBA,
                      width, height, res.length);

仅支持调整大小的内部格式glTexStorage3D(),这意味着这GL_RGBA不是有效的格式。如果您想要每个组件 8 位,正确的调用是:

GLES30.glTexStorage3D(GLES30.GL_TEXTURE_2D_ARRAY, 1, GLES30.GL_RGBA8,
                      width, height, res.length);

这并不能解释GL_INVALID_OPERATION,但我肯定会尝试解决这个问题,看看它是否能正常工作。

于 2015-08-14T16:50:03.997 回答