OpenGLES图形编程入门:基础与变换
立即解锁
发布时间: 2025-08-24 00:52:51 阅读量: 1 订阅数: 8 

### OpenGL ES 图形编程入门:基础与变换
#### 1. OpenGL ES 基础注意事项
在使用 OpenGL ES 进行图形编程时,有一个重要的点需要注意:混合操作(Blending)成本较高。当前的移动 GPU 在处理大量像素的混合时表现并不理想,所以应避免过度使用混合,仅在绝对必要时才使用。
#### 2. 更多图元类型
除了常见的三角形,OpenGL ES 还能渲染点和线等图元。这些图元同样通过顶点来定义,并且之前提到的纹理映射、逐顶点颜色等操作也适用于它们。在调用 `glDrawArrays()` 或 `glDrawElements()` 时,使用除 `GL10.GL_TRIANGLES` 之外的常量即可渲染这些图元。以下是 OpenGL ES 提供的所有图元类型:
| 图元类型 | 描述 |
| ---- | ---- |
| 点(Point) | 每个顶点就是一个独立的图元 |
| 线(Line) | 由两个顶点组成,2 * n 个顶点可定义 n 条线 |
| 线带(Line strip) | 所有顶点被解释为属于一条长线 |
| 线环(Line loop) | 类似于线带,但 OpenGL ES 会自动从最后一个顶点到第一个顶点绘制一条额外的线 |
| 三角形(Triangle) | 由三个顶点组成 |
| 三角形带(Triangle strip) | 只需指定三角形数量 + 1 个顶点,OpenGL ES 会依次构建三角形 |
| 三角形扇(Triangle fan) | 有一个共享的基础顶点,以此构建多个三角形 |
三角形带和三角形扇的灵活性稍逊于单纯的三角形列表,但它们能提升一些性能,因为需要与投影和模型视图矩阵相乘的顶点更少。不过,在代码中我们通常还是使用三角形列表,因为它更易于使用,并且通过使用索引也能达到相近的性能。
在 OpenGL ES 中,点和线的渲染有点特殊。当使用像素完美的正交投影时,例如屏幕分辨率为 320 * 480 像素,并且 `glOrthof()` 调用使用这些确切的值,在某些情况下仍无法实现像素完美的渲染。由于所谓的菱形退出规则,点和线顶点的位置需要偏移 0.375f。在进行像素完美的点和线渲染时,需要牢记这一点。
#### 3. 2D 变换与模型视图矩阵
到目前为止,我们只是以三角形列表的形式定义了静态几何图形,没有涉及移动、旋转或缩放操作。而且,即使顶点数据本身保持不变,若要在不同位置绘制相同的矩形,仍需复制顶点。而模型视图矩阵可以解决这个问题。
##### 3.1 世界空间与模型空间
为了理解模型视图矩阵的工作原理,我们需要跳出正交视图平截头体的概念。视图平截头体处于一个特殊的坐标系,即世界空间,所有顶点最终都会落在这个空间中。此前,我们一直使用相对于世界空间原点的绝对坐标来指定顶点位置。现在,我们希望顶点位置的定义独立于世界空间坐标系,这可以通过为每个模型(如 Bob 的矩形、宇宙飞船等)赋予自己的坐标系来实现,这个坐标系就是模型空间。
以下是一个简单的模型定义示例:
```java
Vertices vertices = new Vertices(glGraphics, 4, 12, false, false);
vertices.setVertices(new float[] { -50, -50,
50, -50,
50, 50,
-50, 50 }, 0, 8);
vertices.setIndices(new short[] {0, 1, 2, 2, 3, 0}, 0, 6);
```
当不做任何修改直接渲染这个模型时,它会在最终图像的世界空间原点附近显示。若要将其渲染到不同位置,例如中心位于世界空间的 (200, 300),可以重新定义顶点位置:
```java
vertices.setVertices(new float[] { -50 + 200, -50 + 300,
50 + 200, -50 + 300,
50 + 200, 50 + 300,
-50 + 200, 50 + 300 }, 0, 8);
```
但这种方法比较繁琐。
##### 3.2 矩阵与模型视图矩阵
矩阵可以编码平移、旋转和缩放等变换。投影矩阵用于将顶点投影到投影平面,而模型视图矩阵则可以更优雅地解决顶点位置移动的问题。以下是如何使用模型视图矩阵将模型原点移动到特定位置的示例:
```java
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glTranslatef(200, 300, 0);
vertices.draw(GL10.GL_TRIANGLES, 0, 6);
```
操作步骤如下:
1. 告诉 OpenGL ES 要操作的矩阵,这里是模型视图矩阵(`GL10.GL_MODELVIEW`)。
2. 将模型视图矩阵设置为单位矩阵,清空之前的内容。
3. 使用 `glTranslatef()` 方法指定在 x、y、z 轴上的平移量。由于是 2D 编程,忽略 z 轴,将其平移分量设为 0。
4. 调用 `vertices.draw()` 方法渲染模型。
从这一步开始,OpenGL ES 的模型视图矩阵就编码了一个 (200, 300, 0) 的平移变换,该变换会应用到通过 OpenGL ES 管线的所有顶点上。
##### 3.3 平移示例
假设我们要在世界中不同位置渲染 100 个 Bob 图形,并且让它们在屏幕上移动,每次碰到屏幕边缘就改变方向。一种方法是使用一个大的 `Vertices` 实例来存储 100 个矩形的顶点,并在每一帧重新计算顶点位置。更简单的方法是使用一个小的 `Vertices` 实例只存储一个矩形(Bob 的模型),并通过模型视图矩阵实时平移来重复使用它。
以下是 Bob 模型的定义:
```java
Vertices bobModel = new Vertices(glGraphics, 4, 12, false, true);
bobModel.setVertices(new float[] { -16, -16, 0, 1,
16, -16, 1, 1,
16, 16, 1, 0,
-16, 16, 0, 0, }, 0, 8);
bobModel.setIndices(new short[] {0, 1, 2, 2, 3, 0}, 0, 6);
```
每个 Bob 的大小为 32 * 32 单位,并且进行了纹理映射。
接下来定义一个 `Bob` 类来管理 Bob 的位置和移动:
```java
package com.badlogic.androidgames.glbasics;
import java.util.Random;
class Bob {
static final Random rand = new R
```
0
0
复制全文
相关推荐










