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 条评论
登录 后参与评论

相关文章

来自专栏Android知识点总结

TIII-Android技术篇之注解Annotation

682
来自专栏为数不多的Android技巧

Android插件化原理解析——广播的管理

在Activity生命周期管理 以及 插件加载机制 中我们详细讲述了插件化过程中对于Activity组件的处理方式,为了实现Activity的插件化我们付出了相...

682
来自专栏何俊林

OpenGL ES总结(三)OpenGL通过计算纹理坐标来显示一张图片

导读:OpenGL是在图形图像中,非常优秀的渲染库,文中Demo下载地址:https://github.com/hejunlin2013/OpenGLTextu...

2299
来自专栏Java编程技术

就是让你懂Spring中Mybatis的花样配置

Mybatis作为一个优秀的存储过程和高级映射的持久层框架,目前在项目实践中运用的比较广泛,最近做项目时候发现了一种之前没见过的配置方式,这里总结下常用的配置方...

932
来自专栏Hongten

java开发_jcrop_网页截图工具(插件)

===========================================

1353
来自专栏salesforce零基础学习

salesforce 零基础学习(三十三)通过REST方式访问外部数据以及JAVA通过rest方式访问salesforce

本篇参考Trail教程: https://developer.salesforce.com/trailhead/force_com_dev_intermedia...

4388
来自专栏图形学与OpenGL

WebGL三角形平移变换

1103
来自专栏java相关

基于注解实现SpringBoot多数据源配置

1113
来自专栏杂烩

组件化项目搭建(非专业,无聊的一次尝试)四 原

        这下好了,业务也分完了,剩下的前端也有事干了。我们来一个贯穿的,把刚才从数据查询出的数据展示到页面。

543
来自专栏积累沉淀

ie8和chrome获取上传图片的宽度和高度等尺寸

测试后可用 <html> <head>     <title>测试</title>     <meta chars...

3658

扫码关注云+社区