在某些设备上渲染纹理时(仅确认了galaxy s3 mini),我在纹理上出现了暗区闪烁:
Black Artifacts on Android in OpenGL ES 2
我不允许评论这个帖子(信用不足),但我想澄清解决这个问题的作者:
您能否再解释一下如何使用glTexImage2D()
和glTexSubImage2D()
来解决这个问题?
在代码中我得到了这些行来加载位图:
(如您所见,我使用texImage2D
加载位图,关于gltexImage2D
的Android文档仅提供属性类型但没有解释)
...
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
final Bitmap bitmap = BitmapFactory.decodeResource(
context.getResources(), resourceId, options);
if (bitmap == null) {
if (LoggerConfig.ON) {
Log.w(TAG, "Resource ID " + resourceId + " could not be decoded.");
}
glDeleteTextures(1, textureObjectIds, 0);
return 0;
}
glBindTexture(GL_TEXTURE_2D, textureObjectIds[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
texImage2D(GL_TEXTURE_2D, 0, bitmap, 0);
glGenerateMipmap(GL_TEXTURE_2D);
...
编辑:
尝试按照顶部的链接实现解决方案,但没有运气,同样的闪烁效果, 加载位图的新代码:
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(bitmap.getWidth() * bitmap.getHeight() * 4);
byteBuffer.order(ByteOrder.BIG_ENDIAN);
IntBuffer ib = byteBuffer.asIntBuffer();
int[] pixels = new int[bitmap.getWidth() * bitmap.getHeight()];
bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
for(int i=0; i<pixels.length; i++){
ib.put(pixels[i] << 8 | pixels[i] >>> 24);
}
bitmap.recycle();
byteBuffer.position(0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap.getWidth(), bitmap.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, null);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap.getWidth(), bitmap.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, byteBuffer);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
奇怪行为的图示,请参见图像中间右侧的黑色区域:
(我需要10个声誉才能张贴图片?!?!?)
https://dl.dropboxusercontent.com/u/61092317/blackflickering.jpg
答案 0 :(得分:0)
您引用的另一个问题中的问题似乎是这样:作者在最初加载纹理时指定了MipMaps,并且MipMaps无法正常工作。他可能没有正确使用glTexImage2d
。
他得到的神器是:当纹理单元试图从一个MipMap级别移动到另一个MipMap级别时,那里没有信息,而是渲染了一个空白(显然是黑色)纹理。所以,他的MipMap中至少有一个级别被加载了。
我不确定该作者是否真正妥善解决了他的问题。 OpenGL可以非常具体地说明如何将纹理加载到其中,即使代码中的最小错误也可能导致问题。问题可能只发生在某些平台上,因此您会得到设备出现问题的印象,但它仍然可能是代码。
最好的起点是红皮书:http://www.glprogramming.com/red/chapter09.html
然后:http://www.opengl.org/sdk/docs/man3/xhtml/glGenerateMipmap.xml
您想了解的所有功能都在那里列出。
您的问题中没有回答一些细节。你手动创建自己的MipMaps吗?您是否希望OpenGL自动生成MipMaps?
我建议从一个简单的纹理开始,它具有 no MipMaps,只有一个级别。看看你是否可以做到这一点。如果这可以解决问题,那么就开始使用MipMaps。
对于原始问题,使用glTexImage2D
加载纹理数据或使用glTexSubImage2D
更新纹理数据之间没有完全不同。 glTexImage2D
用于指定纹理(即:纹理的宽度/高度,每个MipMap级别不同),而glTexSubImage2D
用于更新已由glTexImage2D
指定的全部或部分纹理。在第二个例子中,您只需使用新的纹素进行更新。