Android OpenGLES使用示例

Android OpenGLES使用示例

正多边形
//正多边形
public class Polygon {
   //顶点着色器(顶点画笔)
    public final String vertexShaderCode =
            "uniform mat4 uMVPMatrix;" +
                    "attribute vec4 vPosition;" +
                    "void main() {" +
                    "  gl_Position = uMVPMatrix * vPosition;" +
                    "}";
	//片着色器(内容填充色画笔)
    public final String fragmentShaderCode =
            "precision mediump float;" +
                    "uniform vec4 vColor;" +
                    "void main() {" +
                    "  gl_FragColor = vColor;" +
                    "}";

    private FloatBuffer vertexBuffer;//顶点位置数据
    float[] color = new float[4];//RGBA数据
     private static final int COORDS_PER_VERTEX = 3;//x,y,z三维坐标系
    private final int vertexStride = COORDS_PER_VERTEX * 4; 
    private int positionHandle;//顶点画笔
    private int colorHandle;//片画笔
    private int vPMatrixHandle;//矩阵
    private float[] positions;//顶点数据

    public Polygon(int n, float radius, @ColorInt int color) {
        this.color[0] = Color.red(color);
        this.color[1] = Color.green(color);
        this.color[2] = Color.blue(color);
        this.color[3] = Color.alpha(color);
        positions = createPositions(n, radius);//获取顶点坐标
        ByteBuffer bb = ByteBuffer.allocateDirect(positions.length * 4);//预处理(格式化)顶点数据
        bb.order(ByteOrder.nativeOrder());
        vertexBuffer = bb.asFloatBuffer();
        vertexBuffer.put(positions);
        vertexBuffer.position(0);
    }

    public void init(int mProgram) {
    //获取对应画笔
        positionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
        colorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
        vPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
    }

    ArrayList<Float> data = new ArrayList<>();

    private float[] createPositions(int n, float radius) {
        data.clear();
        data.add(0.0f);             //设置圆心坐标
        data.add(0.0f);
        data.add(0.0f);
        float angDegSpan = 360f / n;
        for (float i = 0; i <= 360; i += angDegSpan) {
            data.add((float) (radius * Math.sin(i * Math.PI / 180f)));
            data.add((float) (radius * Math.cos(i * Math.PI / 180f)));
            data.add(0.0f);
        }
        float[] f = new float[data.size()];
        for (int i = 0; i < f.length; i++) {
            f[i] = data.get(i);
        }
        return f;
    }

// GL 支持画点  线  面(三角形)
    public void draw(int mProgram, float[] mvpMatrix) {
        int vertexCount = positions.length / COORDS_PER_VERTEX;
        GLES20.glUseProgram(mProgram);
        GLES20.glEnableVertexAttribArray(positionHandle);
        GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX,
                GLES20.GL_FLOAT, false,
                vertexStride, vertexBuffer);
        GLES20.glUniform4fv(colorHandle, 1, color, 0);
        GLES20.glUniformMatrix4fv(vPMatrixHandle, 1, false, mvpMatrix, 0);
        //绘制连续三角形
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, vertexCount);
        //绘制连续线条
        GLES20.glDrawArrays(GLES20.GL_LINE_LOOP, 0, vertexCount);
        GLES20.glDisableVertexAttribArray(positionHandle);
    }
}
矩阵操作
public class MatrixUtils {
    private final float[] vPMatrix = new float[16];//相机投影结果矩阵
    private final float[] projectionMatrix = new float[16];//投影矩阵
    private final float[] viewMatrix = new float[16];//视图矩阵/相机矩阵
    private float[] operateMatrix = {1, 0, 0, 0,
            0, 1, 0, 0,
            0, 0, 1, 0,
            0, 0, 0, 1};//操作矩阵
    private final float[] resultMatrix = new float[16];//结果矩阵

    private final Stack<float[]> stack = new Stack<>();

    public void pushMatrix() {
        stack.push(Arrays.copyOf(operateMatrix, 16));
    }

    public void popMatrix() {
        operateMatrix = stack.pop();
    }

    /**
     * 投影
     */
    public void frustumM(float left, float right, float bottom, float top,
                         float near, float far) {
        Matrix.frustumM(projectionMatrix, 0, left, right, bottom, top, near, far);
    }

    /**
     * 设置相机
     */
    public void setLookAtM(float eyeX,
                           float eyeY,
                           float eyeZ,
                           float centerX,
                           float centerY,
                           float centerZ,
                           float upX,
                           float upY,
                           float upZ) {
        Matrix.setLookAtM(viewMatrix, 0, eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ);
    }

    /**
     * 平移
     */
    public void translateM(float x, float y, float z) {
        Matrix.translateM(operateMatrix, 0, x, y, z);
    }

    /**
     * 旋转
     */
    public void rotateM(float angle, float axisX, float axisY, float axisZ) {
        Matrix.rotateM(operateMatrix, 0, angle, axisX, axisY, axisZ);
    }

    /**
     * 缩放
     */
    public void scaleM(float scaleX, float scaleY, float scaleZ) {
        Matrix.scaleM(operateMatrix, 0, scaleX, scaleY, scaleY);
    }

    public void orthoM(float left, float right, float bottom, float top,
                       float near, float far) {
        Matrix.orthoM(operateMatrix, 0, left, right, bottom, top, near, far);
    }

    public float[] getResultMatrix() {
        Matrix.multiplyMM(vPMatrix, 0, projectionMatrix, 0, viewMatrix, 0);
        Matrix.multiplyMM(resultMatrix, 0, vPMatrix, 0, operateMatrix, 0);
        return resultMatrix;
    }
}

绘制示例
public class TestView extends GLSurfaceView {
    private static final String TAG = "GLES20";
    private BarrageRenderer renderer;

    public TestView(Context context) {
        this(context, null);
    }

    public TestView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setEGLContextClientVersion(2);//设置OpenGL版本
        renderer = new BarrageRenderer();//画布
        setRenderer(renderer);//设置画布
        setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);//设置刷新模式
    }


    private final float TOUCH_SCALE_FACTOR = 180.0f / 320;
    private float previousX;
    private float previousY;

    @Override
    public boolean onTouchEvent(MotionEvent e) {
     
        float x = e.getX();
        float y = e.getY();

        switch (e.getAction()) {
            case MotionEvent.ACTION_MOVE:
                float dx = x - previousX;
                float dy = y - previousY;
                // reverse direction of rotation above the mid-line
                if (y > getHeight() / 2) {
                    dx = dx * -1;
                }
                // reverse direction of rotation to left of the mid-line
                if (x < getWidth() / 2) {
                    dy = dy * -1;
                }

                renderer.setAngle(
                        renderer.getAngle() +
                                ((dx + dy) * TOUCH_SCALE_FACTOR));
                requestRender();
        }

        previousX = x;
        previousY = y;

        return true;
    }


    private static class BarrageRenderer implements GLSurfaceView.Renderer {

        private Polygon mPolygon;
        private int mPolygonProgram;
        public volatile float mAngle;
        private MatrixUtils matrixUtils;

        public float getAngle() {
            return mAngle;
        }

        public void setAngle(float angle) {
            mAngle = angle;
        }

        @Override
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
            GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);//清屏 设置背景色
            mPolygon = new Polygon(5, 0.5f, Color.GREEN);//初始化多边形(正五边形  支持直线->圆形)
            mPolygonProgram = createProgram(mPolygon.vertexShaderCode, mPolygon.fragmentShaderCode);
            mPolygon.init(mPolygonProgram);
            matrixUtils = new MatrixUtils();
        }

        @Override
        public void onSurfaceChanged(GL10 gl, int width, int height) {
            GLES20.glViewport(0, 0, width, height);//设置宽高
            //计算宽高比
            float ratio = (float) width / height;
            //以下设置保证GL绘制的图像 在不同屏幕设备上的适配
            matrixUtils.frustumM(-ratio, ratio, -1, 1, 3, 7);//设置投影
            matrixUtils.setLookAtM(0, 0, 7.0f, 0f, 0f, 0f, 0f, 1.0f, 0.0f);//设置相机
        }


        float x = 0.01f;

        @Override
        public void onDrawFrame(GL10 gl) {
        //清屏
            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_STENCIL_BUFFER_BIT);
            //旋转视图矩阵
            matrixUtils.rotateM(mAngle, 0, 0, 1.0f);
            //平移视图矩阵
            matrixUtils.translateM(x, x, x);
            //绘制图像
            mPolygon.draw(mPolygonProgram, matrixUtils.getResultMatrix());
        }

		//获取着色器  编译多边形着色器代码
        private int getShader(int shaderType, String sourceCode) {
            int shader = GLES20.glCreateShader(shaderType); //创建着色器 必要
            if (shader != 0) {
               //着色器为已编译的二进制数据时可省以下步骤
                GLES20.glShaderSource(shader, sourceCode); //添加着色器代码 必要
                GLES20.glCompileShader(shader); //编译 必要
                int[] status = new int[1];
                GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, status, 0);
                if (status[0] == 0) {
                    Log.e(TAG, GLES20.glGetShaderInfoLog(shader));
                    GLES20.glDeleteShader(shader);
                    return 0;
                }
            }
            return shader;
        }

      //创建OpenGL绘制程序
        private int createProgram(String vertexSource, String fragmentSource) {
            int vertex = getShader(GLES20.GL_VERTEX_SHADER, vertexSource);
            if (vertex == 0) {
                return vertex;
            }
            int fragment = getShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
            if (fragment == 0) {
                return fragment;
            }
            int program = GLES20.glCreateProgram();//创建程序  必要
            if (program != 0) {
                GLES20.glAttachShader(program, vertex);//附加着色器 必要
                GLES20.glAttachShader(program, fragment);
                GLES20.glLinkProgram(program);//链接程序 必要
                int[] status = new int[1];
                GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, status, 0);
                if (status[0] == 0) {
                    Log.e(TAG, GLES20.glGetProgramInfoLog(program));
                    GLES20.glDeleteProgram(program);
                }
            }
            return program;
        }
    }
}

class MainActivity : AppCompatActivity() {
    private var barrageView: TestView? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        barrageView = TestView(this).also {
            it.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT)
        }
        setContentView(barrageView)
    }

    override fun onResume() {
        super.onResume()
        barrageView?.onResume()
    }

    override fun onPause() {
        barrageView?.onPause()
        super.onPause()
    }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值