OpenGL ES读书笔记(一)—初始庐山真面目

1. OpenGL ES简介

OpenGL ES(OpenGL for Embedded Systems)是以手持和嵌入式设备为目标的高级3D图形应用程序编程接口。OpenGL ES是当今智能手机中占据统治地位的图形API,支持的平台包括IOS,,Android,BlackBerry,bada,Linux和Windows。 OpenGL ES 实现了具有可编程着色功能的图形管线。下图展示了OpenGL ES 图形管线,图中带有阴影的方框表示OpenGL ES中管线的可编程阶段。

1.1 顶点着色器

其工作过程为首先将原始的顶点几何信息及其他属性传送到顶点着色器中,经过自己开发的顶点着色器处理后产生纹理坐标,颜色,点位置等后续流程需要的各项顶点属性信息,然后将其传递给图元装配阶段。

顶点着色器的输入包括:

  • 着色器程序——描述顶点上执行操作的顶点着色器程序源代码或者可执行文件。
  • 顶点着色器输入(或者属性)——用顶点数组提供的每个顶点的数据。
  • 统一变量(uniform)——顶点着色器使用的不变数据。
  • 采样器——代表顶点着色器使用纹理的特殊统一变量类型。

1.2 片段着色器

片元着色器是用于处理片元值及其相关数据的可编程单元,其可以执行纹理的采样,颜色的汇总,计算雾颜色等操作,每片元执行一次。片元着色器主要功能为通过重复执行(每片元一次),将3D物体中的图元光栅化后产生的每个片元的颜色等属性计算出来送入后继阶段。

片段着色器的输入包括:

  • 着色器程序——描述片段上所执行操作的片段着色器程序源代码或者可执行文件。
  • 输入变量——光栅化单元用插值为每个片段生成的顶点着色器输出。
  • 统一变量(uniform)——顶点着色器使用的不变数据。
  • 采样器——代表片段着色器使用纹理的特殊统一变量类型。

2. 一个OpenGL ES 2.0实例——绘制一个三角形

2.1 创建简单的顶点和片段着色器

OpenGL ES 2.0程序必须至少要有一个顶点着色器和一个片段着色器。 着色器的代码可以存储在后缀名为”.glsl”文件中,这些文件存放到项目的asserts目录下。

  • 一个简单的顶点着色器 //assert目录下面的vertex.glsl //总变换矩阵 uniform mat4 uMVPMatrix; //顶点位置 attribute vec3 aPosition; //顶点颜色 attribute vec4 aColor; //用于传递给片元着色器的易变变量 varying vec4 vColor; void main(){ //根据总变换矩阵计算此次绘制此顶点的位置 gl_Position = uMVPMatrix * vec4(aPosition, 1); //将接收的顶点颜色传递给片元着色器 vColor = aColor; }
  • 一个简单的片段着色器 //assert目录下面的fragment.glsl //声明着色器中浮点变量的默认精度 precision mediump float; //接收从顶点着色器传过来的易变变量 varying vec4 vColor; void main(){ //给此片元赋颜色值 gl_FragColor = vColor; }

2.2 编译和加载着色器

上面已经定义了着色器源代码,接下来将着色器加载到OpenGL SE中。

//ShaderUtil.java
public static int loadShader(int shaderType, String source){
        //创建shader,并记录其id
        int shader = GLES20.glCreateShader(shaderType);
        if(shader != 0){
            //加载着色器的源代码
            GLES20.glShaderSource(shader, source);
            //编译
            GLES20.glCompileShader(shader);
            //获取shader的编译结果
            int[] compiled = new int[1];
            GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
            if(compiled[0] == 0){
                Log.e("ES20_ERROR", "could not compile shader " + shaderType+ ":" + GLES20.glGetShaderInfoLog(shader));
                shader = 0;
            }
        }
        return shader;
    }

2.3 创建一个程序对象并链接着色器

    //ShaderUtil.java
    public static int createProgram(String vertexSource, String fragmentSource){
        //加载顶点着色器
        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
        if(vertexShader == 0){
            return 0;
        }

        //加载片元着色器
        int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
        if(fragmentShader == 0){
            return 0;
        }

        //创建程序
        int program = GLES20.glCreateProgram();
        if(program != 0){
            //程序创建成功后,向程序中加入顶点着色器和片元着色器
            GLES20.glAttachShader(program, vertexShader);
            GLES20.glAttachShader(program, fragmentShader);

            //链接程序
            GLES20.glLinkProgram(program);

            //获取链接情况,若链接失败则报错并删除程序
            int[] linkStatus = new int[1];
            GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
            if(linkStatus[0] != GLES20.GL_TRUE){
                Log.e("ES20_ERROR", "could not link  program: " + GLES20.glGetProgramInfoLog(program));
                GLES20.glDeleteProgram(program);
                program = 0;
            }
        }
        return program;
    }

2.4加载几何图形和绘制图元

public class MyGLSurfaceView extends GLSurfaceView {
    public MyGLSurfaceView(Context context) {
        super(context);
        //使用OpenGL ES 2.0需要设置该值为2
        this.setEGLContextClientVersion(2);

        //设置渲染器
        SceneRender render = new SceneRender();
        this.setRenderer(render);
        this.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
    }

    private class  SceneRender implements  GLSurfaceView.Renderer{
        int mPositionHandle;

        @Override
        public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
            String vertexSource = ShaderUtil.loadFromAssertsFile("VertexShader.glsl", getContext());
            String fragmentSource = ShaderUtil.loadFromAssertsFile("FragmentShader.glsl", getContext());
            int mShaderProgram = ShaderUtil.createProgram(vertexSource, fragmentSource);

            GLES20.glUseProgram(mShaderProgram);
            mPositionHandle = GLES20.glGetAttribLocation(mShaderProgram, "aPosition");
        }

        @Override
        public void onSurfaceChanged(GL10 gl10, int width, int height) {
            //设置视口
            GLES20.glViewport(0, 0, width, height);
        }

        @Override
        public void onDrawFrame(GL10 gl10) {
            //缓冲区将用glCleanColor指定的颜色清除
            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

            //将顶点位置数据传送进渲染管线
            GLES20.glVertexAttribPointer(mPositionHandle, 2, GLES20.GL_FLOAT, false, 0, mVertexBuffer);
            //启用顶点位置数据
            GLES20.glEnableVertexAttribArray(mPositionHandle);
            //执行绘制
            GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
        }
    }
}

文章写得比较匆忙,如果有错别字或者理解错的,欢迎和楼主交流,谢谢~

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Brian

数据分析利器Pandas基本功能

---- 概述 pandas是基于Numpy构建的,让处理数据、分析数据和可视化数据都会变得更加简单,官网Pandas.正如官网所说: pandas is an...

3327
来自专栏来自地球男人的部落格

[LeetCode] 79. Word Search

【原题】 Given a 2D board and a word, find if the word exists in the grid. The wo...

17410
来自专栏编程理解

排序算法(四):归并排序

归并排序是通过分治的方式,将待排序集合拆分为多个子集合,对子集合排序后,合并子集合成为较大的子集合,不断合并最终完成整个集合的排序。

411
来自专栏我是攻城师

一个优雅的反转数组的算法

` 比较简单粗暴的方法是,遍历原始数组从最后一项向前遍历,然后把输出结果保存在一个新的数组里面,这样就完成了所谓的反转。

551
来自专栏简书专栏

基于Pandas的DataFrame、Series对象的apply方法

这篇文章主要讲解DataFrame、Series对象的apply方法。 豆瓣排名前250电影数据集下载链接: https://pan.baidu.com/s/...

755
来自专栏软件开发 -- 分享 互助 成长

C++STL 之排列

固然我们可以自己使用递归编写全排列程序,但是既然STL里面已将有了这个功能为什么不直接用呢,下面就写一下直接使用C++ STL生成全排序的程序 函数名:next...

1877
来自专栏WD学习记录

牛客网 数字游戏

小易邀请你玩一个数字游戏,小易给你一系列的整数。你们俩使用这些整数玩游戏。每次小易会任意说一个数字出来,然后你需要从这一系列数字中选取一部分出来让它们的和等于小...

671
来自专栏xingoo, 一个梦想做发明家的程序员

剑指OFFER之调整数组顺序使奇数位于偶数前面找(九度OJ1516)

题目描述: 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和...

2056
来自专栏calmound

HDU 3555 Bomb(数位DP)

http://acm.hdu.edu.cn/showproblem.php?pid=3555 题意:0-n之间有多少个数包含"13"的 分析:dp[pos][h...

2595
来自专栏猿人谷

二维数组的查找

题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否...

1795

扫码关注云+社区