Android 为什么OpenGL纹理在Eclipse中与调试器一起运行时呈现良好,而在自己运行应用程序时呈现白色?
我有一个sprite类和另一个使用OpenGLSurvace视图来渲染的扩展sprite类的类。看起来像这样Android 为什么OpenGL纹理在Eclipse中与调试器一起运行时呈现良好,而在自己运行应用程序时呈现白色?,android,opengl-es,textures,Android,Opengl Es,Textures,我有一个sprite类和另一个使用OpenGLSurvace视图来渲染的扩展sprite类的类。看起来像这样 public class Invader extends Sprite { static int mTextureId = -1; Invader(Context context, float x, float y, float angle) { super(context, x, y, angle); super.setSiz
public class Invader extends Sprite {
static int mTextureId = -1;
Invader(Context context, float x, float y, float angle)
{
super(context, x, y, angle);
super.setSize(width, height);
// super.setPos(x, y);
// super.setAngle(angle);
// Check to see if the texture is loaded already. If it is a valid texture
// id, don't bother loading it again
if (mTextureId < 0)
{
super.loadBitmap(context.getResources(), R.drawable.piano_key_white);
}
else
{
super.setTexture(mTextureId);
}
}
@Override
protected int getTexture()
{
return mTextureId;
}
@Override
protected void setTexture(int textureId)
{
mTextureId = textureId;
}
}
public class Sprite {
private static int mTextureID = -1;
private static boolean mShouldLoadTexture = true;
...
onReder(GL10 gl) {
if (mShouldLoadTexture) {
mTextureID = loadTexture(gl, someBitmap);
mShouldLoadTexture = false;
}
}
}
公共类入侵者扩展了Sprite{
静态int mTextureId=-1;
入侵者(上下文、浮动x、浮动y、浮动角度)
{
super(上下文、x、y、角度);
超级设置尺寸(宽度、高度);
//super.setPos(x,y);
//超级设定角(角度);
//检查纹理是否已加载。它是否为有效纹理
//id,不要麻烦再次加载它
if(mTextureId<0)
{
super.loadBitmap(context.getResources(),R.drawable.piano\u key\u white);
}
其他的
{
super.setTexture(mTextureId);
}
}
@凌驾
受保护的int getTexture()
{
返回mTextureId;
}
@凌驾
受保护的void setTexture(int-textureId)
{
mTextureId=textureId;
}
}
如您所见,它使用一个指向纹理的静态指针,该纹理由loadBitmap函数加载,该函数调用decodeResource函数来创建OpenGL纹理。当我使用SDK插件从调试器通过Eclipse运行应用程序时,一切看起来都很棒。当我在手机上正常运行应用程序时,除了这个类将入侵者渲染为白色正方形(这是对象的颜色)之外,其他所有东西都呈现良好
据我所知,纹理可能没有正确加载,因此绘制了一个纯白色正方形。我不明白为什么这在调试时有效,而在正常执行时无效。有什么想法吗?当程序没有通过远程调试运行时有什么不同?确保纹理大小为2的幂。各种设备无法正确加载纹理,除非它们符合这些大小限制 即 1x2 2x2 512x256 128x128
etc以下是您需要执行的操作:
// Load the texture from resource
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
Bitmap bitmap = BitmapFactory.decodeResource(m_resources, R.drawable.tex, options);
gl.glGenTextures(1, m_textureID, 0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, m_textureID[0]);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
// Free resources
bitmap.recycle();
// Do some error checking
if(m_textureID[0] == 0)
throw new RuntimeException("Error loading texture!");
我明白了;我认为这是一个很好的教训。我的班级看起来像这样
public class Invader extends Sprite {
static int mTextureId = -1;
Invader(Context context, float x, float y, float angle)
{
super(context, x, y, angle);
super.setSize(width, height);
// super.setPos(x, y);
// super.setAngle(angle);
// Check to see if the texture is loaded already. If it is a valid texture
// id, don't bother loading it again
if (mTextureId < 0)
{
super.loadBitmap(context.getResources(), R.drawable.piano_key_white);
}
else
{
super.setTexture(mTextureId);
}
}
@Override
protected int getTexture()
{
return mTextureId;
}
@Override
protected void setTexture(int textureId)
{
mTextureId = textureId;
}
}
public class Sprite {
private static int mTextureID = -1;
private static boolean mShouldLoadTexture = true;
...
onReder(GL10 gl) {
if (mShouldLoadTexture) {
mTextureID = loadTexture(gl, someBitmap);
mShouldLoadTexture = false;
}
}
}
另一个静态类包含精灵列表
public static class SpriteList {
private static Vector<Sprite> mSprites;
...
}
公共静态类SpriteList{
私有静态向量mSprites;
...
}
当我以调试的方式运行它时,与仅从手机上的启动器运行它时,两者之间的区别是,包是所有的静态类都被重置的,而手机上的启动器不必重置静态类
因此,当我第一次将其作为debug运行时,该类将看到它需要加载纹理,然后在GL10对象中分配纹理指针,并将其分配给staticmTextureID。此时,mTextureID包含有效的GL纹理指针
现在,我将退出调试,断开与eclipse的连接,并在手机上运行启动器。由于Sprite类的容器尚未重置,mTextureID仍有一些值指向不存在的GL纹理id。此外,mShouldLoadTexture将保持“false”,这意味着该类不会尝试从位图重新加载纹理。因此,onRender()将尝试使用指向无效纹理id的指针,并呈现一个白色框
我简化了场景,使其更易于理解。我知道静态容器在这个示例中没有太多意义,但我认为它可以说明我发现的情况。当我使包含类不再是静态的时,一切都正常工作。我遇到了同样的问题。对我来说,我的纹理会在我第一次以调试模式启动应用程序时加载,但是如果我从应用程序退出手机并再次打开它,我所有的纹理都会消失。除非我从IDE中再次启动应用程序,否则无法加载纹理 对我来说,我接受了移除静态场的建议,并完全修复了它(我有一个静态场,保持一个正方形的旋转角度,该角度将循环通过一组不同的纹理,还有一个静态场,保持我的纹理列表中当前纹理的数量) 我仍然不明白为什么有静态字段会导致这种情况
记录在案,是的,我的纹理是2次方的尺寸,我把它们放在可绘制的nodpi文件夹中 我也有类似的问题,问题是,连接到adb时运行会造成一些延迟。这种延迟导致我的应用程序只能在非常特定的条件下工作,没有这些延迟根本无法工作。
我希望这能帮助一些人。纹理都是2的幂。如果图像在res/drawable Xdpi/中,是否可能在编译时更改为非2次幂?我试着把纹理放在res/raw文件夹中,它也做了同样的事情。嗯,我不知道你在做什么,你发布了绝对0的OpenGL代码,所以我们没有什么要解决的问题。试试我的答案,如果这不起作用-那么你是索尔,需要发布一些实际的OpenGL代码以获得进一步的帮助。回顾我发布的代码,我意识到它没有任何OpenGL代码。不过,我想我找到了错误所在。我有一个对渲染器对象的静态引用,当我开始调试并释放该对象时,该对象被重置。但是,当我在没有调试的情况下从手机上运行程序时,先前的静态引用已经存在,引用了gl纹理ID,但gl资源已被释放,因此创建了一个白色框。请阅读我对您答案的评论;如果我听起来很粗鲁,我向你道歉,但你所说的毫无意义。另外,请不要把任何东西称为推荐人,这会让人感到困惑和不安