Tutorial de OpenGL ES com Android – Alternando do Canvas para o OpenGL

Nesse artigo, publicado em 14/06/2012 no blog obviam.net, o autor se aprofunda nos recursos gráficos da plataforma Android. O Android suporta a API OpenGL ES. Não é preciso dizer que a manipulação de gráficos através de uma GPU dedicada é muito mais eficiente do que faze-lo na CPU. Muitos dispositivos Android possuem uma GPU dedicada.

O OpenGL é uma API para desenhar gráficos 2D e 3D que são renderizados na GPU. Isso libera recursos preciosos de computação da CPU que podem ser usados em física mais complexa ou mais entidades ou algo não relacionado a parte gráfica.

Se você tem conhecimento de como exibir gráficos em um dispositivo Android, você já sabe que para poder exibir elementos gráficos, precisa de uma superfície (surface) ou renderizador (renderer). No artigo indicado no último link, é mostrado o uso de um SurfaceView a partir do qual obtemos o Canvas e fazemos todos os desenhos nele chamando o método draw de dentro do loop do jogo.

O uso do OpenGL não é muito diferente. O Android vem com uma implementação dedicada da interface SurfaceView para exibir imagens renderizadas pela OpenGL.

Vamos criar o projeto da forma comum.

Screen-shot-2011-01-22-at-19.10.15

Chamaremos a Activity simplesmente de Run. Verifique o que o assistente gerou, que deve ser o seguinte:

public class Run extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
}

Criando o renderizador do OpenGL

Vamos criar agora o renderizador. Crie um classe com o nome GlRenderer que implementa a interfaceandroid.opengl.GLSurfaceView.Renderer .

Ela deve ficar dessa forma:

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

import android.opengl.GLSurfaceView.Renderer;

public class GlRenderer implements Renderer {

	@Override
	public void onDrawFrame(GL10 gl) {
	}

	@Override
	public void onSurfaceChanged(GL10 gl, int width, int height) {
	}

	@Override
	public void onSurfaceCreated(GL10 gl, EGLConfig config) {
	}
}

Precisamos implementar os 3 métodos acima. No momento eles estão vazios e não fazem nada.

Os métodos

onSurfaceCreated(GL10 gl, EGLConfig config)criado ou recriado. É importante dar suporte a parte da recriação pois a cada vez que o dispositivo entra em hibernação e acorda, a superfície é recriada. Como o contexto que guarda os recursos é destruído também, esse é local onde iremos carrega-los (imagens para as texturas, etc).

onSurfaceChanged(GL10 gl, int width, int height) é chamado sempre a superfície muda de tamanho. Isso afeta principalmente nosso viewport. O viewport é apenas uma região retangular na qual visualizamos o mundo do jogo.

onDrawFrame(GL10 gl) é chamado pela thread do renderizador para desenhar cada quadro. Aqui é onde todo o processo de desenho acontece. Não precisamos chamar esse método explicitamente. Uma thread de renderização é chamada pelo Android e ela chama esse método.

Vamos alternar para o renderizador do OpenGL. Verifique a nova activity Run.

package net.obviam.opengl;

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

public class Run extends Activity {

	/** The OpenGL view */
	private GLSurfaceView glSurfaceView;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // requesting to turn the title OFF
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        // making it full screen
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
				WindowManager.LayoutParams.FLAG_FULLSCREEN);

        // Initiate the Open GL view and
        // create an instance with this activity
        glSurfaceView = new GLSurfaceView(this);

        // set our renderer to be the main renderer with
        // the current activity context
        glSurfaceView.setRenderer(new GlRenderer());
        setContentView(glSurfaceView);
    }

	/** Remember to resume the glSurface  */
	@Override
	protected void onResume() {
		super.onResume();
		glSurfaceView.onResume();
	}

	/** Also pause the glSurface  */
	@Override
	protected void onPause() {
		super.onPause();
		glSurfaceView.onPause();
	}
}

Na linha 12 declaramos uma variável membro GLSurfaceView. Esse é o nosso view OpenGL fornecido pelo Android. Quando instanciamos ele (linha 27) temos que fazer com que ele tenha ciência do contexto. Isso é, para o view ter acesso ao ambiente da aplicação.

Tudo o que precisamos fazer é adicionar nosso renderizador a esse view. Isso fazemois na linha 31. A linha 32 diz à activity para usar nosso view OpenGL.

Os métodos onResume() e onPause() estão sendo substituídos e disparam os métodos respectivos em nosso view.

Você pode executar a aplicação como uma app Android e deve visualizar uma tela preta vazia. E é isto. Alternamos nossa aplicação do canvas para o renderizador OpenGL.

Baixe o código fonte e o projeto Eclipse aqui

Para aprender como exibir primitivas (triângulos, retângulos) como o OpenGL, verifique o próximo artigo.

Traduzido de obviam.net