blog

OpenGLの場合:"球の世界 "の実装

球の世界の場合は、ケースに基づいています:テクスチャとミラーディスプレイの追加に基づいて小さなボールの回転の大きなボールの回転は、再生したり、図に示す効果を達成するために、より興味深い:ケースは、フロ...

Nov 21, 2020 · 7 min. read
シェア

球の世界の場合に基づいています:テクスチャとイメージ表示の追加に基づいて小さなボールの回転の大きなボールの回転は、図に示すような効果を達成するために、遊びやより面白い:

ケース実現のフローチャート:



関数の説明

  • main: プログラム入力、ウィンドウ、メニュー、レンダリング環境の初期化、コールバック関数の登録
  • SetupRC: 背景色、シェーダー、テクスチャーデータの初期化
  • LoadTGATexture: TGAファイルを2Dテクスチャとして読み込みます。
  • changeSize:ビューポートとビューボディを変更します。ウィンドウサイズを変更するとき、またはウィンドウを初期化するときに呼び出されます。
  • RenderScene: キャッシュをクリアして球体を描画し、テクスチャデータを設定します。
  • drawSomething: 大きなボール、小さなボール、球の回転などの描画をカプセル化します。
  • ShutDownRC: レンダリング環境をシャットダウンし、テクスチャを削除glDeleteTextures
  • メイン関数の分析

    SetupRC

    この関数は、主に頂点やテクスチャなどのデータを初期化するためのものです。



    loadTGATexture

    主な処理としては、以下のようにメモリからTGAファイルを読み込み、2Dテクスチャデータとして読み込みます:



    drawSomething



    RenderScene



    ケースコード:

    ヘッダーファイルの導入

    #include "GLTools.h"
    #include "GLShaderManager.h"
    #include "GLFrustum.h"
    #include "GLBatch.h"
    #include "GLMatrixStack.h"
    #include "GLGeometryTransform.h"
    #include "StopWatch.h"
    #include <math.h>
    #include <stdio.h>
    #ifdef __APPLE__
    #include <glut/glut.h>
    #else
    #define FREEGLUT_STATIC
    #include <GL/glut.h>
    #endif
    

    グローバル変数の宣言

    //**追加のランダムボールを追加する
    #define NUM_SPHERES 50
    GLFrame spheres[NUM_SPHERES];
    GLShaderManager		shaderManager;			// シェーダマネージャ
    GLMatrixStack		modelViewMatrix;		// モデルビュー行列
    GLMatrixStack		projectionMatrix;		// 投影行列
    GLFrustum			viewFrustum;			//  
    GLGeometryTransform	transformPipeline;		// ジオメトリ変換パイプライン
    GLTriangleBatch		torusBatch; // フラワーブラケットバッチ
    GLBatch				floorBatch; // フロアバッチ
    //**メトリック球のバッチを定義する**
    GLTriangleBatch sphereBatch; //球バッチ
    //**キャラクターフレーム カメラキャラクターフレーム
    GLFrame cameraFrame;
    //**テクスチャを追加する
    //テクスチャマーカーの配列
    GLuint uiTextures[3];
    

    実装機能

    bool LoadTGATexture(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode) {
     GLbyte *pBits;
     int nWidth, nHeight, nComponents;
     GLenum eFormat;
     
     //1.テクスチャデータを読み込む
     pBits = gltReadTGABits(szFileName, &nWidth, &nHeight, &nComponents, &eFormat);
     if(pBits == NULL)
     return false;
     
     //テクスチャパラメータを設定する
     //パラメータ1:テクスチャの寸法
     //パラメータ2:S / T座標のモードを設定する。
     //パラメータ3:wrapMode。
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
     
     //パラメータ1:テクスチャの寸法
     //パラメータ2:リニアフィルタ
     //パラメータ3:wrapMode。
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
     
     //3.テクスチャをロードする
     //パラメータ1:テクスチャの寸法
     //パラメータ2:ミップマッピングレベル
     //パラメータ3:テクスチャユニットに格納されているカラーコンポーネント - ユニバーサル圧縮テクスチャフォーマットGLに内部パラメータnComponentsを変更した_COMPRESSED_RGB
     //パラメータ4:テクスチャ幅をロードする
     //パラメータ5:テクスチャの高さをロードする
     //パラメータ6:ロードされたテクスチャの深さ
     //パラメータ7:ピクセルデータ(GL)のデータ型_UNSIGNED_BYTE,(各色成分は、8ビットの符号なし整数である)
     //パラメータ8:テクスチャイメージデータへのポインタ。
     glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB, nWidth, nHeight, 0,
     eFormat, GL_UNSIGNED_BYTE, pBits);
     
     //使用後にpBitsを解放する
     free(pBits);
     
     //Mipマップは、minFilterが次の4つのモードに等しい場合にのみ生成することができる
     //GL_NEAREST_MIPMAP_NEAREST非常に良いパフォーマンスと非常に低いちらつき。
     //GL_LINEAR_MIPMAP_NEAREST多くの場合、ゲームを高速化するために使用される、それは高品質の線形フィルタを使用する
     //GL_LINEAR_MIPMAP_LINEAR  _NEAREST_MIPMAP_LINEAR フィルタは、Mipレイヤー間のフィルタトレースを除去するために、Mipレイヤー間でいくつかの追加補間を実行する。
     //GL_LINEAR_MIPMAP_LINEAR トリリニアMipマッピング。最高の精度でテクスチャフィルタリングの黄金律。
     if(minFilter == GL_LINEAR_MIPMAP_LINEAR ||
     minFilter == GL_LINEAR_MIPMAP_NEAREST ||
     minFilter == GL_NEAREST_MIPMAP_LINEAR ||
     minFilter == GL_NEAREST_MIPMAP_NEAREST)
     //4.ロードMipは、テクスチャは、すべてのMip層を生成する。
     //パラメータ:GL_TEXTURE_1DGL_TEXTURE_2DGL_TEXTURE_3D
     glGenerateMipmap(GL_TEXTURE_2D);
     
     
     return true;
    }
    void SetupRC() {
     //1.カラーバッファにクリア画面の色を設定する
     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
     
     //2.シェーダマネージャを初期化する
     shaderManager.InitializeStockShaders();
     
     //3.深さテスト/バックサイドカリングを有効にする
     glEnable(GL_DEPTH_TEST);
     glEnable(GL_CULL_FACE);
     //4.大きな球体を設定する
     gltMakeSphere(torusBatch, 0.4f, 40, 80);
     
     //5.球体を設定する
     gltMakeSphere(sphereBatch, 0.1f, 26, 13);
     
     //6.床の頂点データを設定する&床のテクスチャ
     GLfloat texSize = 10.0f;
     floorBatch.Begin(GL_TRIANGLE_FAN, 4,1);
     floorBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
     floorBatch.Vertex3f(-20.f, -0.41f, 20.0f);
     
     floorBatch.MultiTexCoord2f(0, texSize, 0.0f);
     floorBatch.Vertex3f(20.0f, -0.41f, 20.f);
     
     floorBatch.MultiTexCoord2f(0, texSize, texSize);
     floorBatch.Vertex3f(20.0f, -0.41f, -20.0f);
     
     floorBatch.MultiTexCoord2f(0, 0.0f, texSize);
     floorBatch.Vertex3f(-20.0f, -0.41f, -20.0f);
     floorBatch.End();
     
     //7.ランダム球の頂点座標データ
     for (int i = 0; i < NUM_SPHERES; i++) {
     
     //y軸は変更せず、X,Zはランダムな値を生成する。
     GLfloat x = ((GLfloat)((rand() % 400) - 200 ) * 0.1f);
     GLfloat z = ((GLfloat)((rand() % 400) - 200 ) * 0.1f);
     
     //Y方向に、球を0に設定する。.0これにより、目の高さに浮いているように見える。
     //球の配列内の各頂点について、頂点データを設定する
     spheres[i].SetOrigin(x, 0.0f, z);
     }
     
     
     //8.テクスチャオブジェクトに名前を付ける
     glGenTextures(3, uiTextures);
     
     //9.2DテクスチャとしてTGAファイルをロードする。
     //パラメータ1:テクスチャファイル名
     // &パラメータ3:縮小する必要がある&ズームフィルタ
     //パラメータ4:テクスチャ座標サラウンドモード
     glBindTexture(GL_TEXTURE_2D, uiTextures[0]);
     LoadTGATexture("marble.tga", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_REPEAT);
     
     
     glBindTexture(GL_TEXTURE_2D, uiTextures[1]);
     LoadTGATexture("marslike.tga", GL_LINEAR_MIPMAP_LINEAR,
     GL_LINEAR, GL_CLAMP_TO_EDGE);
     
     
     glBindTexture(GL_TEXTURE_2D, uiTextures[2]);
     LoadTGATexture("moonlike.tga", GL_LINEAR_MIPMAP_LINEAR,
     GL_LINEAR, GL_CLAMP_TO_EDGE);
     
    }
    //テクスチャを削除する
    void ShutdownRC(void) {
     glDeleteTextures(3, uiTextures);
    }
    // 画面のサイズ変更または初期化
    void ChangeSize(int nWidth, int nHeight) {
     //1.ビューポートを設定する
     glViewport(0, 0, nWidth, nHeight);
     
     //2.投影法を設定する
     viewFrustum.SetPerspective(35.0f, float(nWidth)/float(nHeight), 1.0f, 100.0f);
     
     //3.投影行列スタックに投影行列をロードする,
     projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
     modelViewMatrix.LoadIdentity();
     
     //4.パイプラインに投影行列スタックとモデルビュー行列オブジェクトを設定する
     transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
     
    }
    void drawSomething(GLfloat yRot)
    {
     //1.光源の位置を定義する&拡散色
     static GLfloat vWhite[] = { 1.0f, 1.0f, 1.0f, 1.0f };
     static GLfloat vLightPos[] = { 0.0f, 3.0f, 0.0f, 1.0f };
     
     //2.ホバリング球体を描画する
     glBindTexture(GL_TEXTURE_2D, uiTextures[2]);
     for(int i = 0; i < NUM_SPHERES; i++) {
     modelViewMatrix.PushMatrix();
     modelViewMatrix.MultMatrix(spheres[i]);
     shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
     modelViewMatrix.GetMatrix(),
     transformPipeline.GetProjectionMatrix(),
     vLightPos,
     vWhite,
     0);
     sphereBatch.Draw();
     modelViewMatrix.PopMatrix();
     }
     
     //3.大きな球体を描く
     modelViewMatrix.Translate(0.0f, 0.2f, -2.5f);
     modelViewMatrix.PushMatrix();
     modelViewMatrix.Rotate(yRot, 0.0f, 1.0f, 0.0f);
     glBindTexture(GL_TEXTURE_2D, uiTextures[1]);
     shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
     modelViewMatrix.GetMatrix(),
     transformPipeline.GetProjectionMatrix(),
     vLightPos,
     vWhite,
     0);
     torusBatch.Draw();
     modelViewMatrix.PopMatrix();
     
     //4.回転する球を描く(回転)
     modelViewMatrix.PushMatrix();
     modelViewMatrix.Rotate(yRot * -2.0f, 0.0f, 1.0f, 0.0f);
     modelViewMatrix.Translate(0.8f, 0.0f, 0.0f);
     glBindTexture(GL_TEXTURE_2D, uiTextures[2]);
     shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
     modelViewMatrix.GetMatrix(),
     transformPipeline.GetProjectionMatrix(),
     vLightPos,
     vWhite,
     0);
     sphereBatch.Draw();
     modelViewMatrix.PopMatrix();
     
    }
    //シーンを描画する呼び出しを行う
    void RenderScene(void)
    {
     //1.床の色の値
     static GLfloat vFloorColor[] = { 1.0f, 1.0f, 0.0f, 0.75f};
     
     //2.時間ベースのアニメーション
     static CStopWatch	rotTimer;
     float yRot = rotTimer.GetElapsedSeconds() * 60.0f;
     
     //3.カラーバッファと深度バッファをクリアする
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     
     //4.スタックに押す
     modelViewMatrix.PushMatrix();
     
     //5.オブザーバ行列を設定する
     M3DMatrix44f mCamera;
     cameraFrame.GetCameraMatrix(mCamera);
     modelViewMatrix.MultMatrix(mCamera);
     
     //6.スタック
     modelViewMatrix.PushMatrix();
     
     //7.---反射を追加する
     //Y軸を反転させる
     modelViewMatrix.Scale(1.0f, -1.0f, 1.0f);
     //ミラーワールドは、一定の距離だけY軸周りに平行移動される。
     modelViewMatrix.Translate(0.0f, 0.8f, 0.0f);
     
     //8.前面として時計回りを指定する
     glFrontFace(GL_CW);
     
     //9.地面以外のものを描く
     drawSomething(yRot);
     
     //10.フロント反時計回りに戻す
     glFrontFace(GL_CCW);
     
     //11.ミラーを描画し、行列を復元する
     modelViewMatrix.PopMatrix();
     
     //12.ブレンド関数を有効にする
     glEnable(GL_BLEND);
     //13. glBlendFuncカラー混合式を指定する。
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
     
     //14.地面のテクスチャをバインドする
     glBindTexture(GL_TEXTURE_2D, uiTextures[0]);
     
     /*15.
     テクスチャ調整シェーダ
     パラメータ1:GLT_SHADER_TEXTURE_MODULATE
     パラメータ2:モデルビューの投影行列
     パラメータ3:色
     パラメータ4:テクスチャユニット
     
     */
     shaderManager.UseStockShader(GLT_SHADER_TEXTURE_MODULATE,
     transformPipeline.GetModelViewProjectionMatrix(),
     vFloorColor,
     0);
     //shaderManager.UseStockShader(GLT_SHADER_TEXTURE_REPLACE,transformPipeline.GetModelViewProjectionMatrix(),0);
     
     //描画を開始する
     floorBatch.Draw();
     //ブレンドをキャンセルする
     glDisable(GL_BLEND);
     
     //16.地面以外のものを描く
     drawSomething(yRot);
     
     //17.描画後、行列を復元する
     modelViewMatrix.PopMatrix();
     
     //18.バッファを交換する
     glutSwapBuffers();
     
     //19.再レンダリングに提出する
     glutPostRedisplay();
     
    }
    //**3.矢印キーに応答するようにカメラのフレームを移動する。
    void SpeacialKeys(int key,int x,int y)
    {
     
     float linear = 0.1f;
     float angular = float(m3dDegToRad(5.0f));
     
     if (key == GLUT_KEY_UP) {
     
     //MoveForward  
     cameraFrame.MoveForward(linear);
     }
     
     if (key == GLUT_KEY_DOWN) {
     cameraFrame.MoveForward(-linear);
     }
     
     if (key == GLUT_KEY_LEFT) {
     //RotateWorld  
     cameraFrame.RotateWorld(angular, 0.0f, 1.0f, 0.0f);
     }
     
     if (key == GLUT_KEY_RIGHT) {
     cameraFrame.RotateWorld(-angular, 0.0f, 1.0f, 0.0f);
     }
    }
    int main(int argc, char* argv[])
    {
     gltSetWorkingDirectory(argv[0]);
     
     glutInit(&argc, argv);
     glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
     glutInitWindowSize(800,600);
     
     glutCreateWindow("OpenGL SphereWorld");
     
     glutReshapeFunc(ChangeSize);
     glutDisplayFunc(RenderScene);
     glutSpecialFunc(SpeacialKeys);
     
     GLenum err = glewInit();
     if (GLEW_OK != err) {
     fprintf(stderr, "GLEW Error: %s
    ", glewGetErrorString(err));
     return 1;
     }
     
     SetupRC();
     glutMainLoop();
     ShutdownRC();
     return 0;
    }
    

    添付デモアドレス:

    08-OpenGL-Sphere Worlds



    Read next

    Danteクラウドインターフェイス仕様

    ゲートウェイ仕様\nインターフェイスは、ゲートウェイを通過するために統一され、すべてのシステムのインターフェイスは、ログインするために統一されています。\nインターフェース環境 テスト環境:yang800、オンライン環境\nリクエスト仕様\nメソッド:'POST'、データ:JS\n データ:JS

    Nov 21, 2020 · 2 min read