现在的位置: 首页 > 综合 > 正文

The Cg Runtime:OpenGL中调用Cg程序

2013年10月15日 ⁄ 综合 ⁄ 共 14261字 ⁄ 字号 评论关闭

原文:《The Cg Tutorial》(Cg手册):Appendix B:The Cg Runtime,Page195

很多地方可能翻译得不好,还请大家见谅、指教!

注意:我省略了其中的Direct3D的部分,因为本人现在正使用OpenGL开发。


B.1 什么是Cg Runtime?

Cg程序支持运行在GPU上的程序,但是它们需要应用程序的支持才能渲染图像。

为了把Cg程序和应用程序链接起来,你必须做两件事情:

(1)把程序编译为不同的版本。这一步把你的Cg程序转化成与应用程序的3D编程接口和硬件兼容的形式。

(2)把程序和应用程序链接起来。这一步使得应用程序能够配置程序来执行,并且能够赋予不同的以及全局变量参数。

你可以在任何想使用这些操作的时候来选择它。你可以在编译时刻使用它们,此时应用程序已经被编译成可执行的形式,或者是在运行时刻使用它们,此时应用程序已经被执行。Cg Runtime是这样一些应用程序编写接口的集合:它们使得一个应用程序能够在运行时刻编译和链接Cg程序。


B.2 为什么要使用Cg Runtime?

B.2.1 面向未来

大多数应用程序需要在不同性能的GPU上运行,所以这些应用程序需要在不同的profile(一个Cg profile是被特定图形硬件和API所支持的Cg语言子集)上运行。如果一个应用程序在编译时刻预编译了它的Cg程序,它必须为每个程序保存适用于每个profile的预编译版本。对于一个使用了很多Cg程序的应用程序来说十分累赘。更糟糕的是,这些Cg程序在运行时刻不能灵活更改。通过预编译的方法,一个应用程序牺牲了未来的编译器可能提供的优化功能。

B.2.2 去除依赖性的问题

如果你把已经已经编译的Cg程序和一个应用程序链接起来,应用程序就和编译结果绑定了,尤其是和编译器如何分配参数有关。应用程序不得不通过使用Cg编译器输出的硬件寄存器名来参照Cg程序输入参数。

1. 在Cg程序中,不查看编译器输出结果寄存器名字难以和Cg程序中的相关有意义的名字关联起来。

2. 每当Cg程序、Cg编译器或者编译的profile改变时寄存器分配都可能发生变化。这就意味着你不得不每次更新应用程序,这是很不方便的。

B.2.3 输入参数管理

Cg runtime也提供了管理Cg程序输入参数的功能。特别的,它使得处理比如数组和矩阵这样的数据类型更加容易。

这些传统的函数也包括了那些必要的3D API调用,它们能够使得代码更短,减少程序员犯错误的次数。


B.3 Cg Runtime是如何工作的?

下图显示了组成Cg runtime API的三个库:


(1)一个函数和结构的核心集封装了runtime的独立于3D API的功能。

(2)建立于核心集之上的面向OpenGL的函数集

(3)建立于核心集之上的面向Direct3D的函数集

为了使应用程序编写者更加方便的编写程序,OpenGL和Direct3D库都能够采用他们各自API的规范和数据结构类型。你只需要把你的应用程序所使用的3D API和针对特定3D API的Cg runtime库链接起来。这样,大多数应用程序能够使用OpenGL或者Direct3D Cg runtime库。

B.3.1 头文件

下面显示了如何在你的C或者C++程序中包含核心Cg runtime API:

#include <Cg/cg.h>

下面显示了如何包含针对OpenGL的Cg runtime API:

#include <Cg/cgGL.h>

B.3.2 创建上下文

一个上下文是用来存放Cg程序的容器。它存放你加载的Cg程序以及他们共享的数据。

下面显示了如何创建上下文:

CGcontext context = cgCreateContext();

B.3.3 编译程序

使用cgCreateProgram函数通过把它添加到一个上下文中来编译一个Cg程序:

  1. <SPAN style="FONT-FAMILY: 'Microsoft YaHei'">CGprogram program =   
  2. cgCreateProgramFromFile(  
  3.                         context,  
  4.                         CG_SOURCE,  
  5.                         programString,  
  6.                         profile,  
  7.                         "main",  
  8.                         args  
  9.                         );</SPAN>  


参数CG_SOURCE表明接下来的参数programString是包含了Cg源代码的字节,而不是预编译代码。Cg runtime也允许你通过使用CG_OBJECT而不是CG_SOURCE来从已经编译的代码(也称目标代码)创建一个程序。

profile指明了这个程序将要编译成的profile。

"main"指明了你的程序的入口函数名。

args是这样的一个字符串,它提供选项给编译器。

B.3.4 加载程序

 在你编译完程序之后,你需要将结果目标代码传递给你使用的3D API。这时,你需要调用Cg runtime的特定的3D API函数。

在OpenGL中,你可以这样加载一个程序:

cgGLLoadProgram(program);

B.3.5 更改程序参数

runtime允许你更改你的程序的参数值。第一步是获得参数的句柄。

CGparameter myParameter = cgGetNamedParameter(program,"myParameter");

myParameter是出现在程序源代码中的参数名。

第二步就是设置参数的值,所需使用的函数取决于参数类型。

比如OpenGL中的一个例子:

cgGLSetParameter4fv(myParameter,value);

这个函数把值value(一个包含4个浮点类型的数组)赋给参数myParameter。

B.3.6 执行程序

在你执行一个程序之前,你必须使其相关的profile可用。比如:

cgGLEnableProfile(CG_PROFILE_ARBFP1);

接下来。你必须把程序与当前3D API状态绑定起来。这就意味着它将要在接下来的每个顶点(假设是顶点程序)以及每个片段(假设是片段程序)的绘制调用中执行。

下面显示了在OpenGL中如何绑定一个程序:

cgGLBindProgram(program);

在同一时刻你只能为特定的profile绑定一个顶点及片段程序。因此,只有别的顶点程序没有被绑定时,这个顶点程序才会被执行。对于片段程序也是一样。

在OpenGL中,禁用profile使用以下调用:

cgGLDisableProfile(CG_PROFILE_ARBFP1);

B.3.7 释放资源

如果你的应用程序不再需要Cg程序,那么释放由Cg runtime为程序维护的资源是一个好的编程习惯。

释放为单一程序分配的资源,使用下列函数调用:

cgDestroyProgram(program);

释放为一个上下文所分配的所以资源,使用下列函数调用:

cgDestroyContext(context);

注意:destroy一个上下文意味着释放了它包含的所以程序。

B.3.8 错误捕获

核心Cg runtime通过设置一个包含错误码的全局变量来报告错误。你能够以下列方式查询它以及相关错误字符串:

CGerror error = cgGetError();
const char *errorString = cgGetErrorString(error);

每次一个错误发生时,核心库会可选的调用一个由应用程序提供的回调函数。这个回调函数经常会调用cgGetError:
调用特定3D API也可能会产生关于特定API的错误。对于OpenGL Cg runtime库,使用glGetError来检测。

以这种方式,很多有用的信息都会被输出到调试输出控制台上。

  1. void MyErrorCallbask()  
  2. {  
  3.     const char* errorString = cgGetErrorString(cgGetError());  
  4.     printf(logfile,"Cg error:%s",errorString);  
  5. }  
  6. cgSetErrorCallback(MyErrorCallbask);  

最后粘贴一个实例:

C3E1v_green.cg:

  1. struct C3E1v_Output{  
  2.     float4 position:POSITION;  
  3.     float3 color:COLOR;  
  4. };  
  5.   
  6. C3E1v_Output C3E1v_green(float2 position:POSITION,  
  7.                                             uniform float3 constantColor)  
  8. {  
  9.     C3E1v_Output OUT;  
  10.     OUT.position = float4(position,0,1);  
  11.     OUT.color = constantColor;  
  12.     return OUT;  
  13. }  

C2E2f_passthru.cg:

  1. struct C2E2f_Output{  
  2.     float4 color:COLOR;  
  3. };  
  4.   
  5. C2E2f_Output C2E2f_passthru(float4 color:COLOR)  
  6. {  
  7.     C2E2f_Output OUT;  
  8.     OUT.color = color;  
  9.     return OUT;  
  10. }  

02_vertex_and_fragment_program.cpp:

  1. #pragma comment( lib, "cg.lib" )
      
  2. #pragma comment( lib, "cgGL.lib" )
      
  3.   
  4. #include <iostream>   
  5. #include <stdlib.h>
      
  6. #include <cmath>   
  7.   
  8. #define GLUT_DISABLE_ATEXIT_HACK
      
  9. #include <GL/glut.h>
      
  10.   
  11. #include <Cg/cg.h>
      
  12. #include <Cg/cgGL.h>   
  13.   
  14. using namespace std;  
  15.   
  16. static CGcontext myCgContext;  
  17. static CGprofile myCgVertexProfile;  
  18. static CGprofile myCgFragmenrProfile;  
  19. static CGprogram myCgVertexProgram;  
  20. static CGprogram myCgfragmentProgram;  
  21. static const char *myProgramName = "02_vertex_and_fragment_program",  
  22.                         *myVertexProgramFileName = "C3E1v_green.cg",  
  23.                         *myVertexProgramName = "C3E1v_green",  
  24.                         *myFragmenrProgramFileName = "C2E2f_passthru.cg",  
  25.                         *myFragmentProgramName = "C2E2f_passthru";  
  26.   
  27. static CGparameter myCgVertexParam_constantColor;  
  28.   
  29. static void checkForError(const char* situation)  
  30. {  
  31.     CGerror error;  
  32.     const char *string = cgGetLastErrorString(&error);  
  33.     if (error != CG_NO_ERROR)  
  34.     {  
  35.         cout<<myProgramName<<":"<<situation<<":"<<string<<endl;  
  36.         if (error == CG_COMPILER_ERROR)  
  37.         {  
  38.             cout<<cgGetLastListing(myCgContext)<<endl;  
  39.         }  
  40.         exit(1);  
  41.     }  
  42. }  
  43.   
  44. static void display();  
  45. static void keyboard(unsigned char c,int x,int y);  
  46.   
  47. int main(int argc,char** argv)  
  48. {  
  49.     glutInitWindowSize(400,400);  
  50.     glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);  
  51.     glutInit(&argc,argv);  
  52.   
  53.     glutCreateWindow(myProgramName);  
  54.     glutDisplayFunc(display);  
  55.     glutKeyboardFunc(keyboard);  
  56.   
  57.     glClearColor(0.1,0.3,0.6,0.0);  
  58.   
  59.     myCgContext = cgCreateContext();  
  60.     checkForError("creating context");  
  61.     cgGLSetDebugMode(CG_FALSE);  
  62.     cgSetParameterSettingMode(myCgContext,CG_DEFERRED_PARAMETER_SETTING);  
  63.   
  64.     myCgVertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);  
  65.     cgGLSetOptimalOptions(myCgVertexProfile);  
  66.     checkForError("selecting vertex profile");  
  67.   
  68.     myCgVertexProgram = cgCreateProgramFromFile(  
  69.         myCgContext,  
  70.         CG_SOURCE,  
  71.         myVertexProgramFileName,  
  72.         myCgVertexProfile,  
  73.         myVertexProgramName,  
  74.         NULL  
  75.         );  
  76.     checkForError("creating vertex program from file");  
  77.     cgGLLoadProgram(myCgVertexProgram);  
  78.     checkForError("loading vertex program");  
  79.   
  80.     myCgVertexParam_constantColor = cgGetNamedParameter(  
  81.         myCgVertexProgram,"constantColor");  
  82.     checkForError("could not get constantColor parameter");  
  83.   
  84.     myCgFragmenrProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);  
  85.     cgGLSetOptimalOptions(myCgFragmenrProfile);  
  86.     checkForError("selecting fragment profile");  
  87.   
  88.     myCgfragmentProgram = cgCreateProgramFromFile(  
  89.         myCgContext,  
  90.         CG_SOURCE,  
  91.         myFragmenrProgramFileName,  
  92.         myCgFragmenrProfile,  
  93.         myFragmentProgramName,  
  94.         NULL  
  95.         );  
  96.     checkForError("creating fragment program from file");  
  97.     cgGLLoadProgram(myCgfragmentProgram);  
  98.     checkForError("loading fragment program");  
  99.   
  100.     glutMainLoop();  
  101.     return 0;  
  102. }  
  103.   
  104. static void drawStar(float x, float y,  
  105.                      int starPoints, float R, float r)  
  106. {  
  107.     int i;  
  108.     double piOverStarPoints = 3.14159 / starPoints,  
  109.         angle = 0.0;  
  110.   
  111.     cgUpdateProgramParameters(myCgVertexProgram);  
  112.   
  113.     glBegin(GL_TRIANGLE_FAN);  
  114.     glVertex2f(x, y);  /* Center of star */  
  115.     /* Emit exterior vertices for star's points. */  
  116.     for (i=0; i<starPoints; i++) {  
  117.         glVertex2f(x + R*cos(angle), y + R*sin(angle));  
  118.         angle += piOverStarPoints;  
  119.         glVertex2f(x + r*cos(angle), y + r*sin(angle));  
  120.         angle += piOverStarPoints;  
  121.     }  
  122.     /* End by repeating first exterior vertex of star. */  
  123.     angle = 0;  
  124.     glVertex2f(x + R*cos(angle), y + R*sin(angle));  
  125.     glEnd();  
  126. }  
  127.   
  128. static void drawStars(void)  
  129. {  
  130.     /*                     star    outer   inner  */  
  131.     /*        x      y     Points  radius  radius */  
  132.     /*       =====  =====  ======  ======  ====== */  
  133.     const float green[3] = {0.2,0.8,0.3};  
  134.     cgSetParameter3fv(myCgVertexParam_constantColor,green);  
  135.   
  136.     drawStar(-0.1,   0,    5,      0.5,    0.2);  
  137.     drawStar(-0.84,  0.1,  5,      0.3,    0.12);  
  138.     drawStar( 0.92, -0.5,  5,      0.25,   0.11);  
  139.   
  140.     cgSetParameter3f(myCgVertexParam_constantColor,  
  141.         0.7,0.1,0.1);  
  142.   
  143.     drawStar( 0.3,   0.97, 5,      0.3,    0.1);  
  144.     drawStar( 0.94,  0.3,  5,      0.5,    0.2);  
  145.     drawStar(-0.97, -0.8,  5,      0.6,    0.2);  
  146. }  
  147.   
  148. static void display()  
  149. {  
  150.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  
  151.   
  152.     cgGLBindProgram(myCgVertexProgram);  
  153.     checkForError("Binding vertex program");  
  154.   
  155.     cgGLEnableProfile(myCgVertexProfile);  
  156.     checkForError("enabling vertex profile");  
  157.   
  158.     cgGLBindProgram(myCgfragmentProgram);  
  159.     checkForError("Binding fragment program");  
  160.   
  161.     cgGLEnableProfile(myCgFragmenrProfile);  
  162.     checkForError("enabling fragment profile");  
  163.   
  164.     drawStars();  
  165.   
  166.     cgGLDisableProfile(myCgVertexProfile);  
  167.     checkForError("disabling vertex profile");  
  168.   
  169.     cgGLDisableProfile(myCgFragmenrProfile);  
  170.     checkForError("disabling fragment profile");  
  171.   
  172.     glutSwapBuffers();  
  173. }  
  174.   
  175. static void keyboard(unsigned char c,int x,int y)  
  176. {  
  177.     switch(c)  
  178.     {  
  179.         case 27:  
  180.             cgDestroyProgram(myCgVertexProgram);  
  181.             cgDestroyProgram(myCgfragmentProgram);  
  182.             cgDestroyContext(myCgContext);  
  183.             exit(0);  
  184.             break;  
  185.     }  
  186. }  

运行结果:

抱歉!评论已关闭.