1. 程式人生 > >Cg程式設計自學心得

Cg程式設計自學心得

在計算機圖形學領域,用計算機處理圖形資訊我們最先接觸的通常是使用opengld3d這些圖形程式設計介面,這些通常稱為固定管線的程式設計,也就是程式設計師不直接操縱可程式設計的GPU,在常見的opengl的程式設計管線中,底層為我們設定了固定的渲染過程,程式設計師控制的只是這個過程中的各種引數。但是在有些情況下,尤其是硬體效能突飛猛進的今天,為了得到更好的效果,得到對圖形計算更好的控制,就需要自己對GPU進行程式設計,這也就是可程式設計的圖形渲染,這些用於對GPU的程式設計介面就是GPU語言,CGNVIDIA開發的針對NVDIA圖形處理器的硬體程式語言,它的全程是C for graph,也就是影象的

C語言,因為它和c的文法很相似,所以有了c語言的基礎,學習cg將是很輕鬆的事情。以下是我學習的Cg語言的一些心得。

1圖形渲染管線

現代計算機處理圖形主要依靠圖形處理單元(GPU)來完成,在GPU上渲染圖形的整個過程就是圖形渲染管線,整個管線的輸入是最初的描述圖元的資料,輸出是螢幕上每個畫素的顏色,一切圖形學的處理過程都在這個管線中進行。

常見的Gpu的渲染管線的具體內容如下

 

注意這個圖中的每個操作是有嚴格的先後順序之分的。

在過去,在我們簡單的使用opengl或者到到d3d進行圖形繪製時,底層自動按照上述順序為我們生成圖形,我們在opengl中做的只是調節其中各個“引數”,但是資料走的通路是一樣的,這稱為固定渲染管線。

Gpu主要包括頂點處理器和片段處理器,在第三代顯示卡(GEforce3)之後,gpu的頂點處理器可以進行程式設計,也就是上圖中的頂點變換部分可以被控制,在第四代顯示卡(GEForceFX)之後gpu的片段處理器可以進行程式設計,也就是插值紋理取樣著色這一過程可以進行程式設計,現在我們可以自行調控上述兩個紅色部分的工作流程,而不必沿著固定渲染管線,這就叫做可程式設計的圖形渲染。

當然cg語言也要依託於opengld3d這些圖形硬體的藉口,因為上圖中的藍色部分仍需他們來做,只是紅色部分我們可以不再用opnegl來寫和控制,另外諸如向硬體傳送和接受資料也需要他們,cg語言的作用只是在opnegl

中控制上述兩個紅色方塊中的處理過程。

2頂點程式

在頂點處理器中執行的程式叫做頂點程式,頂點程式的作用也就是進行頂點變化,在圖形渲染管線中,它可以做三件事,一是將輸入的物體的區域性座標轉化成最終的剪裁座標,二是生成每個頂點的紋理座標,三是產生每個頂點的顏色。所以在一個頂點程式中,允許的輸入有位置資訊(這個位置是區域性座標),頂點顏色(在opengl中繪製頂點時指定的),法向資訊,n個紋理座標(在opengl中指定的),輸出通常有位置、顏色、n個紋理座標,不輸出的有預設值。

也就是我們可以直接掌控的頂點的屬性有這三個:

1剪裁座標系的位置:這個位置的值只有在-11之間才能被看見,也就是x1的點恰好落在渲染視窗的最右邊的線上,而剪裁座標的z值就是深度值,可以直接控制這個座標來控制圖形的繪製於隱藏及其他集合變化等。

Projection Matrix*Modelview Matrix *區域性座標=剪裁座標

2顏色就是每個頂點最終的著色

3紋理座標通常就是我們去直接控制每個頂點的紋理座標。但是更重要的是這裡的紋理座標通常不儲存紋理,而是一個大的“快取器”,它通常用來儲存每個頂點的其他屬性(如發向或其他任何想儲存的和每個頂點有關的)然後傳入給片段處理器進行處理。如我們要在片段處理器中每個頂點的法向進行差值做phone shading,這時就要先在頂點處理器中將法向裝入一個紋理中傳給片段程式。通常紋理的數量由opengl和硬體決定。

3片段程式

在片段處理器中執行的程式稱作片段程式,片段程式的作用其實說到底只有一個,就是為已經光柵化的每一個片段產生它的顏色。對於片段程式,它的輸入只有紋理資訊,輸出也只有顏色資訊。當然輸入的紋理資訊可以封裝其他的可以被光柵化的資訊(如位置、法向等),我們可以根據不同的需要和紋理取樣來直接控制每個片段的最終顏色。

4 Cg程式在C/C++環境中的使用

通常cg程式需要依附於opengld3d程式使用,在opengl中的典型使用方式如下:

1建立一個cg上下文

context = cgCreateContext();

2 設定profile(每個頂點或片段程式各需要一個)

myCgVertexProfile=cgGLGetLatestProfile(CG_GL_VERTEX);

3 動態的編譯cg程式

vertexProgram=cgCreateProgramFromFile(context,CG_SOURCE,"v_shadowmap.cg",myCgVertexProfile,"vShadowmap",NULL);

4 載入編譯好的cg程式

cgGLLoadProgram(vertexProgram);

在使用cg程式之前都要先繫結這個cg程式

cgGLBindProgram(vertexProgram)

每次在使用cg程式之前要啟用這個profile

cgGLEnableProfile(myCgFragmentProfile);

使用之後要讓這個profile失效

cgGLDisableProfile(myCgVertexProfile)

動態的改變cg 程式中的uniform引數:在cg程式中的uniform引數是指可以再外部動態改變的輸入引數,改變這個引數的語法有很多,常用的有

首先用paramtex0=cgGetNamedParameter(fragProgram,"tex0");得到cg程式fragProgramtex0這個uniform引數,

再用cgGLSetTextureParameter(paramtex0,textureObj)cgSetParameter4fv(paramtex0,accelar)等函式改變這個引數,最後用cgUpdateProgramParametersfragProgram)來更新這個cg程式。

什麼時候呼叫cg程式?

在一個opengl的環境中通常在什麼時候cg程式被執行呢,也就是說該在哪個地方呼叫cgGLEnableProfile()讓cg程式起作用呢?答案是每次再opengl進行實際上的繪製時cg程式在管線中起作用,opengl的繪製通常是用glBegin(GL_QUADS) glEnd()glutsolidsphear()等方式進行的,所以我們在這些語句前啟用呼叫cgGLEnableProfile,再繪製之後取消啟用cgGLDisableProfile()。

5 一些例子

可程式設計的圖形渲染相比固定管線的渲染的優勢是不用多說的,它交給程式設計師更多的空間去發揮,去自由的操縱圖形的處理過程,通常他可以做到在固定管線程式設計中難以實現甚至根本無法實現的效果,還可以大大加速渲染的效率,因為指令在gpu上的執行速度比在cpu上要快的多的多。所以從渲染效果和效率上講我們都儘量使用可程式設計的圖形渲染。

theCg Tutorial》一書中為我們實現了很多cg 程式的例項,可以自己嘗試實現一下,包括phone shading、動畫、環境貼圖、bumpe mappingfog等,當然所有的你想實現的效果都可以用cg 來實現,關鍵看你的想象空間和程式設計能力了。