2D game: Canvas to OpenGL

Problems with Canvas, OpenGL, etc...

2D game: Canvas to OpenGL

Postby Wing Eraser » Fri Feb 04, 2011 6:17 pm

I've ported a 2D game engine from Flash to Android. At the moment the engine use Canvas. The performance are ok, even with 200-300 particles on screen (depending on device).

Now I want to replace Canvas with OpenGL ES. I've looked at examples from SpriteMethodTest. Somehow it didn't work. I started with a simple clean code. I can draw a square and use the camera.

The only things I need now, exact behaviour with OpenGL as Canvas. So an 10x10px square on (0,0) must be the same in OpenGL as Canvas.

I've here some code:

OpenGLActivity
Code: Select all
package org.opengl;

import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;

public class OpenGLActivity extends Activity
{
   private GLSurfaceView view;
   
   @Override
   protected void onCreate(Bundle savedInstanceState)
   {      
      super.onCreate(savedInstanceState);
      
      // Remove the title bar from the window.
      this.requestWindowFeature(Window.FEATURE_NO_TITLE);

      // Make the windows into full screen mode.
      getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
      
      view = new GLSurfaceView(this);
      view.setRenderer(new OpenGLRenderer());
      setContentView(view);
   }
   
   @Override
   protected void onResume()
   {
      super.onResume();
      view.onResume();
   }
   
   @Override
   protected void onPause()
   {
      super.onPause();
      view.onPause();
   }
}



Square
Code: Select all
package org.opengl;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

import javax.microedition.khronos.opengles.GL10;

public class Square
{
   private float[] vertices =    {
                           -1.0f,   1.0f, 0, // 0, Top left
                           -1.0f, -1.0f, 0, // 1, Bottom left
                            1.0f, -1.0f, 0, // 2, Bottom right
                            1.0f,  1.0f, 0
                        };
   
   private short[] indices = {0, 1, 2, 0, 2, 3};
   
   private FloatBuffer vertexBuffer;
   
   private ShortBuffer indexBuffer;
   
   public Square()
   {
      ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
      vbb.order(ByteOrder.nativeOrder());
      vertexBuffer = vbb.asFloatBuffer();
      vertexBuffer.put(vertices);
      vertexBuffer.position(0);
      
      ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2);
      ibb.order(ByteOrder.nativeOrder());
      indexBuffer = ibb.asShortBuffer();
      indexBuffer.put(indices);
      indexBuffer.position(0);
   }
   
   public void draw(GL10 gl)
   {
      gl.glFrontFace(GL10.GL_CCW);
      gl.glEnable(GL10.GL_CULL_FACE);
      gl.glCullFace(GL10.GL_BACK);
      
      gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
      gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
      
      gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_SHORT, indexBuffer);
      
      gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
      gl.glDisable(GL10.GL_CULL_FACE);
   }   
}



OpenGLRenderer
Code: Select all
package org.opengl;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.opengl.GLU;
import android.opengl.GLSurfaceView.Renderer;
import android.util.Log;

public class OpenGLRenderer implements Renderer
{
   private Square square;
   private int mViewWidth;
   private int mViewHeight;

   public OpenGLRenderer()
   {
      square = new Square();
   }

   @Override
   public void onSurfaceCreated(GL10 gl, EGLConfig config)
   {
      gl.glClearColor(0.5f, 0.0f, 0.0f, .5f);
       gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
       gl.glShadeModel(GL10.GL_FLAT);
       gl.glDisable(GL10.GL_DEPTH_TEST);
       gl.glEnable(GL10.GL_BLEND);
       gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);

       gl.glViewport(0, 0, mViewWidth,  mViewHeight);
       gl.glMatrixMode(GL10.GL_PROJECTION);
       gl.glLoadIdentity();
       gl.glEnable(GL10.GL_BLEND);
       gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
       gl.glShadeModel(GL10.GL_FLAT);
       gl.glEnable(GL10.GL_TEXTURE_2D);

       GLU.gluOrtho2D(gl, 0, mViewWidth, mViewHeight, 0);

   }
   
   @Override
   public void onDrawFrame(GL10 gl)
   {
      gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
      
      gl.glLoadIdentity();
      square.draw(gl);
   }

   
   @Override
   public void onSurfaceChanged(GL10 gl, int width, int height)
   {
      mViewWidth = width;
       mViewHeight = height;

       gl.glViewport(0, 0, mViewWidth,  mViewHeight);
       gl.glMatrixMode(GL10.GL_PROJECTION);
       gl.glLoadIdentity();
       GLU.gluOrtho2D(gl, 0, mViewWidth, mViewHeight, 0);
//       gl.glOrthof(0.0f, mViewWidth, 0.0f, mViewHeight, -1.0f, 1.0f);
   }
}





The code is very simple. Draw a white 1x1px square on 0,0. What I get is an full size square on the screen. Using glFrustum I can adjust the distance of the camera, but I don't need that function. The engine is purely for creating 2D games. So I've to use ortho.

Can someone please help me creating a working example?
Wing Eraser
Freshman
Freshman
 
Posts: 3
Joined: Sat Jan 15, 2011 2:54 pm

Top

Re: 2D game: Canvas to OpenGL

Postby omgnoseat » Sat Aug 06, 2011 2:24 am

I have the exact same problem.
I'm a big noob when it comes to opengl, I don't mind if I don't understand now. I just want to display sprites at their true sizes so I can get started. I will pick up on opengl on the way :)
I'm also creating a 2d game so I'd like not having to rely on 3d camera zooming to get the correct scale.

Image
The small left image is the size it is supposted to be (64x64). But the image on the right is how it shows up on my 800x480 android screen. The colour also doesn't seem right, but that might be because of the upscaling.

Here is the source code (sorry alot of bullshit in there, have been experimenting and writing notes)

GlRenderer
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. /**
  2.  *
  3.  */
  4. package net.obviam.opengl;
  5.  
  6. import javax.microedition.khronos.egl.EGLConfig;
  7. import javax.microedition.khronos.opengles.GL10;
  8.  
  9. import android.R.integer;
  10. import android.app.Activity;
  11. import android.app.AlertDialog;
  12. import android.content.Context;
  13. import android.opengl.GLSurfaceView.Renderer;
  14. import android.opengl.GLU;
  15. import android.view.Display;
  16.  
  17. /**
  18.  * @author impaler
  19.  *
  20.  */
  21. public class GlRenderer implements Renderer {
  22.  
  23.         private Square          square;         // the square
  24.         private Renderable      pig;
  25.         private Context         context;
  26.         private Activity        activity;
  27.        
  28.         private int viewX = 0;
  29.         private int viewY = 0;
  30.         private int viewWidth;
  31.         private int viewHeight;
  32.        
  33.         /** Constructor to set the handed over context */
  34.         public GlRenderer(Activity context) { //should be passing Context
  35.                 this.context = context;
  36.                 this.activity = activity;
  37.                
  38.                 // initialise the square
  39.                 this.square = new Square();
  40.                 this.pig = new Renderable();
  41.         }
  42.  
  43.         @Override
  44.         public void onDrawFrame(GL10 gl) {
  45.                 // clear Screen and Depth Buffer
  46.                 gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
  47.  
  48.                 // Reset the Modelview Matrix -
  49.                 //matrix = described translations and rotations of object
  50.                 gl.glLoadIdentity(); //resetting stuff, keeps camera at -5
  51.                
  52.                 // Drawing - location x y z
  53.                 //gl.glTranslatef(0, 0.0f, -0.0f);              // move z units INTO the screen is the same as moving the camera 5 units away
  54.                                                                                                
  55.                 //gl.glScalef(0.5f, 0.5f, 0.5f);                        // scale the square to 50%
  56.                                                                                                 // otherwise it will be too large
  57.                 pig.draw(gl);                                                   //don't forget to load the image!
  58.                
  59.                
  60.                 //trying to move the camera...
  61.                 //Display display = activity.getWindowManager().getDefaultDisplay(); //throws an error
  62.                 //int width = display.getWidth();
  63.                 //int height = display.getHeight();
  64.                
  65.                 gl.glViewport(viewX, viewY,viewWidth, viewHeight);  //x, y, width, height acts alot like vcam
  66.                 //viewX += 1;
  67.  
  68.         }
  69.  
  70.         @Override
  71.         public void onSurfaceChanged(GL10 gl, int width, int height) {
  72.                 if(height == 0) {                                               //Prevent A Divide By Zero By
  73.                         height = 1;                                             //Making Height Equal One
  74.                 }
  75.                
  76.                 viewWidth = width;
  77.                 viewHeight = height;
  78.                
  79.                 gl.glViewport(0, 0, width, height);     //Reset The Current Viewport
  80.                 gl.glMatrixMode(GL10.GL_PROJECTION);    //Select The Projection Matrix
  81.                 gl.glLoadIdentity();                                    //Reset The Projection Matrix
  82.  
  83.                 //Calculate The Aspect Ratio Of The Window
  84.                 GLU.gluPerspective(gl, 45.0f, (float)width / (float)height, 0.1f, 100.0f);
  85.  
  86.                 gl.glMatrixMode(GL10.GL_MODELVIEW);     //Select The Modelview Matrix
  87.                 gl.glLoadIdentity();                                    //Reset The Modelview Matrix
  88.        
  89.         }
  90.  
  91.         @Override
  92.         public void onSurfaceCreated(GL10 gl, EGLConfig config) {
  93.                 // Load the texture for the square
  94.                 square.loadGLTexture(gl, this.context);
  95.                 pig.loadGLTexture(gl, this.context,"pig_up");
  96.                
  97.                
  98.                 gl.glEnable(GL10.GL_TEXTURE_2D);                        //Enable Texture Mapping ( NEW )
  99.                 gl.glShadeModel(GL10.GL_SMOOTH);                        //Enable Smooth Shading
  100.                 gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);        //Black Background
  101.                 gl.glClearDepthf(1.0f);                                         //Depth Buffer Setup
  102.                 gl.glEnable(GL10.GL_DEPTH_TEST);                        //Enables Depth Testing
  103.                 gl.glDepthFunc(GL10.GL_LEQUAL);                         //The Type Of Depth Testing To Do
  104.                
  105.                 //Really Nice Perspective Calculations
  106.                 gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
  107.                
  108.  
  109.         }
  110.  
  111. }
  112.  
Parsed in 0.042 seconds, using GeSHi 1.0.8.4


Renderable
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. package net.obviam.opengl;
  2.  
  3. /**
  4.  *
  5.  */
  6.  
  7. import java.nio.ByteBuffer;
  8. import java.nio.ByteOrder;
  9. import java.nio.FloatBuffer;
  10.  
  11. import javax.microedition.khronos.opengles.GL10;
  12.  
  13. import android.R.string;
  14. import android.content.Context;
  15. import android.graphics.Bitmap;
  16. import android.graphics.BitmapFactory;
  17. import android.opengl.GLUtils;
  18.  
  19. /**
  20.  *
  21.  *
  22.  */
  23. public class Renderable extends glSprite { //glsprite simply has x, y, z variables
  24.        
  25.         //1 is  100%, so when using 0.5, you only show part of the texture
  26.        
  27.         private FloatBuffer vertexBuffer;       // buffer holding the vertices
  28.         private float vertices[] = {
  29.                         -1.0f, -1.0f,  0.0f,            // V1 - bottom left
  30.                         -1.0f,  1.0f,  0.0f,            // V2 - top left
  31.                          1.0f, -1.0f,  0.0f,            // V3 - bottom right
  32.                          1.0f,  1.0f,  0.0f                     // V4 - top right
  33.         };
  34.  
  35.         private FloatBuffer textureBuffer;      // buffer holding the texture coordinates
  36.         private float texture[] = {            
  37.                         // Mapping coordinates for the vertices
  38.                         0.0f, 1.0f,             // top left             (V2)
  39.                         0.0f, 0.0f,             // bottom left  (V1)
  40.                         1.0f, 1.0f,             // top right    (V4)
  41.                         1.0f, 0.0f              // bottom right (V3)
  42.         };
  43.        
  44.  
  45.        
  46.         /** The texture pointer */
  47.         private int[] textures = new int[1];
  48.  
  49.         public Renderable() {
  50.                 // a float has 4 bytes so we allocate for each coordinate 4 bytes
  51.                 ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length * 4);
  52.                 byteBuffer.order(ByteOrder.nativeOrder());
  53.                
  54.                 // allocates the memory from the byte buffer
  55.                 vertexBuffer = byteBuffer.asFloatBuffer();
  56.                
  57.                 // fill the vertexBuffer with the vertices
  58.                 vertexBuffer.put(vertices);
  59.                
  60.                 // set the cursor position to the beginning of the buffer
  61.                 vertexBuffer.position(0);
  62.                
  63.                 byteBuffer = ByteBuffer.allocateDirect(texture.length * 4);
  64.                 byteBuffer.order(ByteOrder.nativeOrder());
  65.                 textureBuffer = byteBuffer.asFloatBuffer();
  66.                 textureBuffer.put(texture);
  67.                 textureBuffer.position(0);
  68.         }
  69.  
  70.         /**
  71.          * Load the texture for the square
  72.          * @param gl
  73.          * @param context
  74.          */
  75.         public void loadGLTexture(GL10 gl, Context context, String assetname) {
  76.                
  77.                 // loading texture
  78.                 // This will tell the BitmapFactory to not scale based on the device's pixel density:
  79.             BitmapFactory.Options opts = new BitmapFactory.Options();
  80.             opts.inScaled = false;
  81.            
  82.                 Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),
  83.                                 R.drawable.pig_up);
  84.                 //texture must be 64*64...
  85.                
  86.             int width = bitmap.getWidth();
  87.             int height = bitmap.getHeight();
  88.            
  89.             //doesn't seem to do anything, should resize the plane
  90.             /*vertices = new float[12];
  91.             vertices[0] = -(width/2); vertices[1] = (height/2); vertices[2] = 0.0f;// V1 - bottom left
  92.             vertices[3] = -(width/2); vertices[4] = -(height/2); vertices[5] =  0.0f;// V2 - top left
  93.             vertices[6] = width/2; vertices[7] = (height/2); vertices[8] =  0.0f;// V3 - bottom right
  94.             vertices[9] = width/2; vertices[10] = -(height/2); vertices[11] = 0.0f;// V4 - top right*/
  95.                
  96.  
  97.                 // generate one texture pointer
  98.                 gl.glGenTextures(1, textures, 0);
  99.                 // ...and bind it to our array
  100.                 gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
  101.                
  102.                 /// - - - - - -  M E T H O D 1 - - - - - - -
  103.                 // create nearest filtered texture
  104.                 gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
  105.                 gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
  106.  
  107.                 //Different possible texture parameters, e.g. GL10.GL_CLAMP_TO_EDGE
  108.                 gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
  109.                 gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
  110.                
  111.                
  112.                 // Use Android GLUtils to specify a two-dimensional texture image from our bitmap
  113.                 GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
  114.                
  115.                 // - - - - - - M E TH O D 2 - - - - - - -
  116.                  // Set all of our texture parameters:
  117.            /* gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR_MIPMAP_NEAREST);
  118.             gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR_MIPMAP_NEAREST);
  119.             gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
  120.             gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
  121.            
  122.             // Generate, and load up all of the mipmaps:
  123.             for(int level=0, height = bitmap.getHeight(), width = bitmap.getWidth(); true; level++) {
  124.                 // Push the bitmap onto the GPU:
  125.                 GLUtils.texImage2D(GL10.GL_TEXTURE_2D, level, bitmap, 0);
  126.                
  127.                 // We need to stop when the texture is 1x1:
  128.                 if(height==1 && width==1) break;
  129.                
  130.                 // Resize, and let's go again:
  131.                 width >>= 1; height >>= 1;
  132.                 if(width<1)  width = 1;
  133.                 if(height<1) height = 1;
  134.                
  135.                 Bitmap bmp2 = Bitmap.createScaledBitmap(bitmap, width, height, true);
  136.                 bitmap.recycle();
  137.                 bitmap = bmp2;
  138.             }*/
  139.            
  140.             // Clean up
  141.                 bitmap.recycle();
  142.  
  143.         }
  144.  
  145.        
  146.         /** The draw method for the square with the GL context */
  147.         public void draw(GL10 gl) {
  148.                 // bind the previously generated texture
  149.                 gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
  150.                
  151.                 // Point to our buffers - !!open drawing!!
  152.                 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
  153.                 gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
  154.                
  155.                 // Set the face rotation
  156.                 gl.glFrontFace(GL10.GL_CW);
  157.                
  158.                 //scales!
  159.                 //gl.glScalef(0.5f, 0.5f, 1f);
  160.                
  161.                 //gl.gl
  162.                
  163.                 //location
  164.                 gl.glTranslatef(x, 0.0f, -5.0f);       
  165.                
  166.                 // Point to our vertex buffer
  167.                 gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
  168.                 gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
  169.                
  170.                 // Draw the vertices as triangle strip
  171.                 gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
  172.  
  173.                 //Disable the client state before leaving - close drawing
  174.                 gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
  175.                 gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
  176.         }
  177. }
  178.  
Parsed in 0.047 seconds, using GeSHi 1.0.8.4
omgnoseat
Once Poster
Once Poster
 
Posts: 1
Joined: Sat Aug 06, 2011 1:48 am

Top

Return to Android 2D/3D Graphics - OpenGL Problems

Who is online

Users browsing this forum: No registered users and 3 guests