blog

OpenGLの場合 - ミラー回転+テクスチャマッピング

まず、ケースの効果:\nこのケースは、再開発の基礎にケースの回転と回転にあり、まず最終的な効果を見てください:\n第二に、コード分析:\nsetupRC関数:\nsetupRCフローチャート\nSet...

Dec 18, 2020 · 7 min. read
シェア

I. ケース効果

このケースは回転とスピンのケースをベースにしています:

次に、コードの解析:

セットアップRC機能

  • setupRC
  • SetupRC
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.TGAファイルを2Dテクスチャーとして読み込む。
 //パラメーター1:テクスチャーファイルの名前
 // 2&パラメータ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);
 
 
}

主にステップ8と9:

  • ステップ8で、uiTexturesは、使用する床、大きなボール、小さなボールのテクスチャを含む定義されたテクスチャの配列です。
//テクスチャー・マーカーの配列
GLuint uiTextures[3];
  • ステップ9では、カスタムテクスチャローディング関数LoadTGATextureを使用します:これは、述べたテクスチャ関連のAPIを使用します:
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;
 
 //2main関数ではテクスチャのパラメータを設定する。
 //パラメータ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,wrapMode
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
 
 //3.テクスチャを読み込む
 //パラメータ1:テクスチャの寸法
 //パラメータ2:mipマッピングレベル
 //パラメータ3:テクスチャー・セルの色成分。-内部パラメーターnComponentsを一般的な圧縮テクスチャー・フォーマットに変更する。GL_COMPRESSED_RGB
 //パラメータ4:読み込んだテクスチャの幅
 //パラメータ5:テクスチャの高さを読み込む
 //パラメータ6:読み込んだテクスチャの深さ
 //パラメータ7:ピクセル・データのデータ型
 //パラメータ8:テクスチャのイメージデータへのポインタ。
 glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB, nWidth, nHeight, 0,
 eFormat, GL_UNSIGNED_BYTE, pBits);
 
 //使用後はテクスチャーを解放する。pBits
 free(pBits);
 
 //Mipマップを生成できるのは以下の4つのモードと等しいminFilterだけである。
 //GL_NEAREST_MIPMAP_NEARESTパフォーマンスも非常によく ちらつきも非常に弱い。
 //GL_LINEAR_MIPMAP_NEARESTゲームのスピードアップによく使われる 高品質のリニア・フィルターを使う。
 //GL_LINEAR_MIPMAP_LINEAR  GL_NEAREST_MIPMAP_LINEAR フィルタは、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_1D、GL_TEXTURE_2D、GL_TEXTURE_3D
 glGenerateMipmap(GL_TEXTURE_2D);
 
 
 return true;
}

これでsetupRCのコードは終わりで、いくつかの初期化が行われます。

RenderSence関数

  • renderSence

  • RenderSence

//シーンを描画するために呼び出しを行う
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();
}
  • 実コンテンツとミラーコンテンツが実際に同じであるため、ちょうどイメージは、フロント方向を設定することによって、OpenGLで知っている前のコンテンツでは、フロントのデフォルトの反時計回りの方向ですので、実コンテンツは、反時計回りの方向で使用することができます達成することができます時計回りのミラーコンテンツができます。
  • どのdrawSomething関数は、大きなボールを描画するために使用され、小さなボールは、フロントまたはミラーコンテンツかどうかは同じですが、方向が同じではないので、すべての呼び出しdrawSomethingを描画することができます。
  • drawSomethingのコードは以下の通り:
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 ShutdownRC(void)
{
 glDeleteTextures(3, uiTextures);
}
int main(int argc, char* argv[])
{
 gltSetWorkingDirectory(argv[0]);
 
 glutInit(&argc, argv);
 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
 glutInitWindowSize();
 
 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;
}

OK、それで最終的な効果が得られます。いいと思ったら、好きになるしかありません!それを読んで気に入った人は、すべての試験に合格し、すべての賞を獲得すると聞いたことがあります!

Read next

基本的な RocketMQ メッセージ送信と消費の例

この信頼性が高く同期的な送信方法は、重要メッセージの通知、SMS通知など、広く使用されています。 非同期メッセージは通常、応答時間に敏感なビジネス・シナリオで使用されます。つまり、送信者はブローカーからの応答を長時間待つことができません。 この方法は、ログ送信など、送信結果を気にしないシナリオで主に使用されます。

Dec 18, 2020 · 5 min read