OpenGLES3D图形编程入门
立即解锁
发布时间: 2025-08-24 00:53:56 阅读量: 1 订阅数: 13 

### OpenGL ES 3D 图形编程入门
#### 1. 从 2D 到 3D 的跨越
在之前的开发中,借助 OpenGL ES 的强大功能成功创建了 2D 游戏。使用纹理图集和精灵批处理器,不仅让游戏实现起来轻松,还保证了良好的性能。同时,合理设计游戏机制以及明确世界单位和像素单位的关系,大大简化了游戏开发过程。
现在,是时候迈向 3D 图形编程的世界了。其实在定义视锥体和精灵顶点时,我们已经在 3D 空间中工作过,只是顶点的 z 坐标默认设为 0。与 2D 渲染相比,3D 渲染有以下不同:
- 顶点不仅有 x 和 y 坐标,还增加了 z 坐标。
- 采用透视投影而非正交投影。
- 离相机越远的物体看起来越小。
- 变换(如旋转、平移和缩放)在 3D 中有更多自由度,可以在三个轴上自由移动顶点。
- 可以在 3D 空间中定义任意位置和方向的相机。
- 物体三角形的渲染顺序变得重要,离相机近的物体要覆盖离相机远的物体。
#### 2. 准备工作
接下来会编写几个示例,沿用之前创建的整个框架,包括 GLGame、GLScreen、Texture 和 Vertices 类。本章的启动活动名为 GL3DBasicsStarter,可复用之前的 GLBasicsStarter 活动代码,只需将示例类的包名改为 com.badlogic.androidgames.gl3d,并将每个测试以 <activity> 元素的形式添加到清单文件中。所有测试将以固定的横向方向运行,在每个 <activity> 元素中指定。
每个测试都是 GLGame 抽象类的实例,实际的测试逻辑以 GLScreen 实例的形式在 GLGame 实现中实现。为节省篇幅,后续仅展示 GLScreen 实例的相关部分。测试的命名约定为 XXXTest 和 XXXScreen 分别对应 GLGame 和 GLScreen 的实现。
#### 3. 3D 顶点处理
在之前的学习中,我们知道顶点有几个属性:位置、颜色(可选)和纹理坐标(可选)。之前创建的 Vertices 类处理顶点相关细节,但顶点位置仅限于 x 和 y 坐标。要实现 3D 渲染,只需对 Vertices 类进行修改,使其支持 3D 顶点位置。
下面是新创建的 Vertices3 类,用于处理 3D 顶点:
```java
package com.badlogic.androidgames.framework.gl;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import javax.microedition.khronos.opengles.GL10;
import com.badlogic.androidgames.framework.impl.GLGraphics;
public class Vertices3 {
final GLGraphics glGraphics;
final boolean hasColor;
final boolean hasTexCoords;
final int vertexSize;
final IntBuffer vertices;
final int[] tmpBuffer;
final ShortBuffer indices;
public Vertices3(GLGraphics glGraphics, int maxVertices, int maxIndices,
boolean hasColor, boolean hasTexCoords) {
this.glGraphics = glGraphics;
this.hasColor = hasColor;
this.hasTexCoords = hasTexCoords;
this.vertexSize = (3 + (hasColor ? 4 : 0) + (hasTexCoords ? 2 : 0)) * 4;
this.tmpBuffer = new int[maxVertices * vertexSize / 4];
ByteBuffer buffer = ByteBuffer.allocateDirect(maxVertices * vertexSize);
buffer.order(ByteOrder.nativeOrder());
vertices = buffer.asIntBuffer();
if (maxIndices > 0) {
buffer = ByteBuffer.allocateDirect(maxIndices * Short.SIZE / 8);
buffer.order(ByteOrder.nativeOrder());
indices = buffer.asShortBuffer();
} else {
indices = null;
}
}
public void setVertices(float[] vertices, int offset, int length) {
this.vertices.clear();
int len = offset + length;
for (int i = offset, j = 0; i < len; i++, j++)
tmpBuffer[j] = Float.floatToRawIntBits(vertices[i]);
this.vertices.put(tmpBuffer, 0, length);
this.vertices.flip();
}
public void setIndices(short[] indices, int offset, int length) {
this.indices.clear();
this.indices.put(indices, offset, length);
this.indices.flip();
}
public void bind() {
GL10 gl = glGraphics.getGL();
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
vertices.position(0);
gl.glVertexPointer(3, GL10.GL_FLOAT, vertexSize, vertices);
if (hasColor) {
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
vertices.position(3);
gl.glColorPointer(4, GL10.GL_FLOAT, vertexSize, vertices);
}
if (hasTexCoords) {
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
vertices.position(hasColor ? 7 : 3);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, vertexSize, vertices);
}
}
public void draw(int primitiveType, int offset, int numVertices) {
GL
```
0
0
复制全文
相关推荐










