本站首页    管理页面    写新日志    退出


«July 2025»
12345
6789101112
13141516171819
20212223242526
2728293031


公告

谦卑,荣誉,牺牲,英勇,怜悯,诚实,精神,公正。


我的分类(专题)

日志更新

最新评论

留言板

链接

 

 


Blog信息
blog名称:
日志总数:183
评论数量:698
留言数量:7
访问次数:3018431
建立时间:2005年12月29日




[编程学习]Cg编程入门编(OpenGL)
文章收藏,  软件技术

newqiang 发表于 2006/10/25 21:24:19

Cg编程入门编(OpenGL) 原注: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\libTo:   C:\Program Files\Microsoft Visual Studio\VC98\Lib From: C:\Program Files\NVIDIA Corporation\Cg\includeTo:   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和别的一些相关网站中,有许多着色代码提供给我们使用,同时也可我和他们一起分享你的经验。相关档案:sf_2005102615296.doc (58368bytes)   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[i][0]); cgGLSetParameter3f(VertexColorParam, 1.0, 0.0, 0.0); glVertex3fv(&CubeVertices[CubeFaces[i][0]][0]); cgGLSetParameter3f(VertexColorParam, 0.0, 1.0, 0.0); glVertex3fv(&CubeVertices[CubeFaces[i][1]][0]); cgGLSetParameter3f(VertexColorParam, 0.0, 0.0, 1.0); glVertex3fv(&CubeVertices[CubeFaces[i][2]][0]); cgGLSetParameter3f(VertexColorParam, 1.0, 1.0, 1.0); glVertex3fv(&CubeVertices[CubeFaces[i][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  作者:B Alex D'Angelo | 日期:2005-11-28   


阅读全文(8881) | 回复(1) | 编辑 | 精华
 


回复:Cg编程入门编(OpenGL)
文章收藏,  软件技术

stupidboys1027(游客)发表评论于2011/7/7 13:10:38

运行不起来啊


个人主页 | 引用回复 | 主人回复 | 返回 | 编辑 | 删除
 


» 1 »

发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.047 second(s), page refreshed 144749724 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号