追溯歷史
讓我們把時(shí)間撥回到1992年。當(dāng)時(shí)的CPU處理速度比現(xiàn)在的要慢1000倍,通過(guò)GPU加速當(dāng)時(shí)還未問(wèn)世,而且CPU也是無(wú)法承受的。3D游戲僅在CPU上進(jìn)行計(jì)算,渲染引擎使用單一顏色對(duì)多邊形進(jìn)行渲染填充。
MicroProse于1991年發(fā)布的游戲Gunship 2000
同年NovaLogic也發(fā)布了游戲科曼奇。
NovaLogic于1992年發(fā)布的游戲Comanche
在我看來(lái),當(dāng)時(shí)這種圖形出來(lái)以后簡(jiǎn)直嘆為觀止,它最起碼提前了3年。用戶可以看到很多的細(xì)節(jié),比如山脈,甚至山谷的紋理,這是第一次有一個(gè)比較清晰的陰影。當(dāng)然,它是像素化的,但那時(shí)候所有的游戲都是像素化的。
渲染算法
科曼奇使用了一種名為體素空間(Voxel Space)的技術(shù),它和ray casting是基于同一個(gè)想法。因此,體素空間引擎是2.5D引擎,它不具有規(guī)則的3D引擎提供的所有自由度。。
高度地圖和顏色地圖
高度地圖和顏色圖是表示地形最簡(jiǎn)單的方法。科曼奇使用了1024 * 1024一個(gè)字節(jié)代表了高度地圖,同樣使用了1024 * 1024一個(gè)字節(jié)表示顏色地圖,你可以在這個(gè)網(wǎng)站上下載。這些地圖是周期性:
這樣的地圖將地形限制為“地圖上每個(gè)位置一個(gè)高度” - 因此像建筑物或樹(shù)木這樣的復(fù)雜幾何形狀不可能表示出來(lái)。然而,色彩地圖的一大優(yōu)點(diǎn)是,它已經(jīng)包含了色彩和陰影。體素空間引擎只需要顏色,在渲染過(guò)程中不需要計(jì)算光照。
基本算法
對(duì)于3D引擎來(lái)說(shuō),渲染算法非常簡(jiǎn)單。體素空間引擎負(fù)責(zé)渲染高度地圖和顏色地圖,并繪制垂直線。下圖演示了這種技術(shù)。
清除屏幕。
為了保證遮擋從后面開(kāi)始并呈現(xiàn)在前面。這被稱為畫(huà)家算法。
確定地圖上的線,它對(duì)應(yīng)于與觀察者相同的光距離。考慮視場(chǎng)和透視投影(物體在更遠(yuǎn)的地方)
光柵線是用來(lái)匹配屏幕的列數(shù)。
從線段對(duì)應(yīng)的二維地圖中檢索高度和顏色。
執(zhí)行高度坐標(biāo)的透視投影。
用透視投影中檢索到的高度畫(huà)一條垂直線。
核心算法以最簡(jiǎn)單的形式包含了幾行代碼(python語(yǔ)法):
def Render(p, height, horizon, scale_height, distance, screen_width, screen_height):
# Draw from back to the front (high z coordinate to low z coordinate)
for z in range(distance, 1, -1):
# Find line on map. This calculation corresponds to a field of view of 90°
pleft = Point(-z + p.x, -z + p.y)
pright = Point( z + p.x, -z + p.y)
# segment the line
dx = (pright.x - pleft.x) / screen_width
# Raster line and draw a vertical line for each segment
for i in range(0, screen_width):
height_on_screen = (height - heightmap[pleft.x, pleft.y]) / z * scale_height. + horizon
DrawVerticalLine(i, height_on_screen, screen_height, colormap[pleft.x, pleft.y])
p1eft.x += dx
# Call the render function with the camera parameters:
# position, height, horizon line position,
# scaling factor for the height, the largest distance,
# screen width and the screen height parameter
Render( Point(0, 0), 50, 120, 120, 300, 800, 600 )
1234567891011121314151617181920
評(píng)論