当前位置: 首页 > backend >正文

OpenGL-ES 学习(10) ---- OpenGL-ES Shader语言语法

目录

      • Shader 举例
      • Shader 语法
        • 版本规范声明
        • 变量和定法方法
        • 向量构造方法
        • 矩阵构造方法
        • 结构,数组,函数定义
          • 结构
          • 数组
          • 函数
        • 内建函数
        • 条件语句和运算符
        • 统一变量
        • 统一变量块
        • Shader 输入输出
        • 插值限定符
        • 预处理命令
        • 精度限定符
        • 不变性

Shader 举例

一个典型的简单的 Shader 程序:

const char vShaderStr[] ="#version 300 es                            \n""layout(location = 0) in vec4 a_position;   \n""layout(location = 1) in vec4 a_color;      \n""out vec4 v_color;                          \n""void main()                                \n""{                                          \n""    v_color = a_color;                     \n""    gl_Position = a_position;              \n""}";

Shader 语法

版本规范声明

定义在 Shader 程序的第一行;
Shader 版本规范 没有声明版本号的默认将会使用 1.0 版本,但是3.0版本中显然定义了更多的功能

变量和定法方法
分类类型描述
浮点向量float、vec2、vec3、vec4有1,2,3,4 个分量的浮点向量类型
整数向量int, ivec2, ivec3, ivec4有1,2,3,4 个分量的整数向量类型
无符号整数向量uint, uvec2, uvec3, uvec4有1,2,3,4 个分量的无符号整数向量类型
布尔向量bool, bvec2, bvec3, bvec4有1,2,3,4 个分量基于bool的向量类型
矩阵mat2 mat2x3 mat2x4 mat3x2 mat3 mat3x4 mat4x2 mat42-2 2-3 2-4 等不同的向量类型

OpenGL ES 的变量只能赋值为同类型的其他变量
或者和同类型的其他变量进行运算

举例:

float myFloat = 1.0	
float myFloat2 = 1	 **定义错误,类型转换错误**
bool myBool = true	
int myInt = 0	
int myInt2 = 0.0	**定义错误,类型转换错误**
myFloat = float(myBool)	 **类型转换 bool -> float**
myFloat = float(myInt)	**类型转换 int -> float**
myBool=bool(myInt)	**类型转换 int -> bool**
向量构造方法
定义方法含义
vec4 myVec4 = vec4(1.0)vec4 myVec4 = vec4{1.0, 1.0,1.0,1.0}
vec3 myVec3 = vec3(1.0,0.0,0.5)myVec3 = {1.0, 0.0, 0.5}
vec3 temp = vec3(myVec3)temp = myVec3
vec2 myVec2 = vec2(myVec3)myVec2 = {myVec3.x, myVec3.y}
myVec4 = vec4(myVec2, temp)myVec4 {myVec2.x, myVecy, temp.x, temp.y}
矩阵构造方法

矩阵的每个分量可以用 {r, g, b, a} {x, y, z, w} {s, t, p, q}

  • 矩阵分量如果只设定为一个标量参数,那么该值将会被放置在对角线上
  • 矩阵可以从多个向量参数构造,mat2 可以用两个 vec2 构造
  • 矩阵可以从多个标量参数构造
结构,数组,函数定义
结构

结构可以认为是C语言中的结构体的概念

struct {vec4 color;float start;float end;
} fogVar;
数组

数组与C语言类型 从 0 开始索引

float floatArray[4];
vec4 vecArray[2];

数组的构造初始化形式:

float floatArray[4] = float[](1.0, 2.0, 3.0,4.0);
float floatArray[4] = float[4](1.0, 2.0, 3.0,4.0);
vec2 c[2] = vec2[2](vec(1.0), vec2(1.0)))
函数

声明方法和C语言相同,如果函数在定义之前使用,那么必须要提供原型声明,区别在于参数的传递方法,Open-GL ES 中的限定符:

限定符描述
in没有指定时的默认限定符 这个限定值按照参数值传递,函数不能修改
inout 这个限定符按照引用传入参数,在函数退出后会变化
out 该变量不被传入函数,在函数返回时会被修改

函数不能递归

内建函数

常用的内建函数都是有的,比如 sincos 等等

条件语句和运算符

举例:
if(color.a < 0.25)
条件语句中测试的表达式必须是一个 bool 值

统一变量

统一变量是应用程序通过 Open-GL ES API 传入的, Shader 只是读取 Uniform 的值

uniform mat4 viewProjMatrix;
uniform mat4 viewMatrix;
uniform vec3 lightPosition;

注意统一变量的命名空间在 VertexShaderPixelShader 都是共享的,也就是说,如果 VertexShaderPixelShader 一起链接到一个程序对象,它们就会共享同一组统一变量,如果在VertexShaderPixelShader 声明同一个同一变量,那么两个声明必须匹配

统一变量通常保存在硬件中,这个区域被叫做常量存储,是硬件中为存储常量值而分配的特殊空间,因为常量的大小一般是固定的,所以程序中可以使用统一变量数量受到限制,OpenGL ES 3.0 实现必须提供 256 个顶点统一向量和224 个片段统一向量

统一变量块

统一变量缓冲区对象可以通过一个缓冲区对象支持统一变量数据的存储,具备下面的优势:

  • 统一变量的缓冲区数据可以在多个程序之间共享,但是只需要设置一次
  • 统一变量对象可以存储大量的统一变量数据
  • 在缓冲区对象之间切换比单独加载一个统一变量更加高效
Shader 输入输出

顶点输入变量用于指定 VetexShader每个顶点的输入,用 in 关键字指定;它们通常存储位置,法线,纹理坐标和颜色 这样的数据
顶点输入是为绘制的每个顶点指定的数据;本质上,应用程序会为每个顶点创建一个顶点数组,该数组包含位置和颜色。
底层硬件通常可以在输入Vertex shader 的数量上有限制,OpenGL ES 3.0 实现可支持的最小属性为 16个

#version 300 es
uniform mat4 u_matViewProjection;
layout(location  =  0) in vec4  a_position
layout(location  =  1) in vec4  a_color
out vec3  v_color
void main(void) {gl_position = u_matViewProjection * a_positionv_color = a_color;
}#version 300 es
precision medium floatin vec3 v_color
layout(location = 0) out vec4 o_fragColor
void main()
{o_fragColor = vec4(v_color, 1.0)
}
插值限定符

OpenGL ES 支持两种插值

  • 线性插值,平滑着色
  • 平面着色
    定义了顶点着色器在基本图元中的插值形式:

线性插值:

smooth out vec3 v_color
smooth in vec3 v_color

平面着色

flat out vec3 v_color
flat in vec3 v_color
预处理命令
#define
#undef
#if
#ifdef
#ifndef
#else
#elif
#endif
__LINE__
__FILE__
#version
GL_ES#error
#extension
#pragma
精度限定符

精度限定符可以用作任何基于浮点数或者整数的变量的精度,关键字为
lowpmeidumphighp
示例:

highp vec4 position;
varying lowp vec4 color;
mediump float specularExp;

也可以对类型指定默认精度

presision highp float;
presision medium int;

float 指定的精度将用作基于浮点值的变量的默认精度,

  • VertexShader ,没有指定默认精度,为 intfloat 的值都是 highp;
  • 但是在 Pixel Shader 没有默认的精度值,每个Pixel Shader 必须指定一个精度
不变性

OpenGL-ES 规定的 invariant 关键字可以用于任何可变顶点的 Shader 输出;
Shader 编译的时候,编译器进行优化,可能导致指令的重新排序; 这种指令的重排意味着两个 Shader 之间的等价计算不能保证产生完全相同的结果,这种不一致性在多变的Shader 特效的时候尤其会有可能产生问题,在这种情况下,相同的对象会用Alpha 混合绘制在自身上方,如果计算输出位置的数值的精度不完全一样,精度差异就会产生伪像。这个对象通常表现为深度冲突(Z Fighting),
可以将变量定义为 invariant变量,比如:

	invarient gl_positioninvarirent textCoord

一旦某个输出变量声明了不变性,编译器便保证相同的计算和 Shader 输入的条件下计算结果相同,

也可以用 #pragma 让所有的变量保持不变:

	#pragma STDGL   invarient(all)
http://www.xdnf.cn/news/3391.html

相关文章:

  • CMake中强制启用option定义变量的方法
  • Unity SpriteEditor(精灵图片编辑器)
  • C++笔记-继承(下)(包含派生类的默认成员函数,菱形继承等)
  • AJAX 实例
  • vscode 的空格和 tab 设置 与 Rime 自建词库
  • AI大模型基础设施:主流的几款开源AI大语言模型的本地部署成本
  • 企业内训|智能驾驶与智能座舱技术——某汽车厂商
  • Ubuntu18 登录界面死循环 Ubuntu进不了桌面
  • 初学Vue之记事本案例
  • 【Linux】VSCode用法
  • 【嵌入式———通用定时器基本操作——实验需求2:案列:测量PWM的频率/周期】
  • 用手机相册教我数组概念——照片分类术[特殊字符][特殊字符]
  • 构建现代分布式云架构的三大支柱:服务化、Service Mesh 与 Serverless
  • 第十一届蓝桥杯 2020 C/C++组 门牌制作
  • vue 常见ui库对比(element、ant、antV等)
  • 兰亭妙微:数据驱动的 B 端设计:如何用 UI 提升企业级产品体验?
  • 【Qt】网络
  • ZYNQB笔记(十六):AXI DMA 环路测试
  • FreeSWITCH 发送 sip message 的 lua 程序
  • 深挖Java基础之:变量与类型
  • 总结C++中的STL
  • 分布式事务,事务失效,TC事务协调者
  • 图数据库榜单网站
  • 算法每日一题 | 入门-顺序结构-字母转换
  • X²+1素数问题
  • DirectX12(D3D12)基础教程七 深度模板视图\剔除\谓词
  • 【数据结构与算法】跳表实现详解
  • Windows结合WSL之ext4.vhdx不断增大问题
  • 第九节:文件操作
  • C++漫游指南——字符串篇与内存分配篇