OpenGL ES 对纹理存储的无效操作
OpenGL ES invalid operation on texture storage
我正在 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 is generated if the default texture object is curently bound to target.
GL_INVALID_OPERATION is generated if the texture object curently bound to target already has GL_TEXTURE_IMMUTABLE_FORMAT set to GL_TRUE.
GL_INVALID_OPERATION is generated if target is GL_TEXTURE_2D_ARRAY and levels is greater than ⌊log2(max(width, height))⌋+1.
我检查了这些条件并打印到 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﹕ texture binding 2d array: 0
08-14 10:24:00.332 17416-17429/? D/a﹕ texture binding 2d array after bind method: 1
08-14 10:24:00.332 17416-17429/? D/a﹕ immutable after binding is 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];
}
也有可能还有其他事情发生,但您实际上应该从 glTexStorage3D()
调用中收到 GL_INVALID_ENUM
错误:
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
,但我肯定会尝试解决这个问题,看看是否能正常工作。
我正在 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 is generated if the default texture object is curently bound to target.
GL_INVALID_OPERATION is generated if the texture object curently bound to target already has GL_TEXTURE_IMMUTABLE_FORMAT set to GL_TRUE.
GL_INVALID_OPERATION is generated if target is GL_TEXTURE_2D_ARRAY and levels is greater than ⌊log2(max(width, height))⌋+1.
我检查了这些条件并打印到 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﹕ texture binding 2d array: 0
08-14 10:24:00.332 17416-17429/? D/a﹕ texture binding 2d array after bind method: 1
08-14 10:24:00.332 17416-17429/? D/a﹕ immutable after binding is 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];
}
也有可能还有其他事情发生,但您实际上应该从 glTexStorage3D()
调用中收到 GL_INVALID_ENUM
错误:
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
,但我肯定会尝试解决这个问题,看看是否能正常工作。