最新消息:2008-2023,十五年。青青子吟,悠悠我心。但为君故,沉吟至今。

【业界】开发者和你谈——关于电视游戏机的图形运算处理技术(二)

游戏业界类 Lafirel 3324浏览 0评论

yxzj

从今天开始,我们来看一下Nintendo 64的新特性。

大家先来看一张比较的图片,好有一个直观的印象。

kfzhnt1

实在是有太多的不同了!有太多的内容可以聊了!

我做了一个艰难的选择,先从纹理(Texture)开始吧。
我们以前讲过,贴图(Texture Mapping)就是给3D模型蒙一张皮的过程。我们需要告诉显卡,什么顶点对应纹理的什么坐标(UV数据)。然后,GPU会根据所有的顶点,计算出所有线和面的像素颜色。这里需要做插值(Interpolation)计算。

SS和PS的插值方法很简单,就是取最近的像素(Nearest-neighbor interpolation)的颜色。

我们仔细观察一下图片里面的石头,PS版的纹理非常的像素化(Pixelated)。同色的大块像素,就是Nearest-neighbor interpolation的结果。

N64的GPU则支持更高阶的插值方法,叫做三重线性纹理过滤(Trilinear texture filtering)。

这个名词很长,不过大家不要被它吓到了。想要了解这个概念,并不需要很高深的知识。

首先,所谓过滤,就是上面所说的插值方法的一种。SS和PS对纹理是完全没有过滤的,它们直接取最近的像素的颜色,也就没
有什么计算。如果有过滤的话,就会进行额外的计算了。

为了理解过滤的基本思想,我们今天暂时先讨论一下单纯的过滤(filtering)技术。毕竟纹理过滤(texture filtering)还要牵涉更多的细节,所以我把它放到明天来讲。

最常见的过滤技术,叫做双重线性过滤(Bilinear filtering)。

相信大家在很多场合都见到过这个东西吧?比如说,用vita跑psp游戏的时候就有这个画面选择。

PS Vita屏幕的分辨率是544p,PSP游戏的分辨率是272p,长宽都是两倍,像素的数量是四倍。大家可以想象一下,vita屏幕上每个2X2的色块,都会对应psp游戏的一个像素,对不对?

如何决定这些2X2的色块的颜色值呢?我们需要一种插值方法。

假如我们不勾选双重线性过滤,那vita就会进行Nearest-neighbor interpolation。

在这个情况下,每个2X2的色块(含四个像素),它们最邻近的像素就是那个对应的psp游戏的像素。因为是选取最邻近像素的颜色,所以屏幕上每个2X2的色块都是同一个颜色。

打个直观的比喻,就好像是一个像素生出了好几个相同的像素。这就是最邻近方法的核心思想。

假如我们勾选了双重线性过滤,那vita就会进行更多的计算了。

这时候,针对vita屏幕上的每个像素,GPU会去找离它最近的四个psp游戏的像素。有了这四个像素之后,再分别根据自己与它们之间的距离,做加权平均值(Weighted average)。距离越近,权重就越大。

简单的说,每一个新像素都会受到几个旧像素的染色,最后会出现一个比较平滑过渡的结果。

kfzhnt2

以上就是过滤(filtering)最基本的思想。无论是单纯的把小图像放大,还是应用到纹理上,大致都是这样一个思路。

最后提一下,双重线性过滤在视频播放器和模拟器中应用的很多,它是把分辨率低的图像放大的常用方法。

关心更多细节的玩家,可以参考这篇:http://msdn.microsoft.com/en-us/ … 7%28v=vs.85%29.aspx

好,今天的内容就结束啦~
最开始我们提到过,N64的GPU支持三重线性纹理过滤(Trilinear texture filtering)。那么,三重是什么?纹理过滤又有什么不一样呢?大家明天见!

第二天 Mipmap和三重线性纹理过滤(Trilinear texture filtering)

我们先来回答昨天留下的一个问题:纹理过滤和普通的过滤技术有什么不同?

答案是,纹理过滤要牵涉到Mipmap。

于是,我们便遇到了第一个我查不到中文翻译的词汇:Mipmap。

Mipmap可以作为名词,于是就有了复数形式Mipmaps。它也可以作为动词,应用到Mipmap的技术,就被我们叫做Mipmapping。
下图中的纹理(Texture)就有Mipmap:

kfzhnt3

纹理里面有很多相同的人造卫星,但是它们的太小都不同。我们称做不同的细节程度(Level of detail)。

那么,我们为什么要存这么多个相同的图案呢?难道不浪费空间吗?

其实,它确实很占用空间!不过,它也非常有用,因此被使用的非常广泛。

当物体很远的时候,或者只是侧面面对镜头的时候,这个物体在屏幕上将会占用非常少的像素。这时候,如果我们使用分辨率很高的纹理,效果肯定是不理想的。

有了Mipmap技术之后,显卡就有挑选的余地了。我们可以告诉显卡,在什么情况下使用什么的细节程度,显卡就可以挑选合适大小的纹理了。

如果大家玩基于虚幻引擎3的游戏比较多的话,肯定能注意到一个现象。有时候,最开始纹理是模糊的,然后慢慢变得细致。

最开始的那个纹理,就是最低细节度的Mipmap。这是虚幻3减少游戏读取时间的方法。
在了解了Mipmap之后,我们再来想象一下这样的情形:

当镜头离物体忽远忽近的时候,纹理的细节度会发生什么呢?

分辨率高的Mipmap和分辨率低的Mipmap会来回的切换。

我们把这种现象叫做Texture Popping。要拿最近的游戏来说,这个现象在ID software的狂怒(Rage)里面就很常见。应该是Mipmap的控制没有做到最好的原因。

为了解决这个问题,一个早期的解决方案就诞生了!那就是三重线性纹理过滤(Trilinear texture filtering).

顾名思义,这个东西是在双重线性纹理过滤的基础上,加了一层计算。

它会在两个临近细节度的Mipmap中,取一个中间值。这样一来,纹理的细节度就不会突然变化了,而是会缓慢的过渡。
相比较最邻近像素的插值方法,Mipmap+三重线性纹理过滤可以很好的解决纹理马赛克的问题。但是也有两个缺点:
1.纹理的体积会膨胀。
2.纹理会变得模糊,失去锐利度(Sharpness)。

尤其是第二个问题,我个人是非常讨厌的。

在火箭鸟2的开发过程中,我们使用了4K乘以4K的高清晰纹理。这个分辨率应付1080P的游戏绰绰有余了~

可是,由于Mipmap的存在,导致纹理有些模糊,从而失去了很多细节。后来我只好禁用了一部分Mipmap,这样整体图像的细节丰富程度才比较让人满意。

Mipmap本身也不是那么容易控制的,就连id software也不能完全杜绝Texture Popping这种现象。
今天的内容就结束了。大家复习一下,三重线性纹理过滤是怎么工作的?

大家明天见!

第三课 动态分辨率和透视修正

我的工作一向是非常忙碌的,昨天和今天都是干到现在才下班。。。

好在这两天的工作成果都很有意义,今天实现了动态分辨率(Dynamic Resolution)这个技术。

此技术是2011-2012才开始流行的,我记得Rage和忍龙3都使用了这个技术。

它的概念其实非常简单:当GPU算不过来的时候,我们就可以通过降低游戏分辨率的方式,来减少屏幕上像素的总数。这样一来,GPU就算得过来了。

不过,我可以自豪的宣布,我们正式发行的PS4版多半是用不到这个技术的!

很多人肯定要问:那你费劲做这个技术干什么呢?!

那是因为我们公司pc的GPU跑不动。这个技术是给pc版做的,pc版比较方便大家测试。

我前段时间实现了全局光照,而且游戏里的动态光源数量极多,虽然充分利用了ps4的GPU和带宽,但是对于pc来说,每一个像素都太昂贵了。这时候,降低分辨率就对帧数很有帮助了。

而我们的艺术人员又需要在1080p的分辨率下观察游戏的细节,所以我才选择了动态分辨率这个技术。

这个技术的实现牵涉到后期处理(Post Effects),所以细节的部分我们以后再聊。

最后,大家考虑一个问题:如果是CPU算不过来,那么动态分辨率对帧数有帮助吗?

答案是,没有。

因此,我们大致也可以判定,那些使用了动态分辨率技术的游戏,通常就应该是受GPU局限了(GPU-bound)。

言归正传,我们继续来看N64的技术。

大家先来看一张PS上GT赛车2的图片:

kfzhnt4

再来看一张N64上的Rush 2049的图片:

kfzhnt5

大家仔细观察一下GT2赛道的边栏的形状以及上面的纹理,是不是哪里不太对?好像哪里跟我们现实中的不太一样?N64的图像是不是好很多?

其中的原因就是,N64有透视修正(Perspective Correction),而SS和PS没有。SS和PS使用的则是仿射纹理贴图(Affine Texture Mapping)。

我们在第一期和前几天都讲过,贴图都需要一种插值方式。

透视修正是决定顶点之间线的位置的最正确的插值方式,而仿射就不太准确了。

这个仿射是什么意思呢?其实我也不知道~

但是,我知道这种贴图的算法是什么。大家看一看下面的图片:

kfzhnt6

大家请看Affine那个棋盘格的任意一个半边,注意到没有?棋盘格仍然是平行的!

相信大家在美术课中都学过透视原理,最右边一个棋盘格才是正确的,每一条线最终都会延伸交汇到一点。

Affine Texture Mapping的算法很简单了,它就是根据纹理的二维坐标(UV)做了一个简单的线性插值,所以才导致了上面的情况。

相比较,透视修正的计算量则稍大,因为考虑到了顶点的深度(Depth)。好在N64的硬件直接支持透视修正,所以它也成了N64游戏的标准配置。

有了以上的知识,我们可以进一步总结:因为透视修正的存在,深度缓冲(Depth buffer或者Z-buffer)的存在也就理所当然了,对不对?

N64有深度缓冲,SS和PS则是没有深度缓冲的。

今天的内容就到这里,我也要赶紧去收衣服了。

大家明天见!

第四天 栅格化

抱歉,今天的更新晚了点。因为我抗锯齿的文章写了一大半,又不得不推翻,重新写了这一篇。

昨天有人跟我提意见说:不讲栅格化就不可能讲清很多概念!

说实话,我原本是不打算写这一篇的,因为觉得不适合入门。况且分辨率也属电脑常识。

但是仔细想了之后,觉得人家讲的有道理!比如说,不讲栅格化就不可能讲清锯齿出现的成因。

而且,经过的第一期的讨论,大家都应该已经懂了不少东西,这时候回头再看栅格化的概念,应该事半功倍。

我知道,今天有人看完心里肯定说:这TM也太简单了!老子早就会了!

我要说的是,栅格化和分辨率本身虽然简单,但是却可以引申出一些很重要的结论。今天虽然是一个过渡章节,但是大家可不要轻敌了~

我们先来回忆一下,3D模型是如何描述的?

答案:有了所有的顶点和它们之间的连接方式,就可以精确描述一个3D物体了。

这种描述方式是非常精确的,毫无误差。可惜电视机的图像都是由像素点阵构成的,所以我们迟早都必须把所有的线和面都转化成像素点阵的形式。这个转化的过程就叫做栅格化(Rasterization)。

栅格化这个翻译我非常喜欢!像素点阵就是一格一格的,非常形象~因为这个原因,我没有采用光栅化这个说法。

一格一格的像素点阵的数量必然是有限的。在显卡做栅格化的时候,我们需要指定这个点阵有多少行、多少列。这也叫做分辨率(或者解析度,Resolution)。

大家都知道,分辨率越高,像素的数量越多,图像就越精细。

相反,如果像素数量少,那么图像就容易呈颗粒状(想象一下3DSXL的画面)。

以上就是我们今天的基础知识。有了这个知识,我们可以引申出一些很重要的结论。

首先,细心的玩家肯定已经发现了。把一个三维的物体栅格化,最后的结果其实应该是有长、宽、高的三维立体像素点阵,为什么最后只剩一个二维的像素点阵呢?

这里其实分两种情况:

SS和PS在做栅格化之后,深度值是被抛弃不用的,仅仅留下二维的点阵作为帧缓冲(Framebuffer)。

而N64及以后的主机,第三维的坐标会进入深度缓冲(Depth buffer或者z-buffer)。

我前几天也说,SS和PS没有深度缓冲,就是指这个。

我们再进一步分析,为什么只有N64及以后的主机才有透视修正呢?

因为透视修正依赖深度值。SS和PS之间把深度值扔掉了,自然就不可能实现正确的透视效果。
其次,栅格化之后,我们会有一个二维像素点阵,每个像素都有颜色值,这个就是我们之前说的帧缓冲(Framebuffer)。

现在我问大家一个问题:论坛里面经常提到的一个名词“渲染分辨率”,它到底是什么?

答案:所谓渲染分辨率(Rendering resolution),就是指帧缓冲和深度缓冲的分辨率,也就是栅格化所使用的分辨率。

接下来一个问题:GPU所处理的像素的数量,跟什么有关?

答案:只跟上面提到的渲染分辨率有关。

跟电视机的分辨率无关,跟1080p的信号或者720p的信号也无关!

大家不要看见电视显示1080p,就以为游戏是在1080p下面运行的。这一点务必要理解。

最后,栅格化是发生在顶点、UV、法线等数据的变换和插值之后,在纹理贴图和半透明处理等特效之前的。

因此,我们得到一个结论:纹理贴图和半透明效果等特效的工作量,是跟渲染分辨率高度相关的。

我们玩pc游戏,通常降低分辨率可以获得更高的帧数,就是这个原因。当然,如果是CPU算不过来,降低分辨率也没用了。

在N64之前,SS没有UV,PS的framebuffer没有alpha通道,但是这仅仅是实现方法的不同。我们上面介绍的概念和结论,仍然是成立的。

好,大家明天见!

第五天 抗锯齿基础

这两天一直生病请假,跟大家说一声对不起。

在介绍吴小林之前,我们先来看一下,游戏画面为什么会产生锯齿(Jaggies)。

锯齿这个词非常有意思,英文原文通常叫做Jaggies。大家能猜出这词的单数形式吗?

答案是,一般不用单数形式。

这词的词源是Jagged,形容锯齿状。名词形式Jaggies,直到视频游戏流行之后才出现。可以说是美国人活用(或者说是乱用)英文单词的典型例子了。

产生锯齿的现象,还有一种比较学术的说法,叫做Aliasing。这是抗锯齿(Anti-aliasing)一词的词源。

锯齿出现的根本原因是:游戏的分辨率不够。

大家看下面的图片就明白了。

kfzhnt7

大家想象一下,如果显示设备和游戏的分辨率是4K、8K、甚至16K,上面的直线就不需要任何抗锯齿技术了,肉眼完全看不到边缘。

如果分辨率是有限的,就必须进行昨天(其实是五天前了。。。)讲解的栅格化。如果不使用任何硬件或者软件的抗锯齿(Anti-aliasing)技术,锯齿的产生就不可避免了。

上图的画直线的算法叫做Bresenham’s line algorithm,是效率最高的画直线的方法,也是大多数显卡的默认显示方法。

下面介绍一种早期的抗锯齿技术,叫做吴小林直线算法(Xiaolin Wu’s line algorithm)。

这个算法的运行效率也非常高。当然,速度肯定不如上面的那个算法。

它的基本思想也很简单,大家看图就知道了:

kfzhnt8

直线所通过的像素都会着色,但是颜色则不是纯色,而是取决于跟直接的距离,距离越远颜色就越淡。离远了看,可以达到边缘柔化的效果。

吴小林直线算法也有一些局限性,它也不能控制反锯齿的程度。

N64的显卡,从硬件层面上支持吴小林直线算法,因此N64游戏的抗锯齿是很普遍的事情。

到了今天,这种抗锯齿技术已经不是主流了。PC上普遍使用的是多重取样的MSAA,而在PS360世代的主机游戏的研发中,很多依赖post effects的抗锯齿算法被创造出来了。这些都是后话了。

今天的话题就说到这里,大家明天见!

第六天 统一内存架构

我原本也是不打算这么早就讲这个话题的,直到新闻区出了这么一帖:
http://bbs.a9vg.com/thread-3556533-1-3.html

希望大家读完今天的文章之后,都会有自己判断真伪的能力。

我们都知道,自从xbox 360使用了统一内存架构(Unified memory architecture)之后,它就成了游戏主机的标准配置,WiiU,PS4和Xbox One都沿用了这一设计。甚至,将来的PC可能也会向这方面发展。

但是,xbox 360却并不是这个架构的最早实践者。它的爷爷辈的N64就已经有了统一内存。

可惜的是,比起xbox 360的辉煌,N64对这项前瞻技术的实践只是一个败笔。

那么,究竟什么是统一内存?为什么N64的统一内存失败了呢?

我们早在第一期就讲过:在传统架构中,内存只能被CPU读写,显存只能被GPU读写。如果CPU和GPU之间要通讯或者共享数据的话,数据就只能在内存和显存之间复制。

统一内存架构则颠覆了这一事实。

在统一内存架构中,同一块内存既可以被CPU读写,也可以被GPU读写。

如此一来,显而易见的,统一内存架构有如下优点:
1. 内存空间的运用更为灵活。如果CPU用的少,就可以匀一些给GPU用,反之也成立。
2. 节省一些内存空间和带宽。一部分内存和显存之间的数据复制可以避免掉了。

很多玩家肯定要说了:我擦,这东西太好了!那我们一直用它不就行了!

可惜的是,统一内存并没有大家想象的那么好。

一块特定的内存,虽然CPU和GPU都能访问,但是它们不可能都处在高速访问的状态。原因有很多:

首先,CPU用数据的内存排布(Memory Layout)和GPU用数据的内存排布是不同的。

我们在申请内存空间的时候,只能二选一。如果选择了比较适合CPU用的内存排布,那么GPU的访问速度就会下降,反之亦然。

其次,内存通往CPU的总线和通往GPU的总线是分开的。如果这两条总线同时在访问,内存控制器的效率会降低。在这样的情况下,CPU带宽和GPU带宽的总和,往往达不到内存本身的带宽。如果单用一条总线,就没有这个问题。

最后,CPU和GPU仍旧是独立的两个处理器,它们分别拥有自己的一套缓存(Cache)。同一个资源,如果被两套缓存共享,那么写入和清楚缓存的操作会大大增加,往往不止是简单的乘二。Cache的工作原理,我们明天会做详细的讲解。

综合以上原因,我们知道统一内存架构有两个缺点:
1. 内存会有更高的延迟(Latency)。比如说,原本读取一个数据需要XX时间,现在可能要花两倍的时间才能拿到这个数据了。
2. 在CPU和GPU同时访问的情况下,内存的带宽不能充分发挥。比如说,原本一秒钟可以传送XX个字节的数据,现在当CPU和GPU同时读写的时候,只能传送到原本的2/3了。

我在A9看到有一个误区:认为有了统一内存,就可以完全避免内存和显存之间的数据复制,所以对带宽的需求就不那么高了。

假如真想避免的话,确实可以避免。但是没有意义,因为数据读写的速度会因此变慢。

所以在实践中,我们多半还是会像传统架构一样,在两块不同排布的内存之间复制数据。

比如说,一张纹理,它会被放在GPU比较喜欢的内存里面,以保证绘制的效率。如果CPU想直接更改纹理的内容,速度就很慢了。这时候,我们会在CPU比较喜欢的内存里建立一个缓冲区,很有效率的完成数据的操作,再一次性写入GPU那边。

可想而知,这样对带宽要求是没有下降的。

有了以上的知识,我们可以回头看看最上面那个链接了。

AMD那个大嘴巴所解读的hUMA技术的作用,其实是统一内存的标准功能,N64就有了。至于我们上面所说到的统一内存的很多问题,似乎也没有得到解决。

实际上,hUMA的作用并不像那文章解读的那样。根据我能够找到的资料,它似乎可以缓解我们提到的Cache的问题。因为现在没有任何游戏主机使用了这项技术,所以具体的效果就很难说了。

总而言之,AMD那位员工提供了很多错误信息,更像是给AMD自己的技术打广告,大家以后都要留意了。

最后,N64的统一内存为什么是败笔,就显而易见了:内存延迟太大。

N64有4MB的RDRAM,也就是当年的新型内存Rambus。它的带宽非常高,可惜被统一内存的延迟拖了后腿。

实际上,N64的败笔可不止这一项。

明天我们来一起看一下Cache的工作原理,大家明天见!

第七天 高速缓存(Cache)

高速缓存有很多种,我们今天讲的是其中的一种,叫做Cache。

这里我不得不提一件往事,是关于当年我毕业之后的第一份工作。

有一天我跟我前老板聊天,我说我必须要利用什么什么Cache的机制,那货很生气的说:什么?你是在找我要现金吗?

这个故事告诉我们两个道理:

1. 满脑子是钱的老板,以及完全不懂技术的老板,绝对是个灾难!
2. Cache和Cash同音。

Cache就是附属于CPU或者GPU的高速缓存。它是处理器性能的关键因素之一。

它存在的意义很简单:处理器访问Cache的延迟,比起处理器访问内存的延迟,要小很多倍。如果数据是装在Cache里面的,那么处理器拿到数据的速度就能提升很多倍。

很多人就要问了:那如果数据不在Cache里面怎么办呢?

因为Cache协议的种类实在是非常多,我在这里挑一种最普遍的情况来举例说明。

我们假设一个最初始的情况:数据全部在内存里,Cache是空的。

这时候,CPU需要拿一个字节的数据来计算一个东西,于是它就向Cache申请访问了。

Cache会告诉CPU:我这里没有这个数据。这种情况叫做Cache Miss。

于是CPU只好向内存申请访问了。慢就慢点吧,咱也没办法啊。

最后内存告诉CPU:我有这个数据。于是内存会给CPU这一个字节的数据。

注意,重点来了:与此同时,内存还会把邻近的一排数据都放到Cache里面存起来。

Cache里面的每一排数据,叫做一个Cache Line。一个Cache Line的大小通常是几个KB。

因此,我们还知道了一个结论:在Cache Miss的情况下,读取一个数据需要耗费双倍的内存带宽。

接下来,CPU又想拿同一个数据来计算了,于是它又向Cache申请。

这回Cache里面有这个数据了,所以CPU可以以非常小的延迟拿到这个数据,同时不消耗任何带宽。

这种情况叫做Cache Hit,命中了!

然后,CPU想拿下一个数据来计算了,于是它再一次向Cache申请。

我们上面已经学过,Cache一次性会拿一整排的数据,所以邻近的数据都是在Cache里面的。又是一个Cache Hit!

所以说,Cache对处理器性能的提速是建立在两个事实之上的:

1. 处理器的运算能力远远超过内存的读写速度。
2. 处理器经常拿重复或者邻近的数据。这种特性叫做局域行为(Locality)。

游戏任务更是如此,所以Cache对游戏性能的提升是非常重要的。

Cache的成本非常高,所以它们通常都很小。

在现代的处理器中,我们通常会设置多级缓存,即一级缓存(L1 Cache)和二级缓存(L2 Cache)。

L1 Cache的速度最快,但是非常小;L2 Cache的速度慢一点,容量也可以大一些。

Cache还可以进一步分类成I-Cache和D-Cache。

I-Cache专门用来装机器码指令,即Instruction Cache。D-Cache则是专门用来装数据,即D-Cache。

有了上面的知识,我们就可以来看看N64了。

N64用来装纹理的Cache只有4K,可想而知,它是装不了任何清晰的纹理的。

因此,GPU在读取大纹理的时候,会出现大量的Cache Miss。我们上面说过,Cache Miss的成本非常高,会消耗两倍的带宽,也利用不到Cache的低延迟。

很多N64游戏不得不牺牲纹理的大小,导致贴图模糊。

这就是N64另一个硬件设计上的败笔。

以上就是Cache大致的工作原理。有兴趣的玩家可以继续读下面的内容。

上面说的都是CPU读取数据的情况,那么Cache是怎么帮助写入数据的呢?

同理,我还是拿最常见的写入协议来讲解,这个协议叫做Write-Back。

当CPU写入数据的时候,如果数据不在Cache里面,会先申请读取一个Cache Line。

然后,CPU只写入Cache,真正内存里的内容不会更新,直到那个数据被读取为止。

这样就可以避免CPU反复写入内存的情况了。

我们也因此知道,在Write-Back协议下,即便是写入内存,也是会有读取内存的操作来占用带宽的。

这个协议比较适合CPU的读写和计算,因为Cache Locality非常普遍。

而GPU方面更普遍的写入情况就是大块内存的写入(Framebuffer之类的),这时候Write-Combining协议的效率就更高了。WC是会无视Cache而进行内存写入的。

根据这篇论文的结论,WC的速度是WB的1倍至10倍不等:
http://download.intel.com/design/pentiumii/applnots/24442201.pdf

第八天 高氏着色

高氏着色并不复杂,但是要理解它,就必须理解我们之前讲解过的很多概念。所以,今天也是一个很好的复习机会。

接着昨天的话题:因为Cache的限制,导致N64不能高效的处理高分辨率的纹理。所以N64游戏的材质往往看起来比较模糊。

但是,也有一些游戏就没有这个情况,比如下图中的马尿64:

kfzhnt9

图像的锐利度并不低,这是怎么做到的呢?

因为根本没有用到纹理!

希望大家还记得我们以前讲过的一个东西:插值方法。

当有纹理的时候,N64的硬件支持三重线性纹理过滤。那么,没有纹理的时候怎么办呢?

N64还支持另一种插值方法:高氏着色(Gouraud shading)。上面图片里面的大多数像素都是用高氏着色的。

接着还需要大家复习一下光照的基础:要想进行光照的处理,我们必须要有每个三角形顶点的法线数据,以及光线的方向。

有了以上的数据,我们就可以计算出每个顶点的光照强度了。

如果有纹理,像素的颜色就是在纹理颜色乘以光照的强度。因为高氏着色没有纹理,所以只需要指定一个单色,再乘以光照的强度。

接下来,高氏着色是怎么决定顶点之间的线和线和线之间像素的颜色值的呢?

答案很简单:就是线性插值。

大家再次复习一下,线性插值的基本概念。

应用在这里的线性插值,就是指一个像素会同时受到周围顶点的染色,染色的程度是跟距离相关的。

最后出来的结果就是平滑的颜色过渡了。

kfzhnt10

前两天讲的内容相对比较难,今天正好有机会调整一下节奏。

我可是非常认真的在安排内容和顺序,如果觉得哪里卡住了,我就强烈推荐大家借这个机会复习一下相关内容。

当然,如果以前都有认真读,今天的内容就真的是超简单的了!

距离我们的SS vs PS vs N64大对决已经不远了,大家明天见!

第九天 微程序

今天的中国生活在一个“微”时代。微博、微信,就连抄袭也改头换面立牌坊,叫做“微创新”。

这就是所谓的物是人非。小时候我们把电脑叫“微机”(微型计算机),于是也有了微机课和微机房。那时候,同样是一个“微”字,却代表了超大规模集成电路的技术进步:我们终于可以把计算机缩小到可以放上桌子了。

就像当我小学四年级开始在APPLE-II型电脑上玩LOGO语言并开始接触汇编的时候,我怎么也想不到,今天的苹果会制造出那种数码泡沫产业。不以科技推动和人类真实需求出发的产业,自然是泡沫产业,也自然有消失的那一天。

我们今天讲的微程序(Micro-code)也代表着技术的进步,以及一种新思维。

N64可以使用微程序对GPU进行编程。可惜它非常难用,跟统一内存架构一样,是一次失败的尝试。

微程序后来被PS2和GameCube所继承,并获得了很大的成功。直到Xbox出现之后 ,才被Shader取代。

不得不说的是,PS3的CELL处理器里面的协处理器(SPU),可以说是微程序思维的多线程版本,并且跟Shader同时存在于PS3中。最后,它也即将退出主机游戏的历史舞台。

那么,微程序到底能用来做什么呢?

首先,我们需要提一下N64的GPU的细节。

N64的图像处理器和音频处理器是在一起的,它叫做Reality Co-Processor。(因此,音频可能会影响图像性能,这也是N64另一个设计上的问题。)

然后,我们来复习一下,GPU所做的工作是什么?

它取得所有的顶点,将它们转换,以便显示在屏幕上,然后进行栅格化,变成像素,再进行插值运算,决定每个像素的颜色值。

我们之前也说过,GPU的这整套流程分成顶点处理和像素处理两部分。它们的分界线是栅格化。

于是我们可以发现,整个顶点处理和像素处理的方式,都是比较固定的。

顶点处理就是进行坐标系的变换;像素处理也是固定的,只是有一些有限的选择:你可以选择做三重线性纹理过滤,或者进行高氏着色等等。

如果你想有更多的控制和更复杂的特效,GPU就必须支持编程(Programmable)。

我们今天要讲的微程序(Micro-code)就是在N64、PS2、Gamecube等主机中使用的,一种比较早期的,同时也是比较复杂的GPU编程方式。

N64的GPU默认运行的微程序是任天堂事先编写好的,它做的任务就是我们上面所说的固定的顶点处理和像素处理。

游戏开发者也可以自己编写一套不同的微程序,这样就可以做到与众不同的效果或者优化了。

举例来说。。。前几天我们说过,因为纹理Cache和统一内存架构的原因,N64的像素填充率会受到很大的限制。

解决这个问题的方式之一,就是使用微程序来替换掉原有的Mipmap和深度缓冲机制。

纹理的格式可以自定义,让它们尽量占用最小的空间。

深度缓冲也不是所有场合都需要的,有选择性的使用它可以提高像素填充的速度。

N64可以做到这种比较底层、也非常困难的技巧,这也是Rare等厂商发挥N64机能的不二法门。

细心的玩家肯定已经发现了:这种方式是不是跟顽皮狗发掘PS3的机能很类似?

没错!但问题是任天堂提供的工具非常难用,很多人甚至怀疑任天堂的动机,是不是不想让第三方掌握这种技术。

因此,可以比较好利用N64机能的游戏非常少,其中最重要的原因之一就在这里。

好了,现在我们应该把很多基础的概念讲解的很清楚了。明天我们会对SS、PS和N64的机能做一个总结和比较,也会迎来本文第二期的结束。

大家明天见!

第十天 SS vs PS vs N64

“朱門酒肉臭,路有凍死骨。榮枯咫尺異,惆悵難再述。
北轅就涇渭,官渡又改轍。群冰從西下,極目高崒兀。”

历史的洪流浩浩荡荡,游戏主机经过了多少兴旺交替,其中不乏很多大宝石、直接倒在路边没人记得的主机。在第五代游戏主机中,多数人只记住了三个明星:世嘉土星,索尼Playstation和任天堂64。

那么,是什么使得这三台主机可以脱颖而出呢?我们今天要做一个总结。

(当然,我还要强调第101遍,本文只讨论3D机能。)

我们先来看一下这三台主机能做什么、不能做什么。

N64能做的事情最多。它硬件支持半透明效果、深度缓冲、Mipmap、纹理过滤、全屏抗锯齿、透视修正以及高氏着色,甚至可以做到简单的即时光照,简直就是一台低分辨率的Dreamcast。

同时,它也大胆尝试各种新技术新思路。它是第一台使用统一内存架构、以及可编程的GPU的游戏主机,虽然实际效果很差,但是勇气可嘉。

(可惜的是,这种勇气并没有被今天的任天堂所继承。)

虽然N64能做到的事情最多,但是在跨平台游戏中,往往是比较差的一个。

总的来说,N64非常接近现代主机,也几乎是为3D游戏量身定制的游戏主机。

Playstation硬件支持半透明效果和简单的光照。(没了。)

PS的设计非常均衡,相比N64来说,几乎没有犯什么设计上的错误。

在没有明显瓶颈的基础上,原始计算能力也不错,编程的难度也相对比较简单,所以跨平台游戏往往会有比较好的表现。

PS还通过光盘载体对游戏的体验进行了创新,播片的风潮对视频游戏影响深远。

SS的硬件只支持最基本的3D图像处理,应该说是对3D游戏的流行没有做出正确的预测。如同Wii没有对HD游戏的流行做出正确的判断一样。

SS是游戏主机历史上唯一一台以四边形为3D图像处理单位的主机,它处理2D图像和3D图像并没有太大的区别,可以看出SS的设计非常的保守。

保守的设计也导致没有很多技术和游戏方式上的创新。

我们第一期说过,分析机能要看三方面:
1.计算能力(兵力)
2.存储器容量(粮草)
3.数据读写和传输速度(运输队)

N64拥有第五代主机中最强的CPU和GPU。但是,并不像广告宣传所说的,这个性能跟64位没有太大的联系。

Atari Jaguar也号称是64位主机,它的广告词是“Do the maths”(“自己算”),可是实际机能却只能达到SFC的水准。

N64跑的都是32位程序,自然也就利用不到多数的64位数据处理能力。

任天堂官方宣称N64可以处理50万多边形,实际上因为粮草和运输队的拖累,屏幕上能有2000三角形就算不错了。

PS方面,官方说是100万多边形(更离谱了。。。),实际结果则是跟N64是差不多的。

SS方面,官方说是20万多边形,从实际结果来看,往往跨平台游戏中,SS版的多边形还要多一点。(你们到底有谱吗。。。)

可见官方的宣传是多么的自由奔放。

其中的原因我们之前都强调过,因为他们从来就不统一衡量的方法和标准。这种情况下,那些数据就连参考的价值都没有了。

即便是次世代的宣传也是一样的,大家都要留意这一点。

另外,N64的音频和图像共用一个处理器。音频处理会影响到图像处理,这个问题也是前无古人、后无来者的。

N64有4MB的RAM,而且是统一内存架构,所以使用上还会更节省一点。

PS有2MB的内存,1MB的显存。

SS的存储器非常多!我们暂时这样归纳:2MB内存,1.5MB显存。

大家都半斤八两,而且肯定都够用了。其中,N64的存储器应该稍微有余裕一些。

按照正常的逻辑,是不是N64就可以有更精细的建模和纹理呢?

不是,因为N64写入深度缓冲很慢,多边形多了来不及写;N64的纹理缓存也太小,纹理体积大了就会太慢。粮草够用是够用了,就是运不出去。

现在我们都知道了,N64的运输队非常不给力!

但讽刺的是,N64的内存带宽却远远高于PS和SS。那到底为什么数据传输的这么慢呢?

原因包括:
1. 统一内存架构导致延迟太长。
2. 支持深度缓冲,但是写入的速度太慢。
3. 处理器的缓存设计不合理。

如果游戏开发者决定自己写一套微代码,也许还可以解决这些问题。可是这个技术难度很大,老任也不给好的文档和工具,多数第三方也只好作罢。

PS和SS则不存在这个瓶颈。

最后提一下存储介质。其实64MB的N64卡带容量对游戏来说是足够的,不过因为成本的问题,大家都选择比较小容量的卡带,间接影响了游戏的效果。

但是,卡带肯定不能提供长时间播放视频的容量,这也损失了一种游戏体验的可能性。

好了,今天的内容就到这里,大家明天见!

其实今天通篇都是结论啊。比较机能又不是比较数字,哪会有一个大于小于的结果呢?

真要有结论的话,不如就以现在的主机做个比喻吧:

N64像是PS3。很难用,但是用好了最强大。

PS像是Xbox 360。设计均衡,没有明显的短板。

SS像是提高几倍性能的Wii。3D机能也不弱,但是对业界的判断不准,技术上也较为保守。

这三台主机不知道碾压了多少竞争对手,它们都是赢家。

转载请注明:No.77 疯人院 - 游戏业界新闻 - 主机游戏资料攻略 » 【业界】开发者和你谈——关于电视游戏机的图形运算处理技术(二)

发表我的评论
取消评论
7+6 (必填)

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址