用OpenGL ES作图一个彩色的三角形
用OpenGL ES绘制一个彩色的三角形
每个顶点需要两个坐标和4个(RGBA)颜色分量,因此一共需要6个浮点数。每个浮点数占4个字节,也就是说,一个顶点需要24个字节。当调用ByteBuffer.allocateDirect()方法时,只需把顶点数乘以VERTEX_SIZE就可得到需要的ByteBuffer空间。
现在OpenGL ES知道它可以得到每个顶点的位置和颜色信息,还需要告诉它从哪里可以获得这些信息:
首先设置FloatBuffer的位置。FloatBuffer从0开始保存这些顶点。这个位置指向缓冲区第一个顶点的x坐标。接下来调用glVertexPointer()方法。唯一与前面实例不同的地方是这里需要指明顶点的大小(以字节为单位)。OpenGL ES将从指定的缓冲区的起始位置读取顶点位置。第一个顶点位置的地址增加VERTEX_SIZE字节后得到第二个顶点位置的地址,以此类推。
运行效果如下:
以下均转自Android游戏编程入门经典,转载请标明出处
通过使用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 } } }
运行效果如下: