qiitaにおいて、一連のOpenGL ES2.0の知見をまとめましたので、もしよかったらそちらもご覧ください
前回、画像を使ってみて、多分同じ書き方で増やしていけば画像の方をいくつも用意はできるのですが、一部よりCPUの効率がよい方法がありましたので、それで対応してみます。
OpenGL1.0でも行って描画の直前に該当の画像のテクスチャをバインドしていました
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture[0]);
で、これが、実は重い動作のようでした。画像へのアクセスを作るというよりも、画像を作業場に持ち出すみたいな感じ。
GLES20.glGenTextures(1, texture, 0); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture[0]);
こうやって設定をしていたtextureの中のidを使っていたのですが。
ここで、参照用に
GLES20.glGenTextures(1,texture,0); GLES20.glActiveTexture(GLES20.GL_TEXTURE2); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture[0]);
みたいにします。glActiveTextureでGLES20.GL_TEXTUREっていうのが、存在していて、これが該当の番号でGLES20.GL_TEXTURE0からGLES20.GL_TEXTURE31まで用意されていて、それぞれに該当するテクスチャを登録する事ができます。
もっとたくさんテクスチャを用意したい場合には、よくわからないですが、メモリ圧迫をしてしまうので、シーンで分けるとかしたりスプライトシートにしてひとつの画像にいくつかの画像をまとめるのがよいかと思います
でDrawをする前に
// 描画に利用をする画像のデータをする int textureuniform = GLES20.glGetUniformLocation (shaderProgram, "s_texture" ); GLES20.glUniform1i(textureuniform,2);
みたいにする事で、2番目のテクスチャ持ってくるよ!ってしてくれます。で、このUniformLocationっていうのが、簡単にいうと、shaderの中に記載していた、s_textureの値を変更しますよーっていう関数です。
これは、参照だけなので、Bindよりも高速なようですが、速度は計測してないので、どうかはわかりませんが、おそらくこちらの方がスタンダードな方法のようです。
前回のSpriteを複製したクラスを作って、表示位置を変更するクラスを作って重ねたところ問題なく動作しました
public class Sprite2 { //画面の方の座標 zも含む private float vertices[] = { 0.0f, 0.0f,0.0f, 0.0f, -1.0f,0.0f, -1.0f, 0.0f,0.0f, -1.0f, -1.0f,0.0f }; //画像の方の座標 public static float uvs[] = new float[] { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f }; public FloatBuffer vertexBuffer; public ShortBuffer drawListBuffer; public FloatBuffer uvBuffer; //最もシンプルなシェーダー public final String vertexShaderCode = "attribute vec4 vPosition;" + "attribute vec2 a_texCoord;" + "varying vec2 v_texCoord;" + "void main() {" + " gl_Position = vPosition;" + " v_texCoord = a_texCoord;" + "}"; public final String fragmentShaderCode = "precision mediump float;" + "varying vec2 v_texCoord;" + "uniform sampler2D s_texture;" + "void main() {" + " gl_FragColor = texture2D( s_texture, v_texCoord );" + "}"; public static int loadShader(int type, String shaderCode){ int shader = GLES20.glCreateShader(type); GLES20.glShaderSource(shader, shaderCode); GLES20.glCompileShader(shader); return shader; } int shaderProgram; Context ctx; public Sprite2(Context _ctx){ ctx = _ctx; setupImage(); //頂点座標をバッファーに変換 ByteBuffer bb = ByteBuffer.allocateDirect(vertices.length * 4); bb.order(ByteOrder.nativeOrder()); vertexBuffer = bb.asFloatBuffer(); vertexBuffer.put(vertices); vertexBuffer.position(0); //ここからシェーダーを使うっていう、定形 int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode); int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode); shaderProgram = GLES20.glCreateProgram(); GLES20.glAttachShader(shaderProgram, vertexShader); GLES20.glAttachShader(shaderProgram, fragmentShader); GLES20.glLinkProgram(shaderProgram); } int[] texture; private void setupImage(){ //画像側の頂点座標をバッファーに変換 ByteBuffer bb = ByteBuffer.allocateDirect(uvs.length * 4); bb.order(ByteOrder.nativeOrder()); uvBuffer = bb.asFloatBuffer(); uvBuffer.put(uvs); uvBuffer.position(0); texture = new int[1]; Bitmap bitmap = Util.loadBitmapFromAsset(ctx,"256_2.png"); // Bind texture to texturename GLES20.glGenTextures(1,texture,0); GLES20.glActiveTexture(GLES20.GL_TEXTURE2); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture[0]); // 拡大縮小の時のフィルターの設定 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); // ちょっとわからないけど何かの設定 GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,GLES20.GL_CLAMP_TO_EDGE); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,GLES20.GL_CLAMP_TO_EDGE); // 画像をテクスチャに登録 GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0); bitmap.recycle(); Log.e("CHECLK", "ID:" + texture[0]); Log.e("CHECLK", "GLES20.GL_TEXTURE2:" + GLES20.GL_TEXTURE2); } public void draw(){ GLES20.glUseProgram(shaderProgram); // シェーダーの準備(図形側) int mPositionHandle = GLES20.glGetAttribLocation(shaderProgram, "vPosition"); // シェーダー:ON GLES20.glEnableVertexAttribArray(mPositionHandle); //シェーダーの準備(テクスチャ側) int mTexCoordLoc = GLES20.glGetAttribLocation(shaderProgram,"a_texCoord" ); // シェーダー:ON GLES20.glEnableVertexAttribArray(mTexCoordLoc ); //////////////////////////////////START //vertexBufferをデータ列から頂点データという解釈に変換 GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer); //uvBufferをデータ列から頂点データという解釈に変換 GLES20.glVertexAttribPointer(mTexCoordLoc, 2, GLES20.GL_FLOAT, false, 0, uvBuffer); // 描画に利用をする画像のデータをする int textureuniform = GLES20.glGetUniformLocation (shaderProgram, "s_texture" ); GLES20.glUniform1i(textureuniform,2); // 描画に利用をする画像のデータをする //GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture[0]); // 描画する。何で描くのかは、「関数内で登録してある」という暗黙の了解的な。 GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); //////////////////////////////////END // シェーダー:OFF GLES20.glDisableVertexAttribArray(mPositionHandle); GLES20.glDisableVertexAttribArray(mTexCoordLoc); } }