如何在Android中的Ortho投影上渲染纹理

时间:2011-04-14 19:24:06

标签: android opengl-es

问候。我过去涉及OpenGL,据我所知,使用基于精灵的动画进行2D游戏的最佳方法是消除z平面并设置正交投影,这样你就可以使用笛卡尔坐标进行纹理和绘图位置。

所以我一直在尝试在android中实现它。我只是在绘制函数中使用所有构建,但是使用vanilla drawbitmap函数分别渲染几百个图像会破坏我的帧速率。

屏幕右边会显示一个矩形,但纹理拒绝显示。如果你能看看,让我知道我在哪里错了,我真的很感激。警告我不要像我想的那样全面了解opengl。我尊重任何可以围绕这些东西的人。

这是使用绑定纹理绘制rect的精灵类:

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.allocateDirect(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);

}
}

这是渲染器...我通过srfaceview来保持这样我可以获得投影的高度和宽度

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);     
}
}

3 个答案:

答案 0 :(得分:0)

你试过吗

glActiveTexture(GL10.GL_TEXTURE0);

渲染精灵之前?

答案 1 :(得分:0)

以下是关于我的Galaxy S的,但是我无法使用投影让它在我朋友的HTC上工作。虽然他们确实在模特空间工作......你能试试吗?

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) {

    }

} 

答案 2 :(得分:0)

尝试将纹理环境设置为GL_REPLACE(使用glTexEnv)。如果设置为GL_MODULATE,纹理颜色将乘以当前颜色(或照明中的颜色,如果启用),如果此颜色为黑色,则结果为黑色。