CG 頂點指令碼

來源:互聯網
上載者:User

CG 頂點指令碼
nVidio的面向GPU的C語言,如果你相信它就好好學學吧,同樣這裡也只是個入門。記住,類似的語言還有微軟的HLSL,OpenGL的GLSL,ATI的shaderMonker。不要選錯哦:)            

        
     
使用頂點和片斷指令碼去做渲染工作可以得到額外的好處,最大的好處就是把CPU的一些工作交給了GPU,Cg提供了書寫這些強大的指令碼的一種手段。
這篇教程有許多目的,第一向你展現了一個非常簡單的頂點指令碼,第二向你說明如何在OpenGL中使用Cg編寫的指令碼。
這個教程是基於最新的NeHeGL的基本代碼,為了獲得更多的資訊,你可以訪問nVidia的官方網站(developer.nvidia.com),它會給你一個完整的答案。

注意:這個教程不是叫你如何去寫一個完整的Cg指令碼,而是教你在OpenGL中載入並運行指令碼。
開始:
第一步,從nVidia的網站上下載Cg Compiler庫,最好去下載1.1版本的,因為nvidia各個版本的變化很大,為了讓程式不出現任何問題,最好這樣做,因為我們用的是1.1版本的。

下一步,包含編譯需要的標頭檔和庫檔案。
      
     
     

我已經幫你把它們拷貝到了工程的檔案夾裡了。
Cg介紹
你必須有以下幾個概念:
1、頂點指令碼會作用於你輸入的每一個頂點,如果你想要作用於一些頂點,那麼你必須在作用前載入頂點指令碼,並於作用後釋放頂點指令碼。
2、頂點指令碼輸出的結果被送入到片斷處理器中,你不用管這其中是如何?的。
最後,記住頂點指令碼在圖元裝配前被執行,片斷指令碼在光柵化後被執行。
好了,現在我們建立一個空白的檔案吧(儲存為wave.cg),接著我們建立一個資料結構,它被我們得指令碼使用。下面的代碼被加入到wave.cg檔案中。    
    struct appdata
{
float4 position : POSITION;
float4 color : COLOR0;
float3 wave : COLOR1;
};
  
     
上面的結果說明,我們輸入的頂點包含一個位置座標,一個顏色和我們自訂的波的顏色
下面的代碼定義一個輸出頂點的資料,包括一個頂點和顏色     
    struct vfconn
{
float4 HPos : POSITION;
float4 Col0 : COLOR0;
};
  
     
下面的代碼是Cg的主函數,每個頂點都會被以下函數執行:
      
   
vfconn main(appdata IN, uniform float4x4 ModelViewProj)
{
vfconn OUT; // 儲存我們輸出頂點的資料
// 計算頂點y的座標
IN.position.y = ( sin(IN.wave.x + (IN.position.x / 5.0) ) + sin(IN.wave.x +
(IN.position.z / 4.0) ) ) * 2.5f;

// 儲存到輸出資料中
OUT.HPos = mul(ModelViewProj, IN.position);
// 不改變輸入的顏色
OUT.Col0.xyz = IN.color.xyz;
return OUT;
}   
     

完成了上面的代碼,記得儲存一下.
下面我們到了程式中,首先包含使用cg需要的標頭檔,和庫檔案     
    #include <cg/cg.h>
#include <cg/cggl.h> #pragma comment( lib, "cg.lib" )
#pragma comment( lib, "cggl.lib" )
  
     
下面我們定義一些全域變數,用來計算我們得網格和控制cg程式的開關    
    #define   SIZE 64 // 定義網格的大小
bool   cg_enable = TRUE, sp; // 開關Cg程式
GLfloat   mesh[SIZE][SIZE][3]; // 儲存我們的網格
GLfloat   wave_movement = 0.0f; // 記錄波動的移動   
     
下面我們來定義一些cg相關的全域變數
    
    CGcontext cgContext; // 用來儲存cg指令碼
  
     
我們需要的第一個變數是CGcontext,這個變數是多個Cg指令碼的容器,一般來說,你獲得你可以用函數從這個容器中獲得你想要的指令碼
接下來我們定義一個CGprogram變數,它用來儲存我們得頂點指令碼     
    CGprogram cgProgram; // 我們得頂點指令碼   
     
接下來我們需要一個變數來設定如何編譯這個頂點指令碼    
    CGprofile cgVertexProfile; // 被頂點指令碼使用
  
     
下面我們需要一些參數用來把Cg指令碼使用的資料從程式中傳送過去。    
    CGparameter position, color, modelViewMatrix, wave; // 指令碼中需要的參數
  
     
在初始化階段我們先要建立我們網格資料    
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
for (int x = 0; x < SIZE; x++)
{
for (int z = 0; z < SIZE; z++)
{
mesh[x][z][0] = (float) (SIZE / 2) - x;
mesh[x][z][1] = 0.0f;
mesh[x][z][2] = (float) (SIZE / 2) - z;
}
}
  
     
我們設定多邊形的現實模式為線框圖,接著遍曆沒有頂點,設定其高度。
接下來,我們初始化Cg程式
      
    // 設定Cg
cgContext = cgCreateContext(); // 建立一個Cg容器
// 測試是否建立成功
if (cgContext == NULL)
{
MessageBox(NULL, "Failed To Create Cg Context", "Error",
MB_OK);
return FALSE;
}
   
     
我們建立一個Cg程式的容器,並檢查它是否建立成功    
    cgVertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX); // 配置在OpenGL中使用頂點緩衝
// 檢測Cg程式的是否建立成功
if (cgVertexProfile == CG_PROFILE_UNKNOWN)
{
MessageBox(NULL, "Invalid profile type", "Error", MB_OK);
return FALSE;
}
cgGLSetOptimalOptions(cgVertexProfile); // 啟用設定檔   
     
如果你想使用片斷指令碼,使用CG_GL_FRAGMENT變數。如果返回的變數為CG_PROFILE_UNKNOW表示沒有可用的設定檔,則不能編譯你需要的Cg程式。    

    // 從檔案中載入Cg程式
cgProgram = cgCreateProgramFromFile(cgContext, CG_SOURCE, "CG/Wave.cg", cgVertexProfile, "main", 0);

// 檢測是否成功
if (cgProgram == NULL)
{
CGerror Error = cgGetError();
MessageBox(NULL, cgGetErrorString(Error), "Error", MB_OK);
return FALSE;
}
   
     
我們嘗試從源檔案中建立一個Cg程式,並返回編譯後的結果。    
    // 載入指令碼
cgGLLoadProgram(cgProgram);
  
     
下面我們把頂點指令碼載入到顯存,並準備幫定給GPU。所有的指令碼在使用前必須載入。    
    // 把資料變數地址發送給Cg程式
position = cgGetNamedParameter(cgProgram, "IN.position");
color   = cgGetNamedParameter(cgProgram, "IN.color");
wave   = cgGetNamedParameter(cgProgram, "IN.wave");
modelViewMatrix = cgGetNamedParameter(cgProgram, "ModelViewProj");
return TRUE;
   
     
在初始化的最後,我們必須告訴Cg指令碼在那裡去獲得輸入的資料,我們需要把變數的指標傳遞過去,下面的函數完成了這個功能。
程式結束時,記得釋放我們建立的內容。     
    cgDestroyContext(cgContext);   
     
下面的代碼使用空格切換是否使用Cg程式    
    if (g_keys->keyDown [' '] &amp;&amp; !sp)
{
sp=TRUE;
cg_enable=!cg_enable;
} if (!g_keys->keyDown [' '])
sp=FALSE;
  
     
現在我們已經完成了所有的準備工作了,到了我們實際繪製網格的地方了,按照慣例我們還是先設定我們得視口。
      
   
gluLookAt(0.0f, 25.0f, -45.0f, 0.0f, 0.0f, 0.0f, 0, 1, 0);
// 把當前Cg程式的模型變化矩陣告訴當前程式
cgGLSetStateMatrixParameter(modelViewMatrix, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY);   

     

上面我們要做的事就是把當前Cg程式的模型變化矩陣告訴當前程式。
結下來如果使用cg程式,則把頂點的顏色設定為綠色    
    // 如果使用Cg程式
if (cg_enable)
{
// 使用頂點指令碼設定檔
cgGLEnableProfile(cgVertexProfile);
// 幫定到當前的頂點指令碼
cgGLBindProgram(cgProgram);
// 設定繪製顏色
cgGLSetParameter4f(color, 0.5f, 1.0f, 0.5f, 1.0f);
}
  
     
下面我們來繪製我們的網格。    
    // 開始繪製我們的網格
for (int x = 0; x < SIZE - 1; x++)
{
glBegin(GL_TRIANGLE_STRIP);
for (int z = 0; z < SIZE - 1; z++)
{
// 設定Wave參數
cgGLSetParameter3f(wave, wave_movement, 1.0f, 1.0f);
//設定輸入的頂點
glVertex3f(mesh[x][z][0], mesh[x][z][1], mesh[x][z][2]);
glVertex3f(mesh[x+1][z][0], mesh[x+1][z][1], mesh[x+1][z][2]);
wave_movement += 0.00001f;
if (wave_movement > TWO_PI)
wave_movement = 0.0f;
}
//經過Cg程式處理,進行繪製
glEnd();
}
  
     
上面的程式碼完成具體的繪製操作,對於每一個頂點,我們動態傳入波動係數和輸入原始的頂點資料。在繪製開始前,頂點指令碼接受所有的頂點資料並處理,接著進行光柵華操作。
別忘了在繪製完成後,關閉我們啟用的頂點指令碼,否則在繪製其它的模型時會讓你得到不想要的結果。     
    if (cg_enable)
cgGLDisableProfile(cgVertexProfile); // 禁用頂點指令碼設定檔   
     

好了上面就是所有的內容了,簡單吧.Cg就是這麼簡單  

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.