3.OpenGL中GLSurfaceView使用
GLSurfaceView作为SurfaceView的子类,打开了一扇叫作OpenGL的大门。
它实现了SurfaceHolder.Callback2
接口,需要传入一个GLSurfaceView.Render
接口
public class TriangleGLView extends GLSurfaceView implements GLSurfaceView.Renderer {
private Triangle mTriangle;
public TriangleGLView(Context context) {
this(context, null);
}
public TriangleGLView(Context context, AttributeSet attrs) {
super(context, attrs);
setEGLContextClientVersion(2);//设置OpenGL ES 2.0 context
setRenderer(this);//设置渲染器
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
mTriangle=new Triangle();
GLES20.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);//rgba
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES20.glViewport(0, 0, width, height);//GL视口
}
@Override
public void onDrawFrame(GL10 gl) {
//清除颜色缓存和深度缓存
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT| GLES20.GL_DEPTH_BUFFER_BIT);
mTriangle.draw();
}
}
OpenGL的绘制可谓让人望而却步,下面是最简单的三角形绘制,
如果有兴趣可以看一下笔者OpenGL相关文章,仔细看完,基本上可以入门
Android多媒体之GL-ES战记第一集–勇者集结
Android多媒体之GL-ES战记第二集–谜团立方
Android多媒体之GLES2战记第三集–圣火之光
Android多媒体之GLES2战记第四集–移形换影
Android多媒体之GLES2战记第五集–宇宙之光
Android多媒体之GLES2战记第六集–九层之台
public class Triangle {
private FloatBuffer vertexBuffer;//顶点缓冲
private final String vertexShaderCode =//顶点着色代码
“attribute vec4 vPosition;” +
“void main() {” +
" gl_Position = vPosition;" +
“}”;
private final String fragmentShaderCode =//片元着色代码
“precision mediump float;” +
“uniform vec4 vColor;” +
“void main() {” +
" gl_FragColor = vColor;" +
“}”;
private final int mProgram;
private int mPositionHandle;//位置句柄
private int mColorHandle;//颜色句柄
private final int vertexCount = sCoo.length / COORDS_PER_VERTEX;//顶点个数
private final int vertexStride = COORDS_PER_VERTEX * 4; // 34=12
// 数组中每个顶点的坐标数
static final int COORDS_PER_VERTEX = 3;
static float sCoo[] = { //以逆时针顺序
0.0f, 0.0f, 0.0f, // 顶部
-1.0f, -1.0f, 0.0f, // 左下
1.0f, -1.0f, 0.0f // 右下
};
// 颜色,rgba
float color[] = {0.63671875f, 0.76953125f, 0.22265625f, 1.0f};
public Triangle() {
//初始化顶点字节缓冲区
ByteBuffer bb = ByteBuffer.allocateDirect(sCoo.length * 4);//每个浮点数:坐标个数 4字节
bb.order(ByteOrder.nativeOrder());//使用本机硬件设备的字节顺序
vertexBuffer = bb.asFloatBuffer();// 从字节缓冲区创建浮点缓冲区
vertexBuffer.put(sCoo);// 将坐标添加到FloatBuffer
vertexBuffer.position(0);//设置缓冲区以读取第一个坐标
int vertexShader = loadShader(
GLES20.GL_VERTEX_SHADER,//顶点着色
vertexShaderCode);
int fragmentShader = loadShader
(GLES20.GL_FRAGMENT_SHADER,//片元着色
fragmentShaderCode);
mProgram = GLES20.glCreateProgram();//创建空的OpenGL ES 程序
GLES20.glAttachShader(mProgram, vertexShader);//加入顶点着色器
GLES20.glAttachShader(mProgram, fragmentShader);//加入片元着色器
GLES20.glLinkProgram(mProgram);//创建可执行的OpenGL ES项目
}
private int loadShader(int type, String shaderCode) {
int shader = GLES20.glCreateShader(type);//创建着色器
GLES20.glShaderSource(shader, shaderCode);//添加着色器源代码
GLES20.glCompileShader(shader);//编译
return shader;
}
public void draw() {
// 将程序添加到OpenGL ES环境中
GLES20.glUseProgram(mProgram);
//获取顶点着色器的vPosition成员的句柄
mPositionHandle = GLES20.glGetAttribLocation(mProgram, “vPosition”);
//启用三角形顶点的句柄
GLES20.glEnableVertexAttribArray(mPositionHandle);
//准备三角坐标数据
GLES20.glVertexAttribPointer(
mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
// 获取片元着色器的vColor成员的句柄
mColorHandle = GLES20.glGetUniformLocation(mProgram, “vColor”);
//为三角形设置颜色
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
//绘制三角形
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
//禁用顶点数组
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
}
4.OpenGL在相机中的使用
现在捋一下,相机需要一个SurfaceHolder,而GLSurfaceView是一个SurfaceView,郎情妾意。 但好事多磨,并没有想象中的这么简单…
在CameraGLView主类中创建SurfaceTexture对象,并将纹理绑定其上
而通过SurfaceTexture作为入参可以创建SurfaceHolder,一条路就通了。
public class CameraGLView extends GLSurfaceView implements GLSurfaceView.Renderer {
private CameraDrawer cameraDrawer;
public SurfaceTexture surfaceTexture;
private int[] textureId = new int[1];
//----------------------------相机操作------------------------------
private Handler mainHandler;
private Handler childHandler;
private String mCa