GLES2.0 顶点和着色器 第二课

注意一下:
1、在OpenGL里面,只会绘制点,直线和三角形。
2、OpenGL作为本地系统库,是直接运行到硬件上的,没有虚拟机,垃圾回收和内存压缩。所有的 android.opengl.GLES2.0包中的方法,实际上都是使用 JNI 调用的本地方法库。
3、由于2的因素,所以openGL绘制需要的数据,都需要做一层转换,从java内存中转到 本地 内存中(我理解的就是 native)

// 因为上面 3 中 所描述的所以,数据的传输,我们采用的是 ByteBuffer
FloatBuffer vertexData;
    // 2 个 三角形
    float tableVerticesWithTriangles[] = {
            -0.5f,-0.5f,
            0.5f,0.5f,
            -0.5f,0.5f,

            -0.5f,-0.5f,
            0.5f,-0.5f,
            0.5f,0.5f,

            -0.5f,0f,
            0.5f,0f,

            0f,-0.25f,
            0f,0.25f};

ByteBuffer.allocateDirect(tableVerticesWithTriangles.length * BYTES_PER_FLOAT)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer();
// allocateDirect 方法是 C++ 中申请内存的方法,什么类型,每个类型多少字节
// 把数据 放到 FloatBuffer 的实例中
        vertexData.put(tableVerticesWithTriangles);

上面是java中的数据往 native 中作一个迁移吧。下面需要介绍着色器了,这个很重要。

OpenGL 中的着色器分为 顶点着色器 和 片元着色器
1、着色器是用来描述 openGL 需要绘制的内容的 代码,专门告诉GPU的
2、顶点着色器描述顶点的位置,属性(颜色,大小,渐变色等)
3、片元着色器描述点、线、三角形的颜色,渐变色,大小

// 给顶点增加 颜色属性
   private static String vertex_shader_step3 = "attribute vec4 a_Position; \n" +
           // a_Color 记录顶点的 颜色
           "attribute vec4 a_Color; \n" +
// 正交投影 的 矩阵 数据 (位置 a_Position * u_Matrix 得到一个新的位置 投影位置)
           "uniform mat4 u_Matrix; \n" +  // mat4 代表一个 4 X 4 的矩阵
           // varying 表明颜色是在变化的
           "varying vec4 v_Color; \n" +
           "void main()\n" +
           "{\n" +
           // gl_Position是OpenGL中提供的变量,装载顶点坐标
           "    gl_Position = a_Position * u_Matrix;\n" +
           "    v_Color = a_Color; \n"+
           // 指定 绘制 的 点的 大小
           "    gl_PointSize = 10.0;\n" +
           "}";

gl_Position gl_PointSize 都是一些固定的属性 attribute 、uniform和varying 是具有特殊意义的修饰词

attribute 声明一个属性数据 vec4 类型的数据,存放位置数据
varying 声明 渐变的颜色数据

// 片元着色器,主要还是 声明颜色的
public static final String fragment_shader_step3 = "precision mediump float;\n" +
           "varying vec4 v_Color; \n" +
           "void main() {\n" +
           // gl_FragColor 装载 当前片段的最终颜色
           // 这里使用的是 v_Color 也就是 varying的属性,说明该片元的颜色根据两个顶点计算之后使用
           "    gl_FragColor=v_Color;\n" +
           "}";

着色器的创建

/**
    *  创建 着色器 对象
    *  type : GLES20.GL_VERTEX_SHADER / GLES20.GL_FRAGMENT_SHADER
    *  shaderCode: 着色器 代码
    */
   public static int createShader(int type, String shaderCode) {
      // 1、创建一个 着色器 对象,并检查是否创建成功
      //TODO glCreateShader 在 native 中创建了 一个 着色器对象,并返回了这个 着色器的 id
      int shaderObjectId = GLES20.glCreateShader(type);
      if (shaderObjectId == 0) {
         System.out.println("majie " + TAG + "  Could not create new shader");
         return 0;
      }

      // 2、上传 着色器 源码 到 着色器 对象里
      // TODO shaderObjectId 代表着色器对象, shaderCode 是我们定义的 顶点着色器源码
      GLES20.glShaderSource(shaderObjectId, shaderCode);

      // 3、告诉 openGL 编译 第二步 上传的源码(字符串)
      GLES20.glCompileShader(shaderObjectId);

      // 4、获取 openGL 的编译结果
      int compileStatue[] = new int[1];
      // TODO openGL 的通用写法 --> 将 shaderObjectId 的编译结果 写到 compileStatue 中的第一个元素中
      GLES20.glGetShaderiv(shaderObjectId, GLES20.GL_COMPILE_STATUS, compileStatue, 0);

      // TODO 额外信息,可以获取 着色器 的编译日志
      System.out.println("majie " + TAG + "  Results of compiling source: " + compileStatue[0]
              + "  \n:" + GLES20.glGetShaderInfoLog(shaderObjectId));

      // 5、验证 编译状态 ,并 返回着色器的对象 ID TODO:TMD就是最开始生成的那个 ID
      if (compileStatue[0] == 0) {
         // 如果失败,就删除 shader 对象
         GLES20.glDeleteShader(shaderObjectId);
      }

      return shaderObjectId;
   }

这里要理解一个点,就是

因为 OpenGL 实际上是通过jni调用的 native 方法,所以 通过 GLES20 调用的方法,创建的实例,返回的一般都是int ,说白了应该是 内存地址 ,在通过指针去获取 其中的数据,在C++ 中进行操作和执行
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。