English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Desenvolvimento de Android com OpenGL ES3Detalhamento do exemplo gráfico D

OpenGL ES é um subconjunto do API de gráficos tridimensionais OpenGL, projetado para dispositivos embutidos como telefones celulares, PDA e consoles de jogos. O Ophone atualmente suporta OpenGL ES 1.0, OpenGL ES 1.0 é baseado no OpenGL 1.3 Baseado na norma OpenGL ES 1.1 Baseado no OpenGL 1.5 baseada em normas. Este artigo principal introduce os passos básicos de desenho de gráficos utilizando OpenGL ES.

O conteúdo deste artigo é composto por três partes. Primeiro, obter a interface de programação OpenGL ES através do EGL; em seguida, introduzir a construção3Conceitos básicos do D; por fim, um exemplo de aplicativo.

OpenGL ES é essencialmente um estado machine de linha de renderização gráfica, enquanto EGL é uma camada externa usada para monitorar esses estados e manter o buffer de frames e outras superfícies de renderização.1 É um diagrama de layout típico do sistema EGL. O design do EGL View é baseado no interface nativo conhecido para OpenGL em Microsoft Windows (WGL) e UNIX (GLX), que é mais próximo do último. O estado da linha de renderização OpenGL ES é armazenado em um contexto gerenciado pelo EGL. O buffer de frames e outras superfícies de renderização são criados, gerenciados e destruídos através da API EGL. O EGL também controla e fornece acesso às configurações de exibição do dispositivo e possíveis configurações de renderização do dispositivo.


Figura1

O OpenGL ES precisa de um contexto de renderização e uma superfície de renderização. O contexto de renderização armazena informações de estado do OpenGL ES, e a superfície de renderização é usada para desenhar primitivas. Antes de escrever OpenGL ES, operações EGL necessárias incluem:

Consultar os handles de exibição suportados pelo dispositivo e inicializar.

Criar superfície de renderização, desenhar gráficos OpenGL ES.

Criar contexto de renderização. O EGL precisa criar um contexto de renderização OpenGL ES para associar a uma superfície de renderização.

No Ophone, o EGL inclui4classe, que inclui EGLDisplay: handle de exibição, EGLConfig: classe de configuração; EGLContext: contexto de renderização; e EGLSurface: classe de visão renderizável.

O EGL pode ser considerado uma camada intermediária entre o OpenGL ES e o sistema de janelas local. O sistema de janelas local se refere ao GNU/No sistema operacional Linux, ou no X Window System do Mac OS X, ou no Quartz. Antes que o EGL determine o tipo de superfície de renderização, o EGL precisa se comunicar com o sistema de janelas de baixo nível. Porque os sistemas de janelas diferentes em diferentes sistemas operacionais são diferentes, o EGL fornece um tipo de janela transparente, chamado EGLDisplay. Ele abstrai vários sistemas de janelas. Portanto, primeiramente, você precisa criar e inicializar um objeto EGLDisplay.

// O método estático getEGL da EGLContext obtém a instância EGL
EGL10 egl = (EGL10)EGLContext.getEGL();
//Criar EGLDisplay, EGL_DEFAULT_DISPLAY obter o tipo de sistema de janelas local padrão
EGLDisplay dpy = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
//Ao inicializar EGLDispla, obter o número da versão
int[] version = new int[2]);
egl.eglInitialize(dpy, version);

Cada EGLDisplay precisa ser inicializado antes de ser usado. Ao inicializar EGLDisplay, você pode obter a versão de implementação do EGL no sistema. Através da versão, você pode usar os API's OpenGL ES de maneira razoável, escrevendo programas compatíveis para adaptar-se a mais dispositivos e fornecer a maior portabilidade. O原型 da função de inicialização é:
boolean eglInitialize(EGLDisplay display, int[] major_minor)

no qual display é uma instância válida de EGLDisplay. Quando a função for chamada, major_minor será atribuído ao número da versão atual do EGL. Por exemplo, EGL1.0 , major_minor[0] é1,major_minor[1]为0。EGLSurface包含了EGL渲染面相关的所有信息。查询EGLSurface配置信息有两种方法,一是查询所有的配置信息,从中选择一个最为适合的;二是指定好配置信息,由系统给出最佳匹配结果。一般采用第二种方法。用户通过configSpec指定出希望获得的配置,函数eglChooseConfig通过参数Configs返回最佳的配置列表。之后利用已获得的Configs,调用eglCreateContext创建一个渲染上下文,该函数返回EGLContext结构。渲染面EGLSurface的创建通过函数eglCreateWindowSurface完成。一个应用程序可以创建多个EGLContext。 eglMakeCurrent就是将某个渲染上下文绑定到渲染面。查询函数eglGetCurrentContext, eglGetCurrentDisplay和eglGetCurrentSurface分别用于获得当前系统的渲染上下文、显示句柄和渲染面。最后EGLContext的静态方法getGL获得OpenGL ES的编程接口。下面的程序片段总结了上述内容。

EGL10 egl = (EGL10)EGLContext.getEGL();
EGLDisplay dpy = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); int[] version = new int[2]);
egl.eglInitialize(dpy, version);
int[] configSpec = {
EGL10.EGL_RED_SIZE, 5,
EGL10.EGL_GREEN_SIZE, 6,
EGL10.EGL_BLUE_SIZE, 5,
EGL10.EGL_DEPTH_SIZE, 16,
EGL10.EGL_NONE
};
EGLConfig[] configs = new EGLConfig[1]);
int[] num_config = new int[1]);
egl.eglChooseConfig(dpy, configSpec, configs, 1, num_config);
EGLConfig config = configs[0];
EGLContext context = egl.eglCreateContext(dpy, config,
EGL10.EGL_NO_CONTEXT, null);
EGLSurface surface = egl.eglCreateWindowSurface(dpy, config,
sHolder, null);
egl.eglMakeCurrent(dpy, surface, surface, context);
GL10 gl = (GL10)context.getGL();

Construir3Os pontos gráficos D

Os pontos são construídos3A base do modelo D. As operações internas do OpenGL ES são baseadas em pontos. Pode-se usar pontos para representar a posição da fonte de luz, a posição do objeto. Geralmente, usamos um conjunto de números de ponto flutuante para representar um ponto. Por exemplo, um quadrado4Os vértices podem ser representados como:

float vertices[] = {
-1.0f, 1.0f, 0.0f, //Superior esquerdo
-1.0f, -1.0f, 0.0f, //Inferior esquerdo
1.0f, -1.0f, 0.0f, //Inferior direito
1.0f, 1.0f, 0.0f, //Superior direito
};

Para melhorar o desempenho, é necessário armazenar o array de ponto flutuante em um buffer de bytes. Portanto, temos as seguintes operações:

ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
vbb.order(ByteOrder.nativeOrder());
FloatBuffer vertexBuffer = vbb.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);

Onde ByteOrder.nativeOrder() é obter a ordem de bytes do sistema. O OpenGL ES possui funções para operar no pipeline de renderização gráfica, que, por padrão, essas funções estão desativadas. Pode-se ativar e desativar essas funções usando glEnableClientState e glDisableClientState.

// Especifique os arrays de vértices que precisam ser ativados
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
// Descrição para ativar o tipo de array e o buffer de bytes, o tipo é GL_FLOAT
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
// Feche o array de vértices quando não for mais necessário
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

Lado

O lado é uma linha que conecta dois pontos, é a margem da superfície do polígono.

Polígono

O polígono é uma única circunferência fechada composta por lados. Os polígonos no OpenGL ES devem ser polígonos convexos, ou seja, em qualquer ponto interno do polígono, se a linha que conecta esses dois pontos estiver completamente dentro do polígono, esse polígono é convexo. Ao desenhar um polígono, é necessário especificar a direção de renderização, que pode ser no sentido horário ou no sentido anti-horário. Pois a direção determina a orientação do polígono, ou seja, a face frontal e a face traseira. Evitar a renderização das partes ocultas pode aumentar significativamente o desempenho do programa. A função glFrontFace define a direção de renderização dos vértices.

// 设置CCW方向为“正面”,CCW即CounterClockWise,逆时针
Define a direção CCW como 'frente', CCW significa CounterClockWise, no sentido anti-horário
// glFrontFace(GL_CCW);
Define a direção CW como 'frente', CW significa ClockWise, no sentido horário

glFrontFace(GL_CW);

renderização

Com a explicação dos conceitos acima, agora vamos para a tarefa mais importante — renderização. Renderização é transformar os elementos geométricos especificados pelas coordenadas dos objetos em imagens do buffer de frame. As imagens e as coordenadas dos vértices têm uma relação íntima. Esta relação é dada pelo modo de desenho. Modos de desenho comuns incluem GL_POINTS、GL_LINE_STRIP、
GL_LINE_LOOP、GL_LINES、GL_TRIANGLES、GL_TRIANGLE_STRIP、GL_TRIANGLE_FAN. Abaixo, apresentamos detalhes sobre cada um:

GL_POINTS: Trata cada vértice como um ponto, onde o vértice n define o ponto n, desenhando um total de n pontos.2n-1e2GL_LINES: Considera cada vértice como um segmento independente. O vértice/2n entre eles definem n segmentos, desenhando um total de N

os segmentos. Se N for ímpar, o último vértice é ignorado.+1GL_LINE_STRIP: Desenha um grupo de segmentos conectados, desde o primeiro vértice até o último, e o segmento n e n-1os segmentos. Os vértices definem o segmento n, desenhando um total de N


GL_LINE_LOOP: Desenha um grupo de segmentos conectados, desde o primeiro vértice até o último, e, em seguida, conecta o último vértice ao primeiro. O segmento n e n+1os vértices definem o segmento n, e o último segmento é formado pelos vértices N e1entre eles define N segmentos, desenhando um total de N


GL_TRIANGLES: Considera cada três vértices como um triângulo independente. O vértice3n-2,3n-1e3n define o triângulo n-ésimo, desenhando um total de N/3três triângulos.

GL_TRIANGLE_STRIP: Desenha um grupo de triângulos conectados. Para números ímpares n, o vértice n, n+1e n+2Define o triângulo n-ésimo; para números pares n, o vértice n+1,n e n+2Define o triângulo n-ésimo, desenhando um total de N-2três triângulos.


GL_TRIANGLE_FAN: Desenha um grupo de triângulos conectados. Os triângulos são determinados pelo primeiro vértice e pelos vértices subsequentes. O vértice1,n+1e n+2Define o triângulo n-ésimo, desenhando um total de N-2três triângulos.

Funções de desenho:

void glDrawArrays(int mode, int first, int count)
void glDrawElements(int mode, int count, int type, Buffer indices)

glDrawArrays cria uma sequência de figuras geométricas, usando cada array de pontos a partir do first até o first + count – 1O elemento final do array, mode é o modo de desenho.

glDrawElements usa count elementos para definir uma sequência de figuras, type é o tipo de dados no array indices, mode é o modo de desenho, o array indices armazena os

O valor de índice do ponto.

Exemplo de aplicação

Usar o conteúdo explicado acima para fornecer um exemplo de desenhar um3O programa do esferoide D. O efeito visual é como follows:


Figura2 Exemplo de esfera

O programa de desenho principal:

static private FloatBuffer vertex;//O buffer de bytes correspondente ao vértice
static private FloatBuffer normal;//O buffer de bytes correspondente ao vetor normal
float[] lightPos = new float[] {10.0f, 10.0f, 10.0f, 1.0f };//Coordenadas da luz
private static final int STEP = 24;//
private static final float RADIUS = 1.0f;//Raio
protected void init(GL10 gl) {
gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);//Definir a cor de fundo
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lightPos, 0);
gl.glEnable(GL10.GL_LIGHTING);//Ativar a iluminação
gl.glEnable(GL10.GL_LIGHT0); //Ligar a luz
gl.glClearDepthf(1.0f);//Definir o cache de profundidade
gl.glDepthFunc(GL10.GL_LEQUAL);//Definir a função de comparação do cache de profundidade, GL_LEQUAL indica que o valor de profundidade do novo pixel é menor ou igual ao valor de profundidade do pixel atual quando passa pelo teste de profundidade
gl.glEnable(GL10.GL_DEPTH_TEST);//Ativar o cache de profundidade
gl.glEnable(GL10.GL_CULL_FACE);
gl.glShadeModel(GL10.GL_SMOOTH);//Definir o modo de sombra GL_SMOOTH
}
protected void drawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT |
GL10.GL_DEPTH_BUFFER_BIT);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
GLU.gluLookAt(gl, 0, 0, 7f, 0f, 0f, 0f, 0f, 1.0f, 0.0f);//
drawSphere(gl, RADIUS, STEP, STEP); //Desenhar esfera
}
public static void gluLookAt (GL10 gl, float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ)

Ele aceita três conjuntos de coordenadas, respectivamente eye, center e up. Eye representa a posição do nosso olho no "sistema de coordenadas mundo", center representa as coordenadas do ponto que o olho "olha", e o eixo up representa a direção do observador, se compararmos o ponto de observação com os nossos olhos, então o eixo up representa se estamos olhando de pé, deitado ou em algum ângulo, aqui é de pé, então é {0,1,0}。

private static void drawSphere(GL10 gl, float radius,
int stacks, int slices) {
vertex=allocateFloatBuffer( 4* 6 * stacks * (slices+1) );
normal=allocateFloatBuffer( 4* 6 * stacks * (slices+1) );
int i, j, triangles;
float slicestep, stackstep;
stackstep = ((float)Math.PI) / stacks;
slicestep = 2.0f * ((float)Math.PI) / slices;
for (i = 0; i < stacks; ++i)
{
float a = i * stackstep;
float b = a + stackstep;
float s0 = (float)Math.sin(a);
float s1 = (float)Math.sin(b);
float c0 = (float)Math.cos(a);
float c1 = (float)Math.cos(b);
float nv;
for (j = 0; j <= slices; ++j)
{
float c = j * slicestep;
float x = (float)Math.cos(c);
float y = (float)Math.sin(c);
nv=x * s0;
normal.put(nv);
vertex.put( nv * radius);
nv=y * s0;
normal.put(nv);
vertex.put( nv * radius);
nv=c0;
normal.put(nv);
vertex.put( nv * radius);
nv=x * s1;
normal.put(nv);
vertex.put( nv * radius);
nv=y * s1;
normal.put(nv);
vertex.put( nv * radius);
nv=c1;
normal.put(nv);
vertex.put( nv * radius);
}
}
normal.position(0);
vertex.position(0);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normal);
gl.glEnableClientState (GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState (GL10.GL_NORMAL_ARRAY);
triangles = (slices + 1) * 2;
for(i = 0; i < stacks; i++)
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,
i * triangles, triangles);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
}
private static FloatBuffer allocateFloatBuffer(int capacity){
ByteBuffer vbb = ByteBuffer.allocateDirect(capacity);
vbb.order(ByteOrder.nativeOrder());
return vbb.asFloatBuffer();
}

Resumo:

Este artigo apresenta os conceitos básicos e métodos para desenhar gráficos no Ophone usando OpenGL ES. Existem muitos outros conteúdos no OpenGL ES, como texturas, iluminação e materiais, mistura, nevoeiro, máscara, reflexão,3A carga do modelo D e outros. Pode-se desenhar aplicações gráficas e interfaces de jogos usando funções OpenGL ES.

Você também pode gostar