着色器

本页使用了标题或全文手工转换,现处于中国大陆简体模式
求闻百科,共笔求闻
着色器的常见应用是为三维模型生成光照和阴影。

计算机图形学领域中,着色器(英语:shader)是一种计算机程序,原本用于进行图像的浓淡处理(计算图像中的光照亮度颜色等),但近来,它也被用于完成很多不同领域的工作,比如处理CG特效、进行与浓淡处理无关的视频后期处理、甚至用于一些与计算机图形学无关的其它领域。[1]

使用着色器在图形硬件上计算渲染效果有很高的自由度。尽管不是硬性要求,但目前大多数着色器是针对GPU开发的。GPU的可编程绘图管线已经全面取代传统的固定管线,可以使用着色器语言对其编程。构成最终图像的像素顶点纹理,它们的位置、色相、饱和度、亮度、对比度也都可以利用着色器中定义的算法进行动态调整。调用着色器的外部程序,也可以利用它向着色器提供的外部变量、纹理来修改这些着色器中的参数。

电影后期处理、计算机成像电子游戏等领域,着色器常被用来制作各种特效。除了普通的光照模型,着色器还可以调整图像的色相饱和度亮度对比度,生成模糊高光、有体积光源、失焦、卡通渲染色调分离畸变凹凸贴图色键(即所谓的蓝幕、绿幕抠像效果)、边缘检测等效果。

历史

1988年5月,Pixar公布了第三版RenderMan规范,将“着色器”的使用推广到了我们目前所知的各大应用领域。[2]

随着图形处理器的进步,OpenGLDirect3D等主要的图形软件库都开始支持着色器。第一批支持着色器的 GPU 仅支持像素着色器,但随着开发者逐渐认识到着色器的强大,很快便出现了顶点着色器。2000年,第一款支持可编程像素着色器的显卡 Nvidia GeForce 3(NV20)问世。Direct3D 10 和 OpenGL 3.2 则引入了几何着色器。

目前,图形硬件正在朝统一着色器模型发展。

种类

常用的着色器有三种。比较老的显卡倾向于使用不同的处理单元处理不同类型的着色器,但新出的显卡通常都支持统一着色器模型,可以执行任意类型的着色器、更好地发挥显卡的处理能力。[3]

二维着色器

二维着色器处理的是数字图像,也叫纹理,着色器可以修改它们的像素。二维着色器也可以参与三维图形的渲染。目前只有“像素着色器”一种二维着色器。

像素着色器

像素着色器(英语:pixel shader)也叫片段着色器(英语:fragment shader),用于计算“片段”的颜色和其它属性,此处的“片段”通常是指单独的像素。最简单的像素着色器只有输出颜色值;复杂的像素着色器可以有多个输入输出[4]。像素着色器既可以永远输出同一个颜色,也可以考虑光照、做凹凸贴图、生成阴影高光,还可以实现半透明等效果。像素着色器还可以修改片段的深度,也可以为多个渲染目标输出多个颜色。

三维图形学中,单独一个像素着色器并不能实现非常复杂的效果,因为它只能处理单独的像素,没有场景中其它几何体的信息。不过,像素着色器有屏幕坐标信息,如果将屏幕上的内容作为纹理传入,它就可以对当前像素附近的像素进行采样。利用这种方法,可以实现大量二维后期特效,例如模糊和边缘检测

像素着色器还可以处理管线中间过程中的任何二维图像,包括精灵纹理。因此,如果需要在栅格化后进行后期处理,像素着色器是唯一选择。

三维着色器

三维着色器处理的是三维模型或者其它几何体,可以访问用来绘制模型的颜色和纹理。顶点着色器是最早的三维着色器;几何着色器可以在着色器中生成新的顶点;细分曲面着色器(英语:tessellation shader)则可以向一组顶点中添加细节。

  • 顶点着色器处理每个顶点,将顶点的空间位置投影在屏幕上,即计算顶点的二维坐标。同时,它也负责顶点的深度缓冲(Z-Buffer)的计算。顶点着色器可以掌控顶点的位置、颜色和纹理坐标等属性,但无法生成新的顶点。顶点着色器的输出传递到流水线的下一步。如果有之后定义了几何着色器,则几何着色器会处理顶点着色器的输出数据,否则,光栅化器继续流水线任务。
  • 几何着色器可以从多边形网格中增删顶点。它能够执行对CPU来说过于繁重的生成几何结构和增加模型细节的工作。Direct3D版本10增加了支持几何着色器的API, 成为Shader Model 4.0的组成部分。OpenGL只可通过它的一个插件来使用几何着色器,但极有可能在3.1版本中该功能将会归并。几何着色器的输出连接光栅化器的输入。

由于这些类型的着色器终究会用在GPU的流水线中,下面简述它们是如何被安排在流水线中的。

简化图形流水线

对于图形流水线的一般描述,参见绘图管线

  • 中央处理器(CPU)发送指令(编译的着色器程序)和几何数据到位于显卡内的图形处理器(GPU)。
  • 顶点着色器执行几何变换和光照计算。
  • 若几何着色器位于图形处理器内,它便会修改一些几何信息。
  • 计算后的几何模型被三角化(分割为三角形)。
  • 三角形被映射为2×2的像素块。

并行计算

着色器被用来同时处理大量的数据,比如屏幕上的一整块像素群,或者一个模型结构的所有顶点并行计算适用于这样的情况,而且当今的GPU也设计有多核结构来极大的提高处理效率。

对着色器编程

OpenGL从版本1.5开始集成了一种类C语言着色语言,称为OpenGL着色语言(GLSL)。同时NVidia也开发了Cg,其语法与GLSL类同。

在Direct3D里,着色器使用高级着色器语言HLSL)。它的数据类型和允许的算法复杂程度因不同的版本而异。下表简述了Direct3D的不同版本:

Direct3D 版本 像素着色器 顶点着色器
8.0 1.0, 1.1 1.0, 1.1
8.1 1.2, 1.3, 1.4 1.0, 1.1
9.0 2.0 2.0
9.0a 2_A, 2_B 2.x
9.0c 3.0 3.0
10.0 4.0 4.0
10.1 4.1 4.1
11 5.0 5.0

XNA中执行Shader

XNA中执行Shader很简单。对XNA程序来说,Shader是一个小程序,只要把shader文件(.fx)导入到Contents 即可,会自动生成素材。再透过XNA Effect class 来加载和编译shader。HLSL可以在XNA或是DirectX使用。

旧版:

 effect = Content.Load("MyShader"); 
 effect.CurrentTechnique = effect.Techniques ["AmbientLight" ]; 
 effect.Begin(); 
 foreach (EffectPass pass in effect.CurrentTechnique.Passes) 
 {
    pass.Begin(); 
 ... 
    pass.End();
 }
 effect.End(); // 終止使用 effect

新版(4.0):

 effect = Content.Load("MyShader"); 
 effect.CurrentTechnique = effect.Techniques ["AmbientLight" ];  
 foreach (EffectPass pass in effect.CurrentTechnique.Passes) 
 {
    pass.Apply();
 ... 
 }

另见

参考资料

拓展阅读

外部链接