“呼唤”渲染世界真色彩

硬件周刊

  从16bit的渲染过渡到32bit的渲染已经有相当长的一些年头了。虽然32bit的渲染色彩精度对普通办公娱乐而言已足够,但在专业图形处理场合,32bit每通道区区8bit精度已经远远不能满足需要,提高色彩精度已是势在必行。为此,随着支持更高色彩精度的DirectX9.0c、新一代绘图芯片──NV40的出现,新一代颜色精度规范也成为了大家所关注的对象。

  PC系统的颜色精度

  颜色精度也称为色深,是指在某一分辨率下,每一个像点可以有多少种色彩来描述,它的单位是“bit”(位)。我们知道,在电脑上并不能够显示所有的颜色,因为自然界中的颜色是无数的。计算机标准的色彩空间是由R、G、B(红、绿、蓝)三种原色构成的,其他颜色是由这三种颜色透过不同的混合比例在调色板配搭而成的,又加入了Alpha值作为亮度的表现。因此,我们电脑上能够显示的颜色是红、绿、蓝、Alpha 4个通道组成(图1)。

  目前PC的最高色彩精度为32bit,每个通道8bit,每个通道可以显示28=256种颜色,存储一种颜色就需要4个8bit的空间,也就是32bit的空间。32bit整数的范围是0到232-1=4,294,967,295。如果仅仅从这个观点来看,你可以认为32bit色彩可以表示超过40亿种颜色,但事实并非如此。首先,32bit色彩并不能真正使用40亿种色彩。事实上,只有24bit被用来表示“RGB”(红/绿/蓝)色彩信息,而8bit通常携带的是Alpha值。224只有16,777,216(16.8M)种颜色,这就是常说的“真彩色”(图2)。

  提示:32bit色深与24bit色深所真正的显示色彩数是一样的,不同之处是32bit提供了256级灰度值。

  虽然这个数值看起来相当大,但24bit携带的色彩信息是由8bit红色,8bit绿色,8bit蓝色组成的。这意味着每一种基本色彩都只有8bit的精度,范围只要0到255而已,因此不能支持完全的动态(dynamic)。动态意味着最低与最高值的差别,而这里的动态最大值只有255而已。而游戏开发人员往往希望在3D世界里既有绝对的黑暗,也能完全的光明,因此每个颜色通道只有1到255的范围是远远不够的。如果单单用于静态画面显示,这个数字应该是足够用的,但在3D画面生成的动态环境中就不同了。因为3D画面生成往往需要几十个光照计算和纹理计算,期间涉及到大量色彩值的转换处理,如果这些中间值只能使用256种色彩状态来保存,误差将不可避免。而且电脑对图形处理时,颜色会随着图形的运算而发生变化,这样就不能保证每个通道所存储的颜色是256个颜色值中的一个了,从而出现非整数颜色值的情况。当出现这种情况是,系统就必须对这些非整数颜色值进行取整的操作,这就会造成图像色彩细节的丢失。

  经过几十步取整操作之后,原本可忽略的色彩误差会被明显放大,导致屏幕上生成的3D画面出现严重的色彩失真。同时系列在渲染时遇到光源传输、色调映射和颜色/伽马纠正这三种情况时也无法进行处理。因此以前开发人员不得不为图形卡开发出一些独特的解决方案──包括采用像素着色器(RGBE,来实现动态光源)以及模拟显卡硬件所不具备的功能(如高精度纹理贴图过滤)。随着我们在图形方面的应用日益加强,要求实现比每通道8bit精度更高色彩精度的呼声已经越来越高了。

  在DX8时代,针对这个问题Matrox提出10bit的渲染概念,采用了一些折中的方式来实现高于传统32bit的渲染方式。上面曾经提到,在32bit的渲染中,除去8bit的Alpha渲染之后,仅有24bit的通道来表现颜色。在其新产品Parhelia中大幅度压缩Alpha通道所占用的精度空间(8bit压缩到2bit),并将压缩下来的通道空间重新进行分配,使R、G、B每一个通道的存储空间从8bit扩展到10bit,虽然总和仍是32bit,并符合目前标准的32bit帧缓存储,但实际再通过10bit的RAMDAC(数模转换器)还原后的效果的确比标准的32bit要真实得多。因为这个时候每一种基本色彩已经拥有10bit的精度,范围已经从此前的0~255提升到0~1023,可显示颜色数量是24bit显示的64倍(图3)!但这样的处理是以牺牲Alpha通道来实现的,有时候会让你的游戏在烟雾或者满是硝烟的场面中将不那么真实,出现颗粒感很强或者透明介质表现力不足的画面。

  后来,微软在DirectX 9中引入更先进的浮点色彩处理机制很好地解决以上问题。DirectX 9的关键特性是64bit RGBA色彩(每个色彩通道均为16bit,简称FP16)和128bit浮点精度(每个色彩通道32bit,简称FP32),这也就是我们常说的双精度运算。

  提示:浮点运算操作,实际上就是在计算小数点位置,一般来说小数达到32bit的运算操作称为单精度的浮点运算,如果达到64bit或128bit甚至更高的话,那么就属于双精度的运算。浮点运算中的浮点数是由一个符号位、一些指数位及大量的字位构成尾数。计算公式是x=m*2e,这儿“x”是数字,“m”是尾数,“e”是指数,浮点数的最小和最大值的都是由指数决定的,而尾数则决定数字的精度。

  以128bit浮点精度为例,每个色彩通道有32bit的浮点精度(IEEE 单精度浮点)组成是1个组合,8bit指数(7位加1符号位)和23位的尾数,可以支持2-128到2127的动态范围,并且23位的尾数可以提供比32bit色彩的8bit通道高得多的精度。

  可以说,浮点色彩在动态和精度上的增加可以将很多过去不可能的特效变成现实。由于浮点色彩处理机制的引入,原sRGB规范(一种彩色语言协议)也升级为sRGB64。因此,自从微软推出DX9后,支持浮点色彩精度一直是NVIDIA、ATI产品的宣传热点。

  NV3X、NV40体系中的色彩精度

  早到NV30/35/38时代,NVIDIA的CineFX 2.0架构就引入对FP16、FP32格式的支持,整条渲染流水线提供128bit色彩,可以达到DX9中所规定的标准。

  提示:ATi的R300/350也支持128bit,但受到10bit的RAMDAC的限制,每个色彩通道实际上只有24bit,只不过在写入帧缓存时96bit会被扩充至128bit。

  在进行浮点色彩精度操作时,CineFX 引擎可以选择16bit模式和32bit模式。这种工作方式有两大好处,第一是你可以仅使用16bit精度,从而释放一些额外的帧缓存空间用来干别的事,毕竟32bit模式下每一个操作数都所占的帧缓存空间都是16bit的两倍。第二是由于16bit模式处理的数据量较小,处理起来会快一些,这样比起只能使用32bit的情况效率得到了提高。不过,FP16模式是以降低渲染精度来换取性能,因此在一定程度会出现图像色彩细节丢失的现象(图4)。

  此外,虽然NV30/35所支持的动态范围已经比32bit时代有很大的提高,但由于人眼对于快速的光线转换具有快速的适应能力,因此NV30/35在对动态光源渲染时,常会产生不尽如人意的结果,渲染结果会出现溢出的现象。而且受临时寄存器数量的限制,每当像素着色程序需要的临时寄存器数量超过32个FP32或者64个FP16寄存器时,性能就会下降一半。

  针对NV30/35中的问题,NVIDIA新一代NV40绘图显示芯片在支持FP16、FP32浮点色彩精度的基础上,引入了全新HPDR(High-Precision Dynamic-Range,高精度动态范围)技术。利用此技术,当用来存储颜色的32bit寄存器在运算过程中不够用时,NV40会自动采用更大的非标准寄存器来存储颜色数据,在最后显示的步骤时再转换成标准的颜色数据,这样可以大大避免性能下降的问题出现。当然,由于NV40的临时寄存器比NV35的增加了一倍,并不是所有的渲染都会使用到这项技术,只是在常规渲染无法进行的时候才启用。

  同时,NVIDIA采用OpenEXR(电脑图形计算的高动态范围影像文件格式)作为HPDR运算的缓存格式,支持16bit浮点、32bit浮点以及32bit整数格式,从而让NV40可以支持OpenEXR的FP16贴图、过滤、混合、存储。采用OpenEXR 的FP16后,NV40能表达的动态范围相当宽广,可以提供接近人眼的感观范围。

  提示:OpenEXR定义的FP16是参照IEEE 754中FP32格式进行精简后定义的,故FP16也被称为“半精度”。半精度的表达式是SM10E5(意思是1个二进制符号位+10位二进制尾数+5位二进制指数)。在常规下,FP16能表示的数值范围是:2-14~(2-2-10)×215,十进制表示就是0.00006103515625~65504,主要是存储光线的数据,用来反映光传递的信息,从而可以为光线传递等计算提供更大的动态表达范围。

  可以说,采用OpenEXR的FP16作为数据保存格式后,NV40能够表现出更逼真的光源,例如阳光穿过树林所形成的不规则光斑等等,可以在常规渲染力不从心的三个阶段中采用高精度的渲染方式来渲染光线。

  而且OpenEXR还支持浮点混合操作。此前,混合都是从每通道256级别的贴图或屏幕缓冲中取出颜色,然后再进行混合。而现在更高精度意味着像素混合的结果更加精确、品质更高。像运动模糊、柔和阴影以及需要对一个场景的多个动态光照计算进行累积,这些需要颜色混合的特效都能从浮点混合受益(图5),从而实现一些类似于瞳孔在不同强度的环境光条件下自动调节亮度的效果。

  结 语

  可以说,未来的发展趋势是更高的色彩精度,这也是GPU必然的发展趋势。但目前无论采用FP16、FP32哪一种模式,都是基于GPU内部的颜色计算精度,受到显示终端输出系统的制约,最后输出生成的仍然是32bit图像,多余的颜色精度用于模式转换产生损失后依然能保证最后输出画面的品质。虽然DirectX 9早已采用了40bit真彩色机制、可显示的物理色彩总数超过10亿种色彩的静态色彩显示机制,但要真正在实用中实现40bit色显示,除了支持DirectX 9 的显卡外,还需要操作系统和显示器的支持。操作系统方面估计要等到微软的Longhorn发布。至于显示器,CRT对色彩数没有限制,但它目前已逐步被淘汰,现有的LCD显示器最高只能显示出18bit色。幸好,微软和夏普正在联合进行新一代LCD显示器的研发,估计2005年我们就可看到支持40bit色的高质量LCD显示器出现。让我们共同期待真彩色时代的到来!