Android OpenGL es 2.0无法在对象上重新加载纹理。
多亏了这里的几个教程、问题和答案,我成功地加载了纹理并自由旋转了球体,但我偶然发现在运行时需要重新加载纹理(获取位图图像,处理它,然后将其作为新纹理应用于对象)。我没有为我的具体问题找到任何有效的解决方案(我已经阅读了所有相关的问题和答案)。 我对OpenGL还很陌生。这是我的第二个项目,我的第一个3D项目,也是我在这里提出的第一个问题。下面是: 基本上,纹理加载通过以下功能完成: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
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中使用了queueEvent和Runnable
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。我将把我以前的一些答案链接到下面的相关问题。我将开始记录我自己在共享链接中讨论的问题,如果问题来自那里,我将搜索。谢谢你的搜索开始。从这个角度研究这个问题之后,我会回来的。