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用だっていうのは僕と君だけの秘密だぞ。
0 件のコメント:
コメントを投稿