Shader Language

潘辰龙
2023-12-01

shader language,称为着色语言,shade在英语是阴影、颜色深浅的意思,Wikipedia上对shader language 的解释为基于物体本身属性和光照条件,计算每个像素的颜色值。

实际上这种解释具有明显的时代局限性,在gpu编程发展的早期,shader language 的提出目标是加强对图形处理算法的控制,所以对该语言的定义亦针对于此,但随着技术的进步,目前的shader langguage 早已经用于通用计算研究。

shader language被定位为高级语言,如 GLSL的全称是“high level shading language”,cg语言的全称为“c for graphic”,并且这两种 shader language 的语法设计非常类似于c语言。 不过高级语言的一个重要特性是“独立于硬件”,在这一方面shader language暂时还做不到,shader language完全依赖于gpu架构,这一特征在现阶段是非常明显的。任意一种shader language都必须基于图形硬件,所以gpu编程技术的发展本质上还是图形硬件的发展。在shader language存在之前,展示基于图形硬件的编程能力只能靠低级的汇编语言。

目前,shader language的发展方向是设计出在便捷性方面可以和c++、jave相比的高级语言,“赋予程序员灵活而方便的编程方式”,并尽可能的控制渲染过程同时利用图形硬件的并行性,提高算法的效率。 shader language目前主要有3中语言: 基于opengl的glsl,基于direct3d 的hlsl,还有nvidia公司的cg语言。

这里我们是阐述shader语言的基本原理和运行流程,首先从硬件的角度对programmable vertex processor (可编程顶点处理器,又称为顶点着色器)和 programmable fragment processor 可编程片段处理器 又称片段着色器的作用进行阐述,然后在此基础上对 vertex program和fragment program 进行具体的论述,最后对glsl、hlsl和cg进行比较。

shader language 原理

使用shader 语言编写的程序称之为shader program(着色程序)。着色程序分为两类:vertex shader program 和 fragment shader program。为了清楚的解释顶点着色器和片段着色器的含义。

顶点和片段处理器被分离成可编程单元,可编程顶点处理器 是一个硬件单元,可以运行顶点程序,而可编程片段处理器则是一个可以运行片段程序的单元。

顶点和片段处理器都拥有非常强大的并行运算能力,并且非常擅长于矩阵(不高于4阶)计算,片段处理器韩可以高速查询纹理信息

顶点着色器控制顶点坐标转换过程,片段着色器控制像素颜色计算过程。这样就区分出顶点着色器程序和片段着色器程序的各自分工。

现阶段可编程图形硬件的输入、输出:
输入寄存器存放输入的图元信息;输出的寄存器存放处理后的图元信息;纹理buffer 存放纹理数据,目前大多数的可编程图形硬件只支持片段处理器处理纹理;从外部宿主程序输入的常量放在常量寄存器中;临时寄存器存放着色程序在执行过程中产生的临时数据。

Vertex Shader Program

vertex shader program 和 fragment shader program 分别被可编程顶点处理器和可编程片段处理器所执行。

顶点着色器程序从gpu前端模块(寄存器)中提取图元信息(顶点位置、法向量、纹理坐标等),并完成顶点坐标空间转换、法向量空间转换、光照计算等操作,最后将计算好的数据传送到指定寄存器中;然后片段着色程序从中获取需要的数据,通常为纹理坐标、光照信息等,并根据这些信息以及从应用程序传递的纹理信息,进行每个片段的颜色计算,最后将处理后的数据嵩光栅操作模块。

顶点做瑟琪和像素着色器的数据处理流程:
在应用程序中设定的图元信息(顶点位置坐标、颜色、纹理坐标等)传递到vertex buffer中;纹理信息传递到texture buffer 中。当前的顶点程序还不能处理纹理信息,纹理信息只能在片段程序中读入。

顶点着色程序与片段着色程序通常是同时存在,相互配合,前者的输出作为后者的输入。不过,也可以只有顶点着色器。如果只有顶点着色程序,那么只对输入的顶点进行操作,而顶点内部的点则按照硬件默认的方式自动插值。例如输入一个三角面片,顶点着色程序对其进行phong光照计算,只计算三个顶点的光照颜色,而三角面片内部点的颜色按照硬件默认的算法(gourand明暗处理或者快速phong明暗处理)进行插值,如果图形硬件比较先进,默认的处理算法较好(快速phong明暗处理),则效果也会较好;如果图形硬件使用Gourand明暗处理算法,则会出现马赫带效应(条带化)。

而片段着色程序是对每个片段进行独立的颜色计算,并且算法由自己编写,不但可控性好,而且可以达到更好的效果。

由于gpu对数据进行并行处理,所以每个数据都会执行一次shader程序。每个顶点数据都会执行一次顶点程序;每个片段都会执行一次片段程序。

Fragment Shader Program

片段着色程序对每个片段进行独立的颜色计算,最后输出颜色值的就是该片段最终显示的颜色。可以这样说,顶点着色程序主要进行几何方面的运算,而片段着色程序主要针对最终的颜色值进行计算。

片段着色程序还有一个突出的特点是:拥有检索纹理的能力。对于gpu而言,纹理等价于数组,这意味着,如果要做通用计算,例如数组排序、字符串检索等,就必须使用到片段着色程序。让顶点着色器也拥有检索纹理的能力,是目前的一个研究方向。

什么是片段?片段和像素由什么不一样?所谓片段就是所有的三维顶点在光栅化之后的数据集合,这些数据还没有经过深度值比较,而屏幕显示的像素都是经过深度比较的。

CG VS GLSL VS HLSL

shader 语言目前有三种主流语言:基于OpenGL的glsl(OpenGL shading language), 基于direct3d 的hlsl(high level shading language),还有nvidia公司的 cg(c for graphic)语言。
glsl 与hlsl 分别基于OpenGL和direct3d 的接口,两者不能混用,事实上OpenGL和direct3d 一直都是冤家对头,从来都是斗争不休,争斗良久,既然没有分出胜负,那么必然是两败俱伤的局面。

首先ati 系列显卡对OpenGL扩展支持不够,例如在使用osg(open scene graphic)来源图形引擎时,由于该引擎完全基于OpenGL,导致其上编写的3d仿真程序在较老的显卡上常常出现纹理无法显示的问题。其次glsl的语法体系自成一家,而hlsl和cg语言的语法基本相同,这就意味着,只要学习hlsl和cg中的任何一种,就等同学习了两种语言。不过opengl 毕竟图形api的曾经领袖,通常介绍OpenGL都会附上一句“事实上的工业标准”,所以在其长期发展中积累下的用户群庞大,这些用户当然会选择glsl学习。此外,glsl继承了OpenGL良好移植性,一度在unix 等操作系统上独领风骚(已是曾经的往事)。

微软的HLSL 移植性较差,在windows 平台上可谓一家独大,可一出自己
的院子(还好院子够大),就是落地凤凰不如鸡。这一点在很大程度上限制了
HLSL 的推广和发展。目前HLSL 多半都是用于游戏领域。我可以负责任的断言,
在Shader language 领域,HLSL 可以凭借微软的老本成为割据一方的诸侯,但,
决不可能成为君临天下的霸主。这和微软现在的局面很像,就是一个被带刺鲜花
簇拥着的大财主,富贵已极,寸步难行。

上面两个大佬打的很热烈,在这种情况下可以用一句俗话来形容,“鹬蚌相
争,渔翁得利”。NVIDIA 是现在当之无愧的显卡之王(尤其在AMD 兼并ATI
之后),是GPU 编程理论的奠基者,GeForce 系列显卡早已深入人心,它推出的
Cg 语言已经取得了巨大的成功,生生形成了三足鼎立之势。NVIDIA 公司深通
广告之道,目前最流行的GPU 编程精粹一书就出自该公司,书中不但介绍了大
量的GPU 前沿知识,最重要的是大部分都用Cg 语言实现。凭借该系列的书籍,
NVIDIA 不光确定了在青年学子间的学术地位,而且成功的推广了Cg 语言。
使用Cg 语言进行研发,基于如下理由:
其一,Cg 是一个可以被OpenGL 和Direct3D 广泛支持的图形处理器编程语
言。 Cg 语言和OpenGL、DirectX 并不是同一层次的语言,而是OpenGL和DirectX
的上层,即,Cg 程序是运行在OpenGL 和DirectX 标准顶点和像素着色的基础
上的;
其二,Cg 语言是Microsoft 和NVIDIA 相互协作在标准硬件光照语言的语法
和语义上达成了一致,,HLSL 和Cg 其实是同一种语言(参
见Cg 教程_可编程实时图形权威指南29 页的致谢部分)。很多时候,你会发现
用HLSL 写的代码可以直接当中Cg 代码使用。也就是说,cg 基于知识联盟
(Microsoft 和NVIDIA),且拥有跨平台性,选择cg 语言是大势所趋。有心的读
者,可以注意市面上当前的GPU 编程方面的书籍,大都是基于CG 语言的。(附:
Microsoft 和NVIDIA 联手推出Cg,应该是一种经济和技术上的双赢,通过这种方式联手打击GLSL)

此外,Cg,即C for graphics,用于图形的C 语言,这其实说明了当时设计
人员的一个初衷,就是“让基于图形硬件的编程变得和C 语言编程一样方便,自
由”。正如C++和Java 的语法是基于C 的,cg 语言本身也是基于C 语言的。如
果您使用过C、C++、Java 其中任意一个,那么Cg 的语法也是比较容易掌握的。
Cg 语言极力保留了C 语言的大部分语义,力图让开发人员从硬件细节中解脱出
来,Cg 同时拥有高级语言的好处,如代码的易重用性,可读性提高等。使用cg
还可以实现动画驱动、通用计算(排序、查找)等功能。

语言无高低,用法有高下。着色程序中的算法才是精髓所在!

 类似资料:

相关阅读

相关文章

相关问答