Shader-1
写一些简单的小文章的目的主要是记录阅读相关书籍的内容,以及主观上记录各种术语的含义,可能会有偏颇,在深入学习之后会进行修正。
1.游戏图形
作为一个shader的开端,我希望学习的是如何去使用,本着木匠不需要知道如何制作扳手的观念去学习,当然,这只是开端,有了一定的基础之后还是会深入的学习,接下来的内容主要就是宏观的介绍一下图形以及相关背景知识。
1.1 什么是渲染?
在计算机图形学当中,渲染(render)指的是创建图形的过程,从一组2D或3D网格,以及相关的场景信息创建图像的过程。由渲染过程创建的图像有时被称为渲染或者帧。很多情况下,大多数游戏一秒会生成30到60次的新帧,以提供流畅的体验。
在计算机图形学当中,许多的术语都是由电影中借用的,摄像机便是借用的术语之一。在电影中,摄像机的位置和方向决定了屏幕上的内容。在图形学当中,摄像机也决定了哪些图像应该显示出来、哪些不应该显示出来。归根结底,摄像机的本质就是一个包含着位置和方向的数据结构。这些位置和方向的信息决定了哪些对象可见,并且哪些需要在当前帧绘制出来。
在图像开发的代码中,负责绘制图像(专业点就是渲染帧)的代码称为渲染引擎,渲染引擎将网格数据转换为新的图像的一系列步骤称为渲染管线(rendering pipeline)又称为渲染流水线。管线的作用就是能高效的处理大量的,有相似处理过程的数据。绘制图形的过程中需要大量相似的处理顶点。网格是管线操作的对象,换句话来说就是渲染管线处理的是大量的顶点数据。
1.2 网格
网格是一种用计算机能理解的方式描述形状的方法之一。为了定义形状,网格需要储存3个信息:顶点、边和面。
网格的基本概念:
一系列的面片F=(fi,f2,…,fn),每一个面片都是三角形(为了速度和简单性);
一系列的顶点V=(v1,v2,…,vn),F中的每个面片是V中顶点的序列组。(网上大佬文章摘抄)
网格在代码中定义起来十分简单,只有网格的顶点储存在内存中,网格的边和面由顶点的顺序隐式定义。顶点的顺序由两种定义方式:
一是顶点本身的储存方式。
二是利用索引值(indices)来定义。
顶点的顺序决定了网格的哪一面被称为“正面”。在检查一个网格面时,假设顶点是围绕一个多边形的中心逆时针顺序定义的,那么我们可以称为这个面就是网格面的“正面”,当然也可以顺时针定义“正面”。
判断网格面的哪一侧是正面是十分重要的,许多游戏不会渲染网格面的“背面”,这是一种称为背面剔除的优化,经常在游戏中使用。
网格的顶点是使用向量定义的。具体到例子就是之前的光照模型当中,光源的位置定义为:
"uniform vec4 u_LightPosition;\n" +
这里说的用向量定义是指在专门的着色器语言中,若要定义一个顶点,采用的是向量类型来定义,但是在着色器当中,向量的含义仅仅是一系列相同数值类型的数值组合而成的一个数据结构。它所蕴涵的矢量中方向的含义是人主观上理解的。因此对于向量的乘法和除法,并不符合常规的数学定义,其原因也在于此。
从目前的角度理解,网格面就相当于一个立体的绘画板,网格就相当于方便绘图的背景(对应着方便计算机理解的方式定义图形),这个绘画板上只有点,线和三角面,并且只有点是能在绘画板上实际表示出来的,线和三角面的表达都依赖顶点的顺序,从正面和反面的方式来看绘画板上的图形是不一样的,也可以理解为独立的。绘画板上顶点的坐标都是已知的。渲染的过程就是在计算机的窗口系统中根据绘画板上的数据重现你的绘画板上的内容的过程。点,线和面就相当于基本的图形API的图元,通过这三个基本的图元可以通过数学公式描述和近似逼近去近似出各种各样的复杂图形。绘画板或者说网格面是二维的,但是许多复杂的图像是三维的,这就需要依赖于矩阵的变换。
下面大致的讨论下向量,着重记录的是向量在GLSL中的含义。
1.3 基本向量知识
这里的向量都是在网格面中的,主要作用是用来描述顶点的位置,因此主要的形式是坐标的形式而不是常规上的字母上的形式。
向量各种正式的定义就是将其描绘成既有大小也有方向的量。但是从向量的名称来看,向量可以看为从一个点到另一个点的运动:向量的名称来源于拉丁语单词vehere,意思是"携带",因此可以将向量看成携带某物从一个点到另一个点。
尽管向量本身不表示任何的位置信息,但是向量用于定义位置却非常常见。当一个向量被用来指代某物的位置时,该向量的起始点被假定为这个向量所在任意坐标系下的原点。这里的原点是数学上抽象的定义,具体到例子可以有很多的含义,比如门前10米的树,那么原点就为门口,以门口建立二维坐标系,则 (10,0)或者(0,10)向量表示的就是树的位置。
向量通常被称为括号里的一系列数字。数字的个数称为向量的维数。一个向量可以有任意数量的维数。在图形学当中最常用的向量的维数就是四维,也就是齐次坐标,该点所在的坐标系称为齐次坐标系。基本形式为(x,y,z,w)。GLSL中内置的矢量类型vec2 vec3 vec4对应的分别就是二维向量,三维向量和四维向量。下面大致介绍向量的加法和减法。
向量的加法:数学上定义向量的加法遵从两个法则,分别是三角形法则和平行四边形法则,坐标上的定义就是矢量对应的分量直接相加。从实际上含义上,向量的加法可以表示成路径的选取。假设有两个点A B。他们最直接的路径就是从A直接走到B,也就是AB线段。当然,A B中也可以有很多点,假设有个点C,那么从A到C然后从C到B最终的效果还是从A到B。这里体现出的就是向量加法的含义而不是抽象的定义。
向量的减法:对应的是矢量对应的分量相减,对应到几何意义表示的就是方向。向量B减去向量A表示从A到B的一条有向线段,这在光照当中也有应用,用于定义光线方向。
向量的乘法和除法,对应的就是矢量对应方向的直接相乘或者相除,这一点与数学定义上很不一样。这就反应出矢量这种数据类型在GLSL中只是一个有序的数字序列。它所代表的位置含义是人为所赋予它的。并且用向量来描述位置要依赖于坐标系。若要计算向量的点积或叉积,在GLSL/GLSL ES中具有相关的内置函数来辅助计算。
但是以上定义的向量运算在图像的处理是十分便捷的。
1.4 计算机图形学中定义颜色
在所有类型的编程当中,通常是将颜色表示为3个值的序列,一个表示红色分量,一个表示绿色分量,一个表示蓝色分量。有时他们表示为一系列整数(0到255)、一系列浮点数或一系列十六进制数。
在着色器中,我们几乎总将颜色视为一系列的浮点数,并且还另外加了一个分量,用于表示颜色的透明度alpha值。用向量储存时各个分量称为R G B A。
1.5 渲染管线
渲染管线(rendering pipeline)用来表示GPU将网格数据转换为屏幕上的图像所需的一系列过程。着色器(shader)作为管线的一部分完成其工作。
简化后的渲染管线大致流程:
网格顶点数据-->顶点着色器-->输出基本图元-->光栅化-->对图元输出一系列的片元(携带信息的像素)-->片元着色器上色-->片元处理
片元处理这个阶段管线的主要作用主要包括片元检测和混合操作:片元检测决定了哪些片元要放在屏幕上,哪些片元要丢弃。通常来说GPU创建的片元要多与屏幕要填充的片元,因为片元的产生仅仅依赖于顶点数据,它无法确定哪些顶点会被遮盖而不用显示以及相似的情况。片元检测就用于处理多余的片元。混合操作是指有透明度的物体的本身颜色和后面物体的颜色混合起来所产生的新的颜色。
以上只是简化后的渲染管线,真正的渲染管线要复杂的多。
1.6 着色器
随着现代的GPU的发展以及open GL2.0的发布,允许了GPU的可编程性。我们通过着色器来对GPU操作,着色器本身就是一段程序,编写着色器的语言称为shader语言,目前学习的主要是GLSL /GLSL ES(GLSL的嵌入版),着色器分为顶点着色器和片元着色器,影响到渲染管线中的顶点处理部分和片元处理部分。
总结:
主要介绍了:
渲染的相关概念,网格的相关概念,向量用来储存颜色,方向,位置,基本运算,颜色的表示方法,渲染管线和着色器。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具