OpenGLAndroid---视频

Android OpenGL ES(一)-开始描绘一个平面三角形

2018-05-04  本文已影响336人  deep_sadness
image.png

关于OpenGL ES Android的介绍这里略过

OpenGL ES世界的基本元素

  1. 着色器
  2. 坐标系。矩阵
  3. 纹理
    ...

本文主要涉及的部分是着色器的使用。

直接开始


创建GLSurfaceView

今天的目标是做一个OpenGL ES学习的开端。就是画一个简单的三角形。暂时不考虑坐标系的矩阵变换和纹理等。只需要用顶点着色器简单的来进行描述。
这一节需要使用和认识的关键类是
GLSurfaceViewGLSurfaceView.Render
一句话来描述就是,我们会在GLSurfaceView.Render上进行描绘,在GLSurfaceView中显示出来。

判断是否支持OpenGL Es2

 /**
     * 判断是否支持es2.0
     *
     * @param context
     * @return
     */
    public static boolean isSupportEs2(Context context) {
        //检查是否支持2.0
        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        if (activityManager != null) {
            ConfigurationInfo deviceConfigurationInfo = activityManager.getDeviceConfigurationInfo();
            int reqGlEsVersion = deviceConfigurationInfo.reqGlEsVersion;
            return reqGlEsVersion >= GLES_VERSION_2 || (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1
                    && (Build.FINGERPRINT.startsWith("generic")
                    || Build.FINGERPRINT.startsWith("unknown")
                    || Build.MODEL.contains("google_sdk")
                    || Build.MODEL.contains("Emulator")
                    || Build.MODEL.contains("Android SDK build for x86")));
        } else {
            return false;
        }

    }

创建GLSurfaceView

接着创建一个GLSurfaceView。并且设置其版本为2。同时设置我们自己的Render

           //创建一个GLSurfaceView
            glSurfaceView = new GLSurfaceView(this);
            glSurfaceView.setEGLContextClientVersion(2);
            //设置自己的Render.Render 内进行图形的绘制
            glSurfaceView.setRenderer(new TriangleShapeRender(this));
            isRenderSet = true;
            setContentView(glSurfaceView);

还需要在Activity对应的生命周期内,来调用我们的GLSurfaceView的方法

 @Override
    protected void onPause() {
        super.onPause();
        if (isRenderSet) {
            glSurfaceView.onPause();
        }

    }

    @Override
    protected void onResume() {
        super.onResume();
        if (isRenderSet) {
            glSurfaceView.onResume();
        }

    }

绘制三角形-Render的实现类

绘制的基础知识


GLThread

因为Android中的GLSurfaceView的操作,其实都是在GLThread中进行。所以生命周期方法的回调也都在GLThread线程中。所有OpenGL的操作也都需要在该线程中。

基础的生命周期方法

接下来转到Render的实现类里面来。先关注需要实现的生命周期方法。

/**
 * 注意:
 * 因为我们是使用g20来进行编程,需要要注意导包
 *
 * 主要在Render类内,完成对应的绘制.
 * 对应的生命周期的回调
 * -> onSurfaceCreated
 * -> onSurfaceChanged
 * -> onDrawFrame
 *
 * Created by a2957 on 2018/5/3.
 */
public class ViewGLRender implements GLSurfaceView.Renderer {
    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        //0.简单的给窗口填充一种颜色
        GLES20.glClearColor(0.0f,0.0f,0.0f,0.0f);

        //在创建的时候,去创建这些着色器

    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        //在窗口改变的时候调用
        GLES20.glViewport(0,0,width,height);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        //0.glClear()的唯一参数表示需要被清除的缓冲区。当前可写的颜色缓冲
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    }
}

如上面代码所示,对应的生命周期方法,对应了各个状态

开始绘制三角形


着色器代码的套路

我们需要熟悉编写着色器代码的套路。
之所以说是套路,因为这些步骤都是类似的。

1. 编写着色器的glsl

我们先简单的写一下顶点着色器和片元着色器的代码。这些代码具体是为什么这样写。我们在这里先不关注。我们先熟悉一下流程。
assets中创建对应的文件。代码内容如下

2. 在onSurfaceCreated方法内初始化

注意OpenGL的操作,都必须在GLThread中进行。生命周期方法的回调也都在这个线程中

这样着色器的套路就基本确定下来了。

三角形的形状

上面编写的顶点着色器中,我们定义了aPosition的属性。就相当于我们将在OpenGL中定义了一个存储的点。接下来,我们就会将这个点来存储我们定义的形状信息。来显示出形状。

OpenGL中的坐标系是从[-1,1]。
我们先用一组数组的坐标系,来描述我们的三角形

  //顶点的坐标系
  private static float TRIANGLE_COORDS[] = {
          //Order of coordinates: X, Y, Z
          0.5f, 0.5f, 0.0f, // top
          -0.5f, -0.5f, 0.0f, // bottom left
          0.5f, -0.5f, 0.0f   // bottom right
  };
三角形的归一化坐标.png

我们还会定义一些常量,来帮助我们操作。常量就如注释说明

 //在数组中,一个顶点需要3个来描述其位置,需要3个偏移量
  private static final int COORDS_PER_VERTEX = 3;
  private static final int COORDS_PER_COLOR = 0;

  //在数组中,描述一个顶点,总共的顶点需要的偏移量。这里因为只有位置顶点,所以和上面的值一样
  private static final int TOTAL_COMPONENT_COUNT = COORDS_PER_VERTEX+COORDS_PER_COLOR;
  //一个点需要的byte偏移量。
  private static final int STRIDE = TOTAL_COMPONENT_COUNT * Constant.BYTES_PER_FLOAT;
onDrawFrame中调用绘制
@Override
    public void onDrawFrame(GL10 gl) {
        super.onDrawFrame(gl);

        //0.先使用这个program?这一步应该可以放到onCreate中进行
        GLES20.glUseProgram(mProgramObjectId);

        //1.根据我们定义的取出定义的位置
        int vPosition = GLES20.glGetAttribLocation(mProgramObjectId, A_POSITION);
        //2.开始启用我们的position
        GLES20.glEnableVertexAttribArray(vPosition);
        //3.将坐标数据放入
        GLES20.glVertexAttribPointer(
                vPosition,  //上面得到的id
                COORDS_PER_VERTEX, //告诉他用几个偏移量来描述一个顶点
                GLES20.GL_FLOAT, false,
                STRIDE, //一个顶点需要多少个字节的偏移量
                mVertexFloatBuffer);

        //取出颜色
        int uColor = GLES20.glGetUniformLocation(mProgramObjectId, U_COLOR);

        //开始绘制
        //设置绘制三角形的颜色
        GLES20.glUniform4fv(
                uColor,
                1,
                TRIANGLE_COLOR,
                0
        );

        //绘制三角形.
        //draw arrays的几种方式 GL_TRIANGLES三角形 
        //GL_TRIANGLE_STRIP三角形带的方式(开始的3个点描述一个三角形,后面每多一个点,多一个三角形) 
        //GL_TRIANGLE_FAN扇形(可以描述圆形)
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, VERTEX_COUNT);
        //禁止顶点数组的句柄
        GLES20.glDisableVertexAttribArray(vPosition);

    }

最后的效果

image.png

总结一下,我们从这第一章节的内容了解到了下面这些使用的知识点:

  1. 运行在GLThread中
  2. 着色器编译和使用的套路
  3. 使用数组的方式来描述图形,使用本地内存分配的方式来分配对应的内存。
  4. 绘制图形的过程中,启用我们设置的属性和变量,并且绘制的套路

未知道的:
坐标矩阵的变化。和纹理等。

整体的代码位置:https://github.com/deepsadness/OpenGLDemo5

系列文章地址
Android OpenGL ES(一)-开始描绘一个平面三角形
Android OpenGL ES(二)-正交投影
Android OpenGL ES(三)-平面图形
Android OpenGL ES(四)-为平面图添加滤镜
Android OpenGL ES(五)-结合相机进行预览/录制及添加滤镜
Android OpenGL ES(六) - 将输入源换成视频
Android OpenGL ES(七) - 生成抖音照片电影

上一篇 下一篇

猜你喜欢

热点阅读