VBOとTextureをワンセットにすることで、DirectXで言うサブセットみたいな処理ができるので、Textureクラスも当然必要です(テクスチャの切り替えを最小限にするため)
- package com.dividebyzero.KszGameBase;
- import java.util.HashMap;
- import javax.microedition.khronos.opengles.GL10;
- import javax.microedition.khronos.opengles.GL11;
- import android.content.Context;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.opengl.GLUtils;
- import android.util.Log;
- /**
- * テクスチャクラス
- * @author ksz
- *
- */
- public class Texture {
- public int resID, texID, w, h;
- private static final RenderParam param = new RenderParam();
- /**
- * @param resID リソースID
- * @param texID OpenGLでのテクスチャID
- * @param w 横幅
- * @param h 縦幅
- */
- public Texture(int resID, int texID, int w, int h) {
- this.resID = resID;
- this.texID = texID;
- this.w = w;
- this.h = h;
- }
- /**
- * staticのrenderを呼びやすくしただけ
- */
- public void render(float x,float y){
- render(this,x,y,0,param.init());
- }
- /**
- * staticのrenderを呼びやすくしただけ
- */
- public void render(float x, float y, RenderParam param) {
- render(this, x, y, 0, param);
- }
- /**
- * staticのrenderを呼びやすくしただけ
- */
- public void render(float x, float y, float z, RenderParam param) {
- render(this, x, y, z, param);
- }
- /**
- * staticのポリラインを呼びやすくしただけ
- */
- public void renderPolyLine(float sx, float sy, float ex, float ey, RenderParam param) {
- renderPolyLine(this, sx, sy, ex, ey, param);
- }
- /**
- * テクスチャのバインド
- */
- public void bind() {
- setTexture(texID);
- }
- //////////////////ここから管理ゾーン
- public static HashMap<Integer, Texture> texMap = new HashMap<:Integer, Texture>();
- /**
- * リソースIDではなく、文字列からテクスチャインスタンスを作成
- * @param resName 読み込みたい文字列 "***.png"のようにしても、拡張子部分は捨てられる
- * @return 作成されたテクスチャインスタンス
- */
- public static Texture get(String resName) {
- Context context = Global.view.getContext();
- int point = resName.lastIndexOf(".");
- if (point != -1) {
- resName = resName.substring(0, point);
- }
- Log.v("debug", resName);
- int id = context.getResources().getIdentifier(resName, "drawable", context.getPackageName());
- return get(id);
- }
- /**
- * リソースIDからテクスチャインスタンスを作成
- * @param resID 読み込みたいリソース
- * @return 作成されたテクスチャインスタンス。既に読み込まれている場合はそのインスタンス
- */
- public static Texture get(int resID) {
- if (texMap.containsKey(resID)) {
- return texMap.get(resID);
- }
- GL10 gl = Global.gl;
- //リソースBMPを読み込む
- BitmapFactory.Options opt = new BitmapFactory.Options();
- opt.inScaled = false; //勝手に拡大縮小するので止める
- Bitmap bitmap = BitmapFactory.decodeResource(Global.view.getResources(), resID, opt);
- //グラボのテクスチャとして登録
- int[] texID = new int[1]; //グラボからテクスチャIDを受け取るための変数
- gl.glGenTextures(1, texID, 0); //グラボから使ってないテクスチャIDを取得
- Texture.setTexture(texID[0]);
- //BMPをテクスチャに割り当てる
- GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
- //テクスチャパラメータをセット
- gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, //拡大の時は
- GL10.GL_LINEAR); //線形補間
- gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, //縮小の時は
- GL10.GL_LINEAR); //線形補間
- gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, //UVがはみ出したときどうしますか
- GL10.GL_CLAMP_TO_EDGE); //端っこで止める
- gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, //UVがはみ出したときどうしますか
- GL10.GL_CLAMP_TO_EDGE); //端っこで止める
- Texture tex = new Texture(resID, texID[0], bitmap.getWidth(), bitmap.getHeight());
- bitmap.recycle();
- texMap.put(resID, tex);
- return tex;
- }
- private static Vbo vbo = null;
- private static int currentTexID = -1;
- /**
- * テクスチャをOpenGLにセット
- * 同じテクスチャが連続でセットされないようにしている
- * @param id セットしたいテクスチャ
- */
- public static void setTexture(int id) {
- if (currentTexID != id) {
- currentTexID = id;
- Global.gl.glBindTexture(GL10.GL_TEXTURE_2D, id);
- }
- }
- /**
- * 指定されたテクスチャを描画 z軸が無いVer
- * @param tex 描画したいテクスチャ
- * @param x 座標x
- * @param y 座標y
- * @param param 描画パラメータ
- */
- public static void render(Texture tex, float x, float y, RenderParam param) {
- render(tex, x, y, 0, param);
- }
- /**
- * 指定されたテクスチャを描画
- * @param tex 描画したいテクスチャ
- * @param x 座標x
- * @param y 座標y
- * @param z 座標z 2Dゲームの場合は0で
- * @param param 描画パラメータ
- */
- public static void render(Texture tex, float x, float y, float z, RenderParam param) {
- if (vbo == null) {
- //頂点4つ分用意
- float v[] = {
- //頂点
- 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0,
- };
- float t[] = {
- //UV
- 0, 0, 0, 1, 1, 0, 1, 1,
- };
- vbo = new Vbo();
- vbo.makeBuffer(v, t);
- }
- vbo.bindVBO();
- GL11 gl = Global.gl;
- setTexture(tex.texID);
- gl.glColor4f(param.r, param.g, param.b, param.a);
- if (param.cw + param.ch < 0) {
- param.cw = (float) tex.w;
- param.ch = (float) tex.h;
- }
- if (param.isCenterOrigin) {
- if (param.isDestsize) {
- param.ox = param.dw / 2;
- param.oy = param.dh / 2;
- } else {
- param.ox = param.cw * Math.abs(param.sx) / 2;
- param.oy = param.ch * Math.abs(param.sy) / 2;
- }
- }
- if (RenderParam.oldAddAlphaMode != param.isAddAlpha) {
- if (param.isAddAlpha) {
- gl.glDisable(GL10.GL_DEPTH_TEST);
- gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE);
- } else {
- gl.glEnable(GL10.GL_DEPTH_TEST);
- gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
- }
- }
- RenderParam.oldAddAlphaMode = param.isAddAlpha;
- gl.glMatrixMode(GL10.GL_TEXTURE);
- gl.glLoadIdentity();
- gl.glTranslatef(param.cx + param.cw / tex.w * param.xindex, param.cy + param.ch / tex.h * param.yindex, 0);
- gl.glScalef(param.cw / tex.w, param.ch / tex.h, 1);
- gl.glMatrixMode(GL10.GL_MODELVIEW);
- gl.glPushMatrix(); //カメラ行列を退避
- //移動させつつ、原点指定しつつ
- if (param.isDestsize) {
- gl.glTranslatef(0.5f * param.dw - param.ox + x, 0.5f * param.dh - param.oy + y, z);
- } else {
- gl.glTranslatef(0.5f * param.cw * Math.abs(param.sx) - param.ox + x, 0.5f * param.ch * Math.abs(param.sy)
- - param.oy + y, z);
- }
- gl.glRotatef(param.ax, 0, 0, 1); //回転(なぜかラジアンじゃない)
- if (param.isDestsize) {
- gl.glScalef(param.dw, param.dh, 1); //拡大縮小
- } else {
- gl.glScalef(param.sx * param.cw, param.sy * param.ch, 1); //拡大縮小
- }
- gl.glTranslatef(-0.5f, -0.5f, 0); //中心を原点に回転するための小細工
- gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); //横1縦1の頂点描画
- gl.glPopMatrix(); //カメラ行列を戻す
- }
- /**
- * ポリライン(テクスチャを線のように描画)
- * @param tex 描画したいテクスチャ
- * @param sx 始点x
- * @param sy 始点y
- * @param ex 終点x
- * @param ey 終点y
- * @param param パラメータ、幅など
- */
- void renderPolyLine(Texture tex, float sx, float sy, float ex, float ey, RenderParam param) {
- Vec3 tang = new Vec3(ex - sx, ey - sy, 0);
- float angle = (float) Math.atan2(tang.y, tang.x) * Util.TOANGLE;
- param.setDestSize(Math.abs(tang.getLength()), Math.abs(param.sx)).setAngle(angle);
- param.setCenterOrigin(true);
- render(tex, sx + tang.x / 2, sy + tang.y / 2, param);
- }
- /**
- * 指定されたリソースを描画
- * 指定されたリソースがまだ読み込まれていない場合は読み込まれる
- * @param resID R.drawable.iconなど、リソースのIDを直指定
- * @param x 描画位置x
- * @param y 描画位置y
- * @param param RenderParamのインスタンスによって描画パラメータを操作
- */
- public static void render(int resID, int x, int y, RenderParam param) {
- render(get(resID), x, y, param);
- }
- /**
- * 管理されているテクスチャを全て開放
- */
- public static void release() {
- int textureID[] = new int[1];
- for(Texture tex:texMap.values()){
- textureID[0] = tex.texID;
- Global.gl.glDeleteTextures(1, textureID, 0);
- }
- texMap.clear();
- texMap = null;
- }
- /**
- * 画面クリア処理
- * Textureクラスに入れるのが適当がどうかは微妙なところ
- * 深度を有効化しないと、深度バッファのクリアがうまくいかない場合があるようなので、毎回入れてます。 負荷だけど。
- */
- public static void clear() {
- Global.gl.glEnable(GL10.GL_DEPTH_TEST);
- Global.gl.glDepthMask(true); // 深度バッファ書き込み有効
- Global.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
- }
- /**
- * 画面をクリアします
- * @param r 赤(0.0f~1.0f)
- * @param g 緑(0.0f~1.0f)
- * @param b 青(0.0f~1.0f)
- * @param a アルファ値(0.0f~1.0f)
- */
- public static void clear(float r,float g,float b,float a) {
- Global.gl.glClearColor(r,g,b,a);
- clear();
- }
- /**
- * 画面をクリアします
- * @param r 赤(0~255)
- * @param g 緑(0~255)
- * @param b 青(0~255)
- * @param a アルファ値(0~255)
- */
- public static void clear(int r,int g,int b,int a) {
- Global.gl.glClearColor(r/255.0f,g/255.0f,b/255.0f, a / 255.0f);
- clear();
- }
- }
しかし、ソースのほとんどが2D用だっていうのは僕と君だけの秘密だぞ。