▼Androidメモ▼
テクスチャの部分表示


OpenGL ES 2.0でテクスチャを部分表示するプログラムを作成する。
HelloGL20_6.png

リソース

画像「sample.png」を「res/drawable-hdpi」に挿入。

sample.png
sample.png



ソースコード
GL20TextureEx2.java
package net.npaka.gl20textureex2;
import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;

//テクスチャの部分表示
public class GL20TextureEx2 extends Activity {
private GLSurfaceView glView;

//アクティビティ生成時に呼ばれる
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);

//GLサーフェイスビュー
glView=new GLSurfaceView(this);
glView.setEGLContextClientVersion(2);
glView.setRenderer(new GLRenderer(this));
setContentView(glView);
}

//アクティビティレジューム時に呼ばれる
@Override
public void onResume() {
super.onResume();
glView.onResume();
}

//アクティビティポーズ時に呼ばれる
@Override
public void onPause() {
super.onPause();
glView.onPause();
}
}

GLRenderer.java
package net.npaka.gl20textureex2;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;

//レンダラー
public class GLRenderer implements
GLSurfaceView.Renderer {
//システム
private Activity activity;//アクティビティ
private int screenW; //画面幅
private int screenH; //画面高さ

//バッファ
private FloatBuffer vertexBuffer0;//頂点バッファ0
private FloatBuffer vertexBuffer1;//頂点バッファ1
private FloatBuffer uvBuffer0; //UVバッファ0
private FloatBuffer uvBuffer1; //UVバッファ1

//テクスチャ
private int textureId;//テクスチャID

//コンストラクタ
public GLRenderer(Activity activity) {
this.activity=activity;
}

//サーフェイス生成時に呼ばれる
@Override
public void onSurfaceCreated(GL10 gl10,EGLConfig eglConfig) {
//プログラムの生成
GLES.makeProgram();

//頂点バッファの有効化
GLES20.glEnableVertexAttribArray(GLES.positionHandle);
GLES20.glEnableVertexAttribArray(GLES.uvHandle);

//テクスチャの有効化
GLES20.glEnable(GLES20.GL_TEXTURE_2D);

//テクスチャの生成
Bitmap bmp=BitmapFactory.decodeResource(
activity.getResources(),R.drawable.sample);
textureId=makeTexture(bmp);

//ブレンドの指定
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA,GLES20.GL_ONE_MINUS_SRC_ALPHA);

//UVバッファの生成
uvBuffer0=makeUVBuffer(256,256,0,0,128,128);
uvBuffer1=makeUVBuffer(256,256,0,128,128,128);
}

//画面サイズ変更時に呼ばれる
@Override
public void onSurfaceChanged(GL10 gl10,int w,int h) {
//画面の表示領域の指定
GLES20.glViewport(0,0,w,h);
screenW=w;
screenH=h;

//頂点バッファ生成
vertexBuffer0=makeVertexBuffer(50,50,200,200);
vertexBuffer1=makeVertexBuffer(50,300,300,300);
}

//毎フレーム描画時に呼ばれる
@Override
public void onDrawFrame(GL10 gl10) {
//画面のクリア
GLES20.glClearColor(1.0f,1.0f,1.0f,1.0f);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

//テクスチャの指定
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,textureId);
GLES20.glUniform1i(GLES.texHandle,0);

//上の四角形のUVバッファの指定
GLES20.glVertexAttribPointer(GLES.uvHandle,2,
GLES20.GL_FLOAT,false,0,uvBuffer0);

//上の四角形の描画
GLES20.glVertexAttribPointer(GLES.positionHandle,3,
GLES20.GL_FLOAT,false,0,vertexBuffer0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP,0,4);

//下の四角形のUVバッファの指定
GLES20.glVertexAttribPointer(GLES.uvHandle,2,
GLES20.GL_FLOAT,false,0,uvBuffer1);

//下の四角形の描画
GLES20.glVertexAttribPointer(GLES.positionHandle,3,
GLES20.GL_FLOAT,false,0,vertexBuffer1);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP,0,4);
}

//テクスチャの生成
private int makeTexture(Bitmap bmp) {
//テクスチャメモリの確保
int[] textureIds=new int[1];
GLES20.glGenTextures(1,textureIds,0);

//テクスチャへのビットマップ指定
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,textureIds[0]);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D,0,bmp,0);

//テクスチャフィルタの指定
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_NEAREST);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_NEAREST);
return textureIds[0];
}

//UVバッファの生成
private FloatBuffer makeUVBuffer(
int textureW,int textureH,int x,int y,int w,int h) {
//ウィンドウ座標を正規化デバイス座標に変換
float left =(float)x/(float)textureW;
float top =(float)y/(float)textureH;
float right =(float)(x+w)/(float)textureW;
float bottom=(float)(y+h)/(float)textureH;

//UVバッファの生成
float[] uvs={
left,top, //左上
left,bottom, //左下
right,top, //右上
right,bottom,//右下
};
return makeFloatBuffer(uvs);
}

//頂点バッファの生成
private FloatBuffer makeVertexBuffer(int x,int y,int w,int h) {
//ウィンドウ座標を正規化デバイス座標に変換
float left =((float)x/(float)screenW)*2.0f-1.0f;
float top =((float)y/(float)screenH)*2.0f-1.0f;
float right =((float)(x+w)/(float)screenW)*2.0f-1.0f;
float bottom=((float)(y+h)/(float)screenH)*2.0f-1.0f;
top =-top;
bottom=-bottom;

//頂点バッファの生成
float[] vertexs={
left, top, 0.0f,//頂点0
left, bottom,0.0f,//頂点1
right,top, 0.0f,//頂点2
right,bottom,0.0f,//頂点3
};
return makeFloatBuffer(vertexs);
}

//float配列をFloatBufferに変換
private FloatBuffer makeFloatBuffer(float[] array) {
FloatBuffer fb=ByteBuffer.allocateDirect(array.length*4).order(
ByteOrder.nativeOrder()).asFloatBuffer();
fb.put(array).position(0);
return fb;
}
}

GLES.java
package net.npaka.gl20textureex2;
import android.opengl.GLES20;

//シェーダ操作
public class GLES {
//頂点シェーダのコード
private final static String VERTEX_CODE=
"attribute vec4 a_Position;"+
"attribute vec2 a_UV;"+
"varying vec2 v_UV;"+
"void main(){"+
"gl_Position=a_Position;"+
"v_UV=a_UV;"+
"}";

//フラグメントシェーダのコード
private final static String FRAGMENT_CODE=
"precision mediump float;"+
"varying vec2 v_UV;" +
"uniform sampler2D u_Tex;"+
"void main(){"+
"gl_FragColor=texture2D(u_Tex,v_UV);"+
"}";

//システム
private static int program;//プログラムオブジェクト

//ハンドル
public static int positionHandle;//位置ハンドル
public static int uvHandle; //UVハンドル
public static int texHandle; //テクスチャハンドル

//プログラムの生成
public static void makeProgram() {
//シェーダーオブジェクトの生成
int vertexShader=loadShader(GLES20.GL_VERTEX_SHADER,VERTEX_CODE);
int fragmentShader=loadShader(GLES20.GL_FRAGMENT_SHADER,FRAGMENT_CODE);

//プログラムオブジェクトの生成
program=GLES20.glCreateProgram();
GLES20.glAttachShader(program,vertexShader);
GLES20.glAttachShader(program,fragmentShader);
GLES20.glLinkProgram(program);

//ハンドルの取得
positionHandle=GLES20.glGetAttribLocation(program,"a_Position");
uvHandle=GLES20.glGetAttribLocation(program,"a_UV");
texHandle=GLES20.glGetUniformLocation(program,"u_Tex");

//プログラムオブジェクトの利用開始
GLES20.glUseProgram(program);
}

//シェーダーオブジェクトの生成
private static int loadShader(int type,String shaderCode) {
int shader=GLES20.glCreateShader(type);
GLES20.glShaderSource(shader,shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
}

−戻る−