我的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.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
指定的near
和far
深度值转换为屏幕的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 / 2
, n和f
代表所需的深度范围。
深度范围值n和f
可以用如下API调用设置:
void glDepthRangef(GLclampf n, GLclampf f)
参数说明:
n、f
指定所需的深度范围。n和f
的默认值分别为0.0 和 1.0
。 这两个值限于(0.0 ,1.0)
区间内。
glDepthRangef
和 glViewport
指定的值用于将顶点位置从规范化设备坐标转换为窗口(屏幕)坐标。
初始视口状态被设置为 w = width , h = height
,分别是OpenGL ES
渲染应用程序创建的窗口的宽度和高度。
这个窗口由 eglCreateWindowSurface
中指定的EGLNativeWindowType
win
参数给出。
以上是关于我的OpenGL学习进阶之旅介绍一下OpenGL ES的图元装配:坐标系统透视分割视口变化的主要内容,如果未能解决你的问题,请参考以下文章
我的OpenGL学习进阶之旅介绍 顶点数组对象VAO并实战一下
我的OpenGL学习进阶之旅介绍一下OpenGL ES的图元装配:坐标系统透视分割视口变化
我的OpenGL学习进阶之旅介绍一下OpenGL ES的图元装配:坐标系统透视分割视口变化