Greetings. I've dabbled in OpenGL in the past and as far as I understood it the best way to do 2d games with sprite-based animation was eliminate the z plane and set up an orthographic projection so you can just use Cartesian coordinates for textures and drawing positions.
So I've been trying to implement this in android. I was just using all the build in draw functions but rendering a few hundred images separately with the vanilla drawbitmap functions was killing my framerate.
A rect shows up on the screen all right but the texture refuses to show. if you could take a look and let me know where I'm going wrong here I'd really appreciate it. Be warned I don;t have nearly as comprehensive understanding of opengl as I would like. I respect anyone that can wrap their heads around this stuff.
This is the sprite class which draws the rect with the bound texture:
public class Sprite {
private FloatBuffer vertexBuffer; // buffer holding the vertices
private FloatBuffer textureBuffer;
private int[] textures = new int[1];
private float vertices[] = {
0.0f, 0.0f,
0.0f, 32.0f,
32.0f, 0.0f,
32.0f, 32.0f
};
private float texture[] = {
0.0f, 0.0f,
0.0f, 16.0f,
16.0f, 0.0f,
16.0f, 16.0f
};
public Sprite() {
ByteBuffer byteBuffer = ByteBuffer.allocate开发者_StackOverflowDirect(vertices.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
vertexBuffer = byteBuffer.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
byteBuffer = ByteBuffer.allocateDirect(texture.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
textureBuffer = byteBuffer.asFloatBuffer();
textureBuffer.put(texture);
textureBuffer.position(0);
}
public void loadGLTexture(GL10 gl, Context context)
{
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),
R.drawable.charactersprites);
gl.glGenTextures(1, textures, 0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
//Not sure if I need these...
//gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
//gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
}
/** The draw method for the triangle with the GL context */
public void draw(GL10 gl) {
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
//gl.glFrontFace(GL10.GL_CW);//is this necessary?
// set the colour for the triangle
//gl.glColor4f(0.0f, 1.0f, 0.0f, 0.5f);
// Point to our vertex buffer
gl.glVertexPointer(2, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
// Draw the vertices as triangle strip
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 2);
//Disable the client state before leaving
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
}
}
And this is the renderer...i pass in the srfaceview to hold onto so i can get the height and width for the projection
public class GlRenderer implements Renderer {
private Sprite sprite;
private GLSurfaceView surfaceView;
private Context context;
/** Constructor to set the handed over context */
public GlRenderer(GLSurfaceView surfaceView, Context context) {
this.sprite = new Sprite();
this.surfaceView = surfaceView;
this.context = context;
}
@Override
public void onDrawFrame(GL10 gl) {
// clear Screen and Depth Buffer
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glMatrixMode(GL10.GL_PROJECTION);
// Reset the Modelview Matrix
gl.glLoadIdentity();
gl.glOrthof(0.0f, surfaceView.getWidth(), surfaceView.getHeight(), 0.0f, -1.0f, 1.0f);
sprite.draw(gl);
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
sprite.loadGLTexture(gl, this.context);
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glShadeModel(GL10.GL_SMOOTH);
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
gl.glClearDepthf(1.0f);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glDepthFunc(GL10.GL_LEQUAL);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
}
}
Have you tried
glActiveTexture(GL10.GL_TEXTURE0);
before rendering sprite?
Try setting the texture environment to GL_REPLACE
(using glTexEnv
). If it is set to GL_MODULATE
, the texture color will be multiplied by the current color (or the color from lighting, if enabled) and if this color is black, the result is just black.
Below works on my Galaxy S but I'm having trouble getting it to work on my friend's HTC using projective. Though they do work in model space... Could you try?
public void draw(GL10 gl) {
gl.glActiveTexture(GL10.GL_TEXTURE0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mCoordinateBuffer);
// Draw the mesh
gl.glFrontFace(GL10.GL_CCW);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer);
gl.glNormalPointer(GL10.GL_FLOAT, 0, mNormalBuffer);
gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, mIndexBuffer.limit(), GL10.GL_UNSIGNED_BYTE, mIndexBuffer);
// Disable texture
gl.glDisable(GL10.GL_TEXTURE_2D);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
}
public void loadTexture(Context context, GL10 gl) {
Bitmap bmp;
try {
bmp = BitmapFactory.decodeStream(context.getResources().openRawResource(R.drawable.texture_loading));
int[] textures = new int[1];
gl.glGenTextures(1, textures, 0);
mTextureID = textures[0];
gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
// Mendatory, tells openGL how to render the texture, nearest will look sharp, smooth will look blurry
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST);
// Not mendatory, tells openGL what to do when sprite is bigger than object
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
// Mendatory,
// GL_REPLACE replaces all color info,
// GL_MODULATE modulates, texture will be affected by lightning
gl.glTexEnvx(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_REPLACE);
bmp.recycle();
} catch (Error e) {
}
}
精彩评论