0001: // ----------------------------------------------------------------------------
0002: //
0003: // main.cpp - GLUT で Cg のサンプルソース
0004: // 
0005: // Copyright (c) 2002 今給黎 隆 (imagire@nify.com)
0006: // All Rights Reserved.
0007: //
0008: // ----------------------------------------------------------------------------
0009: #include <math.h>
0010: #include <stdio.h>
0011: #include <assert.h>
0012: #include <GL/glut.h>
0013: #include <Cg/cg.h>
0014: #include <Cg/cgGL.h>
0015: #include "matrix.h"
0016: 
0017: // ---------------------------------------------------------------------------
0018: // オブジェクト
0019: // ---------------------------------------------------------------------------
0020: 
0021: // Cg のオブジェクト
0022: static cgContext        *VertexContext          = NULL;
0023: static cgProgramIter    *VertexProgramIter      = NULL;
0024: static cgBindIter       *WorldViewProjBind      = NULL; // ワールド射影行列
0025: static cgBindIter       *WorldBind              = NULL; // ワールド行列
0026: static cgBindIter       *LightBind              = NULL; // ライトベクトル
0027: static cgBindIter       *ColorBind              = NULL; // 頂点色
0028: 
0029: static cgContext        *FragmentContext        = NULL;
0030: static cgProgramIter    *FragmentProgramIter    = NULL;
0031: static cgBindIter       *HalfBind               = NULL; // ハーフべクトルの方向
0032: 
0033: static float r = 0.0f;      // ポリゴンの回転角
0034: 
0035: // ---------------------------------------------------------------------------
0036: // 箱のオブジェクト
0037: // ---------------------------------------------------------------------------
0038: 
0039: GLint CubeFaces[6][4] = 
0040:  {  
0041:   {0, 1, 2, 3}, {3, 2, 6, 7}, {7, 6, 5, 4},
0042:   {4, 5, 1, 0}, {5, 6, 2, 1}, {7, 4, 0, 3} 
0043:  };
0044: 
0045: GLfloat CubeVertices[8][3];  
0046: GLfloat CubeNormals[8][3];
0047: 
0048: static void InitializeCube(GLfloat v[8][3])
0049: {
0050:     v[0][0] = v[1][0] = v[2][0] = v[3][0] = 1;
0051:     v[4][0] = v[5][0] = v[6][0] = v[7][0] = -1;
0052:     v[0][1] = v[1][1] = v[4][1] = v[5][1] = 1;
0053:     v[2][1] = v[3][1] = v[6][1] = v[7][1] = -1;
0054:     v[0][2] = v[3][2] = v[4][2] = v[7][2] = 1;
0055:     v[1][2] = v[2][2] = v[5][2] = v[6][2] = -1;
0056: }
0057: #define MATRIX_INDEX(i, j) (j + i * 4)
0058: 
0059: // ---------------------------------------------------------------------------
0060: // 箱の描画
0061: // ---------------------------------------------------------------------------
0062: static void DrawCube(void)
0063: {
0064:     int i;
0065: 
0066:     // 箱の描画
0067:     for(i = 0; i < 6; i++) {
0068:         glBegin(GL_QUADS);  // 四角形の描画
0069: 
0070:         cgGLBindVarying3f(VertexProgramIter, ColorBind
0071:             , 0.5f*CubeVertices[CubeFaces[i][0]][0]+0.5f
0072:             , 0.5f*CubeVertices[CubeFaces[i][0]][1]+0.5f
0073:             , 0.5f*CubeVertices[CubeFaces[i][0]][2]+0.5f
0074:             );  // 頂点色
0075:         glNormal3fv(&CubeNormals [CubeFaces[i][0]][0]);             // 法線
0076:         glVertex3fv(&CubeVertices[CubeFaces[i][0]][0]);             // 座標
0077: 
0078:         cgGLBindVarying3f(VertexProgramIter, ColorBind
0079:             , 0.5f*CubeVertices[CubeFaces[i][1]][0]+0.5f
0080:             , 0.5f*CubeVertices[CubeFaces[i][1]][1]+0.5f
0081:             , 0.5f*CubeVertices[CubeFaces[i][1]][2]+0.5f
0082:             );  // 頂点色
0083:         glNormal3fv(&CubeNormals [CubeFaces[i][1]][0]);
0084:         glVertex3fv(&CubeVertices[CubeFaces[i][1]][0]);
0085: 
0086:         cgGLBindVarying3f(VertexProgramIter, ColorBind
0087:             , 0.5f*CubeVertices[CubeFaces[i][2]][0]+0.5f
0088:             , 0.5f*CubeVertices[CubeFaces[i][2]][1]+0.5f
0089:             , 0.5f*CubeVertices[CubeFaces[i][2]][2]+0.5f
0090:             );  // 頂点色
0091:         glNormal3fv(&CubeNormals [CubeFaces[i][2]][0]);
0092:         glVertex3fv(&CubeVertices[CubeFaces[i][2]][0]);
0093: 
0094:         cgGLBindVarying3f(VertexProgramIter, ColorBind
0095:             , 0.5f*CubeVertices[CubeFaces[i][3]][0]+0.5f
0096:             , 0.5f*CubeVertices[CubeFaces[i][3]][1]+0.5f
0097:             , 0.5f*CubeVertices[CubeFaces[i][3]][2]+0.5f
0098:             );  // 頂点色
0099:         glNormal3fv(&CubeNormals [CubeFaces[i][3]][0]);
0100:         glVertex3fv(&CubeVertices[CubeFaces[i][3]][0]);
0101:     
0102:         glEnd();    // 四角形終わり
0103:     }
0104: }
0105: // ---------------------------------------------------------------------------
0106: // 画面描画
0107: // ---------------------------------------------------------------------------
0108: void display(void)
0109: {
0110:     ifMatrix m, m0;
0111:     cgError Ret;
0112:     
0113:     // -----------------------------------------------------------------------
0114:     // 画面のクリア
0115:     // -----------------------------------------------------------------------
0116:     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
0117: 
0118:     // -----------------------------------------------------------------------
0119:     // ビュー行列の設定
0120:     // -----------------------------------------------------------------------
0121:     glMatrixMode(GL_MODELVIEW);
0122:     glLoadIdentity();
0123:     gluLookAt(  0.0, 0.0, 5.0,      // 視点
0124:                 0.0, 0.0, 0.0,      // 注目点
0125:                 0.0, 1.0, 0.0);     // 上方向
0126: 
0127:     glPushMatrix();                 // ビュー行列が他のポリゴンでも使えるよう退避
0128: 
0129:     // -----------------------------------------------------------------------
0130:     // Cg による描画へ切り替え
0131:     // -----------------------------------------------------------------------
0132:     Ret = cgGLBindProgram(VertexProgramIter);
0133:     assert(Ret == cgNoError);
0134:     cgGLEnableProgramType(cgVertexProfile);
0135: 
0136:     Ret = cgGLBindProgram(FragmentProgramIter);
0137:     assert(Ret == cgNoError);
0138:     cgGLEnableProgramType(cgFragmentProfile);
0139: 
0140:     // -----------------------------------------------------------------------
0141:     // 行列を設定する
0142:     // -----------------------------------------------------------------------
0143:     ifMatrixIdentity( &m );
0144:     ifMatrixRotationZ(&m0, -IF_PI*20/180);
0145:     ifMatrixMultiply( &m, (const ifMatrix *)&m, (const ifMatrix *)&m0 );
0146:     ifMatrixRotationX(&m0,  IF_PI*60/180);
0147:     ifMatrixMultiply( &m, (const ifMatrix *)&m, (const ifMatrix *)&m0 );
0148:     ifMatrixRotationY(&m0,  IF_PI* r/180);
0149:     ifMatrixMultiply( &m, (const ifMatrix *)&m, (const ifMatrix *)&m0 );
0150:     
0151:     glMultMatrixf((const float *)&m);
0152: 
0153:     // ワールド行列を設定する
0154:     cgGLBindUniformMatrixcf(VertexProgramIter, WorldBind, (const float *)&m[0][0]);
0155:     // ワールド - 射影行列
0156:     if(WorldViewProjBind != NULL) {
0157:         cgGLBindUniformStateMatrix(VertexProgramIter, 
0158:                                 WorldViewProjBind,
0159:                                 cgGLModelViewProjectionMatrix,
0160:                                 cgGLMatrixIdentity);
0161:     }
0162: 
0163:     // -----------------------------------------------------------------------
0164:     // ライトの設定
0165:     // -----------------------------------------------------------------------
0166:     ifVector4 dir = {0.3f, 0.3f, 0.1f, 0.0f};
0167:     ifVec4Normalize(&dir, &dir);
0168:     
0169:     // 擬似ハーフベクトルを設定する
0170:     ifVector4 eye = {0,0,1,0};// ここが定数が近似
0171:     ifVector4 half;
0172:     ifVec4Normalize(&half, ifVec4Add(&half, &dir, &eye));
0173:     cgGLBindUniform4f(FragmentProgramIter, HalfBind
0174:                 ,half[0], half[1], half[2], half[3]);
0175:     
0176:     // (ローカル座標の)ライトベクトルを設定する
0177:     ifMatrixTranspose( &m, (const ifMatrix *)&m );
0178:     ifVec4Transform(&dir, &dir, (const ifMatrix *)&m);
0179:     cgGLBindUniform4f(VertexProgramIter, LightBind
0180:                 ,dir[0], dir[1], dir[2], dir[3]);
0181: 
0182:     // -----------------------------------------------------------------------
0183:     // 箱の描画
0184:     // -----------------------------------------------------------------------
0185:     
0186:     DrawCube();
0187: 
0188:     // -----------------------------------------------------------------------
0189:     // 描画の終了
0190:     // -----------------------------------------------------------------------
0191:     cgGLDisableProgramType(cgFragmentProfile);
0192:     cgGLDisableProgramType(cgVertexProfile);
0193: 
0194:     glPopMatrix();                  // ビュー行列に現在の行列を戻す
0195:     glutSwapBuffers();              // 画面の更新の終了
0196: }
0197: // ---------------------------------------------------------------------------
0198: // 画面がリサイズされたとき
0199: // ---------------------------------------------------------------------------
0200: void resize(int w, int h)
0201: {
0202:     // ビューポートの設定
0203:     glViewport(0, 0, w, h);
0204: 
0205:     // 射影行列の設定
0206:     glMatrixMode(GL_PROJECTION);
0207:     glLoadIdentity();
0208:     gluPerspective( 60.0,           // 画角
0209:                     1.0,            // アスペクト比
0210:                     1.0, 10.0);     // 前方面、後方面
0211: }
0212: // ---------------------------------------------------------------------------
0213: // ひまなときに実行される
0214: // ---------------------------------------------------------------------------
0215: void idle()
0216: {
0217:     // ポリゴンの回転
0218:     r = r + 3.0f;
0219:     while (360.0f < r) r -= 360.0f;
0220: 
0221:     glutPostRedisplay();            // 再描画リクエスト
0222: }
0223: // ---------------------------------------------------------------------------
0224: // OpenGL に関する初期化
0225: // ---------------------------------------------------------------------------
0226: static void InitializeGlut(int argc, char *argv[])
0227: {
0228:     // ウィンドウの作成
0229:     glutInitWindowPosition(100, 100);   // 表示位置
0230:     glutInitWindowSize(512, 512);       // サイズ
0231:     glutInit(&argc, argv);              // GLの初期化
0232:     glutInitDisplayMode(GLUT_DOUBLE     // 描画モード
0233:                      | GLUT_RGBA        // wバッファ+RGBA+深度バッファ
0234:                      | GLUT_DEPTH);
0235:     glutCreateWindow(argv[0]);          // ウィンドウの生成
0236: 
0237:     // コールバック関数の設定
0238:     glutDisplayFunc(display);   // 描画関数
0239:     glutReshapeFunc(resize);    // 画面が変形したとき
0240:     glutIdleFunc(idle);         // ひまなとき
0241: 
0242:     // 箱の初期化
0243:     InitializeCube(CubeVertices);
0244:     InitializeCube(CubeNormals);
0245:     for(int i=0;i<8;i++){
0246:         // 法線の正規化
0247:         CubeNormals[i][0] /= sqrt(3);
0248:         CubeNormals[i][1] /= sqrt(3);
0249:         CubeNormals[i][2] /= sqrt(3);
0250:     }
0251: 
0252:     // 一度だけすればいい設定
0253:     glClearColor(0.0, 0.0, 0.3, 0.0);   // 背景色の設定
0254:     glEnable(GL_DEPTH_TEST);            // 深度バッファの使用
0255: }
0256: // ---------------------------------------------------------------------------
0257: // Cgの初期化
0258: // ---------------------------------------------------------------------------
0259: static void InitializeCg()
0260: {
0261:     cgError Ret;
0262:     
0263:     // Cg の作成
0264:     VertexContext = cgCreateContext();
0265:     assert(VertexContext != NULL);
0266: 
0267:     // Cg の作成
0268:     Ret = cgAddProgramFromFile(VertexContext, "vs.cg", cgVertexProfile, NULL);
0269:     fprintf(stderr, "LAST LISTING----%s----\n", cgGetLastListing(VertexContext));
0270:     assert(Ret == cgNoError);
0271: 
0272:     // プログラム名でプログラムを結びつける
0273:     VertexProgramIter = cgProgramByName(VertexContext, "main");
0274:     assert(VertexProgramIter != NULL);
0275: 
0276:     // ソースの表示
0277:     fprintf(stderr, "---- プログラム はじめ ----\n"
0278:                     "%s"
0279:                     "---- プログラム 終わり ----\n",
0280:     cgGetProgramObjectCode(VertexProgramIter));
0281: 
0282:     if(VertexProgramIter != NULL) {
0283:         GLuint ProgId = 1;
0284: 
0285:         Ret = cgGLLoadProgram(VertexProgramIter, ProgId);
0286:         assert(Ret == cgNoError);
0287:         // 変換行列を結びつける
0288:         WorldViewProjBind = cgGetBindByName(VertexProgramIter, "WorldViewProj");
0289:         assert(WorldViewProjBind != NULL);
0290:         // ワールド行列を結びつける
0291:         WorldBind = cgGetBindByName(VertexProgramIter, "World");
0292:         assert(WorldBind != NULL);
0293:         // ライトの方向を結びつける
0294:         LightBind = cgGetBindByName(VertexProgramIter, "Light");
0295:         assert(LightBind != NULL);
0296:         // 頂点色
0297:         ColorBind = cgGetBindByName(VertexProgramIter, "IN.color");
0298:         assert(ColorBind != NULL);
0299:     }
0300: 
0301:  
0302:     // fragment program setup
0303:     FragmentContext = cgCreateContext();
0304:     assert(FragmentContext != NULL);
0305: 
0306:     Ret = cgAddProgramFromFile(FragmentContext, "ps.cg", cgFragmentProfile, NULL);
0307:     assert(Ret == cgNoError);
0308: 
0309:     // プログラム名でプログラムを結びつける
0310:     FragmentProgramIter = cgProgramByName(FragmentContext, "main");
0311:     assert(FragmentProgramIter != NULL);
0312: 
0313:     // ソースの表示
0314:     fprintf(stderr, "---- プログラム はじめ ----\n"
0315:                     "%s"
0316:                     "---- プログラム 終わり ----\n",
0317:     cgGetProgramObjectCode(FragmentProgramIter));
0318: 
0319:     if(FragmentProgramIter != NULL)
0320:     {
0321:         GLuint ProgId = 2;
0322: 
0323:         Ret = cgGLLoadProgram(FragmentProgramIter, ProgId);
0324:         assert(Ret == cgNoError);
0325: 
0326:         // ライト方向
0327:         HalfBind = cgGetBindByName(FragmentProgramIter, "Half");
0328:         assert(HalfBind != NULL);
0329:     }
0330:     
0331: }
0332: // ---------------------------------------------------------------------------
0333: // Cg の後片付け
0334: // ---------------------------------------------------------------------------
0335: static void CleanupCg()
0336: {
0337:     // フラグメント
0338:     if(HalfBind)cgFreeBindIter( HalfBind );
0339:     cgFreeProgramIter( FragmentProgramIter );
0340:     cgFreeContext( FragmentContext );
0341: 
0342:     // 頂点シェーダ
0343:     if(LightBind        )cgFreeBindIter( LightBind );
0344:     if(WorldBind        )cgFreeBindIter( WorldBind );
0345:     if(WorldViewProjBind)cgFreeBindIter( WorldViewProjBind );
0346:     if(ColorBind        )cgFreeBindIter( ColorBind );
0347:     cgFreeProgramIter( VertexProgramIter );
0348:     cgFreeContext( VertexContext );
0349:     cgCleanup( );
0350: }
0351: // ---------------------------------------------------------------------------
0352: // メイン関数
0353: // ---------------------------------------------------------------------------
0354: int main(int argc, char *argv[])
0355: {
0356:     InitializeGlut(argc, argv);
0357:     InitializeCg();
0358:   
0359:     glutMainLoop();                     // メインループ
0360: 
0361:     CleanupCg();
0362:     
0363:     return 0;
0364: }