Android 为什么OpenGL纹理在Eclipse中与调试器一起运行时呈现良好,而在自己运行应用程序时呈现白色?

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

我有一个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.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

以下是您需要执行的操作:

  • 将纹理放置在“res/drawable”文件夹中
  • 加载期间禁用纹理缩放,代码为:
  • 纹理数组分配(duh;))

    和装载:

            // 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资源已被释放,因此创建了一个白色框。请阅读我对您答案的评论;如果我听起来很粗鲁,我向你道歉,但你所说的毫无意义。另外,请不要把任何东西称为推荐人,这会让人感到困惑和不安