OpenGL ES 2.0 Shader相关介绍
来源:互联网 发布:mysql大数据统计报表 编辑:程序博客网 时间:2024/06/06 00:07
http://blog.csdn.net/grafx/article/details/35561487?utm_source=tuicool&utm_medium=referral
最近手机项目要用到opengl和shader,虽然此前也搞过opengl,那时对opengl掌握的也还算熟悉,时隔四五年后,再翻看以前的程序,有些茫然,虽然大体明白怎么回事,但是很多技术细节忘了个干净,于是赶紧查阅了一下相关资料,还好,很多东西很快又捡了回来。在查阅资料过程中,发现这篇文章不错,只是文章发布在网易博客,因为博客排版的原因,阅读体验不是很好,于是周末花点时间,把这篇文章简单整理了下,希望对打算学习opengl shader技术的同学有帮助。再次把原文链接贴出:http://fengmm521.blog.163.com/blog/static/2509135820133254936364/,在整理过程中,对于原文冗余文字,本人对其进行了删减,同时也修正、补充了一些技术细节,其中红色标注的文字为本人新增。
与OpenGL ES1.x渲染管线相比,OpenGL ES 2.0渲染管线中“顶点着色器”取代了OpenGL ES 1.x渲染管线中的“变换和光照”;“片元着色器”取代了OpenGL ES 1.x渲染管线中的“纹理环境和颜色求和”、“雾”以及“Alpha测试”。这使得开发人员在使用OpenGL ES 2.0API进行开发时,可以通过编写顶点及片元着色器程序,来完成一些顶点变换和纹理颜色计算工作,实现更加灵活、精细化的计算与渲染。
一、着色(Shader)语言
着色语言是一种类C的编程语言,但不像C语言一样支持双精度浮点型(double)、字节型(byte)、短整型(short)、长整型(long),并且取消了C中的联合体(union)、枚举类型(enum)、无符号数(unsigned)以及位运算等特性。着色语言中有许多内建的原生数据类型以及构建数据类型,如:浮点型(float)、布尔型(bool)、整型(int)、矩阵型(matrix)以及向量型(vec2、vec3等)等。总体来说,这些数据类型可以分为标量、向量、矩阵、采样器、结构体以及数组等。shader支持下面数据类型:
1. 顶点着色器
1.1 顶点着色器示例代码
1.2 顶点着色器介绍
顶点着色器是一个可编程的处理单元,执行顶点变换、纹理坐标变换、光照、材质等顶点的相关操作,每顶点执行一次。替代了传统渲染管线中顶点变换、光照以及纹理坐标的处理,开发人员可以根据自己的需求自行开发,大大增加了程序的灵活性。
顶点着色器主要是传入相应的Attribute变量、Uniforms变量、采样器以及临时变量,经过顶点着色器后生成Varying变量。如下图所示:
(1)attribute变量(属性变量)只能用于顶点着色器中,不能用于片元着色器。一般用该变量来表示一些顶点数据,如:顶点坐标、纹理坐标、颜色等。
(2)uniforms变量(一致变量)用来将数据值从应用程其序传递到顶点着色器或者片元着色器。该变量有点类似C语言中的常量(const),即该变量的值不能被shader程序修改。一般用该变量表示变换矩阵、光照参数、纹理采样器等。
(3)varying变量(易变变量)是从顶点着色器传递到片元着色器的数据变量。顶点着色器可以使用易变变量来传递需要插值的颜色、法向量、纹理坐标等任意值。在顶点与片元shader程序间传递数据是很容易的,一般在顶点shader中修改varying变量值,然后片元shader中使用该值,当然,该变量在顶点及片元这两段shader程序中声明必须是一致的。例如:上面代码中应用程序中由顶点着色器传入片元着色器中的vColor变量。
(4)gl_Position为内建变量,表示变换后点的空间位置。顶点着色器从应用程序中获得原始的顶点位置数据,这些原始的顶点数据在顶点着色器中经过平移、旋转、缩放等数学变换后,生成新的顶点位置。新的顶点位置通过在顶点着色器中写入gl_Position传递到渲染管线的后继阶段继续处理。
2. 片元着色器
2.1 片元着色器示例代码
此片元着色器的主要功能为根据接收的记录片元纹理坐标的易变变量中的纹理坐标,调用texture2D内建函数从采样器中进行纹理采样,得到此片元的颜色值。最后,将采样到的颜色值传给gl_FragColor内建变量,完成片元的着色。
2.2 片元着色器介绍
片元着色器是一个处理片元值及其相关联数据的可编程单元,片元着色器可执行纹理的访问、颜色的汇总、雾化等操作,每片元执行一次。片元着色器替代了纹理、颜色求和、雾以及Alpha测试,这一部分是需要开发者自己开发的。
(1)varying指的是从顶点着色器传递到片元着色器的数据变量
(2)gl_FragColor为内置变量,用来保存片元着色器计算完成的片元颜色值,此颜色值将送入渲染管线的后继阶段进行处理。
二、加载着色器代码示例
上述示例代码中主要用到了三个方法:
1. GLES20.glCreateShader(),创建一个容纳shader的容器,称为shader容器。
如果调用成功的话,函数将返回一个整形的正整数作为shader容器的id。如果对c++熟悉的话,该函数的返回值理解为指针或者句柄更合适。
2. GLES20.glShaderSource(shader, source),添加shader的源代码。源代码应该以字符串数组的形式表示。当然,也可以只用一个字符串来包含所有的源代码。
3. GLES20.glCompileShader(shader),对shader容器中的源代码进行编译。
4. 调试
调试一个shader是非常困难的。shader的世界里没有printf,无法在控制台中打印调试信息,更没有断点,甚至很多编辑器对shader程序关键字、变量等连高亮显示都不支持。但是可以通过一些OpenGL提供的函数来获取编译和连接过程中的信息。
在编译阶段使用glGetShaderiv获取编译情况,在连接阶段使用glGetProgramiv获取连接情况。当错误产生的时候,还可以从InfoLog中获得更多的信息。InfoLog中存储了关于上一个操作执行时的相关信息,比如编译阶段的警告和错误,以及连接阶段产生的问题。不幸的是对于错误信息没有统一的标准,所以不同的硬件或驱动程序将提供不同的错误信息。
4.1 编译阶段使用glGetShaderiv获取编译情况
4.2编译阶段使用glGetShaderInfoLog获取编译错误
4.3 在连接阶段使用glGetProgramiv获取连接情况
4.4 在连接阶段使用glGetProgramInfoLog获取连接错误
4.5 清理shader的glDeleteShader方法
当不再需要某个shader或某个程序的时候,需要对其进行清理,以释放资源。前面,提到过如何向一个程序中添加一个shader。这里可调用下面的函数来将一个shader从一个程序中清除掉。
如果,一个shader被删除之前没有从相应的程序中排除,那么这个shader不会被实际删除,而只是被标记为被删除;当shader被从程序中排除的时候,才会被真正地删除。
三、创建着色器程序代码示例
1. glCreateProgram,在连接shader之前,首先要创建一个容纳程序的容器,称为着色器程序容器。可以通过glCreateProgram函数来创建一个程序容器。
2. glAttachShader,接下来,我们要将shader容器添加到程序中。这时的shader容器不一定需要被编译,他们甚至不需要包含任何的代码。我们要做的只是将shader容器添加到程序中。使用glAttachShader函数来为程序添加shader容器。
如果你同时拥有了,顶点shader和片元shader,需要分别将他们各自的两个shader容器添加的程序容器中。
3. glLinkProgram,链接程序。
在链接操作执行以后,可以任意修改shader的源代码,对shader重新编译不会影响整个程序,除非重新链接程序。
4. glUseProgram,加载并使用链接好的程序。
如果将program设置为0,表示使用固定功能管线。如果程序已经在使用的时候,对程序进行重新编译,编译后的应用程序会自动替代以前的那个被调用,这时你不需要再次调用这个函数。
四、 向着色器程序中传递数据
1. 获取着色器程序内成员变量的id,也可以理解为句柄、指针。
glGetAttribLocation方法:获取着色器程序中,指定为attribute类型变量的id。
glGetUniformLocation方法:获取着色器程序中,指定为uniform类型变量的id。
如:
// 获取指向着色器中aPosition的index
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
// 获取指向着色器中uMVPMatrix的index
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
2. 传递数据
使用上一节获取的指向着色器相应数据成员的各个id,就能将我们自己定义的顶点数据、颜色数据等等各种数据传递到着色器当中了。
2.1 glVertexAttribPointer,定义顶点属性数组。
2.2 启用或者禁用顶点属性数组。调用glEnableVertexAttribArray和glDisableVertexAttribArray传入参数index。如果启用,那么当glDrawArrays或者glDrawElements被调用时,顶点属性数组会被使用。
2.3 glActiveTexture,选择活动纹理单元。
glActiveTexture()确定了后续的纹理状态改变影响哪个纹理,纹理单元的数量是依据该纹理单元所被支持的具体实现。
0 0
- 【OpenGL】OpenGL ES 2.0 Shader相关介绍
- 15、OpenGL ES 2.0 Shader相关介绍
- OpenGL ES 2.0 Shader相关介绍
- OpenGL ES 2.0 Shader相关介绍
- OpenGL ES 2.0 Shader相关介绍
- android OpenGL ES 2.0 Shader相关介绍
- OpenGL ES 2.0 Shader相关介绍
- OpenGL ES 2.0 Shader相关介绍
- OpenGL ES 2.0 Shader相关介绍
- 【转】OpenGL ES 2.0 Shader相关介绍
- OpenGL ES 2.0Shader相关介绍
- OpenGL ES 2.0 Shader相关介绍
- OpenGL ES 2.0 Shader相关介绍
- OpenGL ES 2.0 Shader相关介绍
- OpenGL ES 2.0 Shader相关介绍
- OpenGL ES 2.0 - Shader
- OpenGL ES 2.0 Shader
- OpenGL ES 2.0 Shader
- 计算广告:基础知识
- Linux软件安装(二)——RPM与YUM
- 第三章 3.5.2 访问数组元素
- iOS开发笔记(三)
- hibernate.hbm2ddl.auto配置浅析
- OpenGL ES 2.0 Shader相关介绍
- C++ Primer | 第一章 开始
- java多线程实现数据共享
- Alluxio(Tachyon) 集群独立运行模式安装遇到的问题(非root用户)
- LA 3514 The Ministers' Major Mess(2-SAT)
- ListView+CheckBox 选中状态错乱问题
- 4.搜索之路——solr部署到Tomcat
- DataReader只读
- CentOS 7.x安装配置