シューティングゲームなんかでよく見るグネグネ曲がったホーミングレーザー
これを実際に作ろうとすると、中々に負荷がかかるです。
普通のテクスチャと違って頂点が固定化できないのでAndroidでは無理かなーと思ってたんだけどもとりあえずやってみた。
- private static final int VMAX = 128;
- private static float v[] = new float[VMAX * 4];
- private static float t[] = new float[VMAX * 4];
-
- public static void renderPolyLine(Texture tex, Vector<vec2> vlist, RenderParam param) {
- if (tex.isEnable == false) return;
-
- GL11 gl = Global.gl;
-
- int vCnt = vlist.size();
- if (vCnt <= 1) return;
- if (vCnt > VMAX) return;
-
- final float w = param.sx / 2;
- tex.bind();
- gl.glColor4f(param.r, param.g, param.b, param.a);
- param.setAlpha();
-
- float uv = 1.0f;
- Vec2 prevPos, pos, nextPos;
- float vx, vy, len;
-
- for (int i = 0; i < vCnt; i++) {
- prevPos = vlist.get(Math.max(0, i - 1));
- pos = vlist.get(i);
- nextPos = vlist.get(Math.min(vCnt - 1, i + 1));
-
- vx = prevPos.x - nextPos.x;
- vy = prevPos.y - nextPos.y;
- len = (float) Math.sqrt(vx * vx + vy * vy);
- if(len == 0.0f)len = 1;
- vx *= w / len;
- vy *= w / len;
-
-
- v[i * 4] = pos.x + vy;
- v[i * 4 + 1] = pos.y - vx;
- v[i * 4 + 2] = pos.x - vy;
- v[i * 4 + 3] = pos.y + vx;
-
-
- t[i * 4] = 0;
- t[i * 4 + 1] = uv;
- t[i * 4 + 2] = 1;
- t[i * 4 + 3] = uv;
-
- uv -= 1.0f / vCnt;
- }
-
- gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, 0);
- gl.glTexCoordPointer(2, GL11.GL_FLOAT, 0, Util.makeFloatBufferArchive(t));
- gl.glVertexPointer(2, GL11.GL_FLOAT, 0, Util.makeFloatBufferArchive(v));
-
- gl.glDrawArrays(GL11.GL_TRIANGLE_STRIP, 0, vCnt*2);
-
- Vbo.repair();
- }
- </vec2>
private static final int VMAX = 128;
private static float v[] = new float[VMAX * 4];
private static float t[] = new float[VMAX * 4];
public static void renderPolyLine(Texture tex, Vector vlist, RenderParam param) {
if (tex.isEnable == false) return;
GL11 gl = Global.gl;
int vCnt = vlist.size();
if (vCnt <= 1) return;
if (vCnt > VMAX) return;
final float w = param.sx / 2;
tex.bind();
gl.glColor4f(param.r, param.g, param.b, param.a);
param.setAlpha();
float uv = 1.0f;
Vec2 prevPos, pos, nextPos;
float vx, vy, len;
for (int i = 0; i < vCnt; i++) {
prevPos = vlist.get(Math.max(0, i - 1));
pos = vlist.get(i);
nextPos = vlist.get(Math.min(vCnt - 1, i + 1));
//一つ手前と、一つ先のベクトルから、向いている方向を得る
vx = prevPos.x - nextPos.x;
vy = prevPos.y - nextPos.y;
len = (float) Math.sqrt(vx * vx + vy * vy);
if(len == 0.0f)len = 1;
vx *= w / len;
vy *= w / len;
//指定した横幅に広げる
v[i * 4] = pos.x + vy;
v[i * 4 + 1] = pos.y - vx;
v[i * 4 + 2] = pos.x - vy;
v[i * 4 + 3] = pos.y + vx;
//テクスチャもセットする
t[i * 4] = 0;
t[i * 4 + 1] = uv;
t[i * 4 + 2] = 1;
t[i * 4 + 3] = uv;
uv -= 1.0f / vCnt;
}
gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, 0);
gl.glTexCoordPointer(2, GL11.GL_FLOAT, 0, Util.makeFloatBufferArchive(t));
gl.glVertexPointer(2, GL11.GL_FLOAT, 0, Util.makeFloatBufferArchive(v));
gl.glDrawArrays(GL11.GL_TRIANGLE_STRIP, 0, vCnt*2);
Vbo.repair();
}
ソースはこんな感じ。
どこかで見かけたソースなんだけど、描画しようとしているある点の一つ前と1つ後から進行方向を求めて、直行ベクトル(と、その反対)に幅を広げてあげている頂点をセットする感じ。 3Dだと外積だけど、2Dなおでxとyを入れ替えるだけ。
で、UVをちょっとずつずらす(綺麗に0~1に収まるようにする)。
テストでホーミングレーザーをした図
予想通り激重いけど、馬鹿みたいにばらまかなければ使えるかな。
でも、ホーミングレーザーって馬鹿みたいにばら撒くから綺麗なのに。 だめじゃな。
ちなみに、レーザー画像を
にすればこんな感じでファンシー(?)になるのがステキング。