由于性能原因,我从canvas.drawBitmap移至OpenGL ES 2D

这是精灵表4x1:

 

现在要使其正常工作,我上了课:

public Vulcan(ScreenObjectsView objectsView, int vulkanSpriteID, Context context) {

    this.b = BitmapFactory.decodeResource(context.getResources(), vulkanSpriteID);

    // 1x4
    height = b.getHeight();
    width = b.getWidth()/4;

    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Display display = wm.getDefaultDisplay();
    x = display.getWidth()/2-width/2;  // deprecated
    y = display.getHeight()-height;  // deprecated

}

public void update() {
    frameFreq++;

    if(frameFreq > 0){
        currentFrame = ++currentFrame % 4;
        frameFreq = 0;
    }
}


@Override
public void draw(Canvas canvas) {
    update();

    int srcX = currentFrame * width;

    Rect  src = new Rect(srcX, 0, srcX+width, height);
    Rect  dst = new Rect(x, y, x+width, y+height);

    canvas.drawBitmap(b, src, dst, null);
}


我在每个时间段内使用Rect并从左向右移动(循环):

currentFrame = ++currentFrame % 4;


到目前为止,一切都很好。

如何在OpenGL ES中为上述精灵表制作动画?

今天,我知道如何在OpenGL ES中绘制和移动对象(感谢good demo

但不知道要玩精灵。

有任何想法,链接,代码段吗?

[编辑]

使用精灵表或4张图像(例如)不再重要:

  , 等等。

仍然没有任何答案或方向的奇怪。

谢谢,

[编辑2]

根据Aert所说,我实现了以下代码,并且可以正常工作。

但是看起来很乱

OpenGL ES的代码过多。对于每个纹理(我有4个),我需要创建FloatBuffer:

也许有人用较短的方法,或者我做错了。

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.opengles.GL10;

public class DevQuestSpriteBase {

private static final String LOG_TAG = "Fess";//DevQuestSpriteBase.class.getSimpleName();

protected int mFrame = 0;
protected int mSwitcher = 0;
private int textureCount = 1; // frame animation
protected int[] textures = new int[textureCount]; // frame animation

// texture and verts
protected FloatBuffer vertexBuffer,
textureBuffer1,
textureBuffer2,
textureBuffer3,
textureBuffer4;

ByteBuffer bb1;

protected float vertices[] = {
        0f,0f,0.0f,
        1f,0f,0.0f,
        0f,1f,0.0f,
        1f,1f,0.0f
};


/** 1 frame */
protected float texture1[] = {
        0.0f, 1.0f,
        0.0f, 0.0f,
        0.25f, 1.0f,
        0.25f, 0.0f
};
/** 2 frame */
protected float texture2[] = {

        0.25f, 1.0f,
        0.25f, 0.0f,
        0.5f, 1.0f,
        0.5f, 0.0f
};
/** 3 frame */
protected float texture3[] = {
        0.5f, 1.0f,
        0.5f, 0.0f,
        0.75f, 1.0f,
        0.75f, 0.0f
};
/** 4 frame */
protected float texture4[] = {
        0.75f, 1.0f,
        0.75f, 0.0f,
        1.0f, 1.0f,
        1.0f, 0.0f
};


public DevQuestSpriteBase(){
    // vertices buffer
    bb1 = ByteBuffer.allocateDirect(vertices.length * 4);
    bb1.order(ByteOrder.nativeOrder());
    vertexBuffer = bb1.asFloatBuffer();
    vertexBuffer.put(vertices);
    vertexBuffer.position(0);

    // texture buffer
    bb1 = ByteBuffer.allocateDirect(texture1.length * 4);
    bb1.order(ByteOrder.nativeOrder());
    textureBuffer1 = bb1.asFloatBuffer();
    textureBuffer1.put(texture1);
    textureBuffer1.position(0);

    //#########################################################

    // texture buffer
    bb1 = ByteBuffer.allocateDirect(texture2.length * 4);
    bb1.order(ByteOrder.nativeOrder());
    textureBuffer2 = bb1.asFloatBuffer();
    textureBuffer2.put(texture2);
    textureBuffer2.position(0);

    //#########################################################

    // texture buffer
    bb1 = ByteBuffer.allocateDirect(texture3.length * 4);
    bb1.order(ByteOrder.nativeOrder());
    textureBuffer3 = bb1.asFloatBuffer();
    textureBuffer3.put(texture3);
    textureBuffer3.position(0);

    //#########################################################

    // texture buffer
    bb1 = ByteBuffer.allocateDirect(texture4.length * 4);
    bb1.order(ByteOrder.nativeOrder());
    textureBuffer4 = bb1.asFloatBuffer();
    textureBuffer4.put(texture4);
    textureBuffer4.position(0);
}


private void update() {

    if(mSwitcher == 5){
        mFrame = ++mFrame % 4;
        mSwitcher = 0;
        // Log.e(LOG_TAG, "DevQuestSpriteBase :: " + mFrame);
    }
    else{
        mSwitcher++;
    }


}

public void draw(GL10 gl){

    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);


    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);

    if(mFrame == 0){
        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer1);
    }
    else  if(mFrame == 1){
        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer2);
    }
    else  if(mFrame == 2){
        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer3);
    }
    else  if(mFrame == 3){
        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer4);
    }


    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);

    //Log.e(LOG_TAG, "DevQuestSpriteBase :: draw");

    update();

    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
    //gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer1);
    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
}


public int[] getTextures() {
    return textures;
}
}

最佳答案

无需赘述,您需要执行以下操作(假设您已经使用4个顶点绘制了一个精灵):


为每个动画帧定义与精灵顶点对应的纹理坐标,例如

texCoordsFrame1 = [0.0f, 0.0f, 0.25f, 0.0f, 0.0f, 1.0f, 0.25f, 1.0f];

上载Spritesheet纹理,例如

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);

使用与您要在需要时显示的框架相对应的纹理坐标进行绘制,例如

...
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexCoordPointer(2, GL_FLOAT, 0, texCoordsFrame1);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);



或者,您可以将单独的帧作为单独的纹理上载,但是从性能的角度来看,这是不希望的。

有一些陷阱


使用GLES1时,只能使用2幂的纹理。在这种情况下,您必须缩放纹理或将其大小增大为2的幂并调整纹理坐标。
位图与GL y坐标方向的差异有点令人困惑,您可能最终会得到一个垂直翻转的精灵。

07-28 01:12
查看更多