Android OpenGL es 2.0无法在对象上重新加载纹理。

Android OpenGL es 2.0无法在对象上重新加载纹理。,android,textures,opengl-es-2.0,reload,Android,Textures,Opengl Es 2.0,Reload,多亏了这里的几个教程、问题和答案,我成功地加载了纹理并自由旋转了球体,但我偶然发现在运行时需要重新加载纹理(获取位图图像,处理它,然后将其作为新纹理应用于对象)。我没有为我的具体问题找到任何有效的解决方案(我已经阅读了所有相关的问题和答案)。 我对OpenGL还很陌生。这是我的第二个项目,我的第一个3D项目,也是我在这里提出的第一个问题。下面是: 基本上,纹理加载通过以下功能完成: public void loadGLTexture(final Context context, fina

多亏了这里的几个教程、问题和答案,我成功地加载了纹理并自由旋转了球体,但我偶然发现在运行时需要重新加载纹理(获取位图图像,处理它,然后将其作为新纹理应用于对象)。我没有为我的具体问题找到任何有效的解决方案(我已经阅读了所有相关的问题和答案)。 我对OpenGL还很陌生。这是我的第二个项目,我的第一个3D项目,也是我在这里提出的第一个问题。下面是:

基本上,纹理加载通过以下功能完成:

    public void loadGLTexture(final Context context, final int texture) {
    GLES20.glGenTextures(1, mTextures, 0);
    if (mTextures[0] != 0)
    {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inScaled = false;
        final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), texture, options);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextures[0]);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,   GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
        bitmap.recycle();
    }

    if (mTextures[0] == 0)
    {
        throw new RuntimeException("Texture load fail");
    }
}
     public void draw(float[] mvpMatrix) {
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, this.mTextures[0]);
    GLES20.glFrontFace(GLES20.GL_CW);


    for (int i = 0; i < this.mTotalNumStrips; i++) {
        //vertex
        this.mVertexBuffer.get(i).position(0);
        GLES20.glVertexAttribPointer(mPositionHandle, NUM_FLOATS_PER_VERTEX,
                GLES20.GL_FLOAT, false,
                vertexStride, this.mVertexBuffer.get(i));
        GLES20.glEnableVertexAttribArray(mPositionHandle);
        //texture
        this.mTextureBuffer.get(i).position(0);
        GLES20.glVertexAttribPointer(mTextureCoordinateHandle, NUM_FLOATS_PER_TEXTURE,
                GLES20.GL_FLOAT, false,
                textureStride, this.mTextureBuffer.get(i));
        GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);
        //draw strip
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, this.mVertices.get(i).length / NUM_FLOATS_PER_VERTEX);
    }

    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
    // Disable the client state before leaving.
    GLES20.glDisableVertexAttribArray(mPositionHandle);
    GLES20.glDisableVertexAttribArray(mTextureCoordinateHandle);
}
在该功能中进行绘制时:

    public void loadGLTexture(final Context context, final int texture) {
    GLES20.glGenTextures(1, mTextures, 0);
    if (mTextures[0] != 0)
    {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inScaled = false;
        final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), texture, options);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextures[0]);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,   GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
        bitmap.recycle();
    }

    if (mTextures[0] == 0)
    {
        throw new RuntimeException("Texture load fail");
    }
}
     public void draw(float[] mvpMatrix) {
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, this.mTextures[0]);
    GLES20.glFrontFace(GLES20.GL_CW);


    for (int i = 0; i < this.mTotalNumStrips; i++) {
        //vertex
        this.mVertexBuffer.get(i).position(0);
        GLES20.glVertexAttribPointer(mPositionHandle, NUM_FLOATS_PER_VERTEX,
                GLES20.GL_FLOAT, false,
                vertexStride, this.mVertexBuffer.get(i));
        GLES20.glEnableVertexAttribArray(mPositionHandle);
        //texture
        this.mTextureBuffer.get(i).position(0);
        GLES20.glVertexAttribPointer(mTextureCoordinateHandle, NUM_FLOATS_PER_TEXTURE,
                GLES20.GL_FLOAT, false,
                textureStride, this.mTextureBuffer.get(i));
        GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);
        //draw strip
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, this.mVertices.get(i).length / NUM_FLOATS_PER_VERTEX);
    }

    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
    // Disable the client state before leaving.
    GLES20.glDisableVertexAttribArray(mPositionHandle);
    GLES20.glDisableVertexAttribArray(mTextureCoordinateHandle);
}
我想在这里实现的是纹理重新加载,因此计划是:

初始化(工作):loadGLTexture(initialtexture)->循环draw()函数

重新加载(不工作):clearGLTextures()->loadGLTexture(newTexture)->循环draw()函数

因此,不仅我无法重新加载纹理,而且调用clearGLTextures()似乎也不起作用,因为initialtexture仍保留在scren上

欢迎任何想法,
谢谢

这是在Android上进行OpenGL编程时一个非常常见的问题示例。不幸的是,这些症状非常多变,因此这些问题实际上并不重复

使用
GLSurfaceView
时,它会创建一个单独的渲染线程。
GLSurfaceView.Renderer
实现(
onSurfaceCreated
onSurfaceChanged
onDrawFrame
)中的所有方法都在此渲染线程中调用

谜题的第二部分是您需要一个当前的OpenGL上下文来进行OpenGL调用。OpenGL上下文是每个线程当前的
GLSurfaceView
负责创建上下文,并使其在渲染线程中成为当前上下文

因此,您不能从其他线程调用任何OpenGL(除非您做更多的工作,并增加复杂性)。最常见的错误是尝试从UI线程调用OpenGL,通常是在处理触摸事件等用户输入时。这些电话不起作用


如果您希望执行OpenGL调用以响应用户输入,则有许多选项。例如,您可以在
渲染器中设置描述必要状态更改的成员,并在
onDraw()
方法中进行检查。另一个方便的选项是在视图上使用
queueEvent()
方法,它允许您传入一个
Runnable
,稍后将在渲染线程中执行。

我遇到了同样的问题

Reto Koradi对此解释得很好,但我想分享我的解决方案: 我在GLSurfaceView中使用了queueEventRunnable

public void addTexture(final int textureResId) {
    queueEvent(new Runnable() {
        @Override
        public void run() {
            mRenderer.loadTexture(textureResId);
            // or different GL thread tasks like clearing the texture
        }
    });
}

您正在调用以在渲染线程中重新加载纹理吗?我正在对渲染器的SurfaceCreated进行初始化调用,并在运行时对某个单击侦听器事件进行重新加载调用。所以基本上,我现在做的每一个调用都是在同一个线程(UI线程)上进行的,而这些线程并不相同
GLSurfaceView
创建一个渲染线程,所有
Renderer
方法都在该线程中调用。如果不做更多的工作,就不能直接从UI线程调用OpenGL。我将把我以前的一些答案链接到下面的相关问题。我将开始记录我自己在共享链接中讨论的问题,如果问题来自那里,我将搜索。谢谢你的搜索开始。从这个角度研究这个问题之后,我会回来的。