ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

基于textureview编写opengl程序

2019-09-17 16:38:31  阅读:325  来源: 互联网

标签:opengl int EGL private textureview import 编写 GL GLES20


原文链接:https://my.oschina.net/fuyajun1983cn/blog/263790

与SurfaceView相比,TextureView并没有创建一个单独的Surface用来绘制,这使得它可以像一般的View一样执行一些变换操作,设置透明度等。

另外,Textureview必须在硬件加速开启的窗口中。下面的例子演示了通过TextureView来创建一个opengl程序。


基于TextureView的程序,我们需要实现TextureView.SurfaceTextureListener这个接口,首先给出Activity的代码,在该类中,我们实现了此接口:

package com.fyj.test;

import java.util.concurrent.atomic.AtomicBoolean;

import android.app.Activity;
import android.graphics.SurfaceTexture;
import android.os.Bundle;
import android.view.TextureView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;

public class TextureviewtestActivity extends Activity implements TextureView.SurfaceTextureListener{

	private TextureView mTextureView;
	private Thread mProducerThread = null;
	private GLRendererImpl mRenderer;
	

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,   
                WindowManager.LayoutParams.FLAG_FULLSCREEN);  
        mTextureView = new TextureView(this);
        mTextureView.setSurfaceTextureListener(this);
        mTextureView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);//隐藏虚拟按键,即navigator bar
        setContentView(mTextureView);
        
    	mRenderer = new GLRendererImpl(this);
    }


	@Override
	public void onSurfaceTextureAvailable(SurfaceTexture surface, int width,
			int height) {
		// TODO Auto-generated method stub
		mRenderer.setViewport(width, height);
		mProducerThread = new GLProducerThread(surface, mRenderer, new AtomicBoolean(true));
		mProducerThread.start();
	}

	@Override
	public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
		// TODO Auto-generated method stub
		mProducerThread = null;
		return true;
	}


	@Override
	public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width,
			int height) {
		// TODO Auto-generated method stub
		mRenderer.resize(width, height);
		
	}


	@Override
	public void onSurfaceTextureUpdated(SurfaceTexture surface) {
		// TODO Auto-generated method stub
		
	}
}

其中,在方法onSurfaceTextureAvailable中,我们开启一个OpenGL线程,在该线程中执行OpenGL的一些操作,该线程的定义如下:

package com.fyj.test;

import java.util.concurrent.atomic.AtomicBoolean;

import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.egl.EGLSurface;
import javax.microedition.khronos.opengles.GL;

import android.graphics.SurfaceTexture;
import android.opengl.GLUtils;

public class GLProducerThread extends Thread {

	private AtomicBoolean mShouldRender;
	private SurfaceTexture mSurfaceTexture;
	private GLRenderer mRenderer;
	
	private EGL10 mEgl;
	private EGLDisplay mEglDisplay = EGL10.EGL_NO_DISPLAY;
	private EGLContext mEglContext = EGL10.EGL_NO_CONTEXT;
	private EGLSurface mEglSurface = EGL10.EGL_NO_SURFACE;
	private GL mGL;
	
	
	private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
	private static final int EGL_OPENGL_ES2_BIT = 4;
	
	public interface GLRenderer {
		public void drawFrame();
	}
	
	public GLProducerThread(SurfaceTexture surfaceTexture, GLRenderer renderer, AtomicBoolean shouldRender) 
	{
		mSurfaceTexture = surfaceTexture;
		mRenderer = renderer;
		mShouldRender = shouldRender;
	}
	
	private void initGL()
	{
		mEgl = (EGL10)EGLContext.getEGL();
		
		mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
		if (mEglDisplay == EGL10.EGL_NO_DISPLAY) {
			throw new RuntimeException("eglGetdisplay failed : " + 
																	GLUtils.getEGLErrorString(mEgl.eglGetError()));
		}
		
		int []version = new int[2];
		if (!mEgl.eglInitialize(mEglDisplay, version)) {
			throw new RuntimeException("eglInitialize failed : " + 
					GLUtils.getEGLErrorString(mEgl.eglGetError()));
		}
		
		int []configAttribs = {
				EGL10.EGL_BUFFER_SIZE, 32,
				EGL10.EGL_ALPHA_SIZE, 8,
				EGL10.EGL_BLUE_SIZE, 8,
				EGL10.EGL_GREEN_SIZE, 8,
				EGL10.EGL_RED_SIZE, 8,
				EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
				EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT,
				EGL10.EGL_NONE
		};
		
		int []numConfigs = new int[1];
		EGLConfig []configs = new EGLConfig[1]; 
		if (!mEgl.eglChooseConfig(mEglDisplay, configAttribs, configs, 1, numConfigs)) {
			throw new RuntimeException("eglChooseConfig failed : " + 
					GLUtils.getEGLErrorString(mEgl.eglGetError()));
		}
		
		int []contextAttribs = {
				EGL_CONTEXT_CLIENT_VERSION, 2,
				EGL10.EGL_NONE
		};
		mEglContext = mEgl.eglCreateContext(mEglDisplay, configs[0], EGL10.EGL_NO_CONTEXT, contextAttribs);
		mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, configs[0], mSurfaceTexture, null);
		if (mEglSurface == EGL10.EGL_NO_SURFACE || mEglContext == EGL10.EGL_NO_CONTEXT) {
			int error = mEgl.eglGetError();
			if (error == EGL10.EGL_BAD_NATIVE_WINDOW) {
				throw new RuntimeException("eglCreateWindowSurface returned  EGL_BAD_NATIVE_WINDOW. " );
			}
			throw new RuntimeException("eglCreateWindowSurface failed : " + 
					GLUtils.getEGLErrorString(mEgl.eglGetError()));
		}
		
		if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
			throw new RuntimeException("eglMakeCurrent failed : " + 
					GLUtils.getEGLErrorString(mEgl.eglGetError()));
		}
		
		mGL = mEglContext.getGL();
	}
	
	private void destoryGL() 
	{
		mEgl.eglDestroyContext(mEglDisplay, mEglContext);
		mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
		mEglContext = EGL10.EGL_NO_CONTEXT;
		mEglSurface = EGL10.EGL_NO_SURFACE;
	}
	
	public void run() 
	{
		initGL();
		
		if (mRenderer != null) {
			((GLRendererImpl)mRenderer).initGL();
		}
		
		while (mShouldRender != null && mShouldRender.get() != false) {
			if (mRenderer != null)
				mRenderer.drawFrame();
			mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
			
			try {
				sleep(5);
			} catch(InterruptedException e) {
				
			}
		}
		
		destoryGL();
	}
}

在该线程中,我们定义了GLRenderer接口,该接口的实现者负责具体的OpenGL绘制代码:

package com.fyj.test;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import android.util.Log;

import com.fyj.test.GLProducerThread.GLRenderer;

public class GLRendererImpl implements GLRenderer {
	
	private int mProgramObject;
	private int mWidth;
	private int mHeight;
	private FloatBuffer mVertices;
	private ShortBuffer mTexCoords;
	private Context mContext;
	private int mTexID;
	private static String TAG = "GLRendererImpl";

	private final float[] mVerticesData = { -0.5f, -0.5f, 0, 0.5f, -0.5f, 0, -0.5f, 0.5f, 0, 0.5f, 0.5f, 0 };
	private final short[] mTexCoordsData = {0, 1, 1, 1, 0, 0, 1, 0};

	public GLRendererImpl(Context ctx)
	{
		mVertices = ByteBuffer.allocateDirect(mVerticesData.length * 4)
				.order(ByteOrder.nativeOrder()).asFloatBuffer();
		mVertices.put(mVerticesData).position(0);
		
		mTexCoords = ByteBuffer.allocateDirect(mTexCoordsData.length * 2)
				.order(ByteOrder.nativeOrder()).asShortBuffer();
		mTexCoords.put(mTexCoordsData).position(0);
		
		mContext = ctx;
		
	}
	
	public void setViewport(int width, int height) 
	{
		mWidth = width;
		mHeight = height;
	}
	
	public void initGL()
	{
		comipleAndLinkProgram();
		
		loadTexture();
		
		GLES20.glClearColor(0,  0, 0, 0);
	}
	
	public void resize(int width, int height) 
	{
		mWidth = width;
		mHeight = height;
		
	}
	
	@Override
	public void drawFrame() {
		// TODO Auto-generated method stub
		GLES20.glViewport(0, 0, mWidth, mHeight);
		
		GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

		GLES20.glUseProgram(mProgramObject);
		
		GLES20.glVertexAttribPointer(0, 3, GLES20.GL_FLOAT, false, 0, mVertices);
		GLES20.glEnableVertexAttribArray(0);
		GLES20.glVertexAttribPointer(1, 2, GLES20.GL_SHORT, false, 0, mTexCoords);
		GLES20.glEnableVertexAttribArray(1);
		
		GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
		GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTexID);
		int loc = GLES20.glGetUniformLocation(mProgramObject, "u_Texture");
		GLES20.glUniform1f(loc, 0);
		GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
	
		Log.i("GLRendererImpl", "drawing..." + mWidth);
	}

	
	private void loadTexture() {
		Bitmap b = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_launcher);
		if (b != null) {
			int []texID = new int[1];
			GLES20.glGenTextures(1, texID, 0);
			GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texID[0]);
			mTexID = texID[0];
			
			GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, 
					GLES20.GL_LINEAR);
			GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, 
					GLES20.GL_LINEAR);
			
			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);
			
			GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, b, 0);
			b.recycle();
		}
	}
	
	private int loadShader(int shaderType, String shaderSource) {
		int shader;
		int[] compiled = new int[1];

		// Create the shader object
		shader = GLES20.glCreateShader(shaderType);

		if (shader == 0)
			return 0;

		// Load the shader source
		GLES20.glShaderSource(shader, shaderSource);

		// Compile the shader
		GLES20.glCompileShader(shader);

		// Check the compile status
		GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);

		if (compiled[0] == 0) {
			Log.e(TAG, GLES20.glGetShaderInfoLog(shader));
			GLES20.glDeleteShader(shader);
			return 0;
		}
		return shader;
	}
	
	private void comipleAndLinkProgram() {
		String vShaderStr = "attribute vec4 a_position;    \n"
				+"attribute vec2 a_texCoords; \n"
				+"varying vec2 v_texCoords; \n"
				+ "void main()                  \n"
				+ "{                            \n"
				+ "   gl_Position = a_position;  \n"
				+"    v_texCoords = a_texCoords; \n"
				+ "}                            \n";

		String fShaderStr = "precision mediump float;					  \n"
				+"uniform sampler2D u_Texture; \n"
				+"varying vec2 v_texCoords; \n"
				+ "void main()                                  \n"
				+ "{                                            \n"
				+ "  gl_FragColor = texture2D(u_Texture, v_texCoords) ;\n"
				+ "}                                            \n";

		int vertexShader;
		int fragmentShader;
		int programObject;
		int[] linked = new int[1];

		// Load the vertex/fragment shaders
		vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vShaderStr);
		fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fShaderStr);

		// Create the program object
		programObject = GLES20.glCreateProgram();

		if (programObject == 0)
			return ;

		GLES20.glAttachShader(programObject, vertexShader);
		GLES20.glAttachShader(programObject, fragmentShader);

		// Bind vPosition to attribute 0
		GLES20.glBindAttribLocation(programObject, 0, "a_position");
		GLES20.glBindAttribLocation(programObject, 1, "a_texCoords");

		// Link the program
		GLES20.glLinkProgram(programObject);

		// Check the link status
		GLES20.glGetProgramiv(programObject, GLES20.GL_LINK_STATUS, linked, 0);

		if (linked[0] == 0) {
			Log.e(TAG, "Error linking program:");
			Log.e(TAG, GLES20.glGetProgramInfoLog(programObject));
			GLES20.glDeleteProgram(programObject);
			return  ;
		}

		mProgramObject = programObject;
	}
}

需要注意的是,所有EGL及GL相关的操作必须置于GLThread线程中进行。

转载于:https://my.oschina.net/fuyajun1983cn/blog/263790

标签:opengl,int,EGL,private,textureview,import,编写,GL,GLES20
来源: https://blog.csdn.net/chijiandao3197/article/details/100930721

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有