[英]Android: How to Change OpenGL ES Texture Image Dynamically
I'm trying to change the texture image displayed on an object in my opengl view in response to a button click. 我试图更改显示在我的opengl视图中的对象上的纹理图像,以响应按钮单击。 Currently, when the user presses a button I set a flag to true in my OpenGL Renderer thread.
当前,当用户按下按钮时,我在OpenGL Renderer线程中将标志设置为true。 My cross-thread communication seems fine: I am able to successfully toggle flag variables in the Renderer thread at will.
我的跨线程通信似乎很好:我能够随意在Renderer线程中成功切换标志变量。 My problem seems to be with the Open GL onDraw() workflow, I can't figure out how to systematically change a texture on an object after a texture has already been set during the Renderer's initial onSurfaceCreated() execution.
我的问题似乎与Open GL onDraw()工作流程有关,在渲染器的初始onSurfaceCreated()执行期间已经设置纹理后,我无法弄清楚如何系统地更改对象上的纹理。
It seems that fretBoardTexture = new OpenGL_TextureData(mActivityContext, R.drawable.dark_wood); 似乎fretBoardTexture = new OpenGL_TextureData(mActivityContext,R.drawable.dark_wood); never works outside of onSurfaceCreated(), why?
永远不会在onSurfaceCreated()之外运行,为什么?
Below is the code i've tried. 以下是我尝试过的代码。 Am I missing a sequence of GLES20() method invocations somewhere?
我是否在某处缺少一系列GLES20()方法调用?
OpenGL Renderer Class OpenGL渲染器类
private int chosenWoodColor = 1;
public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
...
loadFretBoardTexture(); //this call works: it succeeds in changing texture
}
public void onDrawFrame(GL10 glUnused) {
if (flag){
loadFretBoardTexture(); //this call fails: it never changes the texture
}
...
//***Fretboard OpenGL_TextureData Binding***
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
// Bind the texture to this unit.
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, fretBoard._textureID);
//Draw Background
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.translateM(mModelMatrix, 0, 0.0f, 0.0f, -1.0f);
drawFretBoard(); //draw the fretboard
...
}
public void loadFretBoardTexture(){
switch (chosenWoodColor){
case 1:
fretBoardTexture = new OpenGL_TextureData(mActivityContext, R.drawable.dark_wood);
break;
case 2:
fretBoardTexture = new OpenGL_TextureData(mActivityContext, R.drawable.medium_wood);
break;
case 3:
fretBoardTexture = new OpenGL_TextureData(mActivityContext, R.drawable.light_wood);
break;
}
setFretboardTextureRefresh(false);
return;
}
Texture Data Helper Class 纹理数据助手类
public class OpenGL_TextureData {
public int textureID;
public float imageWidth, imageHeight;
public OpenGL_TextureData(Context context, int resourceId) { //constructor
final int[] textureHandle = new int[1];
GLES20.glGenTextures(1, textureHandle, 0);
if (textureHandle[0] != 0) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false; // No pre-scaling
// Read in the resource
final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);
//fetch texture image width & height
imageWidth = options.outWidth;
imageHeight = options.outHeight;
// Bind to the texture in OpenGL
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
// Set filtering
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
// Recycle the bitmap, since its data has been loaded into OpenGL.
bitmap.recycle();
}
if (textureHandle[0] == 0) {
throw new RuntimeException("Error loading texture.");
}
textureID = textureHandle[0];
}
}
Solved. 解决了。
The problem was that I was creating a new texture object and loading a bitmap to it, but since the texture object was already created in my onSurfaceCreated() method this was undesired: I really just needed to load a bitmap onto the already existing texture object. 问题是我正在创建一个新的纹理对象并向其加载位图,但是由于纹理对象已经在我的onSurfaceCreated()方法中创建,因此这是不希望的:我真的只需要将位图加载到已经存在的纹理对象上。
I added the following method to my Texture data helper class: 我在我的Texture data helper类中添加了以下方法:
public void updateTexture(Context context, int resourceId) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false; // No pre-scaling
final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options); //Read in the resource
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 1);
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.