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

OpenGL(三)着色器语言GLSL

着色器语言

在GPU上运行的图形渲染语言,类C风格。

类似于CUDA,但是又没有CUDA通用,又有点像Verilog这种硬件描述语言

GLSL是一种着色器语言,需要有对应的图形API环境配合,可以使用OpenGL,也可以使用OpenGL ES,也可以使用WebGL。三者的关系可以简单理解为ES为GL的精简版,WebGL是ES的二次包装。其他图形API有自己对应的着色器语言,大同小异。

根据上篇blog提到的图形渲染流程,其中要用到着色器语言的流程有:

  • 顶点着色器:计算一个3D空间顶点的2D坐,输出为xyzw,其中xy为相机坐标系中的坐标,z为zbuffer,用于判断覆盖关系,w为放缩值,一般都是1,即不进行放缩。
  • 几何着色器:对所有顶点做处理
  • 片段着色器:计算每个像素的像素像素值,输出每个像素的RGBA,前面的为RGB通道,最后的A为透明通道。

GLSL基本语法

着色器代码结构:

#version version_number //版本信息,GLSL的版本和OpenGL版本是对应的
in type in_variable_name;
in type in_variable_name; //输入数据类型,名称

out type out_variable_name;

uniform type uniform_name;

void main()
{
  // 处理输入并进行一些图形操作
  ...
  // 输出处理过的结果到输出变量
  //GLSL的顶点着色器必须设置gl_Position变量
  //片段着色器必须设置gl_FragColor变量
  out_variable_name = weird_stuff_we_processed;
}

如果我们打算从一个着色器向另一个着色器发送数据,我们必须在发送方着色器中声明一个输出,在接收方着色器中声明一个类似的输入。当类型和名字都一样的时候,OpenGL就会把两个变量链接到一起,它们之间就能发送数据了.
不同着色器之间的局部变量是无法互通的。
想要数据互通,GLSL中提供了一种类似于C语言全局变量的数据类型Uniform,初始化方式如上面代码所示。

数据类型

和其他编程语言一样,GLSL有数据类型可以来指定变量的种类。GLSL中包含C等其它语言大部分的默认基础数据类型:float,int,bool等。GLSL是强数据类型语言,不允许进行数据隐式变换。像int a = 1.0*3这种是不允许的int a = int(1.0)*3是允许的。GLSL中只有一维数组,声明方式和C语言一样,且GLSL数组提供了一个隐式的方法length()返回数组长度。

像cuda一样GLSL有几个数据并在一起的数据向量类型,例如vec4,包含4个float数据的向量。

类型含义
vecn包含n个float分量的默认向量
bvecn包含n个bool分量的向量
ivecn包含n个int分量的向量
uvecn包含n个unsigned int分量的向量
dvecn包含n个double分量的向量

向量最长为4,使用.xyzw来读取。允许一次读取多个元素

vec3 temp1 = vec3(0.1,0.1,0.1);
vec3 temp2 = temp1.zyx // 约等于顺序反转了
vec2 temp3 = temp1.xxx + temp2.xyz; //类似于广播机制

向量的点积和叉积使用内置函数dot和cross。
GLSL中内置的数据类型还有矩阵mat,但是矩阵只有浮点型的,而且是列优先排序。

mat4 m = mat4(1.0)//初始化一个对角线矩阵
vec2 a = vec2(1.0,2.0);
vec2 b = vec2(3.0,4.0);
mat2 n = mat2(a,b);
mat2 m = mat2(1.0,2.0,3.0,4.0);//列优先排列

m = n = [ 1 3 2 4 ] m = n = \begin{bmatrix} 1 & 3\\ 2 & 4 \end{bmatrix} m=n=[1234]

除此之外GLSL中还可以定义结构体,方法和C语言一样。且函数可以进行重载。

控制逻辑

for循环、if分支、函数定义,跟C语言都基本一致。

bool inRect(vec2 pt, vec4 rect)
{
	bool result = false;
	return result;
}

代码

一个顶点着色器和片段着色器的demo
VertexShader:

#version 330 core
layout (location = 0) in vec3 aPos;   // 位置变量的属性位置值为 0 
layout (location = 1) in vec3 aColor; // 颜色变量的属性位置值为 1

out vec3 ourColor; // 向片段着色器输出一个颜色

void main()
{
    gl_Position = vec4(aPos, 1.0);
    ourColor = aColor; // 将ourColor设置为我们从顶点数据那里得到的输入颜色
}

FragmentShader:

#version 330 core
out vec4 FragColor;  
in vec3 ourColor;

void main()
{
    FragColor = vec4(ourColor, 1.0);
}

效果:
在这里插入图片描述


http://www.kler.cn/news/303212.html

相关文章:

  • 深度学习速通系列:依存分析
  • 了解计算机安全性【技术、管理与法律】
  • 如何用 OBProxy 实现 OceanBase 的最佳路由策略
  • 算法类学习笔记 ———— 障碍物检测
  • 如何使用Visual Studio的内存诊断工具进行内存泄漏检测
  • 今年的智能手机不仅仅是AI
  • 区块链领航者孙宇晨:驾驭潮流,共绘未来新篇章
  • 基于Spark 的零售交易数据挖掘分析与可视化
  • Java | Leetcode Java题解之第403题青蛙过河
  • mysql一主2从部署
  • 记者协会评审系统-需求分析
  • 苹果CMS vs. 海洋CMS:哪个系统更易于百度收录?
  • 解决:Vue3 - defineProps 设置默认值报错问题
  • CentOS 入门基础
  • LeetCode 2398.预算内的最多机器人数目:滑动窗口+单调队列——思路清晰的一篇题解
  • 工业设备网关在智能工厂建设中发挥的作用,以某汽车制造厂为例
  • LabVIEW编程语言出于什么原因开发的?
  • 1688商品详情API返回值中的售后保障与服务信息
  • Failed building wheel for opencv-python-headless
  • k8s常用指令续:
  • Day 11-12:查找
  • day14-单例设计模式动态代理
  • Qt 学习第八天:菜单栏、工具栏、状态栏、模态和非模态对话框创建
  • RabbitMQ延迟消息——DelayExchange插件
  • Python之 条件与循环(Python‘s Conditions and loops)
  • 在麒麟系统 v10 SP3 上运行自带的 MariaDB
  • 【鸿蒙】HarmonyOS NEXT星河入门到实战6-组件化开发-样式结构重用常见组件
  • Oracle中VARCHAR和VARCHAR2的区别
  • CSS框架 Tailwind CSS
  • Leetcode3276. 选择矩阵中单元格的最大得分