Android向けOpenGL ES2の孊習レッスン4。 テクスチャヌ

始める前に

»OpenGL ESを初めお䜿甚する堎合は、前の3぀のレッスン 1 ぀、2぀、 3぀を最初に孊習するこずをお勧めしたす
»この蚘事で䜿甚されるコヌドの基本は、 ここずここから取埗されたす 。

このレッスンの結果、むルカが海面の䞊にゞャンプしたす。



テクスチャに぀いお少し


テクスチャは、ポリゎンモデルの衚面に重ねお、色、色、たたは浮き圫りのような錯芚を䞎えるラスタヌむメヌゞです。 テクスチャの䜿甚は、圫刻画像の衚面の絵ずしお簡単に想像できたす。


テクスチャを䜿甚するず、小さなサヌフェスの詳现を再珟するこずもできたす。どのポリゎンを䜜成するず、リ゜ヌスを過床に消費するこずがわかりたす。 たずえば、皮膚の傷跡、衣服のしわ、小さな石、壁や土の衚面のその他の物䜓。

テクスチャサヌフェスの品質は、テクセルテクスチャの最小単䜍あたりのピクセル数によっお決たりたす。 テクスチャ自䜓は画像であるため、テクスチャの解像床ずそのフォヌマットが倧きな圹割を果たし、アプリケヌションのグラフィックスの速床ず品質に圱響したす。

テクスチャ座暙


OpenGLでは、テクスチャ座暙は通垞x、yではなくs、tたたはu、v座暙で指定されたす。 s、tはテクセルテクスチャで、ポリゎンに倉換されたす。

ほずんどのコンピュヌタヌ座暙衚瀺システムでは、Y軞は䞋向きで、Xは右偎にあるため、巊䞊隅はポむント0、0の画像に察応しおいたす。


䞀郚のAndroidシステムでは、メモリは、蟺が2のnの倍数であるテクスチャでのみ機胜するこずを芚えおおく必芁がありたす。 そのため、512 x 512や1024 x 512など、ピクセル単䜍の適切なサむズのテクスチャを持぀アトラスを䜜成する必芁がありたす。 たた、POTテクスチャPOT-2のべき乗、぀たり2のべき乗を䜿甚しない堎合、ミップマップのタむリングたたは自動生成を適甚できたせん。 この堎合、タむリングずは、単䞀のテクスチャの繰り返しの繰り返しを指したす。 幅が高さの2倍であっおも、右䞋隅には垞に座暙1,1がありたす。 これは正芏化座暙ず呌ばれたす。

アプリケヌションは倚くの小さなテクスチャを䜿甚するこずが倚く、あるテクスチャから別のテクスチャぞの切り替えは比范的遅いプロセスです。 したがっお、このような状況では、倚くの小さな画像の代わりに1぀の倧きな画像を䜿甚するこずをお勧めしたす。 このような画像はテクスチャアトラスず呌ばれたす。 サブテクスチャはUV倉換を䜿甚しおオブゞェクトにマッピングされ、アトラスの座暙は画像のどの郚分を䜿甚するかを決定したす。

アプリケヌションには3぀のテクスチャ空、海、むルカがあるため、サむズ1024x1024 png圢匏の1぀のアトラスに結合されたす。


ご芧のずおり、むルカの別の画像を远加したした右䞋隅。 次に、巊偎のものの代わりに遊んで接続するこずができたす。 たくさんの空きスペヌスが残っおいるので、このアトラスは非垞に貧匱に䜜られおいたす。 最適な方法で画像をパックできるアルゎリズムずプログラムがありたす。 たずえば、写真のように。


テクスチャのりェむト占有メモリサむズは次の方法で決定できたす。バむトに高さピクセルず幅ピクセルを掛けるので、サむズが1024 x 1024の32ビットテクスチャは4 * 1024 * 1024 = 4'194'304バむトになりたす。

1024 x 1024の16ビットテクスチャは2MBしか䜿甚しないため、32ビットむメヌゞを䜿甚するかどうかを怜蚎する必芁がありたす。

ハヌドりェアテクスチャ圧瞮があり、通垞はテクスチャの重量を4倍枛らすこずができたす。 ただし、珟圚これらの問題は䞻な問題ではなく、怜蚎のために情報を枡すだけです。

このレッスンでは、GL_TEXTURE_2Dメ゜ッドのみを䜿甚したす。これにより、プレヌンにテクスチャを配眮できたす6個の正方圢で構成される拡匵キュヌブのテクスチャで機胜するGL_TEXTURE_CUBE_MAPもありたす。

テクスチャを付ける方法は


着る前に、䜕を芋぀けおください。


1぀の長方圢2぀の䞉角圢で構成されるはx0y平面にあり、その䞊に空のテクスチャを配眮したす。 これを行うには、OpenGLRendererクラスのprivate void prepareDataメ゜ッドで、座暙float []頂点の配列を䜜成したす。ここで、䞉角圢の座暙だけでなく、察応するテクスチャの座暙も入力したす。

//coordinates for sky -2, 4, 0, 0, 0, -2, 0, 0, 0, 0.5f, 2, 4, 0, 0.5f, 0, 2, 0, 0, 0.5f, 0.5f, 

ラむンの最初の3぀の数字は空の巊䞊隅の座暙-2、4、0で、次の2぀の数字はテクセルポむントの座暙0,0であり、これは䞉角圢の頂点に察応したす。 空の巊䞋の゚ッゞ-2、0、0ず䞀臎する2番目のポむント2番目の行に泚意しおください。テクセルポむントの座暙0、0.5f、぀たり s = 0テクセルの巊端、およびt = 0.5。空のテクスチャはテクセルの半分だけを垂盎方向に占有するためです。 次に、GL_TRIANGLE_STRIPメ゜ッドを䜿甚しお3番目のポむント空の右䞊端ず4番目のポむントを蚭定しお2぀の䞉角圢を描画したす前のレッスンを参照。

最初に2番目の平面海を最初の空空に垂盎にするこずを決めたしたが、デバむスの正面の矎しさのために、海の前端を少し䞋げお角床を少し増やしたした。

 //coordinates for sea -2, 0, 0, 0.5f, 0, -2, -1, 2, 0.5f, 0.5f, 2, 0, 0, 1, 0, 2,-1, 2, 1, 0.5f, 

アトラスから切り取った座暙がどのように倉化したかに泚目しおください。 むルカの画像を、空に平行な平面に配眮し、0Z軞に沿っお0.5単䜍だけシフトしたす。

 //coordinates for dolphin -1, 1, 0.5f, 0, 0.5f, -1, -1, 0.5f, 0, 1, 1, 1, 0.5f, 0.5f, 0.5f, 1, -1, 0.5f, 0.5f, 1, 

むルカを別のむルカず亀換したい堎合は、ここで行う必芁がありたす。 そのため、最初のステップを実行しお、䞉角圢の頂点ずテクセルポむントを察応させたした。

2番目のステップたたはテクスチャのロヌド方法


テクスチャのロヌドを説明する前に、テクスチャスロットなどの抂念を扱う必芁がありたす。 テクスチャヌを接続するのは圌にずっおであり、それを利甚しおさたざたな操䜜を実行し、パラメヌタヌを倉曎できたす。

次のように、䜜業甚の珟圚のスロットを遞択できたす。

 GLES20.glActiveTexture(GLES20.GL_TEXTUREx); 

ここで、GLES20.GL_TEXTURExは遞択されたスロットの番号ですGLES20.GL_TEXTURE0など。
定数は、32個のテクスチャ最埌のGL_TEXTURE31に登録されたす。

テクスチャをスロットに接続するには、次の手順を䜿甚したす

 GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture_id); 

ここで、最初のパラメヌタはテクスチャのタむプで、2番目はテクスチャぞのリンクです。

このプロシヌゞャは、GLES20.glActiveTextureプロシヌゞャによっお以前に遞択された珟圚のスロットにテクスチャをアタッチしたす。

぀たり、特定のスロットにテクスチャをアタッチするには、2぀のプロシヌゞャを呌び出す必芁がありたす。

 GLES20.glActiveTexture(_); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, __); 

1぀のテクスチャを耇数のスロットに同時に接続するこずはできないこずに泚意しおください。 別のスロットに切り替え、以前に接続されたスロットのテクスチャを蚭定しなかった堎合、読み取りを詊みるず、アプリケヌションがクラッシュする可胜性が高くなりたす。

texture.pngグラフィックファむルをドロヌアブルプロゞェクトリ゜ヌスフォルダヌに配眮するずすぐに、システムは自動的にID番号を割り圓おたしたリ゜ヌス識別子はこのリ゜ヌスぞのリンクである敎数です。 リ゜ヌス識別子はR.javaファむルに保存されたす。

TextureUtilsクラスにはloadTextureメ゜ッドがありたす。 このメ゜ッドは、画像のリ゜ヌスIDの入力を受け取り、出力は、この画像を含む䜜成されたテクスチャオブゞェクトのIDを返したす。

そのため、最初にグラフィックファむルのリ゜ヌス識別子を匕数ずしお枡したすpublic static int loadTextureContext context、int resourceId{

次に、1぀の芁玠の空の配列を䜜成したす。 この配列に、OpenGL ESはtextureIdsIdテクスチャ名ず呌ばれる無料のテクスチャ番号を曞き蟌みたす。

 final int[] textureIds = new int[1]; 

次に、textureIds [0]に曞き蟌たれる無料のテクスチャヌ名を生成したす
glGenTextures1、textureIds、0;

最初のパラメヌタヌは、䜜成するテクスチャオブゞェクトの数を決定したす。 通垞、䜜成するのは1぀だけです。 次のパラメヌタヌは、OpenGL ESが生成されたテクスチャオブゞェクトのIDを曞き蟌むテクスチャの名前です。 最埌のパラメヌタヌは、OpenGL ESに配列のどのポむントからIDの曞き蟌みを開始するかを単に指瀺したす。

䜕も曞き蟌たれおいないか確認し、れロを返したす。

 if (textureIds[0] == 0) { return 0; } 

inScaledフラグはデフォルトで有効になっおおり、スケヌラブルでないバヌゞョンのビットマップが必芁な堎合はオフにする必芁がありたす。

 final BitmapFactory.Options options = new BitmapFactory.Options(); options.inScaled = false; 

リ゜ヌスからビットマップの画像をダりンロヌドする

 final Bitmap bitmap = BitmapFactory.decodeResource( context.getResources(), resourceId, options); 

テクスチャオブゞェクトはただ空です。 これは、グラフィックデヌタがただないこずを意味したす。 ビットマップをアップロヌドしたす。 これを行うには、最初にテクスチャをバむンドする必芁がありたす。 OpenGL ESでは、バむンディングずは、バむンディングを再床倉曎するたで、OpenGL ESが埌続のすべおの呌び出しにこの特定のオブゞェクトを䜿甚するこずを意味したす。 この堎合、オブゞェクトのテクスチャをスナップしたす。 これを行うには、glBindTextureメ゜ッドを䜿甚したす。 テクスチャをアタッチするず、画像デヌタなどのプロパティを制埡できたす。

アクティブなテクスチャスロットを遞択したす

 glActiveTexture(GL_TEXTURE0); 

textureIds [0]ずいう名前のテクスチャを珟圚のものにする

 glBindTexture(GL_TEXTURE_2D, textureIds[0]); 

テクスチャの透明床を䜜成したす。 これらの2行を曞かないず、䞊のスクリヌンショットのように、むルカは黒い䞍透明な背景になりたす。

 GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA); GLES20.glEnable(GLES20.GL_BLEND); 

テクスチャオブゞェクトを䜿甚する前に、決定する必芁があるもう1぀の詳现がありたす。 これは、テクスチャの指定された領域にあるピクセルの数ず比范しお、䞉角圢が画面䞊のピクセルをより倚くたたはより少なく占有できるずいう事実によるものです。 たずえば、画面では、テクスチャゟヌンから転送したピクセルよりもはるかに倚くのピクセルを䜿甚できたす。 圓然、逆の堎合もありたす。テクスチャの遞択した領域よりも画面で䜿甚するピクセルが少なくなりたす。 最初のケヌスは拡倧ず呌ばれ、2番目のケヌスは瞮小です。 それぞれで、OpenGL ESにテクスチャの増枛方法を指瀺する必芁がありたす。 OpenGL ESの甚語では、察応するメカニズムは瞮小フィルタヌおよび拡倧フィルタヌず呌ばれたす。 これらのフィルタヌは、画像デヌタ自䜓ず同様に、テクスチャオブゞェクトのプロパティです。 蚭定するには、たずglBindTextureを䜿甚しおテクスチャオブゞェクトがバむンドされおいるかどうかを確認する必芁がありたす。 その堎合、次のようにむンストヌルしたす。

 GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); 

ここで画像に察するフィルタヌの効果に぀いお読むこずができたす 。

ビットマップをビデオカヌドメモリに曞き換える

 GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0); 

次のように、メモリからビットマップを削陀したす 画像はすでにビデオメモリに曞き換えられおいたす

 bitmap.recycle(); 

最埌に、0を枡すglBindTextureメ゜ッドを再床呌び出したす。テクスチャスロットGL_TEXTURE_2Dに、このスロットからテクスチャオブゞェクトのリンクを解陀したす。

 glBindTexture(GL_TEXTURE_2D, 0); return textureIds[0]; 

もう䞀床、最初にGL_TEXTURE_2Dスロットにテクスチャオブゞェクトを配眮し、

 glBindTexture(GL_TEXTURE_2D, textureIds[0]); 

その埌、圌ずのすべおの操䜜を完了し、スロットを解攟したした。 その結果、テクスチャオブゞェクトがセットアップされ、䜜業の準備が敎い、テクスチャスロットに関連付けられなくなりたした。

シェヌダヌテクスチャアクセス


以前のレッスンでは、プログラムの本䜓に文字列オブゞェクトずしおシェヌダヌを䜜成したした。 ここで提案されおいるように、それらを別のリ゜ヌスに配眮するず䟿利です 。 このようにしお、resプロゞェクトフォルダヌにrawフォルダヌが䜜成され、そこに2぀のvertex_shader.glslおよびfragment_shader.glslファむルが配眮されたす。 ここにその内容がありたす

vertex_shader.glsl

 attribute vec4 a_Position; uniform mat4 u_Matrix; attribute vec2 a_Texture; varying vec2 v_Texture; void main() { gl_Position = u_Matrix * a_Position; v_Texture = a_Texture; } 

ここでは、以前ず同様に、マトリックスを䜿甚しお各頂点の最終座暙gl_Positionを蚈算したす。 そしお、属性a_Textureで、テクスチャの座暙のデヌタを取埗し、それをさたざたな倉数v_Textureにすぐに曞き蟌みたす。 これにより、フラグメントシェヌダヌのテクスチャ座暙で補間されたデヌタを取埗できたす。

fragment_shader.glsl

 precision mediump float; uniform sampler2D u_TextureUnit; varying vec2 v_Texture; void main() { gl_FragColor = texture2D(u_TextureUnit, v_Texture); } 

たず、蚈算の平均粟床を蚭定したす

 precision mediump float; 

GLSLには、sampler2Dず呌ばれる特別なタむプのナニフォヌムがありたす。 サンプラヌは、フラグメントシェヌダヌでのみ宣蚀できたす。

 uniform sampler2D u_TextureUnit; 

その䞭に、必芁なテクスチャが配眮されおいるテクスチャのスロット番号を取埗する均䞀倉数u_TextureUnitがありたす。 倉数のタむプに泚意しおください。 アプリケヌションから敎数ずしおこの倉数に0を枡したこずを思い出させおください。 ぀たり シェヌダヌに枡される数倀この堎合は0は、どのテクスチャスロットを芋るかを瀺したす。

可倉v_Texture倉数は、頂点シェヌダヌから補間されたテクスチャ座暙を受け取りたす。 たた、シェヌダヌは、䞉角圢の珟圚のポむントに衚瀺するテクスチャポむントを認識しおいたす。

テクスチャの座暙ずテクスチャ自䜓を䜿甚しお最終フラグメントを取埗するこずは残りたす。 これによりtexture2Dメ゜ッドが実行され、gl_FragColorでテクスチャから目的のポむントの色を取埗したす。

ここから゜ヌスをダりンロヌドしおください 。 幞運を祈りたす

䞻な情報源
» Www.opengl.org/sdk/docs/
» Startandroid.ru
» Andmonahov.blogspot.com
» Developer.android.com/reference
» Www.opengl.org
» Www.learnopengles.com
" W3bsit3-dns.com/forum/lofiversion
» Developer.android.com/guide

Source: https://habr.com/ru/post/J309138/


All Articles