OpenGL ESを初めて使用する場合は、レッスン1と2を最初に学習することをお勧めします。このレッスンは以前のレッスンの知識に基づいているためです。
この記事で使用されるコードの基本は、ここから取得されます。
1. http://andmonahov.blogspot.com/2012/10/opengl-es-20.html
2. http://www.learnopengles.com/android-lesson-two-ambient-and-diffuse-lighting/
その結果、デバイスまたはエミュレータの画面にそのような画像が表示されます。
光と光源の種類について少し
光は、特定の周波数の電磁波、または光子のストリーム(特定のエネルギーを持つ粒子)と見なすことができます。 どの光子が網膜の特定の場所に落ちたかによって、脳は視覚的な感覚を作り出します。
色の感覚は、光子のエネルギーまたは電磁放射の周波数に依存します。 真空中の波長が380〜400 nm(紫)のセクションを、光が占めるスペクトル範囲の短波長境界として採用し、760〜780 nm(赤)の部分を長波長境界としました。
色の感覚に加えて、単位時間あたりに網膜に当たる光子の数または電磁波の強度によって決定される光の明るさの概念は、私たちにとって非常に重要です。
周囲の世界のすべてのオブジェクトは、光を発するものとそれを反射するものに分けることができます。 しかし、私たちは世界の多様性を認識しています。光や色の明るさだけでなく、オブジェクト自体の反射能力、オブジェクトからの影なども重要です。 世界のコンピューターモデリングは、実際のオブジェクトの写真とコンピューターモデルを区別できるのは専門家だけである場合もあります。 照明オブジェクトには多くの分類およびモデリングシステムがありますが、そのうちのいくつかを検討してください。
背景照明
オブジェクトがすべての側面で均等に照らされている場合、背景照明について話します。 自然界では、これは通常曇りの日に起こります。 屋内にいる場合、そのような照明は、異なるオブジェクトから光が複数回反射される場合、または特別な方法で分散された多くの光源がある場合に発生します。 左側の写真には、指向性照明と背景照明が混合されている写真があり、右側には背景のみがあります。 背景の照明を計算するとき、サーフェスの法線(ビームがサーフェスに当たる角度)もカメラの現在の位置も考慮されません。
背景照明をプログラムで記述する方法は?
オブジェクトを赤にし、背景の光をくすんだ白にします。 RGBカラーモデルを使用して、赤、緑、青の3色の配列として色を保存するとします。 次に、色の重み係数に特定の照明定数を掛ける必要があります。
最終色= {1、0、0} * {0.1、0.1、0.1} = {0.1、0.0、0.0}
これで、オブジェクトの最終的な色は鈍い赤になります。これは、赤いオブジェクトを鈍い白色光で照らした場合に実際に見えるものに対応します。
拡散照明
拡散照明(拡散照明)-光源からの光は、特定のポイントに到達した後に散乱します。 光が落ちる角度に応じて、照明は強くまたは弱くなります。 ここでは、表面の法線が考慮されますが、カメラの位置は考慮されません。
光線が水平面上で45度の角度(光線とサーフェスの法線との角度)で落ちると想像してください。 拡散(散乱)反射の結果、光エネルギーはすべての方向に均一に反射されるため、3台のカメラはすべて同じ明るさの表面を削除します。 光が0度の角度(サーフェスに垂直)で落ちる場合、サーフェスが最も明るく照らされることは明らかです。 また、光線が90度に近い角度で落ちた場合、光線は表面上を滑空し、表面を照らしません。
拡散反射のソフトウェアモデリング
拡散反射をモデル化するために、ランバート係数が使用されます。
light vector = light position - object position
cosine = dot product(object normal, normalize(light vector))
lambert factor = max(cosine, 0)
これらの3行のコードを説明します。
まず、光源の位置からオブジェクトの位置を引くことにより、光ベクトルが計算されます。
light vector = light position - object position
次に、表面の法線と正規化された光ベクトルの間のスカラー積を見つけることにより、光ベクトルと法線の間の角度の余弦を計算できます。 ライトベクトルを正規化するとは、その長さが1に等しくなるように変更することを意味しますが、ベクトルの方向は変更されません。 表面の法線の弾性率は既に1に等しくなっています。 2つの正規化されたベクトルのスカラー積を決定したら、それらの間の角度の余弦を求めます。
cosine = dot product(object normal, normalize(light vector))
スカラー積の範囲は-1〜1であるため、0〜1の範囲に制限する必要があります。関数max(x、y)は、「x」が「y」より大きい場合、「x」を返します。
lambert factor = max(cosine, 0)
明確にするために、例を考えてみましょう。
光源をT. S(0.10,10)に置き、法線が垂直に見える(0、1、0)水平面(これは単一ピクセルの場合があります)の照度を計算します。 次に、OSベクトル(ライトベクトル)と法線ベクトル(オブジェクト法線)
light vector = {0, 10, 10} - {0, 0, 0} = {0, 10, 10}
object normal = {0, 1, 0}
OSベクトルの長さを見つける
light vector length = square root(0*0 + 10*10 + 10*10) = square root(200) = 14.14
それを正規化する、すなわち その長さが1になるようにします。
normalized light vector = {0, 10/14.14, 10/14.14} = {0, 0.707, 0.707}
次に、スカラー積を計算します。
dot product({0, 1, 0}, {0, 0.707, 0.707}) = (0 * 0) + (1 * 0.707) + (0 * 0.707) = 0 + 0.707 + 0 = 0.707
誰が数学を忘れたのか、2つのベクトルのスカラー積はそれらのモジュールの積に等しく、それらの間の角度の余弦を乗じたことを思い出します。 モジュールのユニティが等しい場合、スカラー積はコサインに等しくなります。
小さな問題があります。これは、角度アルファが90〜180度の場合、原則としてコサインが負の値をとることができるということです。 したがって、Lambert係数の値の範囲を0〜1に制限します。
lambert factor = max(0.707, 0) = 0.707
反射またはグレア
反射照明(鏡面照明)は、特定のポイントに到達した後に反射される光源からの光です。 反射光は、カメラに当たる場合にのみ表示されます。 したがって、ここでは通常位置とカメラ位置の両方が考慮されます。
ソフトウェアフレアの実装
拡散照明の計算では、照明された点から正規化された光ベクトルに移動する単位長さベクトルが決定されました。 光源から表面上の点への入射光のベクトルを決定するには、符号をマイナスに変更するだけです。
GLSLで反射ベクトル(OS1方向)を計算するには、特別なリフレクト関数があります。
reflectvector = reflect(- normalized light vector, object normal);
カメラ座標は、u_cameraユニフォームとしてフラグメントシェーダーに転送されます。
uniform vec3 u_camera;
次に、照明点からカメラに向けてベクトルOKを計算し、正規化します。
lookvector = normalize(u_camera - object position);
次に、反射ベクトルOS1とカメラの方向OKの間のベータ角の余弦を計算する必要があります。 角度のコサインは、ドット(lookvector、reflectvector)の2つの単位ベクトルのスカラー積であることをすでに示しました。 ベータ角が小さいほど、ハイライトが明るくなります。
また、ランバート係数に関しては、max関数を使用してスカラー積の負の値を切り取ります。
max(dot(lookvector,reflectvector),0.0)
フレア自体のサイズは、光沢パラメーターを使用して調整できます。このためには、スカラー積の計算値を光沢の程度まで上げる必要があります。 べき乗のために、GLSLでpow関数が提供されています。 通常、数十のユニットが光沢値を取ります。 輝度が上がると、グレアのサイズは小さくなりますが、輝度は上がります。 逆に、輝度が低いほどフレアは大きくなりますが、輝度は低くなります。
たとえば、輝度が30である場合、結果のスカラー積を30の累乗に上げます。
pow( max(dot(lookvector,reflectvector),0.0), 30.0 )
結果の値に鏡面照明の係数k_specularを乗算し、指定されたピクセルの鏡面照明の輝度を取得します。
float specular = k_specular * pow( max(dot(lookvector,reflectvector),0.0), 30.0 );
トータルライティング
実生活でオブジェクトの照明をシミュレートするには、さまざまなタイプのオブジェクトの照明を一定の割合で要約する必要があります。 たとえば、照明を考慮に入れてピクセルの色を取得するには、照明の周囲、拡散+鏡面反射の背景、拡散、ミラー部分を追加し、頂点v_colorの色を補間して得られたピクセルの色のベクトルを掛ける必要があります。
gl_FragColor = (ambient+diffuse+specular)*v_color;
頂点の補間色でピクセルを色付けしたくない場合は、白いベクトルを定義するだけで十分です。
vec4 one=vec4(1.0,1.0,1.0,1.0);
そして光の明るさにそれを掛けます:
gl_FragColor = (ambient+diffuse+specular)*one;
最初にアンビエント= 1、拡散= 0、鏡面反射= 0の場合の画像の変化を評価できます。ケースの中心の画像= 0、拡散= 1、鏡面反射= 0、そのような値の右側の画像は環境= 0、拡散= 0、鏡面反射= 1。
この線は、照明と色を混ぜています。
gl_FragColor = mix(lightColor,v_color,0.6)
混合係数が0の場合、画像の見え方(左側)を見てください。実際、光の明るさの分布が見られます。 係数を1にすると、純粋な色が表示されます。
ソースに移る前に、それらについて少しコメントしてください。
1.最後のレッスンで、マニフェストファイルにそのような行が表示されていることに気づきました
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
これで、Google PlayはOpenGL ESをサポートしていないデバイスでアプリケーションを表示しなくなります。
2. 2番目のレッスンでは、GLES20.glDrawArraysメソッド(GLES20.GL_TRIANGLES、0、3)のみを使用して三角形を描きました。
このレッスンでは、新しいメソッドGLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP、0、4)が登場しました。
その助けを借りて、四角形と複雑なレリーフを描くのがより便利です。 海、空、船を描くために使用しました。 このメソッドの適用に関する良いレッスンがここにあります。
http://www.learnopengles.com/tag/triangle-strips/
3.ボートは、0Z軸に沿ってわずかに突出して描かれています。 カメラの位置を変更すると、この変位、マトリックスの働き、表面照明の変化を確認できます。 左側では、カメラは0Uで5単位上昇し、右側では0Xで4単位シフトしました。
コード自体に他の説明があります。
最初にプロジェクトを開始してから、さまざまな係数を再生して実験することをお勧めします。
プロジェクトを作成する
Android StudioでOpenGLESLightingプロジェクトを作成する
メインアクティビティはOpengles3Activityと呼ばれます。
さらに3つのJavaファイルを作成します。
MyClassSurfaceView.java
MyClassRenderer.java
Shader.java
コードをコピーして、自動的に生成されたものの代わりにファイルに貼り付けます。
写真をお楽しみください。
記事にエラーが忍び込んでいる場合、私はそれらを修正し、あなたから学ぶことを嬉しく思います。
最高!
コードソース
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.adc2017gmail.opengleslighting" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="19" /> <uses-feature android:glEsVersion="0x00020000" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".Opengles3Activity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
Opengles3Activity.java
public class Opengles3Activity extends Activity { // MyClassSurfaceView private MyClassSurfaceView mGLSurfaceView; // // onCreate @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // MyClassSurfaceView mGLSurfaceView = new MyClassSurfaceView(this); // MyClassSurfaceView setContentView(mGLSurfaceView); // OpenGl ES } @Override protected void onPause() { super.onPause(); mGLSurfaceView.onPause(); } @Override protected void onResume() { super.onResume(); mGLSurfaceView.onResume(); } }
MyClassSurfaceView.java
package com.adc2017gmail.opengleslighting; import android.content.Context; import android.opengl.GLSurfaceView; // MyClassSurfaceView GLSurfaceView public class MyClassSurfaceView extends GLSurfaceView{ // private MyClassRenderer renderer; // public MyClassSurfaceView(Context context) { // GLSurfaceView super(context); setEGLContextClientVersion(2); // MyClassRenderer renderer = new MyClassRenderer(context); // setRenderer(renderer); // onDrawFrame setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY); // // onDrawFrame // .. } }
MyClassRenderer.java
package com.adc2017gmail.opengleslighting; import android.content.Context; import android.opengl.GLES20; import android.opengl.GLSurfaceView; import android.opengl.Matrix; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; public class MyClassRenderer implements GLSurfaceView.Renderer{ // GLSurfaceView.Renderer // onDrawFrame, onSurfaceChanged, onSurfaceCreated // // private Context context; // private float xamera, yCamera, zCamera; // private float xLightPosition, yLightPosition, zLightPosition; // private float[] modelMatrix= new float[16]; private float[] viewMatrix= new float[16]; private float[] modelViewMatrix= new float[16];; private float[] projectionMatrix= new float[16];; private float[] modelViewProjectionMatrix= new float[16];; // private final FloatBuffer vertexBuffer; private final FloatBuffer vertexBuffer1; private final FloatBuffer vertexBuffer2; private final FloatBuffer vertexBuffer3; private final FloatBuffer vertexBuffer4; // private FloatBuffer normalBuffer; private FloatBuffer normalBuffer1; // private final FloatBuffer colorBuffer; private final FloatBuffer colorBuffer1; private final FloatBuffer colorBuffer2; private final FloatBuffer colorBuffer4; // private Shader mShader; private Shader mShader1; private Shader mShader2; private Shader mShader3; private Shader mShader4; // public MyClassRenderer(Context context) { // // this.context=context; // xLightPosition=0.3f; yLightPosition=0.2f; zLightPosition=0.5f; // // Matrix.setIdentityM(modelMatrix, 0); // xamera=0.0f; yCamera=0.0f; zCamera=3.0f; // // Y // Matrix.setLookAtM( viewMatrix, 0, xamera, yCamera, zCamera, 0, 0, 0, 0, 1, 0); // // - Matrix.multiplyMM(modelViewMatrix, 0, viewMatrix, 0, modelMatrix, 0); // 1 float x1=-1; float y1=-0.35f; float z1=0.0f; // 2 float x2=-1; float y2=-1.5f; float z2=0.0f; // 3 float x3=1; float y3=-0.35f; float z3=0.0f; // 4 float x4=1; float y4=-1.5f; float z4=0.0f; // float vertexArray [] = {x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4}; //coordinates for sky float vertexArray1 [] = {-1.0f,1.5f,0.0f, -1.0f,-0.35f,0.0f, 1.0f,1.5f,0.0f, 1.0f,-0.35f,0}; //coordinates for main sail float vertexArray2 [] = {-0.5f,-0.45f,0.4f, 0.0f,-0.45f,0.4f, 0.0f,0.5f,0.4f}; //coordinates for small sail float vertexArray3 [] = {0.05f,-0.45f,0.4f, 0.22f,-0.5f,0.4f, 0.0f,0.25f,0.4f }; //coordinates for boat float vertexArray4 [] = {-0.5f,-0.5f,0.4f, -0.5f,-0.6f,0.4f, 0.22f,-0.5f,0.4f, 0.18f,-0.6f,0.4f}; // ByteBuffer bvertex = ByteBuffer.allocateDirect(vertexArray.length*4); bvertex.order(ByteOrder.nativeOrder()); vertexBuffer = bvertex.asFloatBuffer(); vertexBuffer.position(0); ByteBuffer bvertex1 = ByteBuffer.allocateDirect(vertexArray1.length*4); bvertex1.order(ByteOrder.nativeOrder()); vertexBuffer1 = bvertex1.asFloatBuffer(); vertexBuffer1.position(0); ByteBuffer bvertex2 = ByteBuffer.allocateDirect(vertexArray2.length*4); bvertex2.order(ByteOrder.nativeOrder()); vertexBuffer2 = bvertex2.asFloatBuffer(); vertexBuffer2.position(0); ByteBuffer bvertex3 = ByteBuffer.allocateDirect(vertexArray3.length*4); bvertex3.order(ByteOrder.nativeOrder()); vertexBuffer3 = bvertex3.asFloatBuffer(); vertexBuffer3.position(0); ByteBuffer bvertex4 = ByteBuffer.allocateDirect(vertexArray4.length*4); bvertex4.order(ByteOrder.nativeOrder()); vertexBuffer4 = bvertex4.asFloatBuffer(); vertexBuffer4.position(0); // vertexBuffer.put(vertexArray); vertexBuffer.position(0); vertexBuffer1.put(vertexArray1); vertexBuffer1.position(0); vertexBuffer2.put(vertexArray2); vertexBuffer2.position(0); vertexBuffer3.put(vertexArray3); vertexBuffer3.position(0); vertexBuffer4.put(vertexArray4); vertexBuffer4.position(0); // // Z float nx=0; float ny=0; float nz=1; // , // 4 float normalArray [] ={nx, ny, nz, nx, ny, nz, nx, ny, nz, nx, ny, nz}; float normalArray1 [] ={0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1}; // ByteBuffer bnormal = ByteBuffer.allocateDirect(normalArray.length*4); bnormal.order(ByteOrder.nativeOrder()); normalBuffer = bnormal.asFloatBuffer(); normalBuffer.position(0); // normalBuffer.put(normalArray); normalBuffer.position(0); // , float red1=0; float green1=1; float blue1=1; // float red2=0; float green2=0; float blue2=1; // float red3=0; float green3=1; float blue3=1; // float red4=0; float green4=0; float blue4=1; // // () float colorArray [] = { red1, green1, blue1, 1, red2, green2, blue2, 1, red3, green3, blue3, 1, red4, green4, blue4, 1, }; float colorArray1[] = { 0.2f, 0.2f, 0.8f, 1, 0.5f, 0.5f, 1, 1, 0.2f, 0.2f, 0.8f, 1, 0.5f, 0.5f, 1, 1, }; float colorArray2[] = { 1, 0.1f, 0.1f, 1, 1, 1, 1, 1, 1, 0.1f, 0.1f, 1, }; float colorArray4[] = { 1, 1, 1, 1, 0.2f, 0.2f, 0.2f, 1, 1, 1, 1, 1, 0.2f, 0.2f, 0.2f, 1, }; // ByteBuffer bcolor = ByteBuffer.allocateDirect(colorArray.length*4); bcolor.order(ByteOrder.nativeOrder()); colorBuffer = bcolor.asFloatBuffer(); colorBuffer.position(0); // colorBuffer.put(colorArray); colorBuffer.position(0); ByteBuffer bcolor1 = ByteBuffer.allocateDirect(colorArray1.length*4); bcolor1.order(ByteOrder.nativeOrder()); colorBuffer1 = bcolor1.asFloatBuffer(); colorBuffer1.position(0); colorBuffer1.put(colorArray1); colorBuffer1.position(0); ByteBuffer bcolor2 = ByteBuffer.allocateDirect(colorArray1.length*4); bcolor2.order(ByteOrder.nativeOrder()); colorBuffer2 = bcolor2.asFloatBuffer(); colorBuffer2.position(0); colorBuffer2.put(colorArray2); colorBuffer2.position(0); ByteBuffer bcolor4 = ByteBuffer.allocateDirect(colorArray4.length*4); bcolor4.order(ByteOrder.nativeOrder()); colorBuffer4 = bcolor4.asFloatBuffer(); colorBuffer4.position(0); colorBuffer4.put(colorArray4); colorBuffer4.position(0); }// //, // -- public void onSurfaceChanged(GL10 unused, int width, int height) { // glViewport GLES20.glViewport(0, 0, width, height); float ratio = (float) width / height; float k=0.055f; float left = -k*ratio; float right = k*ratio; float bottom = -k; float top = k; float near = 0.1f; float far = 10.0f; // Matrix.frustumM(projectionMatrix, 0, left, right, bottom, top, near, far); // , // -- Matrix.multiplyMM( modelViewProjectionMatrix, 0, projectionMatrix, 0, modelViewMatrix, 0); } //, // public void onSurfaceCreated(GL10 unused, EGLConfig config) { // GLES20.glEnable(GLES20.GL_DEPTH_TEST); // GLES20.glEnable(GLES20.GL_CULL_FACE); // , GLES20.glHint( GLES20.GL_GENERATE_MIPMAP_HINT, GLES20.GL_NICEST); // String vertexShaderCode= "uniform mat4 u_modelViewProjectionMatrix;"+ "attribute vec3 a_vertex;"+ "attribute vec3 a_normal;"+ "attribute vec4 a_color;"+ "varying vec3 v_vertex;"+ "varying vec3 v_normal;"+ "varying vec4 v_color;"+ "void main() {"+ "v_vertex=a_vertex;"+ "vec3 n_normal=normalize(a_normal);"+ "v_normal=n_normal;"+ "v_color=a_color;"+ "gl_Position = u_modelViewProjectionMatrix * vec4(a_vertex,1.0);"+ "}"; // String fragmentShaderCode= "precision mediump float;"+ "uniform vec3 u_camera;"+ "uniform vec3 u_lightPosition;"+ "varying vec3 v_vertex;"+ "varying vec3 v_normal;"+ "varying vec4 v_color;"+ "void main() {"+ "vec3 n_normal=normalize(v_normal);"+ "vec3 lightvector = normalize(u_lightPosition - v_vertex);"+ "vec3 lookvector = normalize(u_camera - v_vertex);"+ "float ambient=0.2;"+ "float k_diffuse=0.3;"+ "float k_specular=0.5;"+ "float diffuse = k_diffuse * max(dot(n_normal, lightvector), 0.0);"+ "vec3 reflectvector = reflect(-lightvector, n_normal);"+ "float specular = k_specular * pow( max(dot(lookvector,reflectvector),0.0), 40.0 );"+ "vec4 one=vec4(1.0,1.0,1.0,1.0);"+ "vec4 lightColor = (ambient+diffuse+specular)*one;"+ "gl_FragColor = mix(lightColor,v_color,0.6);"+ "}"; // mShader=new Shader(vertexShaderCode, fragmentShaderCode); // a_vertex mShader.linkVertexBuffer(vertexBuffer); // a_normal mShader.linkNormalBuffer(normalBuffer); // a_color mShader.linkColorBuffer(colorBuffer); // , // mShader1 = new Shader(vertexShaderCode, fragmentShaderCode); mShader1.linkVertexBuffer(vertexBuffer1); mShader1.linkNormalBuffer(normalBuffer); mShader1.linkColorBuffer(colorBuffer1); mShader2 = new Shader(vertexShaderCode, fragmentShaderCode); mShader2.linkVertexBuffer(vertexBuffer2); mShader2.linkNormalBuffer(normalBuffer); mShader2.linkColorBuffer(colorBuffer2); mShader3 = new Shader(vertexShaderCode, fragmentShaderCode); mShader3.linkVertexBuffer(vertexBuffer3); mShader3.linkNormalBuffer(normalBuffer); mShader3.linkColorBuffer(colorBuffer2); mShader4 = new Shader(vertexShaderCode, fragmentShaderCode); mShader4.linkVertexBuffer(vertexBuffer4); mShader4.linkNormalBuffer(normalBuffer); mShader4.linkColorBuffer(colorBuffer4); } //, public void onDrawFrame(GL10 unused) { // GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); // -- mShader.useProgram(); mShader.linkVertexBuffer(vertexBuffer); mShader.linkColorBuffer(colorBuffer); mShader.linkModelViewProjectionMatrix(modelViewProjectionMatrix); mShader.linkCamera(xamera, yCamera, zCamera); mShader.linkLightSource(xLightPosition, yLightPosition, zLightPosition); GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); mShader1.useProgram(); mShader1.linkVertexBuffer(vertexBuffer1); mShader1.linkColorBuffer(colorBuffer1); mShader1.linkModelViewProjectionMatrix(modelViewProjectionMatrix); mShader1.linkCamera(xamera, yCamera, zCamera); mShader1.linkLightSource(xLightPosition, yLightPosition, zLightPosition); GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); mShader2.useProgram(); mShader2.linkVertexBuffer(vertexBuffer2); mShader2.linkColorBuffer(colorBuffer2); mShader2.linkModelViewProjectionMatrix(modelViewProjectionMatrix); mShader2.linkCamera(xamera, yCamera, zCamera); mShader2.linkLightSource(xLightPosition, yLightPosition, zLightPosition); GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3); mShader3.useProgram(); mShader3.linkVertexBuffer(vertexBuffer3); mShader3.linkColorBuffer(colorBuffer2); mShader3.linkModelViewProjectionMatrix(modelViewProjectionMatrix); mShader3.linkCamera(xamera, yCamera, zCamera); mShader3.linkLightSource(xLightPosition, yLightPosition, zLightPosition); GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3); mShader4.useProgram(); mShader4.linkVertexBuffer(vertexBuffer4); mShader4.linkColorBuffer(colorBuffer4); mShader4.linkModelViewProjectionMatrix(modelViewProjectionMatrix); mShader4.linkCamera(xamera, yCamera, zCamera); mShader4.linkLightSource(xLightPosition, yLightPosition, zLightPosition); GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); } }//
Shader.java
package com.adc2017gmail.opengleslighting; import android.opengl.GLES20; import java.nio.FloatBuffer; public class Shader { // // private int program_Handle; // // public Shader(String vertexShaderCode, String fragmentShaderCode){ // , // program_Handle createProgram(vertexShaderCode, fragmentShaderCode); } // , , private void createProgram(String vertexShaderCode, String fragmentShaderCode){ // int vertexShader_Handle = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER); // GLES20.glShaderSource(vertexShader_Handle, vertexShaderCode); // GLES20.glCompileShader(vertexShader_Handle); // int fragmentShader_Handle = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER); // GLES20.glShaderSource(fragmentShader_Handle, fragmentShaderCode); // GLES20.glCompileShader(fragmentShader_Handle); // program_Handle = GLES20.glCreateProgram(); // GLES20.glAttachShader(program_Handle, vertexShader_Handle); // GLES20.glAttachShader(program_Handle, fragmentShader_Handle); // GLES20.glLinkProgram(program_Handle); } //, // vertexBuffer a_vertex public void linkVertexBuffer(FloatBuffer vertexBuffer){ // GLES20.glUseProgram(program_Handle); // a_vertex int a_vertex_Handle = GLES20.glGetAttribLocation(program_Handle, "a_vertex"); // a_vertex GLES20.glEnableVertexAttribArray(a_vertex_Handle); // vertexBuffer a_vertex GLES20.glVertexAttribPointer( a_vertex_Handle, 3, GLES20.GL_FLOAT, false, 0,vertexBuffer); } //, // normalBuffer a_normal public void linkNormalBuffer(FloatBuffer normalBuffer){ // GLES20.glUseProgram(program_Handle); // a_normal int a_normal_Handle = GLES20.glGetAttribLocation(program_Handle, "a_normal"); // a_normal GLES20.glEnableVertexAttribArray(a_normal_Handle); // normalBuffer a_normal GLES20.glVertexAttribPointer( a_normal_Handle, 3, GLES20.GL_FLOAT, false, 0,normalBuffer); } //, // colorBuffer a_color public void linkColorBuffer(FloatBuffer colorBuffer){ // GLES20.glUseProgram(program_Handle); // a_color int a_color_Handle = GLES20.glGetAttribLocation(program_Handle, "a_color"); // a_color GLES20.glEnableVertexAttribArray(a_color_Handle); // colorBuffer a_color GLES20.glVertexAttribPointer( a_color_Handle, 4, GLES20.GL_FLOAT, false, 0, colorBuffer); } //, -- // modelViewProjectionMatrix u_modelViewProjectionMatrix public void linkModelViewProjectionMatrix(float [] modelViewProjectionMatrix){ // GLES20.glUseProgram(program_Handle); // u_modelViewProjectionMatrix int u_modelViewProjectionMatrix_Handle = GLES20.glGetUniformLocation(program_Handle, "u_modelViewProjectionMatrix"); // modelViewProjectionMatrix // u_modelViewProjectionMatrix GLES20.glUniformMatrix4fv( u_modelViewProjectionMatrix_Handle, 1, false, modelViewProjectionMatrix, 0); } // , u_camera public void linkCamera (float xCamera, float yCamera, float zCamera){ // GLES20.glUseProgram(program_Handle); // u_camera int u_camera_Handle=GLES20.glGetUniformLocation(program_Handle, "u_camera"); // u_camera GLES20.glUniform3f(u_camera_Handle, xCamera, yCamera, zCamera); } // , // u_lightPosition public void linkLightSource (float xLightPosition, float yLightPosition, float zLightPosition){ // GLES20.glUseProgram(program_Handle); // u_lightPosition int u_lightPosition_Handle=GLES20.glGetUniformLocation(program_Handle, "u_lightPosition"); // u_lightPosition GLES20.glUniform3f(u_lightPosition_Handle, xLightPosition, yLightPosition, zLightPosition); } // , public void useProgram(){ GLES20.glUseProgram(program_Handle); } // }
ソース:
http://andmonahov.blogspot.com/2012/10/opengl-es-20.html
http://www.learnopengles.com/android-lesson-two-ambient-and-diffuse-lighting/
http:// www .learnopengles.com / tag / triangle-strips /
http://eax.me/opengl-lighting/
http://www.john-chapman.net/content.php?id=3