Cg编程

在计算机图形学领域,用计算机处理图形信息我们最先接触的通常是使用opengl和d3d这些图形编程接口,这些通常称为固定管线的编程,也就是程序员不直接操纵可编程的GPU,在常见的opengl的编程管线中,底层为我们设定了固定的渲染过程,程序员控制的只是这个过程中的各种参数。但是在有些情况下,尤其是硬件性能突飞猛进的今天,为了得到更好的效果,得到对图形计算更好的控制,就需要自己对GPU进行编程,这也就是可编程的图形渲染,这些用于对GPU的编程接口就是GPU语言,CG是NVIDIA开发的针对NVDIA图形处理器的硬件编程语言,它的全程是C for graph,也就是图像的C语言,因为它和c的文法很相似,所以有了c语言的基础,学习cg将是很轻松的事情。以下是我学习的Cg语言的一些心得。

 

1图形渲染管线

现代计算机处理图形主要依靠图形处理单元(GPU)来完成,在GPU上渲染图形的整个过程就是图形渲染管线,整个管线的输入是最初的描述图元的数据,输出是屏幕上每个像素的颜色,一切图形学的处理过程都在这个管线中进行。

常见的Gpu的渲染管线的具体内容如下

 

注意这个图中的每个操作是有严格的先后顺序之分的。

 

在过去,在我们简单的使用opengl或者到到d3d进行图形绘制时,底层自动按照上述顺序为我们生成图形,我们在opengl中做的只是调节其中各个“参数”,但是数据走的通路是一样的,这称为固定渲染管线。

Gpu主要包括顶点处理器和片段处理器,在第三代显卡(GEforce3)之后,gpu的顶点处理器可以进行编程,也就是上图中的顶点变换部分可以被控制,在第四代显卡(GEForceFX)之后gpu的片段处理器可以进行编程,也就是插值 纹理采样 着色这一过程可以进行编程,现在我们可以自行调控上述两个红色部分的工作流程,而不必沿着固定渲染管线,这就叫做可编程的图形渲染。

当然cg语言也要依托于opengl和d3d这些图形硬件的借口,因为上图中的蓝色部分仍需他们来做,只是红色部分我们可以不再用opnegl来写和控制,另外诸如向硬件发送和接受数据也需要他们,cg语言的作用只是在opnegl中控制上述两个红色方块中的处理过程。

 

2顶点程序

在顶点处理器中执行的程序叫做顶点程序,顶点程序的作用也就是进行顶点变化,在图形渲染管线中,它可以做三件事,一是将输入的物体的局部座标转化成最终的剪裁座标,二是生成每个顶点的纹理座标,三是产生每个顶点的颜色。所以在一个顶点程序中,允许的输入有位置信息(这个位置是局部座标),顶点颜色(在opengl中绘制顶点时指定的),法向信息,n个纹理座标(在opengl中指定的),输出通常有位置、颜色、n个纹理座标,不输出的有默认值。

也就是我们可以直接掌控的顶点的属性有这三个:

1剪裁座标系的位置:这个位置的值只有在-1在1之间才能被看见,也就是x为1的点恰好落在渲染窗口的最右边的线上,而剪裁座标的z值就是深度值,可以直接控制这个座标来控制图形的绘制于隐藏及其他集合变化等。

Projection Matrix*Modelview Matrix *局部座标=剪裁座标

2颜色就是每个顶点最终的着色

3纹理座标通常就是我们去直接控制每个顶点的纹理座标。但是更重要的是这里的纹理座标通常不存储纹理,而是一个大的“缓存器”,它通常用来存储每个顶点的其他属性(如发向或其他任何想存储的和每个顶点有关的)然后传入给片段处理器进行处理。如我们要在片段处理器中每个顶点的法向进行差值做phone shading,这时就要先在顶点处理器中将法向装入一个纹理中传给片段程序。通常纹理的数量由opengl和硬件决定。

3片段程序

    在片段处理器中执行的程序称作片段程序,片段程序的作用其实说到底只有一个,就是为已经光栅化的每一个片段产生它的颜色。对于片段程序,它的输入只有纹理信息,输出也只有颜色信息。当然输入的纹理信息可以封装其他的可以被光栅化的信息(如位置、法向等),我们可以根据不同的需要和纹理采样来直接控制每个片段的最终颜色。

4 Cg程序在C/C++环境中的使用

通常cg程序需要依附于opengl与d3d程序使用,在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程序fragProgram的tex0这个uniform参数,

再用cgGLSetTextureParameter(paramtex0,textureObj)、cgSetParameter4fv(paramtex0,accelar)等函数改变这个参数,最后用cgUpdateProgramParameters(fragProgram)来更新这个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 mapping、fog等,当然所有的你想实现的效果都可以用cg 来实现,关键看你的想象空间和编程能力了。


转载自:http://blog.csdn.net/leonwei/article/details/4583045

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章