在我的应用程序中,我使用GLSurfaceView显示二维背景图像,该图像根据显示的内容而变化。该图像用作在与电话屏幕具有相同宽高比的简单矩形上渲染的纹理。当背景改变时,它呈现α混合过渡效果。如果设备不支持Open GL ES 2.0,则使用静态图像。 (附加信息:图像/纹理不是正方形,不是2的幂的大小)
有些客户报告某些设备(例如LG E455)的背景变白,导致应用程序无法使用,因为顶部显示的文字也是白色。我一直在寻找问题的解决方案,但找不到任何东西。
因为我在没有广告的情况下免费提供应用程序(我认为广告不符合应用程序)而且我没有获得外部资金,所以我不能购买有问题的设备(LG E455) - 如它是一个旧设备 - 仅用于调试这个问题。
我使用以下代码加载纹理:
int getTexture(GL10 gl, int index) {
if (BackgroundRenderer.this.textures[index] == 0) {
gl.glGenTextures(1, BackgroundRenderer.this.textures, index);
gl.glBindTexture(GL10.GL_TEXTURE_2D, BackgroundRenderer.this.textures[index]);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
Bitmap bitmap = ResourceStore.getBackgroundBitmap(index);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
}
return BackgroundRenderer.this.textures[index];
}
版本检查和初始化:
private static boolean supportsOpenGLES2(Context context) {
ActivityManager activityManager = (ActivityManager)
context.getSystemService(Context.ACTIVITY_SERVICE);
ConfigurationInfo configurationInfo =
activityManager.getDeviceConfigurationInfo();
return configurationInfo.reqGlEsVersion >= 0x20000;
}
public BackgroundManager(Context context, ViewPager eventSource) {
this.context = context;
supportsRendering = BackgroundManager.supportsOpenGLES2(context);
eventSource.setTag(id.TAG_BACKGROUND_MANAGER, this);
if (this.supportsRendering) {
this.backgroundSurfaceView = new GLSurfaceView(context);
this.backgroundSurfaceView.setFocusable(false);
this.backgroundSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
eventSource.addOnPageChangeListener(BackgroundManager.getRenderer());
this.backgroundSurfaceView.setRenderer(BackgroundManager.getRenderer());
this.backgroundSurfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
} else {
this.backgroundStillView = new View(context);
}
}
如果您需要更多代码,请告诉我。
我考虑过一些可能的解决方案:
a)解决问题(不知道如何......)
b)在设备不支持的情况下禁用花哨效果,但问题是,如何检测呈现是否会提前工作?该设备通过了我的Open GL 2.0版本检查。
c)转移到另一个渲染解决方案而不是OpenGL,因为我觉得这对我的目的来说太过分了。有什么建议吗?
注意:Android 'white box' textures OpenGL ES 1.0 on some devices中提出的解决方案不适用,因为我使用了不同的API,并且设备确实按照http://specdevice.com/showspec.php?id=02c2-cba8-ffff-ffffebe99653支持扩展(虽然我不确定信息是否正确/可信的)
感谢您的建议!
答案 0 :(得分:2)
这里的问题是某些设备不支持非二次幂纹理。这就是为什么有些设备只显示白色纹理。
要解决这个问题,最好在生成纹理时始终使用2的幂位图。
两个位图的位图是位图,其宽度/高度是2的幂(256,512,1024等)。目前的情况是,你通过ResourceStore重新加载你的位图,我怀疑这个工具会创建一个PO2位图。
要解决此问题,请按以下步骤操作:
这是一个代码示例:
public void getTexture(GL10 gl, int index) {
if (BackgroundRenderer.this.textures[index] == 0) {
//calls to gl.glGenTextures, gl.glBindTexture etc
Bitmap originalBitmap = ResourceStore.getBackgroundBitmap(index);
int po2W = 1;
int po2H = 1;
while (po2W < originalBitmap.getWidth())
po2W *= 2;
while (po2H < originalBitmap.getHeight())
po2H *= 2;
Bitmap po2Bitmap = Bitmap.createBitmap(po2W, po2H, Config.ARGB_8888);
Canvas canvas = new Canvas(po2Bitmap);
canvas.drawBitmap(originalBitmap, 0, 0, myPaint);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, po2Bitmap, 0);
// these ratios need to be used for setting the texture coordinates!
mWidthRatio = (float)orignalBitmap.getWidth() / (float)po2Bitmap.getWidth();
mHeightRatio = (float)orignalBitmap.getHeight() / (float)po2Bitmap.getHeight();
}
return BackgroundRenderer.this.textures[index];
}
现在,您需要重新定义纹理坐标:
float textureData[] = {
0, 0, // top left
0, mHeightRatio, // bottom left
mWidthRatio, mHeightRatio, // bottom right
mWidthRatio, 0 // top right
};
现在你应该好好去。
如果有任何问题,请告诉我。