Cg ,你好!------Cg編程入門編(OpenGL)
瀏覽:435477
原注:B Alex D ' Angelo (alexz@FusionIndustries.com)
譯: 川流不息 (huawenguang@hotmail.com)未經本人同意,不能用于商業用途。
本文將介紹如何在你現有的圖形程序中加入對頂點和片段的高級著色。采用CG著色語言,將會另你的工作更加容易實現。在編程過程中,你可以通過調用一些已有的CG函數來完成你的工作。當然,當你學得足夠深入后,你也可以自已編寫一些著色器。最具有參考價值的資料,當然要數Fernando 和 Kilgard 編寫的“The Cg Tutorial”了。在Nvidia公司的網頁中可以下載到。
一、概述
本文的程序中,結合OpenGL和GLUT在屏冪中畫了一個立方體,程序中加入了CG著色程序代碼。Listing1中包含了完整的原程序代碼,其中CG部分用粗體字標識出來,本程序貫穿全文。Listing2是一個CG頂點著色的代碼。
二、建立Cg編程環境
在進行CG編程之前,首先要下載CG工具包“Cg Toolkit”,在以下網址可以找到:
http: // developer.nvidia.com/CG ,請注意看一下你的顯卡是否支持頂點著色編程。
安裝CG工具包,為了能讓它在Visual C ++ 中工作,你可用以下兩種方法之一。第一種:把CG頭文件和庫文件中的內容,分別拷貝到Visual C ++ 的頭文件和庫文件的文件夾中。
From: C:\Program Files\NVIDIA Corporation\Cg\lib
To: C:\Program Files\Microsoft Visual Studio\VC98\Lib
From: C:\Program Files\NVIDIA Corporation\Cg\include
To: C:\Program Files\Microsoft Visual Studio\VC98\Include
第二種方法就是在VC編譯器中增加一個搜索路徑:Tools -> Options -> projects -> " directiress "
我們的程序中雖要連接“cg.lib”“cgGL.lib”這兩個庫文件,你可以把它寫到連接路徑中去:“properties -> Linker -> Input”,式者在程序開頭加入以下代碼:
#ifdef _MSC_VER
#pragma comment( lib, " cg.lib " )
#pragma comment( lib, " cgGL.lib " )
#endif
三、Cg編程細節
為了使用CG著色器,我們必須在程序中建立一個著色上下文(CGcontext),一個程序,只需一個著色上下文就可以了。
要為每個著色器建立一個CGprogram,而每個著色器你都可以為它指定一個單獨的顯卡適配參(CGprofile),CGprofile是用來告訴CG如何選擇最適合你顯卡的方式來對頂點或片段著色。
著色器可以在任何你雖要用到的地方被載入,載入的時候只需要給程序傳遞一個著色器函數入口名,或是著色器文件名。本文例子中,著色器在繪圖循環前被載入,并且,為了適應各種顯卡的在求,我們為著色器指定了一個基礎profile
1 、設定著色器要用到的變量。
首先,把CG頭文件包含到你的程序中:
#include < Cg / cg.h >
#include < Cg / cgGL.h >
接著,增加一些用來保存著色器入口地址的變量:
static CGcontext Context = NULL;
static CGprogram VertexProgram = NULL;
以及一些著色參數的地址變量,在初始化著色器之后,這些地址變量將通過使用“CGparameters”與具體參數綁定在一起。
static CGparameter KdParam = NULL;
static CGparameter ModelViewProjParam = NULL;
static CGparameter VertexColorParam = NULL;
最后指定頂點著色用到的profile:
static CGprofile VertexProfile = CG_PROFILE_VP20;
2 、初始化CG
程序中,初始化OpenGL這后,接著要對CG進行初始化。
首先,要創建一個著色上下文,一個程序中有一個著色上下文(context)就可以了,所有要用到的著色器都將會共享這一個上下文。
Context = cgCreateContext();
其次,通過給上下文指定著色器文件名以及著色器類型(這里是頂點著色),把一個頂點著色器加到著色上下文中去。
VertexProgram = cgCreateProgramFromFile(Context,
CG_SOURCE, " vertexShader.cg " ,
VertexProfile,
NULL, NULL);
只有在頂點著色器被成功創建之后,著色器的代碼才被真正地載入到程序中來,與此同時,各種著色參數地址也最終與著色器中的參數綁定在一起。在這之后的程序中,你便可以自由地使用和改變這些參數的內容了。如例子中所示的:反射光顏色(kdParam),頂點顏色(vertexColorParam)和模型透視矩陣(modelViewProj),些變量都是可以改變的。
在繪圖主循環結束之后,所有著色器占用的資源都要及時釋放,在CG中,提供了兩個函數:cgDestroyProgram();和cgDestroyContext(); 讓我們完成這一工作變得更簡單。
3 、繪圖循環
進入繪圖循環之后,著色器必雖在實際繪圖這前調用,繪圖結束這后就應該被禁用。這個概念和glBegin(); 及 glEnd(); 的意思是相似的,實際上CG是不能在 glBegin(); 和 glEnd(); 之間被調用的。
在所有繪圖工作開媽之前,我們通過調用函數 cgGLBindProgram(); 把著色代碼與OpenGL繪圖代碼關聯起來,緊接著調用cgGLEnableProfile(); 函數來指定CG程序到底是進行頂點著色,還是片段著色。之后我們就可以利用cgGLSetParamter * ();函數來傳遞或使用著色器中的參數了。
在所有繪圖工作完成之后,我們應該馬上調用cgGLDisableProfile(); 來停止著色器的使用。
著色器的參數是可以隨時改變的,例如:立方體的頂點顏色可以通過函數cgGLSetParameter3f(vertexColorParam, 0.0 , 1.0 , 0.00 );來設定。
既然我們知道了如何在繪圖循環中使用一個著色器,那么擴展到在一個繪圖循環中使用多個著色器的情況,那也是很容易實現的,簡單地把著色綁定包在繪圖代碼的外層就可以了。
例如:
void draw()
{
cgGLBindProgram(program);
cgGLEnableProfile(profile);
drawing_code()
cgGLDisableProfile(profile);
cgGLBindProgram(program2);
cgGLEnableProfile(profile2);
drawing_code2()
cgGLDisableProfile(profile2);
}
四、結論
現在我們已經學會了如何把著色代碼加入到我們現有的程序中。在
http: // developer.nvidia.com/CG
和別的一些相關網站中,有許多著色代碼提供給我們使用,同時也可我和他們一起分享你的經驗。
Listing 1 : HelloCg.c
Using Cg with your programs. Cg specific calls are in bold. Heavily based on the runtime_ogl
project in the Cg toolkit.
/* Minimalist program for using shaders, with no error checking */
#ifdef _MSC_VER
#pragma comment( lib, " cg.lib " )
#pragma comment( lib, " cgGL.lib " )
#endif
#include < math.h >
#include < stdio.h >
#include < stdlib.h >
#ifdef __APPLE__
#include < GLUT / glut.h >
#else
#include < GL / glut.h >
#endif
#include < Cg / cg.h >
#include < Cg / cgGL.h >
/* **************************************************************************** */
/* ** Static Data ** */
/* **************************************************************************** */
/* New Cg global variables */
static CGcontext Context = NULL;
static CGprogram VertexProgram = NULL;
static CGparameter KdParam = NULL;
static CGparameter ModelViewProjParam = NULL;
static CGparameter VertexColorParam = NULL;
#ifdef __APPLE__
static CGprofile VertexProfile = CG_PROFILE_ARBVP1;
#else
static CGprofile VertexProfile = CG_PROFILE_VP20;
#endif
/* End new Cg global variables */
GLfloat CubeNormals[ 6 ][ 3 ] =
{
{ - 1.0 , 0.0 , 0.0 }, { 0.0 , 1.0 , 0.0 }, { 1.0 , 0.0 , 0.0 },
{ 0.0 , - 1.0 , 0.0 }, { 0.0 , 0.0 , 1.0 }, { 0.0 , 0.0 , - 1.0 }
};
GLint CubeFaces[ 6 ][ 4 ] =
{
{ 0 , 1 , 2 , 3 }, { 3 , 2 , 6 , 7 }, { 7 , 6 , 5 , 4 },
{ 4 , 5 , 1 , 0 }, { 5 , 6 , 2 , 1 }, { 7 , 4 , 0 , 3 }
};
GLfloat CubeVertices[ 8 ][ 3 ];
/* **************************************************************************** */
static void DrawCube( void )
{
int i;
cgGLBindProgram(VertexProgram);
/*
* Set various uniform parameters including the ModelViewProjection
* matrix for transforming the incoming position into HPOS.
*/
if (KdParam != NULL)
cgGLSetParameter4f(KdParam, 1.0 , 1.0 , 0.0 , 1.0 );
/* Set the concatenate modelview and projection matrices */
if (ModelViewProjParam != NULL)
cgGLSetStateMatrixParameter(ModelViewProjParam,
CG_GL_MODELVIEW_PROJECTION_MATRIX,
CG_GL_MATRIX_IDENTITY);
cgGLEnableProfile(VertexProfile);
/*
* Create cube with per-vertex varying attributes
*/
for (i = 0 ; i < 6 ; i ++ )
{
glBegin(GL_QUADS);
{
glNormal3fv( & CubeNormals[ 0]);
cgGLSetParameter3f(VertexColorParam, 1.0, 0.0, 0.0);
glVertex3fv(&CubeVertices[CubeFaces[0]][0]);
cgGLSetParameter3f(VertexColorParam, 0.0, 1.0, 0.0);
glVertex3fv(&CubeVertices[CubeFaces[1]][0]);
cgGLSetParameter3f(VertexColorParam, 0.0, 0.0, 1.0);
glVertex3fv(&CubeVertices[CubeFaces[2]][0]);
cgGLSetParameter3f(VertexColorParam, 1.0, 1.0, 1.0);
glVertex3fv(&CubeVertices[CubeFaces[3]][0]);
}
glEnd();
}
cgGLDisableProfile(VertexProfile);
}
static void Display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
DrawCube();
glutSwapBuffers();
}
static void InitializeCube(GLfloat v[8][3])
{
/* Setup cube vertex data. */
v[0][0] = v[1][0] = v[2][0] = v[3][0] = -1;
v[4][0] = v[5][0] = v[6][0] = v[7][0] = 1;
v[0][1] = v[1][1] = v[4][1] = v[5][1] = -1;
v[2][1] = v[3][1] = v[6][1] = v[7][1] = 1;
v[0][2] = v[3][2] = v[4][2] = v[7][2] = 1;
v[1][2] = v[2][2] = v[5][2] = v[6][2] = -1;
}
static void InitializeGlut(int *argc, char *argv[])
{
glutInit(argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutCreateWindow(argv[0]);
glutDisplayFunc(Display);
InitializeCube(CubeVertices);
/* Use depth buffering for hidden surface elimination. */
glEnable(GL_DEPTH_TEST);
/* Setup the view of the cube. */
glMatrixMode(GL_PROJECTION);
gluPerspective( /* field of view in degree */ 40.0,
/* aspect ratio */ 1.0,
/* Z near */ 1.0, /* Z far */ 10.0);
glMatrixMode(GL_MODELVIEW);
gluLookAt(0.0, 0.0, 5.0, /* eye is at (0,0,5) */
0.0, 0.0, 0.0, /* center is at (0,0,0) */
0.0, 1.0, 0.); /* up is in positive Y direction */
/* Adjust cube position to be asthetic angle. */
glTranslatef(0.0, 0.0, -1.0);
#if 1
glRotatef(60, 1.0, 0.0, 0.0);
glRotatef(-20, 0.0, 0.0, 1.0);
#endif
}
int main(int argc, char *argv[])
{
InitializeGlut(&argc, argv);
/* Create one context which all shaders will use */
Context = cgCreateContext();
/* Adds shader to the context */
VertexProgram = cgCreateProgramFromFile(Context,
CG_SOURCE, "vertexShader.cg",
VertexProfile,
NULL, NULL);
if(VertexProgram != NULL)
{
/* Vertex shader only needs to be loaded once */
cgGLLoadProgram(VertexProgram);
/* Bind parameters to give access to variables in the shader */
KdParam = cgGetNamedParameter(VertexProgram, "Kd");
ModelViewProjParam = cgGetNamedParameter(VertexProgram, "ModelViewProj");
VertexColorParam = cgGetNamedParameter(VertexProgram, "IN.VertexColor");
}
glutMainLoop();
cgDestroyProgram(VertexProgram);
cgDestroyContext(Context);
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Listing 2 : vertexShader.cg
Cg vertex shader code written. Heavily based on the runtime_ogl project in the Cg toolkit.
struct appdata
{
float4 position : POSITION;
float3 normal : NORMAL;
float3 color : DIFFUSE;
float3 VertexColor : SPECULAR;
};
struct vfconn
{
float4 HPOS : POSITION;
float4 COL0 : COLOR0;
};
vfconn main(appdata IN,
uniform float4 Kd,
uniform float4x4 ModelViewProj)
{
vfconn OUT;
OUT.HPOS = mul(ModelViewProj, IN.position);
OUT.COL0.xyz = Kd.xyz * IN.VertexColor.xyz;
OUT.COL0.w = 1.0;
return OUT;
} // main
技術鄰APP
工程師必備
工程師必備
- 項目客服
- 培訓客服
- 平臺客服
TOP




















