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

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)

相关文章:

  • 健康生活新主张:全方位养生指南
  • WPF嵌入webapi服务器,充当微服务角色
  • 人工智能的前世今生
  • IRF2.0IRF3.1
  • 基于开源链动2+1模式AI智能名片S2B2C商城小程序的个性化与小众化消费社群构建研究
  • Spring Boot 使用 WebMagic 爬虫框架入门
  • 利用无事务方式插入数据库解决并发插入问题
  • 深入解析 .NET Kestrel:高性能 Web 服务器的架构与最佳实践
  • 论文笔记——QWen2.5 VL
  • 二、HTML
  • curl详解
  • 从工厂到生活:算法 × 深度学习,正在改写自动化的底层逻辑
  • 机器人--架构及设备
  • 【数据结构】--- 双向链表的增删查改
  • spring-boot-maven-plugin 将spring打包成单个jar的工作原理
  • 25_04_30Linux架构篇、第1章_02源码编译安装Apache HTTP Server 最新稳定版本是 2.4.62
  • MySQL基础关键_002_DQL(一)
  • 湖北理元理律师事务所观察:民生债务问题的系统性解法
  • 【SpringBoot】基于mybatisPlus的博客管理系统(2)
  • 《操作系统真象还原》第十一章——用户进程
  • 当农民跨进流动的世界|劳动者的书信①
  • 聚焦各领域顶尖工匠,《上海工匠》第十季于五一播出
  • 结婚这件事,年轻人到底怎么想的?
  • 庄语乐︱宋代历史是被“塑造”出来的吗?
  • 我国对国家发展规划专门立法
  • 海南旅文局通报游客入住酒店港币被调包:成立调查组赴陵水调查