6.2.3散乱光(2)OpenGL ES 2.0

8279 ワード

『Android 3 Dゲーム開発技術宝典——OpenGL ES 2.0』第6章光照射では、読者に光照射効果の開発を紹介し、本章の学習を通じて、読者はシーン中の物体にリアルな光照射効果を加えることができ、シーンのリアリティを大幅に向上させることができる.このセクションでは、散乱光について説明します.
6.2.3散乱光(2)
説明図6−11左側の図は、光源がシーン左側に位置して照射される場合を示し、右側の図は、光源が右側に位置して照射される場合を示す.左右の2枚の効果図の対比から,正対光源(入射角が小さい)の位置は明るく見えるが,入射角が大きくなるにつれて暗くなり,入射角が90後より大きくなるまで完全に照らすことができなかった.
散乱光の基本原理とケースの動作効果を理解した後,ケースの開発を行うことができる.実際には、このケースはケースSample 6_2 1部をコピーして修正したので、以下に示すように修正の主な手順のみが示されます.
(1)散乱光効果は光源の位置と密接に関係するため、光源の位置をシェーダに伝達して光照射の計算を行う必要がある.便宜上、まずツールクラスMatrixStateをアップグレードし、現在の光源位置を格納する関連メンバー変数を増やし、光源位置を設定する方法が必要です.具体的なコードは以下のとおりです.
コード位置:随書ディスクのソースコード/第6章/Sample 6を参照してください.3/com/bn/Sample6_3ディレクトリの下にあるMatrixState.java.

  
  
  
  
  1. 1   public static float[] lightLocation = new float[] { 0, 0, 0 };  //  
  2. 2   public static FloatBuffer lightPositionFB;                      //  
  3. 3   static ByteBuffer llbbL = ByteBuffer.allocateDirect(3 * 4);     //  
  4. 4   public static void setLightLocation(float x, float y, float z) {    //  
  5. 5       llbbL.clear();                                      //  
  6. 6       lightLocation[0] = x;lightLocation[1] = y;lightLocation[2] = z;                                                                         //  
  7. 7       llbbL.order(ByteOrder.nativeOrder());                   //  
  8. 8       lightPositionFB = llbbL.asFloatBuffer();                // float  
  9. 9       lightPositionFB.put(lightLocation);                 //  
  10. 10      lightPositionFB.position(0);                        //  
  11. 11  }  

第1〜3動作このクラスに新たに追加されたメンバー変数は、主に光源位置配列、光源位置バッファ、および使用待ちバイトバッファである.
第4−11動作は、パラメータから伝達された光源位置をまず配列に格納し、その後、対応するfloat型バッファに格納してレンダリング時にパイプラインに伝達することを主な機能とする光源位置を設定する方法である.
(2)次に修正する必要があるのはBallクラスであり、主に初期化法ベクトルデータを追加し、法ベクトルデータをレンダリングパイプラインに伝達する関連コードであり、具体的には以下の通りである.
コード位置:随書ディスクのソースコード/第6章/Sample 6を参照してください.3/com/bn/Sample6_3ディレクトリの下のBall.java.

  
  
  
  
  1. 1   public class Ball {                                   
  2. 2       ……// ,  
  3. 3       int maNormalHandle;                                 //  
  4. 4        int maLightLocationHandle;                         //       
  5. 5       FloatBuffer mNormalBuffer;                          //  
  6. 6       public Ball(MySurfaceView mv) {/* */}      
  7. 7       public void initVertexData() {                      //  
  8. 8           ……// ,         
  9. 9           ByteBuffer nbb = ByteBuffer.allocateDirect(vertices.length*4);//  
  10. 10          nbb.order(ByteOrder.nativeOrder());         //  
  11. 11          mNormalBuffer = nbb.asFloatBuffer();            // float  
  12. 12          mNormalBuffer.put(vertices);                    //  
  13. 13          mNormalBuffer.position(0);                  //        
  14. 14      }  
  15. 15      public void initShader(MySurfaceView mv) {      //  
  16. 16          ……// ,            
  17. 17          maNormalHandle= GLES20.glGetAttribLocation( //      
  18. 18                  mProgram, "aNormal");      
  19. 19          maLightLocationHandle=GLES20.glGetUniformLocation(  
  20. 20                  mProgram, "uLightLocation");            //  
  21. 21      }  
  22. 22      public void drawSelf() {      
  23. 23          ……// ,           
  24. 24              GLES20.glUniform3fv(                        //      
  25. 25                  maLightLocationHandle, 1, MatrixState.lightPositionFB);  
  26. 26          GLES20.glVertexAttribPointer(               //  
  27. 27                  maPositionHandle, 3, GLES20.GL_FLOAT,false, 3 * 4, mVertexBuffer);  
  28. 28          GLES20.glVertexAttribPointer(               //  
  29. 29                  maNormalHandle, 3, GLES20.GL_FLOAT, false,3 * 4, mNormalBuffer);          
  30. 30          GLES20.glEnableVertexAttribArray(maPositionHandle);     //  
  31. 31              GLES20.glEnableVertexAttribArray(maNormalHandle);   //  
  32. 32          GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);    //     
  33. 33  }}  

3-5行目には、頂点法ベクトル属性変数参照、光源位置一致変数参照、および頂点法ベクトルデータバッファを宣言するコードが追加されます.
第7〜14の動作は、頂点法ベクトルデータバッファを初期化する関連コードを追加する頂点データを初期化する方法である.この例では元の球心が座標の原点にあるため,各頂点法ベクトルのX,Y,Z軸成分は頂点のX,Y,Z座標と一致する.これにより、各頂点の法線ベクトルを単独で計算する必要がなくなり、頂点座標シーケンスを頂点法線ベクトルシーケンスとして直接使用すればよい.
15-21行目は、シェーダを初期化する方法で、頂点法ベクトル属性変数参照および光源位置一致変数参照を取得するコードを追加します.
22~33行目にボールを描画するdrawSelf法は、法線ベクトルデータと光源位置データをレンダリングラインに転送するコードを追加するとともに、頂点法線ベクトルデータを有効にするコードを追加する.
ヒントはすべての場合、頂点法ベクトルが頂点座標と必然的に関連しているわけではありません.多くの場合、頂点の法ベクトルは単独で与える必要があります.本書の後ろにはこのような例がたくさんあります.