这一节主要讲了三点内容:
- out类型限定符的作用。该限定词限定的形式参数被称为call-by-result参数。也就是说,Cg必须把由out限定的形式参数的最终值传递给它对应的调用参数。
- 顶点程序中如何实现对纹理坐标的偏移。
- 片断程序中如何实现对两个纹理的混合。
附上经自己整理后的源代码:
- //顶点程序:twoTextures_vertex.cg
- void main(float2 position : POSITION,
- float2 texCoord : TEXCOORD0,
- out float4 oPosition : POSITION,
- out float2 leftTexCoord : TEXCOORD0,
- out float2 rightTexCoord : TEXCOORD1,
- uniform float2 leftSeparation,
- uniform float2 rightSeparation)
- {
- oPosition = float4(position,0,1);
- leftTexCoord = texCoord + leftSeparation;
- rightTexCoord = texCoord + rightSeparation;
- }
- //片断程序:twoTextures_fragment.cg
- void main(float2 leftTexCoord : TEXCOORD0,
- float2 rightTexCoord : TEXCOORD1,
- out float4 color : COLOR,
- uniform sampler2D decal)
- {
- float4 leftColor = tex2D(decal,leftTexCoord);
- float4 rightColor = tex2D(decal,rightTexCoord);
- color = lerp(leftColor,rightColor,0.5);
- }
- //整理后的应用程序 2008-9-9 13:24:48
- #ifdef _MSC_VER
- #pragma comment( lib, "cg.lib" )
- #pragma comment( lib, "cgGL.lib" )
- #endif
- #include <stdio.h> /* for printf and NULL */
- #include <stdlib.h> /* for exit */
- #if __APPLE__
- #include <GLUT/glut.h>
- #else
- #include <GL/glut.h>
- #endif
- #include <Cg/cg.h> /* Can't include this? Is Cg Toolkit installed! */
- #include <Cg/cgGL.h>
- static const char *myProgramName = "twoTextures";
- static CGcontext myCgContext;//Cg上下文环境
- static CGprofile myCgVertexProfile;//顶点profile
- static CGprogram myCgVertexProgram;//顶点程序
- static CGparameter myCgVertexParam_leftSeparation;//顶点程序参数
- static CGparameter myCgVertexParam_rightSeparation;//顶点程序参数
- static const char *myVertexProgramFileName = "twoTextures_vertex.cg",//顶点Cg源文件
- *myVertexProgramName = "main";//顶点程序入口函数
- static CGprofile myCgFragmentProfile;//片断profile
- static CGprogram myCgFragmentProgram;//片断程序
- static CGparameter myCgFragmentParam_decal;//片断程序参数
- static const char *myFragmentProgramFileName = "twoTextures_fragment.cg",//片断Cg源文件
- *myFragmentProgramName = "main";//片断程序入口函数
- static const GLubyte //纹理图像数据
- myDemonTextureImage[3*(128*128)] = {
- /* RGB8 image data for a mipmapped 128x128 demon texture */
- #include "demon_image.h"
- };
- static void checkForCgError(const char *situation)
- {
- CGerror error;
- const char *string = cgGetLastErrorString(&error);
- if (error != CG_NO_ERROR) {
- printf("%s: %s: %s/n",
- myProgramName, situation, string);
- if (error == CG_COMPILER_ERROR) {
- printf("%s/n", cgGetLastListing(myCgContext));
- }
- exit(1);
- }
- }
- /* Forward declared GLUT callbacks registered by main. */
- static void display(void);
- static void keyboard(unsigned char c, int x, int y);
- static void initTexture(void);
- static void initCg(void);
- static void initCgVertexProgram(void);
- static void initCgFragmentProgram(void);
- int main(int argc, char **argv)
- {
- glutInitWindowSize(400, 400);
- glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
- glutInit(&argc, argv);
- glutCreateWindow(myProgramName);
- glutDisplayFunc(display);
- glutKeyboardFunc(keyboard);
- glClearColor(0.1, 0.3, 0.6, 0.0); /* Blue background */
- initTexture();
- initCg();
- glutMainLoop();
- return 0;
- }
- static void initTexture(void){
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1); /*Tightly packed texture data.*/
- glBindTexture(GL_TEXTURE_2D, 666);
- /* Load demon decal texture with mipmaps. */
- gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB8,
- 128, 128, GL_RGB, GL_UNSIGNED_BYTE, myDemonTextureImage);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
- GL_LINEAR_MIPMAP_LINEAR);
- }
- static void initCg(void){
- myCgContext = cgCreateContext();//得到当前上下文环境
- checkForCgError("creating context");
- cgGLSetDebugMode( CG_FALSE );
- cgSetParameterSettingMode(myCgContext, CG_DEFERRED_PARAMETER_SETTING);
- initCgVertexProgram();
- initCgFragmentProgram();
- }
- static void initCgVertexProgram(void){
- //-----------------------------选择顶点和片断的profile---------------------------------
- myCgVertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);
- cgGLSetOptimalOptions(myCgVertexProfile);
- checkForCgError("selecting vertex profile");
- //-----------------------------选择顶点和片断的profile-----------------------------
- //-----------------------------载入顶点程序和参数-----------------------------
- myCgVertexProgram =
- cgCreateProgramFromFile(
- myCgContext, /* Cg runtime context */
- CG_SOURCE, /* Program in human-readable form */
- myVertexProgramFileName, /* Name of file containing program */
- myCgVertexProfile, /* Profile: OpenGL ARB vertex program */
- myVertexProgramName, /* Entry function name */
- NULL); /* No extra compiler options */
- checkForCgError("creating vertex program from file");
- cgGLLoadProgram(myCgVertexProgram);
- checkForCgError("loading vertex program");
- myCgVertexParam_leftSeparation =
- cgGetNamedParameter(myCgVertexProgram, "leftSeparation");
- myCgVertexParam_rightSeparation =
- cgGetNamedParameter(myCgVertexProgram, "rightSeparation");
- cgSetParameter2f(myCgVertexParam_leftSeparation, -0.3, 0);
- cgSetParameter2f(myCgVertexParam_rightSeparation, 0.3, 0);
- //-----------------------------载入顶点程序和参数-----------------------------
- }
- static void initCgFragmentProgram(void){
- myCgFragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);
- cgGLSetOptimalOptions(myCgFragmentProfile);
- checkForCgError("selecting fragment profile");
- myCgFragmentProgram =
- cgCreateProgramFromFile(
- myCgContext, /* Cg runtime context */
- CG_SOURCE, /* Program in human-readable form */
- myFragmentProgramFileName, /* Name of file containing program */
- myCgFragmentProfile, /* Profile: OpenGL ARB vertex program */
- myFragmentProgramName, /* Entry function name */
- NULL);
- checkForCgError("creating fragment program from file");
- cgGLLoadProgram(myCgFragmentProgram);
- checkForCgError("loading fragment program");
- myCgFragmentParam_decal =
- cgGetNamedParameter(myCgFragmentProgram, "decal");
- checkForCgError("getting decal parameter");
- cgGLSetTextureParameter(myCgFragmentParam_decal, 666);
- checkForCgError("setting decal 2D texture");
- }
- static void display(void)
- {
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- cgGLBindProgram(myCgVertexProgram);
- checkForCgError("binding vertex program");
- cgGLEnableProfile(myCgVertexProfile);
- checkForCgError("enabling vertex profile");
- cgGLBindProgram(myCgFragmentProgram);
- checkForCgError("binding Fragment program");
- cgGLEnableProfile(myCgFragmentProfile);
- checkForCgError("enabling Fragment profile");
- glBegin(GL_TRIANGLES);
- glTexCoord2f(0, 0);
- glVertex2f(-0.8, 0.8);
- glTexCoord2f(1, 0);
- glVertex2f(0.8, 0.8);
- glTexCoord2f(0.5, 1);
- glVertex2f(0.0, -0.8);
- glEnd();
- cgGLDisableProfile(myCgVertexProfile);
- cgGLDisableProfile(myCgFragmentProfile);
- checkForCgError("disabling vertex profile");
- glutSwapBuffers();
- }
- static void keyboard(unsigned char c, int x, int y)
- {
- switch (c) {
- case 27: /* Esc key */
- /* Demonstrate proper deallocation of Cg runtime data structures.
- Not strictly necessary if we are simply going to exit. */
- cgDestroyProgram(myCgVertexProgram);
- cgDestroyContext(myCgContext);
- exit(0);
- break;
- }
- }