基元是构成复杂物体的基本绘图元素。OpenGL ES 中可以使用的基元有点,线和三角形。我想这些是不需要解释的了。

 

首先,我们先看看一些代码,然后讨论一下这些代码的作用,你可以利用这些代码编写你自己的代码。

 

基元 #1 – 三角形

 

三角形是最“复杂”的基元,但它是如此简单和实用。这是你将要绘制的第一个OpenGL基元。在绘制三角形时,我们所需要做的只是提供给OpenGL三角形3个3D空间中的坐标,OpenGL就会将其渲染出来。

 

开始,先复制OpenGL ES 00教程的项目文件,或下载:AppleCoder-OpenGLES-00.tar.gz

 

在Xcode中打开项目,找到EAGLView.m 中drawView 方法。

 

首先需要定义三角形。我们必须理解两种类型的坐标:模型坐标(Model)和世界坐标(World)。模型坐标是以我们正在绘制的基元为参照的,而世界坐标则告诉OpenGL它与观察者的关系(观察者总是处于世界坐标的(0.0,0.0,0.0)。

 

第一个例子说明了这点。首先,用3个3D坐标(X,Y,Z)定义处于模型空间中的三角形:

1
2
3
4
5
6
7
8
9
const GLfloat triangleVertices[] = {
 
        0.0, 1.0, -6.0,// Triangle top centre

        -1.0, -1.0, -6.0,// bottom left

        1.0, -1.0, -6.0,// bottom right

    };

 

这三个坐标定义了三角形,要注意它们是以反时针方向顺序定义的。尽管你可以顺时针或反时针方向定义,但一定要按顺序(译者注:废话,三角形再怎么定义,顺序也不会乱的)。我建议从反时针坐标开始,因为后面一些更高级的功能需要这样。

 

由于此教程是完全针对iPhone OpenGL ES初学者的,我在这里简单描述一下3D坐标系统。请看下图:

 

上图代表模型空间坐标或世界坐标。想象一下这就是你的电脑屏幕,X和Y分别指向水平和垂直方向,而Z则执行深度方向。原点在(0.0,0.0,0.0)。

 

让我们看一下前面描述的三角形顶点情况,第一点(0.0, 1.0, -6.0) 处于Y轴正中心(译者注:应该是X轴)向上一个单位并向屏幕后延伸6个单位。第二点处于Y轴左方1.0个单位,X轴下方(所以Y为-1),仍向屏幕里6.0个单位。第三点也可以此类推。

 

我将物体放在屏幕后(Z为负值)的原因是观察者总是处于(0.0,0.0,0.0),如果放置在屏幕前,OpenGL的深度测试将会失败不会将其渲染出来。

 

可能会有人反驳:“你指的是模型坐标而不是世界坐标。” 是的,说得很对,但当我们渲染此三角形时,OpenGL只是简单地将目标设置在(0.0,0.0,0.0)。所以我们将其置于屏幕后可以使其可见。当我们讨论各种变换(移动,旋转等)时,你们就可以看到有一些方法不需要将目标设在屏幕后(Z负值)就可使其可见。我们现在还是将z坐标设为-6.0。

 

绘图代码

 

现在,我们已介绍完了三角形坐标。下面我们要告诉OpenGL数据存在什么地方以及怎样绘制。这只需几行代码。找到drawView方法,实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
- (void)drawView {
    const GLfloat triangleVertices[] = {
        0.0, 1.0, -6.0,                    // Triangle top centre

        -1.0, -1.0, -6.0,                  // bottom left

        1.0, -1.0, -6.0                    // bottom right

    };

    [EAGLContext setCurrentContext:context];
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
    glViewport(0, 0, backingWidth, backingHeight);

    // -- BEGIN NEW CODE
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glVertexPointer(3, GL_FLOAT, 0, triangleVertices);
    glEnableClientState(GL_VERTEX_ARRAY);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    // -- END NEW CODE
   
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context presentRenderbuffer:GL_RENDERBUFFER_OES];
    [self checkGLError:NO];
}

 

如你所见,只用四行代码就可实现三角形的渲染。我逐行解释,你们就知道这是多么的容易。

1
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

 

这一行是完成清屏。我们填入的控制位是告诉OpenGL使用我们在上次教程setupView方法中设定的颜色(黑色)清屏并清除深度缓存。注意,如果我们打开了深度缓存而且没有清除,那么渲染将不会进行。如果我们没有启用深度缓存,就不需要将GL_DEPTH_BUFFER_BIT传递到glClear()中。

 

好,我们已清除原先绘制在此缓存中的数据(记住,这是双缓冲动画;当绘制一个缓存时,另一个缓存正在被显示出来。)

1
glVertexPointer(3, GL_FLOAT, 0, triangleVertices);

 

此行代码是告诉OpenGL数据在什么地方以及采用什么格式。此函数有四个参数,简单解释如下:

 

  1. 尺寸 – 指每个坐标的数目值。我们使用3,代表(X,Y,Z)。如果你进行2D绘图,没有深度(Z值),那么此参数为2。

  2. 数据类型 – GL_FLOAT表示我们传递的是浮点数值。你还可以将其设为整数型。不过最好适应浮点数,因为3D世界是用浮点表示的。

  3. 跨度 – 此参数告诉OpenGL忽略各坐标间一定数量的字节。我们将其设为0。唯一需要用到此参数的情况是当你从文件中加载顶点数据,此文件具有额外的填充数据或颜色数据,比如Blender的文件。

  4. 数据指针 – 数据本身。

 

好,我们已经通知OpenGL清除缓存,指定了绘制物体的数据存在什么地方以及数据格式,现在我们要让OpenGL做些重要的事情了:

1
glEnableClientState(GL_VERTEX_ARRAY);

 

OpenGL是一个“状态”机器。这意味着你必须通过调用启动和禁止命令来打开或关闭一些功能。前面,我们已经使用过glEnable(),它影响OpenGL的“服务器”方。而glEnableClientState()将影响我们的程序方(即客户方)。我们所做的是通知OpenGL顶点数据处于一个顶点数组中并且打开OpenGL顶点绘制功能。有时一个顶点可以是一个颜色数组,在这种情况下我们应调用glEnableClientState(GL_COLOR_ARRAY);或者在纹理映射时也可能是一个纹理坐标数组 (别浪费口水!在涉及纹理映射前我们还是先完成基本图形绘制吧!!)

 

随着我们深入了解OpenGL,我们将使用不同的客户方状态并对此有更深的理解。

 

现在到了让OpenGL渲染三角形的命令了:

 

1
glDrawArrays(GL_TRIANGLES, 0, 3);

 

一旦此函数被调用,OpenGL将使用前面几个函数的信息来执行命令。一个填充了白色(白色是缺省绘图色)的三角形将会出现在屏幕上。三角形是填充了的物体,如果你想要绘制未填充的三角形,那么你需要使用不同的绘图方法。

 

分解此函数, 有三个参数:

  1. 绘图方式 – 我们传递了GL_TRIANGLES,这显而易见是要绘制一个三角形。然而当我们需要绘制正方形时,我们才会看到第一个参数的真正功力。

  2. 第一顶点 – 我们的数组包括了3个点,所以我们要OpenGL从数组中的第一个坐标(就像访问标准数组一样指定为0)画起,。如果在顶点数组中有多个基元,我们可以在这里设置一个偏移量。当我在后面的教程中绘制介绍更复杂的物体时,我会介绍怎样使用偏移量。现在我们将其设为0。

  3. 顶点数 – 它告诉OpenGL我们的数组中有多少个顶点需要绘制。由于我们绘制的是三角形,所以只有3点。正方形有四点,线有两点(或多点)而点只有一个顶点或多个(在渲染多点的情况下)。(译者注:真罗嗦!差点晕倒。)

 

在drawView方法中输入上述代码后,按“Build and Go”在仿真器上运行。你将看到:

 

一个白色的三角形显现在屏幕的中央。

 

在我们开始绘制其他基元前,试一下改变Z值。你就会明白将其改为0.0时会发生什么。没有任何东西被渲染出来。

 

有很多行代码需要敲入,但如果你就此明白OpenGL ES是怎样工作的,那我认为这一切是值得的。如果你以前试过”标准“OpenGL教程,我希望你可以看出OpenGL和OpenGL ES的区别来。

 

前瞻

 

下一篇教程将讲述正方形的绘制。源代码。AppleCoder-OpenGLES-01.zip

 

原文见:OpenGL ES 01 – Drawing Primitives 1 – Triangles 作者:Simon Maurice   前一篇:iphone-opengl-es系列之0-建立xcode项目