从零开始实现3D软光栅渲染器 (1) 简介
如何在2D屏幕上表示3D物體?這是學習3D編程必須要搞明白的事情。大家都知道,調用OpenGL的函數,給定三角形的3個頂點位置,顏色,就能在屏幕上畫一個三角形,再加載一幅圖片,就可以給這個三角形附上紋理,還能讓這個三角形繞某個坐標軸發生旋轉… 這些看似簡單的問題的背后,實則是3D編程的內功。大家都知道,學武之人,拼的是內力,花里胡哨的招式的確很博人眼球,但是從長遠來看,收益遠沒有修煉內力高。
而一個軟光柵渲染器幾乎涵蓋了所有的3D渲染知識,從本篇開始,我們將從零開始實現一個3D軟光柵渲染器,學習3D渲染背后的數學原理。
光柵化
所謂光柵化就是將你想畫的東西轉換到2D屏幕上的像素的過程。這個過程涉及到很多光柵化算法,比如說,畫一條直線,大家都知道直線的方程:y = k * x + b (斜截式) 這里的 x , y 的取值范圍是全體實數,但是屏幕是像素組成的,你要想在屏幕上顯示,你就得使用一些算法將這些實數集映射到相應的像素集(離散化)。
3D流水線
光柵化是OpenGL渲染流水線的一個階段,而這個階段是由GPU完成的。一方面,由于現在很多成熟的光柵化算法已經被集成到GPU中,基本不用開發人員手動實現了。另一方面,由于GPU具有很強的并行計算能力,相比在CPU中實現這些算法,圖形的渲染會大大提升。
那么什么是渲染管線呢?你可以想象一下iphone的生成車間,先制作地板,然后焊接電路,再安裝電池…這就是一條流水線。3D編程中,將物體最終顯示到屏幕上也要經歷類似的過程。
我們以游戲開發為例,簡單介紹一下這個流程:
首先,我們需要一個坐標系來描述場景中各物體的位置,否則你根本無法確定游戲角色、道具等的位置,這個坐標就叫世界坐標。就像它的名字那樣,我們可以把它理解成描述我們構建的3D世界的坐標系,它是唯一的,它是固定不變的。
而我們的游戲模型一般都是在3D軟件中創建的,一般建模的時候,也需要一個坐標系用來描述各個頂點的位置,這就是局部坐標系。如下圖就是blender中的局部坐標系,順便說一下,它是右手坐標系,紅綠藍三個箭頭分別對應x,y,z三個坐標軸。局部坐標系的原點一般是由建模者設置的,比如建一個游戲人物的模型,有的人喜歡把局部坐標系的原點放到模型雙腳中心,而有的人喜歡把它放在角色的腰部位置,這都是可以的。
一個游戲場景一般包含很多模型(房屋,角色,道具,樹木 etc.),而要將這些分別來自不同建模者的模型繪制到同一個場景(同一個世界坐標系)中來,就需要進行坐標變換。沒有找到合適的模型,就拿我珍藏的一張合影來舉個例子吧。一圖勝前言,不需要解釋。
好了,現在模型們已經變換到世界坐標系了。你玩游戲的時候,是不是可以控制人物走動,走到不同的位置,會看到不同的景象?此時,你看到視圖,是有一個叫攝像機的東東控制的,又叫虛擬相機。這其實是一個概念,就是為了方便觀察世界坐標系中而抽象出來的一個模型(這里的模型是一種概念上的模型)。即使不同攝像機,我們照樣也可以觀察世界坐標系中各個物體,這個我們在后面介紹?,F在你只要知道,有一個叫攝像機東西,我們可以很方便的通過控制它來觀察世界坐標系中的物體。此時,我們看到的物體是相對攝像機的位置而言的。比如,你拿手機拍照的時候,雖然你拍的是上海的東方明珠,等你拍下來了,就是你手機上的東方明珠,同一個物體,只是描述的方式不同,這個好好品一下。為什么這么干,我們以后再說。
現實世界是3D的,而計算機屏幕是2D的。我們怎么將3D的世界繪制到2D的屏幕上呢?此時,我們就需要選擇一種投影算法,將3D世界中的坐標點投影到2D屏幕上。
3D渲染最注重的就是效率。我們其實只要繪制我們人眼能看見的東西就好了。一個三角形,其實是有2個面的,一般在某一時刻,我們只能看到一個面,所以,另一個面就不需要繪制了。比如,一個精細的人物模型,可能有幾千萬個三角形構成的,而我們只能看到游戲人物的外表,其內部的三角形面片其實就不用繪制了,因為沒人看。
到這里,我們就已經拿到了要進行繪制的頂點數據了。接下來,就是前面說的進行光柵化操作了。也就是說,我給你一堆頂點以及頂點之間的連接關系,你要能夠在屏幕上正確顯示出來(決定到底屏幕上哪些像素被著色,哪些不被著色)。假設我就繪制一個三角形,給3個頂點,光柵化的過程,就是將這三個頂點之間的連線映射到屏幕上相應的像素,如果給了顏色信息,還要給三角形區域著色。到這里,就能夠在屏幕上現實3D圖形了。
接下來,就是一些優化操作了,比如各種測試(像素包含測試、裁剪測試、alpha測試、模板測試、深度測試 etc.)、混合操作等,反正目的就是提升性能、優化渲染效果。
這就是大概的3D渲染流水線。我們的軟光柵渲染器就是要自己編碼實現這一套流程,這樣在調用OpenGL函數的時候,你才知道它背后到底發生了什么,當你遇到問題的時候,你才有能力嘗試猜測可能什么地方出了問題。
開發環境
最后,說一下開發環境。因為我們是學習3D渲染流水線,這個本身已經夠復雜了。為了能把注意力放到軟光柵的實現上,我們的開發環境越簡單越好,所以,我們選擇JavaScript開發一個Web-based軟光柵渲染器,開發環境VS code,記事本也可以。
其實,只要你掌握了這一套流程,隨便什么語言,只是顯示環境不同,核心原理都是相同的。對著我們的教程,你完全可以實現其他語言的軟光柵渲染器。
歡迎大家關注我的公眾號【OpenGL編程】,定期分享OpenGL相關的3D編程教程、算法、小項目。歡迎大家一起交流。
總結
以上是生活随笔為你收集整理的从零开始实现3D软光栅渲染器 (1) 简介的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计算机硬件与软件教学反思,计算机硬件教学
- 下一篇: JSP危险化学品管理系统myeclips