openGL 着色语言 C#-tao框架

来源:互联网 发布:窗帘尺寸怎么算法 编辑:程序博客网 时间:2024/05/03 15:15

2.1.1 顶点:3D图形的基础

OpenGL中的基本单元是顶点。简单来说,顶点就是空间中的一个点。在这些点上可以附加其他信息,如它如何映射到纹理,是否具有一定的重量或颜色等,但是最重要的信息是它的位置。

游戏会把大量的时间用于发送OpenGL顶点,或者告诉OpenGL以特定的方式移动顶点等。游戏可能首先告诉OpenGL它将要发送的全部顶点会构成三角形。此时,OpenGL将使用线把它收到的每三个顶点连接起来以创建一个多边形,然后可能还会使用纹理或颜色填充多边形的表面。

现代图形硬件非常擅长处理大量的顶点,把它们构成多边形,然后渲染到屏幕上。这个从顶点到屏幕的过程叫做流水线(pipeline)。流水线负责定位顶点和提供光照,以及进行投影变换。这个过程将把收到的3D数据变换为2D数据,以便将其显示到屏幕上。投影变换听起来有点复杂,但是几个世纪以来,画家和艺术家们一直在利用这种变换,在平展的画布上绘制出他们周围的世界。


2.1.2 流水线

流水线的流程如图2-3所示。这个流水线叫做固定功能流水线(fixed function pipeline)。当程序员为这种流水线提供输入后,所有的功能已被固定,无法修改。例如,在像素处理阶段很容易向屏幕上添加蓝色调,但是在固定功能流水线中,程序员无法直接控制这个阶段。

图2-3 基本的固定功能流水线

固定功能流水线包含6个主要的阶段。这些阶段几乎都可以并行应用。如果硬件支持的话,每个顶点可以同时经过同一个阶段。由于这个原因,图形卡的处理速度比CPU的处理速度要快得多。


输入阶段。输入以顶点的形式给出,顶点的属性包括位置、颜色和纹理数据。


变换和光照。根据当前视图变换顶点。这包括将顶点的位置由3D空间(也叫做世界空间)改为2D空间(也叫做屏幕空间)。如果有些顶点对最终的显示没有影响,可以在这个阶段移除它们。在这个阶段也可以对每个顶点执行光照计算。


创建图元。这是使用顶点信息创建多边形的过程,需要根据OpenGL的状态把顶点连接到一起。游戏经常使用三角形或者三角带作为图元。


光栅化。这是将多边形转换为像素(也叫做片段)的过程。

像素处理。像素处理也叫做片段处理。这个阶段将测试像素,以确定是否把它们绘制到帧缓冲区中。


帧缓冲区。帧缓冲区是一块内存,代表特定的帧将显示在屏幕上的部分。混合设置将决定像素如何与已经绘制的部分进行混合。


使用程序控制流水线了。将程序上传到图形卡以后,它们将替换固定功能流水线的默认阶段。重写流水线的特定部分的小程序叫做着色器(shader)。


图2-4显示了可编程流水线的阶段。这里删除了变换和光照阶段,添加了顶点和几何着色器。像素处理阶段也可以像像素着色器那样进行编程。通过流水线的每个像素都会被应用像素着色器。像素着色器不能添加顶点,但是可以修改位置、颜色和纹理位置等属性。

图2-4

与像素着色器和顶点着色器相比,几何着色器加入的时间较晚。几何着色器以一个完整的图元(如线、点或三角形组成的带)作为输入,而顶点着色器针对每个图元都会运行。几何着色器可以创建新的顶点信息、点、线,甚至图元。几何着色器还可用于创建点精灵和动态镶嵌,以及实现其他一些效果。点精灵可以快速渲染大量精灵,这种技术经常用于粒子系统,可创建类似于火焰或者烟雾效果。动态镶嵌可以在几何形状中添加更多的多边形。这种技术可以用来增加包含多边形数较少的游戏模型的平滑度,并在摄像机放大模型时展现更多的细节。

像素着色器会应用到被发送到帧缓冲区的每个像素。像素着色器用于创建凹凸贴图效果、镜面高光和逐像素光照。凹凸贴图效果可以给表面增加额外的高度信息。凹凸贴图通常包含一个图片,其中每个像素代表一个标准的法向量,该法向量描述了如何扭曲表面。像素着色器可以使用凹凸贴图来为模型提供一个更有趣的纹理,使其看上去有一定的深度感。逐像素光照用于替换OpenGL的默认的光照公式。OpenGL的光照公式可计算出每个顶点的光照,然后为该顶点提供一种合适的颜色。逐像素光照使用更精确的光照模型,为每个像素单独应用光照。镜面高光是模型中非常亮、反射大量光的区域。


2.2 变化中的OpenGL

现在是学习OpenGL的大好时机。OpenGL的当前版本非常适合学习。这个版本中包含了大量易于使用的函数,可以完成各种各样与图形处理有关的工作。可以把OpenGL的当前版本想象成一个带有辅助轮的自行车,刚开始时借助它们学习怎么骑车,熟练之后就把它们取下来。OpenGL的下一个版本更像是一个性能强大的摩托车,没有必要的东西都被移除了,剩下的就是不受限制的原始力量。对于有经验的OpenGL程序员,其好处自不必言,但是初学者却容易对其望而生畏。

可以使用的OpenGL版本要取决于系统中安装的图形卡驱动程序。几乎每台计算机都支持OpenGL 2.1,而近期生产的图形卡会支持OpenGL 3.x。

2.2.1 OpenGL ES

OpenGL ES是用于嵌入式系统的OpenGL的新版本。它与OpenGL的近期版本相似,但是功能集更加受限。它用于高端手机,例如Android、BlackBerry和iPhone。OpenGL ES也用于军用硬件,例如战机上的平视显示器。

OpenGL ES支持可编程流水线,也支持着色器。


2.2.2 WebGL

WebGL目前仍处于开发中,这个版本的OpenGL是专为在Web上使用而设计的。使用WebGL的浏览器必须支持HTML 5 canvas标签。就现在而言,还无法知道它会取得多大的成功。以前人们曾有过在Web上使用3D的尝试,但是都失败了。例如,VRML(Virtual Reality Modeling Language,虚拟现实建模语言)与HTML类似,但是允许用户创建3D世界,它在学术界受到了不少关注,却从没有吸引过普通的用户。

WebGL有一些强有力的支持者,许多大公司都加入了WebGL工作组,如Google、Apple和Mozilla,而且WebGL还有一些让人印象非常深刻的演示。就目前来看,WebGL的性能还是不错的,在成熟以后很可能可以与Flash一较高低。


2.3 OpenGL和图形卡

OpenGL是一个允许程序员发送指令到图形卡的库。图形卡是一种专用于显示3D数据的硬件,由很多标准组件构成,包括帧缓冲区、纹理内存和GPU。GPU是图形处理单元(Graphics Processing Unit)的缩写,它控制着如何处理顶点并把它们显示到屏幕上。CPU向GPU发送指令和数据,描述每一帧应该怎样显示到屏幕上。纹理内存通常是一块较大的内存,用于存储游戏所需的大量纹理。帧缓冲区是内存中的一块区域,存储下一帧中将显示到屏幕上的图像。现代的图形卡通常有多个GPU,每个GPU上都有许多着色器处理单元来执行大规模的并行着色器操作。分布式应用程序(如模拟蛋白质折叠的Folding@home)和世界各地的数十万台计算机都利用了这一特点。

第一个获得流行的3D图形卡是3dfx Voodoo 1。这是早期的一个图形卡,有2MB的纹理内存和2MB的帧缓冲区,并且使用PCI总线,时钟速度为135MHz。早期的一些游戏使用它来加速执行,例如《古墓丽影(Tomb Raider)》、Descent II、《雷神之锤(Quake)》以及《雷神之锤2(Quake 2)》的演示,从而运行得更加流畅,并且可显示更多的细节。Voodoo 1使用一个标准的PCI总线,允许CPU以最高533MB/s的速度向图形卡发送数据。现代的图形卡已经从PCI转向使用AGP(Accelerated Graphics Port,加速图形端口),其最高数据发送速度为2GB/s,后来又转向使用PCI Express。当前的这一代PCI Express卡的最高数据发送速度为8GB/s。

好像每个月都会有新的图形卡问世,每个新图形卡都比之前的图形卡更快。在编写本书时,最快的图形卡可能是ATI Radeon HD 5970。它有两个GPU,每个GPU都有1600个着色器处理器。它的时钟速度为725MHz,每秒可以处理4.64万亿次浮点运算。

大多数现代图形卡都有专门执行新操作的特殊硬件。这种硬件通过使用扩展提供给OpenGL。当收到一个标识新扩展的字符串时,OpenGL能够展示驱动程序和图形卡中的功能。例如,ATI Radeon HD 5970有两个GPU,这种情况很少见。为了能够充分利用两个GPU,需要使用一些新的扩展方法,如AMD_gpu_association。这个扩展允许用户在两个GPU之间分配任务。如果多家供应商实现了相同的扩展,那么扩展字符串的某个位置会有字母EXT。有时候,控制OpenGL规范的架构评审委员会可能会把某个扩展的状态提升为官方扩展,此时,扩展字符串中将包含字母ARB,所有的供应商都必须支持该扩展。

着色器--图形卡上的程序

着色器(shader)这个词带有一定的误导性。最初的着色器程序主要用于处理组成每个多边形表面的像素,以便为模型着色。但是随着时间推移,着色器程序的功能已经被扩展,现在还可以修改顶点属性、创建新顶点,甚至完成一般的操作。

着色器与运行在CPU上的普通程序具有不同的工作方式。着色器程序在大量的元件上同时执行,这意味着着色器程序是大规模并行程序,而运行在CPU上的程序一般则是串行运行的,一次只有一个实例运行。着色器程序非常适合对构成3D世界的像素和顶点的集合执行操作。

目前共有3类着色器,分别是顶点着色器、几何着色器和像素着色器,每种着色器都只能执行特定的操作。顶点着色器处理顶点,像素着色器处理像素,几何着色器处理图元。为了降低复杂性,并使硬件制造商可以更高效地进行优化,所有这些着色器都被一种叫统一着色器(unified shader)的着色器替代了。

着色器通过运行在图形卡上的特殊语言进行编程。目前,这些语言比C++低级得多(更别提C#了)。OpenGL有一门叫做GLSL(OpenGL Shading Language,OpenGL着色语言)的着色语言,它与C语言有些类似,但是有大量用于处理向量和矩阵的特殊操作。DirectX也有自己的着色语言,叫做HLSL(High Level Shading Language,高级着色语言)。两种语言十分类似。让人更加困惑的是,除了这两种语言以外,还有一种叫做Cg的语言,它由Microsoft和Nvidia开发,与HLSL有些类似。

游戏中的着色器非常适合创建需要进行大量计算的特殊效果,如视差贴图的光照。当前的技术使得着色器程序几乎不能用于其他用途。本书主要介绍游戏编程,由于可编程流水线是一个很大的主题,所以不会讨论该技术。如果对此主题感兴趣,可以参阅附录A部分,那里介绍了几本非常好的书籍。

着色器的一种趋势是用于一般性的并行编程任务,而不只是处理图形。例如,Nvidia PhysX库允许在GPU而非CPU上完成物理计算,从而得到更佳的性能。PhysX是用另外一种叫做CUDA的着色器语言编写的,但是CUDA与其他着色器语言有一些不同,这种语言不怎么关注像素和顶点,而是更关注一般目的的并行编程。假设在游戏中要模拟一个城市,并且有一个非常新奇的并行算法可以更新城市中的全部居民,那么这种计算在GPU上可以更快地执行,而CPU就可以被解放出来,执行其他任务。CUDA通常用于科学研究项目,因为这是利用强大的计算能力的一种廉价的方式。使用CUDA的应用程序包括量子化学计算、心肌模拟和黑洞建模。



2.4 Tao框架

Tao框架是C#使用OpenGL库的一种方式。Tao包装了许多C库(见表2-1),并使得在C#中使用这些函数变得很简单。Tao中还绑定了Mono,所以也可以用在Linux和Mac中。

通过Tao,C#不只可以使用OpenGL,还可以使用其他一些有用的库。

表2-1 Tao框架中包含的库

用途

Tao.OpenAl

OpenAL是一个强大的音频库

Tao.OpenGl

OpenGL是我们将要使用的图形库

Tao.Sdl

SDL(Simple DirectMedia Layer),一个

构建在OpenGL之上的2D库

Tao.Platform.Windows

支持通过Windows.Forms使用OpenGL

Tao.PhysFs

一个I/O的包装器,支持游戏资源的存档文件,如.zip文件

Tao.FreeGlut

OpenGL实用程序工具包(OpenGL Utility

Toolkit)是一组包装器,用于设置OpenGL

程序和一些绘图例程

Tao.Ode

Open Dynamics Engine是在游戏中使用的

一个实时物理引擎

Tao.Glfw

OpenGL Framework是一个可以在多个平台

上使用的轻量级的包装器类

(续表)

用途

Tao.DevIL

DevIL是将各种图片类型(bmp、tif、gif、

png等)加载到OpenGL的出色的工具

Tao.Cg

Cg是一种高级着色语言

Tao.Lua

Lua是游戏业最常用的脚本语言之一

Tao.FreeType

字体包

Tao.FFmpeg

主要用于播放视频

OpenAL代表开放音频库(Open Audio Library),是一个强大的开源库。《生化奇兵(BioShock)》、《雷神之锤4(Quake 4)》、《毁灭战士3(Doom III)》和《虚幻(Unreal)》等游戏都使用了这个音频库。它采用OpenGL作为模型,具有相同的状态机风格的设计和扩展方法。

SDL(Simple DirectMedia Layer)是一个跨平台的库,支持输入、声音和图形。SDL在游戏开发商中非常流行,在独立或者开源游戏中使用得尤其多。使用SDL开发的最著名的开源游戏之一是FreeCiv,它是《文明(Civilization)》的一个联机版本。多数Linux游戏端口中也使用了SDL。

PhysFs初看起来可能是一个物理库,但是实际上却是一个小型的IO库。它可以将全部游戏资源打包为一个较大的二进制文件,或者几个小的二进制文件。许多商业游戏都有类似的系统,例如《毁灭战士(Doom)》的wad系统或《雷神之锤(Quake)》的pak系统。它可以使游戏在发布后的修改和更新变得更加简单。

FreeGLUT是OpenGL实用程序工具包的免费版本。这个库中的函数可以让用户马上就能够使用OpenGL。它还有从键盘和鼠标接受输入的方法,以及绘制各种基本形状的方法,例如球形、立方形,甚至茶壶形(这个茶壶在计算机图形学中非常有名,它是由Martin Newell在犹他大学求学期间进行建模的。茶壶是一个非常复杂的表面,所以在测试新的图形技术时非常有用。动画电影《玩具总动员》中就有一个典型的茶壶模型,DirectX甚至有自己的茶壶创建方法D3DXCreateTeapot( )。在讲授OpenGL时经常用到FreeGLUT,但是它的功能很有限,很少用于真正的项目。

ODE(Open Dynamics Engine)是一个可以用在多个平台上的物理引擎,可以完成碰撞检测和刚体模拟。PC上的第一人称射击游戏《潜行者(S.T.A.L.K.E.R)》中就使用了ODE。Glfw是可以通过Tao使用的第三个可移植的OpenGL包装器。Glfw代表OpenGL框架(OpenGL framework),它的目的是扩展GLUT提供的功能。如果不想使用SDL,但又确实想使用框架来访问OpenGL,就可以考虑使用Glfw。

DevIL(Developer's Image Library)是一个从磁盘加载纹理到OpenGL中的库。DevIL与OpenGL有些类似,因为它也是一个状态机,并且有类似的方法名称。DevIL是跨平台的,支持多种(43种)不同的图片格式。Cg是本章前面提到的一种着色器语言。通过使用Tao.Cg,可以从文本文件或字符串中加载着色器程序,进行处理,然后在OpenGL中使用。

Lua可能是游戏开发中最流行的脚本语言。它是一种小型的、易于嵌入的语言,表达力非常强。使用Tao.Lua可以在脚本和C#程序之间传递函数和数据。Tao.FreeType是一个基本的字体包,可以将FreeType类型的字体转换成一幅位图。它的接口简单易用。

Tao提供的最后一个库是FFmpeg,这个名称由MPEG(一个视频标准)和FF(Fast Forward,快进)组成。它提供了一种播放视频的方式。如果想要在游戏中使用过场动画,FFmpeg是一个不错的选择。

Tao提供的所有库都是完全开源的。其中的多数库都可以免费用在商业项目中,但还是有必要阅读许可证中列出的具体说明。Tao是一个出色的程序包,刚开始涉足游戏的开发商可以把它作为一个起点。对每个库的介绍不在本书的讨论范围之内,我们将只关注其中最重要的那些库。从第5章开始,我们将使用OpenGL和Tao.Platform.Windows库。第6章将讨论DevIL。第9章将讨论使用OpenAL播放声音,以及使用SDL处理手柄输入。每个库都很有用,所以很有必要花些时间研究每个感兴趣的库。