用OpenGL ES作图一个彩色的三角形

用OpenGL ES绘制一个彩色的三角形

以下均转自Android游戏编程入门经典,转载请标明出处用OpenGL ES作图一个彩色的三角形

通过使用glColor4f()为所有的顶点设置一个全局默认颜色。但有时需要更多细粒度的控制(例如,需要为每个顶点设置颜色)。

OpenGL ES提供这样的功能,需要的只是将RGBA浮点分量加到每个顶点,并告诉OpenGL ES在哪里可以找到每个顶点的颜色。

int VERTEX_SIZE = (2 + 4) * 4;
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(3 * VERTEX_SIZE);
			byteBuffer.order(ByteOrder.nativeOrder());
			vertices = byteBuffer.asFloatBuffer();
			vertices.put(new float[]{
					  0.0f,   0.0f, 1, 0, 0, 1,
					319.0f,   0.0f, 0, 1, 0, 1,
					160.0f, 479.0f, 0, 0, 1, 1
			});

每个顶点需要两个坐标和4个(RGBA)颜色分量,因此一共需要6个浮点数。每个浮点数占4个字节,也就是说,一个顶点需要24个字节。当调用ByteBuffer.allocateDirect()方法时,只需把顶点数乘以VERTEX_SIZE就可得到需要的ByteBuffer空间。

如果需要渲染它,就必须告诉OpenGL ES这些顶点不但有位置信息,还有颜色属性。

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

现在OpenGL ES知道它可以得到每个顶点的位置和颜色信息,还需要告诉它从哪里可以获得这些信息:

vertices.position(0);
gl.glVertexPointer(2, GL10.GL_FLOAT, VERTEX_SIZE, vertices);
vertices.position(2);
gl.glColorPointer(4, GL10.GL_FLOAT, VERTEX_SIZE, vertices);

首先设置FloatBuffer的位置。FloatBuffer从0开始保存这些顶点。这个位置指向缓冲区第一个顶点的x坐标。接下来调用glVertexPointer()方法。唯一与前面实例不同的地方是这里需要指明顶点的大小(以字节为单位)。OpenGL ES将从指定的缓冲区的起始位置读取顶点位置。第一个顶点位置的地址增加VERTEX_SIZE字节后得到第二个顶点位置的地址,以此类推。

接下来,设置第一个顶点的R颜色分量在缓冲区中的位置并调用glColorPointer()方法,该方法告诉OpenGL ES在哪里可以找到顶点的颜色。第一个参数是每个颜色的分量数。分量数一直是4.第二个参数指明每个分量的类型,用GL10.GL_FLOAT来声明每个颜色分量都是浮点型,并且取值范围是0~1.第三个参数是顶点颜色间的步长。最后一个参数是顶点缓冲区。

只要在调用glColorPointer()之前调用vertices.position(2),OpenGL ES就会知道第一个顶点的颜色是从缓冲区中的第三个浮点数开始的。如果位置不设为2,OpenGL ES将从位置0开始读取颜色值。

package org.example.androidgames.glbasics;

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

import javax.microedition.khronos.opengles.GL10;

import org.example.androidgames.framework.Game;
import org.example.androidgames.framework.Screen;
import org.example.androidgames.framework.impl.GLGame;
import org.example.androidgames.framework.impl.GLGraphics;

public class ColoredTriangleTest extends GLGame{

	@Override
	public Screen getStartScreen() {
		// TODO Auto-generated method stub
		return new ColoredTriangleScreen(this);
	}
	
	class ColoredTriangleScreen extends Screen {
		final int VERTEX_SIZE = (2 + 4) * 4;
		GLGraphics glGraphics;
		FloatBuffer vertices;

		public ColoredTriangleScreen(Game game) {
			super(game);
			glGraphics = ((GLGame)game).getGLGraphics();
			
			ByteBuffer byteBuffer = ByteBuffer.allocateDirect(3 * VERTEX_SIZE);
			byteBuffer.order(ByteOrder.nativeOrder());
			vertices = byteBuffer.asFloatBuffer();
			vertices.put(new float[]{
					  0.0f,   0.0f, 1, 0, 0, 1,
					319.0f,   0.0f, 0, 1, 0, 1,
					160.0f, 479.0f, 0, 0, 1, 1
			});
		}

		@Override
		public void update(float deltaTime) {
			// TODO Auto-generated method stub

		}

		@Override
		public void present(float deltaTime) {
			// TODO Auto-generated method stub
			GL10 gl = glGraphics.getGL();
			gl.glViewport(0, 0, glGraphics.getWidth(), glGraphics.getHeight());
			gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
			gl.glMatrixMode(GL10.GL_PROJECTION);
			gl.glLoadIdentity();
			gl.glOrthof(0, 320, 0, 480, 1, -1);
			
			gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
			gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
			
			vertices.position(0);
			gl.glVertexPointer(2, GL10.GL_FLOAT, VERTEX_SIZE, vertices);
			vertices.position(2);
			gl.glColorPointer(4, GL10.GL_FLOAT, VERTEX_SIZE, vertices);
			gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);
		}

		@Override
		public void pause() {
			// TODO Auto-generated method stub

		}

		@Override
		public void resume() {
			// TODO Auto-generated method stub

		}

		@Override
		public void dispose() {
			// TODO Auto-generated method stub

		}

	}
	
}

运行效果如下:用OpenGL ES作图一个彩色的三角形