opengl es c语言教程,OpenGL ES2 学习教程4——Shader语言
shader语言可以看成是特殊的C语言,专门用来创建顶点片段着色器程序的语言。像第二节里的程序
// vertex shader
attribute vec4 vPosition;
void main() {
gl_Position = vPosition;
}
// fragment shader
precision mediump float;
void main() {
gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}
基本类型
标量 float int bool
浮点矢量 float vec2 vec3 vec4
整数矢量 int ivec2 ivec3 ivec4
布尔矢量 bool bvec2 bvec3 bvec4
矩阵 mat2 mat3 mat4(分别是22,33,4*4的浮点型矩阵)
void类型(表示没函数返回或空的参数)void
采样器(用于指定纹理)sampler2D samplerCube
结构体和数组
struct type-name { // 结构体不支持嵌套
members
} struct-name; // 结构体也可以声明为数组,struct-name[]
float foo[3];
// 只支持一维数组
修饰符(限定符)
none 默认限定符:默认定义变量都是none,局部可读写变量或参数。
const 常量限定符:编译时的常量,或表示只读的函数参数,结构体的成员不能声明为常量,结构体变量可以。
attribute 属性限定符:可以由应用程序指定通过GLES传给顶点着色器的每一个顶点数据,只能用在顶点着色器。值为只读,只能被是定为float vec2 vec3 vec4 mat2 mat3 mat4,不能被定义为数组和结构体。GLES规定至少支持8个属性,每个属性被存储为4个分量的存储单元,因此可以将float这样的变量组合为一个vec4来节约空间。典型的被用来储存位置、法线、贴图坐标和颜色数据。着色器里被声明为属性的变量是只读资源,不能被修改。
uniform 全局限定符:在图元处理期间不会被改变的值,可以由应用程序通过GLES传给顶点片段着色器的全局变量。被所有的着色器共享。uniform存储各种着色器需要的数据,例如:转换矩阵、光照参数或者颜色。基本上各种输入着色器的常量参数像顶点和片段(但在编译时并不知道)都应该是uniform。他们在硬件中被放在称为“常量存储区(constant store)“中。同样它也有数量限制的,GLES规定至少128个顶点着色器uniform和16个片段着色器uniform。
varying 易变限定符:经过插值的易变变量,由顶点着色器传给片段着色器,易变变量在顶点着色器和片段着色器中要使用相同的类型和名字。只有在片段着色器中静态使用的易变变量才需要在顶点着色器中成对定义。不能用结构体定义,只能声明为浮点型标量,矢量和矩阵。同样有数量限制。包括属性和全局变量最大值都由glGetIntegerv查询(GL_MAX_VERTEX_ATTRIBUTE,GL_MAX_VERTEX_UNIFORM_VECTORS,GL_MAX_FRAGMENT_UNIFORM_VECTORS,GL_MAX_VARYING_VECTORS)。
GLint maxVertexAttribs;
GLint maxVertexUniforms;
GLint maxFragmentUniforms;
GLint maxVaryings;
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxVertexUniforms);
glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxFragmentUniforms);
glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
//在我手机上的输出:
//I/GLES-Tutorial(18378): maxVertexAttribs: 16
//I/GLES-Tutorial(18378): maxVertexUniforms: 256
//I/GLES-Tutorial(18378): maxFragmentUniforms: 224
//I/GLES-Tutorial(18378): maxVaryings: 16
构造器
shader语言有着非常严格的类型判断,不支持隐式转化,类型的转化必须用构造器。
float fA = 1.0;
bool bB = true;
int iC = 0;
fA = float(bB); // convert bool to float
vec4 myVec4 = vec4(1.0); // myVec4 = {1.0, 1.0, 1.0, 1.0}
vec3 myVec3 = vec3(1.0, 0.0, 0.5);
vec3 temp = vec3(myVec3);
struct light {
float intensity;
vec3 position;
};
light lightVar = light(3.0, vec3(1.0));
分量
矢量的分量名称:{x,y,z,w}表示顶点; {r,g,b,a}表示颜色;{s,t,p,q}表示纹理坐标。
每个分量用点号连接(例如v2.x(一个float变量),v3.rg(一个vec2变量))。
不同组的分量不能混合使用(例如v4.xgba不合法),但是顺序可以任意,可以重复(例如v3.yyxx(一个vec4变量)),但不能超过4个,因为编译器不知道转化成什么类型(例如v4.xyzwxy不合法)。
矩阵的分量就是用下标表示,注意的是矩阵是以列优先的。
mat4 m;
m[1] = vec4(1.0); // 矩阵第二列设置为{1.0, 1.0, 1.0, 1.0}
m[2][0] = 1.0;
操作符
和C语言类似,但是更加严格。执行操作的变量必须是相同的基本类型,二进制运算加减乘除必须是浮点型或整型。
函数
函数参数需要加上限定词,指示这个变量是否能够被函数修改。
举个栗子:
vec4 myFunc(inout float myFloat, // inout parameter
mat4 myMat4, // in parameter (default)
out vec4 myVec4); // out parameter
in 默认修饰符,表示为输入,不能被函数修改
inout 表示为引用,可以被修改
out 表示不是函数输入,它的值在函数返回后将被修改
shader语言提供许多内置函数,例如dot
流程控制语句
Shader语言支持简单的if-else;但是条件结果必须是布尔值。
循环语句限制非常严格:必须有循环迭代变量,他必须是增加或减少的,停止的条件必须匹配索引并且为常量表达式,在循环内部不能改变迭代的值。这些限制使得编译器能够把循环语句展开。
// 合法的栗子
for (int i = 0; i < 5; i++)
{
sum += i;
}
// 不合法的栗子1
float myArray[5];
for (int i = 0; i < 5; i++)
{
sum += myArray[i] // 不允许出现非常量表达式
}
// 不合法的栗子2
uniform in loopIter;
for (int i = 0; i < loopIter; i++) // 停止条件不是常量表达式
{
sum += i;
}
预处理指令
#define #undef #if #ifdef #ifndef #else #elif #endif
__LINE__ // 在着色器中的当前行号
__FILE__ // GLES2中总是0
__VERSION__ // GLES的版本 (e.g., 100)
GL_ES // 被定义为1
#version 100 // GLES Shading Language v1.00, 总是要放在最开头
#extension extension_name : behavior
// behavior可以是require, enable, warn,disable
#extension GL_OES_texture_3D : enable // 如果3D贴图扩展不被支持让预编译产生警告
注意和C++不同,宏不能带参数。
精度控制
精度控制能够被使用在任何浮点和整型数变量。可以设置为高highp,中mediump,低lowp。
highp vec4 position;
varying lowp vec4 color;
// 默认的精度可以这么设置在头部
precision highp float;
precision mediump int;
不变性
GLES中,invariance是被用于任何顶点着色器的变量输出的关键字。由于着色器编译时可能进行优化,一些指令被重新整理,可能两个着色器中间相同的计算产出不同的值来。在多通道着色器的特殊情况下,同样的物体使用透明混合(alpha blending)来绘制时能造成清晰度的不同。引入invariance,着色器会让同样的输入计算后输出的值相同。
invariant gl_Position; // 声明不变性输出
// 可以使用#pragma来保证全局变量的不变性
#pragma STDGL invariant(all) // 它将限制编译器的优化,除非必要最好不用,会导致性能下降
编辑工具
在Mac下可以使用Shader Builder(apple-opengl找到 graphics tools的链接,去下载对应你XCode版本的)来编写、运行、测试OpenGL shaders
opengl es c语言教程,OpenGL ES2 学习教程4——Shader语言相关推荐
- Android OpenGL ES 从入门到精通系统性学习教程
1 为什么要写这个教程 目前这个 OpenGL ES 极简教程的更新暂时告一段落,在此之前,很荣幸获得了阮一峰老师的推荐. 因为在工作中频繁使用 OpenGL ES 做一些特效.滤镜之类的效果,加上平 ...
- 【AR实验室】OpenGL ES绘制相机(OpenGL ES 1.0版本)
0x00 - 前言 之前做一些移动端的AR应用以及目前看到的一些AR应用,基本上都是这样一个套路:手机背景显示现实场景,然后在该背景上进行图形学绘制.至于图形学绘制时,相机外参的解算使用的是V-SLA ...
- android opengl es 绘制余弦曲线,Android OpenGL ES - 绘制线、面
前言 之前一篇文章讲了如何绘制点,所谓两点成线,三点成面.一个立体图形就是由很多面组成,在OpenGL ES中,面特指一个三角形. 绘制调用glDrawArrays(int mode, int fir ...
- oracle安装搜狗输入法教程,Linux入门学习教程:在Ubuntu 14.04中安装使用搜狗拼音输入法...
然后,访问搜狗输入法Linux版的官网,http://pinyin.sogou.com/linux,下载搜狗输入法Linux版.从官网可以看到,该输入法官方只支持Ubuntu(不过网上有人通过将deb ...
- 新手先学python还是c语言,初学者应该选择学习Python还是C语言
小编给大家分享一下初学者应该选择学习Python还是C语言,希望大家阅读完这篇文章后大所收获,下面让我们一起去探讨吧! 有人觉得应该从C语言开始入门,原因如下: 1.C语言是你上大学第一门接触的编程语 ...
- ★教程2:fpga学习教程入门100例目录
1.订阅本教程用户可以免费获得本博任意2个(包括所有免费专栏和付费专栏)博文对应代码: 2.本FPGA课程的所有案例(部分理论知识点除外)均由博主编写而成,供有兴趣的朋友们自己订阅学习使用.未经本人允 ...
- opengl es java_java – 在Android OpenGL ES App中加载纹理
1)您应该根据需要分配尽可能多的纹理名称.一个用于您正在使用的每个纹理. 加载纹理是一项非常繁重的操作,会使渲染管道停顿.所以,你永远不应该在游戏循环中加载纹理.您应该在呈现纹理的应用程序状态之前具有 ...
- C语言作业d1138,Git学习教程(六)Git日志
转载:http://fsjoy.blog.51cto.com/318484/245261 第六课 Git 日志 内容提要:浏览项目历史,查询指定提交内容,图形化显示分枝和合并... 'git log' ...
- python是c语言写的吗-学习python还是c语言?
并不是大神,只是CS专业的一名小学生.先说结论,强烈推荐先学C. 简单地说,你用半年时间学C语言,学会之后,再去学C++只需三个月,学python这种东西只要一个月,牛逼的人一个星期也能掌握. 可是反 ...
- PyTorch 1.0 中文官方教程:迁移学习教程
译者:片刻 作者: Sasank Chilamkurthy 在本教程中,您将学习如何使用迁移学习来训练您的网络.您可以在 cs231n 笔记 上关于迁移学习的信息 引用这些笔记: 在实践中,很少有人从 ...
最新文章
- 扎克伯格成美国科技巨头里最后一位在任创始人CEO
- 怎么看服务器上jdk安装位置,查看云服务器jdk安装路径
- wordpress 文章页面 (single.php)
- 服务器响应为4.7.0,454 4.7.0 临时身份验证失败 - Exchange | Microsoft Docs
- 关于html5之canvas的那些事
- Linux 内核与模块调试
- C#操作Excel数据库方法
- UAC白名单解决每次启动都弹出UAC对话框(不用关闭UAC)
- eclipse 中各种小图标含义
- 2022年第一季度保险服务数字化跟踪分析
- Sublime Text3轻量型跨平台C/C++开发环境(上) 安装使用篇
- 抽奖动画 - lao虎机抽奖,手把手教你做一个抽奖机软件
- oracle创建bigfile表空间,表空间管理之bigfile表空间设置
- 单纯形法和单纯形表法
- 3D变电站园区3D可视化电力监控管理平台
- 基于Echarts实现可视化数据大屏实时监测大数据
- android 读取wps_Android 实现 调用 WPS Office手机版接口
- 10个有用的第三方iOS开源库
- 淘宝运营 淘金币的定义 怎样利用淘金币引流 怎样推广
- 恭喜本人的《Three.js基础入门》上线达人课!