Android 如何将自定义视图渲染为OpenGL纹理。在线提供的解决方案仅对渲染Web视图有用,但我希望对自定义视图执行此操作
我正在将自定义视图渲染到OpenGL纹理。我已在表面纹理上方创建了一个曲面,并使用surface.lockCanvas返回的画布在CustomView的onDraw方法中进行绘制。我在surfaceTexture.UpdateMaximage()方法附近遇到异常 下面是显示的错误,我已将代码复制到下面。请告诉我哪里出了问题Android 如何将自定义视图渲染为OpenGL纹理。在线提供的解决方案仅对渲染Web视图有用,但我希望对自定义视图执行此操作,android,opengl-es,textures,android-canvas,Android,Opengl Es,Textures,Android Canvas,我正在将自定义视图渲染到OpenGL纹理。我已在表面纹理上方创建了一个曲面,并使用surface.lockCanvas返回的画布在CustomView的onDraw方法中进行绘制。我在surfaceTexture.UpdateMaximage()方法附近遇到异常 下面是显示的错误,我已将代码复制到下面。请告诉我哪里出了问题 java.lang.RuntimeException: Error during updateTexImage at
java.lang.RuntimeException: Error during updateTexImage
at android.graphics.SurfaceTexture.nativeUpdateTexImage(Native Method)
at android.graphics.SurfaceTexture.updateTexImage(SurfaceTexture.java:169)
代码:Main Activity.java
public class MainActivity extends Activity {
GLSurfaceView ourSurface;
CustomView myView;
GLCubeRendererEx renderer;
private final int TEXTURE_WIDTH=256;
private final int TEXTURE_HEIGHT =256;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ourSurface = new GLSurfaceView(this);
myView = new CustomView(this);
renderer= new GLCubeRendererEx(getBaseContext());
ourSurface.setRenderer(renderer);
setContentView(ourSurface);
addContentView( myView, new ViewGroup.LayoutParams( TEXTURE_WIDTH, TEXTURE_HEIGHT ) );
}
@Override
protected void onResume() {
super.onResume();
ourSurface.onResume();
}
@Override
protected void onPause() {
super.onPause();
ourSurface.onPause();
}
public class CustomView extends View {
public CustomView(Context context) {
super(context);
setLayoutParams( new ViewGroup.LayoutParams( TEXTURE_WIDTH, TEXTURE_HEIGHT ) );
}
@Override
protected void onDraw(Canvas canvas) {
if(renderer.surface!=null) {
try {
final Canvas surfaceCanvas = renderer.surface.lockCanvas(null);
super.onDraw(surfaceCanvas);
surfaceCanvas.drawColor(Color.WHITE);
Paint ourBlue = new Paint();
ourBlue.setColor(Color.BLUE);
Paint ourRed = new Paint();
ourRed.setColor(Color.RED);
Paint ourGreen = new Paint();
ourGreen.setColor(Color.GREEN);
Paint ourYellow = new Paint();
ourYellow.setColor(Color.YELLOW);
//Implementing drawCircle
surfaceCanvas.drawCircle(800, 800, 50, ourRed);
surfaceCanvas.drawCircle(200, 200, 50, ourBlue);
surfaceCanvas.drawCircle(400, 400, 50, ourGreen);
surfaceCanvas.drawCircle(600, 600, 50, textPaint);
renderer.surface.unlockCanvasAndPost(surfaceCanvas);
}
catch(Surface.OutOfResourcesException e)
{
e.printStackTrace();
}
}
}
}
}
glcuberenderex.java-具有导致异常的代码
public class GLCubeRendererEx implements GLSurfaceView.Renderer{
private GLCube cube;
private Context context;
private SurfaceTexture surfaceTexture = null;
public Surface surface;
private final int TEXTURE_WIDTH=256;
private final int TEXTURE_HEIGHT =256;
int glSurfaceTex;
public GLCubeRendererEx(Context context)
{
this.context=context;
cube = new GLCube();
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig eglconfig)
{
gl.glEnable(GL_TEXTURE_2D); //Enable Texture Mapping ( NEW )
gl.glShadeModel(GL10.GL_SMOOTH);
gl.glDisable(GL10.GL_DITHER);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
gl.glClearColor(.2f,0f,.8f,1); //COLOR
gl.glClearDepthf(1f);
gl.glEnable(GL10.GL_DEPTH_TEST); //Enables Depth Testing
gl.glDepthFunc(GL10.GL_LEQUAL);
}
@Override
public void onDrawFrame(GL10 gl)
{
//problematic code
synchronized ( this ) {
surfaceTexture.updateTexImage(); // Update texture
}
gl.glDisable(GL10.GL_DITHER);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
GLU.gluLookAt(gl,0,0,-5,0,0,0,0,2,0);
long time = SystemClock.uptimeMillis() % 4000L;
float angle = 0.090f * ((int)time);
gl.glRotatef(angle,1,0,0);
gl.glRotatef(angle,0,1,0);
gl.glRotatef(angle,0,0,1);
cube.draw(gl);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) //landscape to potrail -changes how everything is setup
{
surface = null;
surfaceTexture = null;
glSurfaceTex = cube.Engine_CreateSurfaceTexture( gl,TEXTURE_WIDTH, TEXTURE_HEIGHT );
if ( glSurfaceTex > 0 ) {
surfaceTexture = new SurfaceTexture( glSurfaceTex );
surfaceTexture.setDefaultBufferSize( TEXTURE_WIDTH, TEXTURE_HEIGHT );
surface = new Surface( surfaceTexture );
if(surface!=null)
System.out.println("surface isnt null");
}
gl.glViewport(0,0,width,height);
float ratio = (float) width/height;
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glFrustumf(-ratio, ratio, -1, 1, 1,25);
}
}
GLCube.java
public class GLCube{
private float vertices[]={
-1.0f, -1.0f, 1.0f, //Vertex 0
1.0f, -1.0f, 1.0f, //v1
-1.0f, 1.0f, 1.0f, //v2
1.0f, 1.0f, 1.0f, //v3
1.0f, -1.0f, 1.0f, //...
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
};
private float rgbaVals[]={
1,1,0,5f,
.25f,0,.85f,1,
0,1,1,1
};
private float texture[] = {
//Mapping coordinates for the vertices
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
1.0f, 1.0f,
};
private FloatBuffer vertBuff,colorBuff;
/** The buffer holding the texture coordinates */
private FloatBuffer textureBuffer;
/** Our texture pointer */
private int[] textures = new int[1];
private short[] pIndex = {
0,1,3, 0,3,2, //Face front
4,5,7, 4,7,6, //Face right
8,9,11, 8,11,10, //...
12,13,15, 12,15,14,
16,17,19, 16,19,18,
20,21,23, 20,23,22,
};
private ShortBuffer pBuff;
public GLCube()
{
ByteBuffer bBuff = ByteBuffer.allocateDirect(vertices.length*4);
bBuff.order(ByteOrder.nativeOrder());
vertBuff = bBuff.asFloatBuffer();
vertBuff.put(vertices);
vertBuff.position(0);
ByteBuffer pbBuff = ByteBuffer.allocateDirect(pIndex.length * 2);
pbBuff.order(ByteOrder.nativeOrder());
pBuff =pbBuff.asShortBuffer();
pBuff.put(pIndex);
pBuff.position(0);
bBuff = ByteBuffer.allocateDirect(texture.length * 4);
bBuff.order(ByteOrder.nativeOrder());
textureBuffer = bBuff.asFloatBuffer();
textureBuffer.put(texture);
textureBuffer.position(0);
}
public void draw(GL10 gl)
{
gl.glFrontFace(GL10.GL_CCW);
gl.glEnable(GL10.GL_CULL_FACE);
gl.glCullFace(GL10.GL_BACK);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glVertexPointer(3,GL10.GL_FLOAT,0,vertBuff);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
gl.glDrawElements(GL10.GL_TRIANGLES,pIndex.length,GL10.GL_UNSIGNED_SHORT, pBuff);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glDisable(GL10.GL_CULL_FACE);
}
int Engine_CreateSurfaceTexture(GL10 gl, int width, int height )
{
gl.glGenTextures(1, textures, 0);
if ( textures[0] > 0 ) {
gl.glBindTexture( GL_TEXTURE_2D, textures[0] );
gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, null );
GLES20.glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
GLES20.glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
GLES20.glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
GLES20.glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
gl.glBindTexture( GL_TEXTURE_2D, 0 );
}
return textures[0];
}
}
我没有注意到你的线程是lockCanvas,因此你对unlockCanvas的调用可以工作。在上面的onDraw方法中的MainActivity.java中完成所有绘制之后,我已经解锁了画布。是的,但是你的lockCanvas在哪里呢?它在MainActivity.java中作为renderer.surface.lockCanvas