我的OpenGL学习进阶之旅介绍一下OpenGL ES的图元装配:坐标系统透视分割视口变化

Posted 字节卷动

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我的OpenGL学习进阶之旅介绍一下OpenGL ES的图元装配:坐标系统透视分割视口变化相关的知识,希望对你有一定的参考价值。

在上一篇文章【我的OpenGL学习进阶之旅】介绍一下 绘制图元中,我们介绍了如何绘制图元,这篇我们来介绍一下图元装配

一、图元装配

下图展示了图元装配阶段。通过glDraw***提供的顶点由顶点着色器执行,顶点着色器变化的每个顶点包括描述顶点(x,y,z,w)值的顶点位置。

图元类型和顶点索引确定将被渲染的单独图元。

对于每个单独图元(三角形、直线和点精灵)及其对应的顶点,图元装配阶段执行如下图所示的操作。

在讨论OpenGL ES 中如何光栅化图元之前,我们需要理解OpenGL ES 3.0 中使用的各种坐标系统。这对于更好地理解 OpenGL ES 3.0管线不同阶段中顶点坐标发生的变化是必需的。

1.1 坐标系统

下图展示了顶点通过顶点着色器和图元装配阶段时的坐标系统。

顶点以物体或者本地坐标空间输入到OpenGL ES ,这是最困难用来建模和存储一个对象的坐标空间。

在顶点着色器指向之后,顶点位置被认为是在裁剪坐标空间内。

顶点位置从本地坐标空间(也就是物体坐标)到裁剪坐标空间的变化通过加载执行这一转换的对应矩阵来完成,这些矩阵保存在顶点着色器中定义的对应统一变量中。

在后续的博客再介绍如何将顶点位置从对象变化到裁剪坐标,以及如何在顶点着色器中加载对应的矩阵以执行这一变换。

1.1.1 裁剪

为了避免在可视景体之外处理图元,图元被裁剪到裁剪空间

执行顶点着色器之后的顶点位置处于裁剪坐标空间内。

裁剪坐标是有(Xc,Yc,Zc,Wc)指定的同类坐标。在裁剪空间(Xc,Yc,Zc,Wc)中定义的顶点坐标根据视景体(又称裁剪体)裁剪。

裁剪体由6个裁剪平面定义,这些平面被称作 近、远、左、右、上、下裁剪平面。如下图所示:

在裁剪坐标中,裁剪体如下:

-Wc<=Xc<=Wc
-Wc<=Yc<=Wc
-Wc<=Zc<=Wc

前面的6项检查根据需要裁剪的图元,有助于确定平面的列表。

裁剪阶段把每个图元裁剪为上图所示的裁剪体。

我们在这里所说的“图元”,是指用

  • GL_TRIANGLES绘制的单独三角形列表中的每一个三角形,或者一个三角形条带或者扇形中的一个三角形,
  • 或者用GL_LINES绘制的单独直线列表中的一条指向,或者一个直线条带或者闭合折线中的一条直线
  • 或者点精灵列表中的一个特定点。

对于每种图元类型,执行如下操作:

  • 裁剪三角形

    1. 如果三角形完全在视景体内部,则不执行任何裁剪。
    2. 如果三角形完全在视景体之外,则该直线被抛弃。
    3. 如果三角形部分在视景体内,则根据相应的平面裁剪三角形。裁剪操作将生成新的顶点,这些顶点被裁剪到安排为三角扇形的平面。
  • 裁剪直线

    1. 如果直线完全在视景体内部,则不执行任何裁剪。
    2. 如果直线完全在视景体之外,则该直线被抛弃。
    3. 如果直线部分在视景体内,则直线被裁剪并生成相应的新顶点。
  • 裁剪点精灵

    1. 如果点位置在近或者远裁剪平面之外,或者如果表示点精灵的正方形在裁剪体之外,裁剪阶段将抛弃点精灵
    2. 否则,它将不做变化地通过该阶段,点精灵将在其从裁剪体内部移到到外部时裁剪,反之亦然。

在图元根据六个裁剪平面进行裁剪时,顶点坐标经历透视分离,从而称为规范化的设备坐标。

规范化的设备坐标范围是 -1.0 到 1.0

1.2 透视分割

透视分割取得裁剪坐标(Xc,Yc,Zc,Wc)指定的点,并将其投影到屏幕或者视口上。

这个投影通过将(Xc,Yc,Zc) 除以 Wc 进行。执行(Xc/Wc)、(Yc/Wc)、(Zc/Wc)之后,我们得到规范化的设备坐标(Xd,Yd,Zd)

这些坐标被称为规范化设备坐标,因为它们落在[ -1.0 ... 1.0 ] 区间

这些规范化的(Xd, Yd)坐标根据视口的大小将被转换为真正的屏幕(或者窗口)坐标。规范化的(Zd)坐标将用glDepthRangf指定的nearfar深度值转换为屏幕的Z值。这些转换在视口变化阶段进行。

1.3 视口变换

视口是一个二维矩形窗口区域,是所有OpenGL ES渲染操作最终显示的地方。

视口变换可用如下API调用设置:

void glViewport(GLint x, GLint y, GLsizei w, GLsizei h)

参数说明:

  • x, y
    指定视口的左下角的窗口坐标,以像素表示
  • w,h
    指定视口的宽度和高度,以像素表示,这些值必须大于0

从规范化设备坐标(Xd,Yd,Zd)到窗口坐标(Xw,Yw,Zw)的转换用如下变换给出:

在这个变换中,Ox = x + w / 2, Oy = y + h / 2n和f代表所需的深度范围。

深度范围值n和f可以用如下API调用设置:

void glDepthRangef(GLclampf n, GLclampf f)

参数说明:

  • n、f 指定所需的深度范围。n和f的默认值分别为 0.0 和 1.0。 这两个值限于 (0.0 ,1.0) 区间内。

glDepthRangefglViewport指定的值用于将顶点位置从规范化设备坐标转换为窗口(屏幕)坐标。

初始视口状态被设置为 w = width , h = height ,分别是OpenGL ES 渲染应用程序创建的窗口的宽度和高度。
这个窗口由 eglCreateWindowSurface中指定的EGLNativeWindowType win 参数给出。

以上是关于我的OpenGL学习进阶之旅介绍一下OpenGL ES的图元装配:坐标系统透视分割视口变化的主要内容,如果未能解决你的问题,请参考以下文章

我的OpenGL学习进阶之旅介绍 顶点数组对象VAO并实战一下

我的OpenGL学习进阶之旅介绍一下OpenGL ES的图元装配:坐标系统透视分割视口变化

我的OpenGL学习进阶之旅介绍一下OpenGL ES的图元装配:坐标系统透视分割视口变化

我的OpenGL学习进阶之旅介绍一下 映射缓冲区对象和复制缓冲区对象

我的OpenGL学习进阶之旅介绍一下 绘制图元

我的OpenGL学习进阶之旅介绍一下 绘制图元