package com.example.datalibrary.gl.shape; import android.graphics.Rect; import android.opengl.GLES20; import com.example.datalibrary.gl.utils.ShaderUtils; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.nio.ShortBuffer; public class Shap { public void setTriangleCoords(float[] triangleCoords) { this.vertices = triangleCoords; verFloatBuffer = getVertices(); } public void setTriangleCoords(float x , float y) { this.vertices = new float[]{ x /*左上角 x*/, y /*左上角 y*/, /*0.0f,*/ x /*左下角 x*/, y - 0.15f /*左下角 y*/, /*0.0f,*/ // 左下角 x /*右上角 x*/, y /*右上角 y*/, /*0.0f, */// 右上角 x + 0.15f, y, /*0.0f,*/ // 右下角 }; verFloatBuffer = getVertices(); } // 三维的顶点坐标,有方向的 private float[] vertices = new float[]{ -0f /*左上角 x*/ , 0f /*左上角 y*/, /*0.0f,*/ -0f /*左下角 x*/, -0f /*左下角 y*/, /*0.0f,*/ // 左下角 -0f /*左上角 x*/ , 0f /*左上角 y*/, /*0.0f,*/ 0f /*左上角 x*/ , 0f /*左上角 y*/, /*0.0f,*/ }; private static final short[] INDICES =new short[] { 0 , 1 , 2 , 3 }; public void setColors(float[] mColors) { this.mColors = mColors; } // 颜色 private float[] mColors = new float[]{0f , 0f , 0f , 0f}; /* 顶点着色器的脚本 */ private static final String VERTEX_SHADER_CODE = "attribute vec2 vPosition; " // 顶点位置属性vPosition + "void main(){ " + " gl_Position = vec4(vPosition,0,1);" // 确定顶点位置 + "}"; /* 片元着色器的脚本 */ private static final String FRAGMENT_SHADER_CODE = "precision mediump float; " // 声明float类型的精度为中等(精度越高越耗资源) + "uniform vec4 uColor; " // uniform的属性uColor + "void main(){ " + " gl_FragColor = uColor; " // 给此片元的填充色 + "}"; private FloatBuffer vertexBuffer; private ShortBuffer indiceBuffer; private int mPositionHandle; //顶点 private int mColorHandle; // 颜色 // 顶点buffer private int mProgram; // private int iboId; // IBO的ID public Shap(){ // 1、存储顶点坐标 vertexBuffer = ByteBuffer.allocateDirect(4) .order(ByteOrder.nativeOrder()) .asFloatBuffer();; vertexBuffer.position(0); } private Rect rect = new Rect(); private int width; private int height; private int screenWidth; private int screenHeight; // 获取图形的顶点坐标 FloatBuffer verFloatBuffer; public void setSize(int screenWidth,int screenHeight,int videoWidth,int videoHeight){ this.screenWidth = screenWidth; this.screenHeight = screenHeight; this.width = videoWidth; this.height = videoHeight; rect(); } private void rect(){ int left; int top; int viewWidth; int viewHeight; float sh = screenWidth*1.0f/screenHeight; float vh = width *1.0f/ height; if (sh < vh){ left = 0; viewWidth = screenWidth; viewHeight = (int)(height *1.0f/ width *viewWidth); top = (screenHeight - viewHeight)/2; }else{ top = 0; viewHeight = screenHeight; viewWidth = (int)(width *1.0f/ height *viewHeight); left = (screenWidth - viewWidth)/2; } rect.left = left; rect.top = top; rect.right = viewWidth; rect.bottom = viewHeight; } public void init(){ ByteBuffer mbb = ByteBuffer.allocateDirect(INDICES.length * 2); // 数组排列用nativeOrder mbb.order(ByteOrder.nativeOrder()); indiceBuffer = mbb.asShortBuffer(); indiceBuffer.put(INDICES); indiceBuffer.flip(); mProgram = ShaderUtils.createProgram(VERTEX_SHADER_CODE, FRAGMENT_SHADER_CODE); int[] ibos = new int[1]; GLES20.glGenBuffers(ibos.length, ibos, 0); this.iboId = ibos[0]; // 绑定VBO GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, iboId); //赋值 GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER,INDICES.length * 2,indiceBuffer,GLES20.GL_STATIC_DRAW); //解绑 GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); verFloatBuffer = getVertices(); } public void onDraw(){ mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition"); mColorHandle = GLES20.glGetUniformLocation(mProgram, "uColor"); GLES20.glDisable(GLES20.GL_DEPTH_TEST); // 使用某套shader程序 GLES20.glUseProgram(mProgram); // 为画笔指定顶点位置数据(mPositionHandle) GLES20.glVertexAttribPointer(mPositionHandle, 2, GLES20.GL_FLOAT, false, 0, verFloatBuffer); // 允许顶点位置数据数组 GLES20.glEnableVertexAttribArray(mPositionHandle); // 设置属性uColor(颜色 索引,R,G,B,A) GLES20.glUniform4f(mColorHandle, mColors[0] / 255f, mColors[1] / 255f, mColors[2] / 255f, mColors[3] / 255f); // 绘制 // GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, 4,GLES20.GL_UNSIGNED_SHORT,0); GLES20.glLineWidth(10); GLES20.glDrawArrays(GLES20.GL_LINES , 0, 4); } /** * 获取图形的顶点 * 特别提示:由于不同平台字节顺序不同数据单元不是字节的一定要经过ByteBuffer * 转换,关键是要通过ByteOrder设置nativeOrder(),否则有可能会出问题 * * @return 顶点Buffer */ private FloatBuffer getVertices() { // 创建顶点坐标数据缓冲 // vertices.length*4是因为一个float占四个字节 ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4); vbb.order(ByteOrder.nativeOrder()); //设置字节顺序 FloatBuffer vertexBuf = vbb.asFloatBuffer(); //转换为Float型缓冲 vertexBuf.put(vertices); //向缓冲区中放入顶点坐标数据 vertexBuf.position(0); //设置缓冲区起始位置 return vertexBuf; } /** * 初始化buffer * */ private static FloatBuffer initBuffer(float[] buffers,int len) { // 先初始化buffer,数组的长度*4,因为一个float占4个字节 ByteBuffer mbb = ByteBuffer.allocateDirect(buffers.length * len); // 数组排列用nativeOrder mbb.order(ByteOrder.nativeOrder()); FloatBuffer floatBuffer = mbb.asFloatBuffer(); floatBuffer.put(buffers); floatBuffer.flip(); return floatBuffer; } /** * 加载shader * @param type 片元、顶点 * @param shaderCode Code * @return int */ private int loadShader(int type, String shaderCode) { //根据type创建顶点着色器或者片元着色器 int shader = GLES20.glCreateShader(type); //将资源加入到着色器中,并编译 GLES20.glShaderSource(shader, shaderCode); GLES20.glCompileShader(shader); return shader; } }