文章目录
- OpenGL到底实现的是什么?
- OpenGL内模型数据的本质是什么?
- 为什么三角形是 3D 渲染的最基本单元?
- MVP 变换(Model-View-Projection 变换)
- OpenGL渲染流程-摄像机变换
- OpenGL渲染流程-投影变换
- OpenGL渲染管线概述
OpenGL到底实现的是什么?
上述图中左边有一个圆柱体。我们的观看视角是从左上方LOOK去观察这个圆柱体,在这种情况下,我们会在右边的屏幕上看到一个扁平的圆柱体。所谓的OpenGL实现的渲染就是从某个方向看向场景中的物体,最终在屏幕上渲染成一张图片的功能。
OpenGL内模型数据的本质是什么?
在 OpenGL 中,顶点数据(Vertex Data) 是渲染 3D 物体的基本单位。每个顶点可以包含位置(Position)、颜色(Color)、法线(Normal)、纹理坐标(Texture Coordinates)等信息。这些数据通常存储在 顶点缓冲对象(VBO,Vertex Buffer Object) 中,并由顶点着色器(Vertex Shader)处理。
为什么三角形是 3D 渲染的最基本单元?
在 OpenGL 和计算机图形学中,三角形是无敌的! 这是因为三角形在 3D 渲染中具有许多独特的优势,使其成为构建复杂几何形状的基础单元。
1. 三角形是最简单的平面图元
- 最少的顶点数:三角形是最简单的多边形,只需 3 个顶点 就能确定一个平面,而四边形可能是非平面的(比如扭曲的四边形)。
- 计算简单:任何 3D 空间中的三角形顶点都可以唯一确定一个平面,避免了几何上的歧义。
2. 三角形永远是平面的
- 在 3D 空间中,任意 3 个不共线的点总能唯一确定一个平面,而四边形或多边形可能会因为顶点不共面而导致扭曲(例如凸起的四边形无法保证在同一平面上)。
- 由于三角形始终是平面的,它在光照、纹理映射和裁剪等渲染计算中更高效、更稳定。
MVP 变换(Model-View-Projection 变换)
1. MVP 变换的三个阶段
MVP 变换由三个矩阵相乘而成:
MVP=Projection×View×Model
Model 变换(M,模型矩阵):
- 作用:把物体从本地坐标系(Local Space)转换到世界坐标系(World Space)。
- 典型操作:平移(Translate)、旋转(Rotate)、缩放(Scale)。
View 变换(V,视图矩阵):
- 作用:把物体从世界坐标系(World Space) 转换到相机坐标系(Camera Space)。
- 典型操作:定义相机位置、方向、朝向,模拟我们用眼睛看物体的方式。
Projection 变换(P,投影矩阵):
- 作用:把物体从相机坐标系(Camera Space)转换到 裁剪坐标系(Clip Space),然后进行透视除法(Perspective Division),最终变换到屏幕坐标系(Screen Space)。
- 透视投影(Perspective Projection):适用于 3D 场景,近大远小。
- 正交投影(Orthographic Projection):适用于 2D 或 CAD 场景,平行投影。
2. MVP 变换流程图
局部坐标 (Local Space)↓ (Model 变换)
世界坐标 (World Space)↓ (View 变换)
相机坐标 (Camera Space)↓ (Projection 变换)
裁剪坐标 (Clip Space)↓ (透视除法)
NDC (Normalized Device Coordinates)↓ (视口变换)
屏幕坐标 (Screen Space)
OpenGL渲染流程-摄像机变换
在 OpenGL 的渲染流程中,摄像机变换(视图变换)是将场景从世界坐标系转换到摄像机坐标系(观察空间)的关键步骤。这一步模拟了从摄像机视角观察场景的效果。
OpenGL 渲染流程概述:
- 顶点着色器:处理顶点属性,如位置、法线和纹理坐标。
- 图元装配:将顶点组装成图元(如点、线、三角形)。
- 几何着色器(可选):对图元进行进一步处理或生成新的图元。
- 光栅化:将图元转换为片段(像素),准备进行逐像素处理。
- 片段着色器:计算每个片段的颜色和其他属性。
- 测试与混合:执行深度测试、模板测试、混合等操作,最终将片段写入帧缓冲区。
摄像机变换(视图变换):
在上述流程中,视图变换发生在顶点着色器阶段之前。它将顶点从世界坐标系转换到摄像机坐标系,使场景以摄像机为中心进行观察。
实现视图变换的关键步骤:
- 定义摄像机位置(Position):确定摄像机在世界坐标系中的位置。
- 定义摄像机目标(Target):确定摄像机所看的目标点。
- 定义上向量(Up Vector):指定摄像机的上方向,用于确定摄像机的旋转和倾斜。
OpenGL渲染流程-投影变换
在 OpenGL 的渲染流程中,投影变换(Projection Transformation)是将场景从摄像机坐标系(视图空间)转换到裁剪坐标系的关键步骤。这一过程决定了如何将三维场景投影到二维屏幕上,以实现逼真的视觉效果。
投影变换的主要类型:
透视投影(Perspective Projection):
- 特点:模拟人眼的视觉效果,具有近大远小的透视效果。
- 应用:广泛用于需要深度感的 3D 场景渲染,如游戏和虚拟现实。
正交投影(Orthographic Projection):
- 特点:平行投影,物体无论远近都保持相同的尺寸,没有透视缩放。
- 应用:常用于工程制图、CAD 应用和某些 2D 游戏。
投影矩阵的作用:
投影矩阵将摄像机坐标系中的三维坐标转换为裁剪坐标系。在裁剪坐标系中,坐标被标准化到一个特定范围内,通常是 [-1, 1]。任何超出这个范围的顶点都会被裁剪掉,即不会被渲染。
投影变换的过程:
- 定义投影矩阵:根据所需的投影类型(透视或正交),设置相应的参数,如视锥体的左右、上下、近远平面等。
- 应用投影矩阵:将投影矩阵应用于顶点坐标,将其从视图空间转换到裁剪空间。
- 透视除法:在裁剪空间中,对顶点的齐次坐标进行透视除法,将其转换为标准化设备坐标(NDC)。
注意事项:
- 在透视投影中,近剪裁面(near plane)必须为正值,且远剪裁面(far plane)大于近剪裁面。
- 投影矩阵的设置直接影响场景的视野、深度感和最终的渲染效果。
OpenGL渲染管线概述
1.顶点着色器(Vertex Shader)
在OpenGL中,顶点着色器(Vertex Shader)是图形渲染管线的第一个可编程阶段,负责处理输入的顶点数据。它的主要作用是对每个顶点进行独立的处理,并将处理后的数据传递给后续的渲染阶段。顶点着色器是OpenGL着色器编程的核心部分之一,开发者可以通过编写顶点着色器代码来实现自定义的顶点变换和处理逻辑。
顶点着色器的作用:
- 顶点变换:将顶点的局部坐标(模型空间)转换为世界坐标、观察坐标(相机空间)和裁剪空间坐标。通常通过矩阵乘法(如模型矩阵、视图矩阵和投影矩阵)来实现。
- 顶点属性处理:处理顶点的属性数据,如位置、颜色、法线、纹理坐标等。可以将这些属性传递给后续的片段着色器或其他着色器阶段。
- 自定义计算:开发者可以在顶点着色器中实现自定义的计算逻辑,例如顶点动画、变形效果、光照计算(如顶点光照)等。
- 数据传递:将处理后的顶点数据(如位置、颜色、纹理坐标等)传递给后续的渲染阶段(如图元装配、几何着色器、片段着色器等)。
2.形状装配(Shape Assembly)
在OpenGL中,Shape Assembly(形状装配)是图形渲染管线中的一个固定功能阶段,位于顶点处理之后和几何处理之前。它的主要作用是将顶点数据组装成基本的几何图元(如点、线、三角形等),为后续的光栅化和片段处理做准备。
形状装配的作用:
- 图元组装:将顶点数据按照指定的图元类型(如 GL_POINTS、GL_LINES、GL_TRIANGLES 等)组装成几何图元。
- 裁剪(Clipping):在组装过程中,OpenGL会检查图元是否在视景体(View Volume)内。如果图元完全在视景体内,则保留;如果完全在视景体外,则丢弃;如果部分在视景体内,则进行裁剪,只保留可见部分。
- 透视除法(Perspective Division):将顶点从裁剪空间坐标(Clip Space)转换为标准化设备坐标(NDC,Normalized Device Coordinates)。透视除法是通过将裁剪空间坐标的(x, y, z, w) 分量除以 w 来实现的。
- 视口变换(Viewport Transformation):将标准化设备坐标(NDC)映射到屏幕空间(窗口坐标)。这一步骤决定了最终的图元在屏幕上的位置和大小。
- 为光栅化做准备:组装后的图元会被传递给光栅化阶段,光栅化会将图元转换为片段(像素)。
3.几何着色器(Geometry Shader)
在OpenGL中,几何着色器(Geometry Shader)是图形渲染管线中的一个可选阶段,位于顶点着色器之后和光栅化之前。它的主要作用是对图元(如点、线、三角形等)进行进一步处理,并可以生成新的图元。几何着色器提供了更大的灵活性,允许开发者在图元级别上实现复杂的几何变换和生成。
几何着色器的作用:
- 图元变换:可以对输入的图元进行修改,例如将点扩展为四边形、将线扩展为带状多边形等。可以实现几何变形、细分、简化等效果。
- 图元生成:可以生成新的图元,例如从一个点生成多个点,或从一个三角形生成多个三角形。适用于粒子系统、几何实例化等场景。
- 图元剔除:以根据某些条件(如位置、法线方向等)决定是否丢弃某些图元。
- 数据传递:可以将处理后的图元数据传递给后续的渲染阶段(如光栅化和片段着色器)。
4.Tests and Blending(测试与混合)
在OpenGL中,Tests and Blending(测试与混合)是图形渲染管线中片段处理阶段的关键步骤,用于决定最终写入帧缓冲区的片段颜色和深度值。这些操作在片段着色器之后执行,主要用于处理片段的可见性、透明度和颜色混合等问题。
- 测试(Tests):深度测试(Depth Test)、模板测试(Stencil Test)、裁剪测试(Scissor Test)。
- 混合(Blending):透明度混合、颜色混合公式、混合因子。
5.片段着色器(Fragment Shader)
在OpenGL中,片段着色器(Fragment Shader)是图形渲染管线中的一个关键可编程阶段,负责处理光栅化后生成的片段(Fragment),并计算每个片段的最终颜色和其他属性。片段着色器是OpenGL着色器编程的核心部分之一,开发者可以通过编写片段着色器代码来实现各种视觉效果,如光照、纹理映射、颜色混合等。
片段着色器的作用:
- 颜色计算:计算片段的最终颜色,通常基于光照模型、纹理采样、顶点颜色等。可以实现复杂的光照效果(如漫反射、镜面反射、环境光等)。
- 纹理映射:通过采样纹理,将纹理颜色应用到片段上。支持多重纹理、纹理混合等高级纹理技术。
- 片段丢弃:根据某些条件(如透明度、深度值等)决定是否丢弃片段。丢弃的片段不会写入帧缓冲区。
- 数据输出:将计算后的颜色和其他数据(如深度值、模板值)写入帧缓冲区。支持多渲染目标(MRT),可以同时输出多个颜色附件。
- 自定义效果:实现各种视觉效果,如阴影、模糊、边缘检测、颜色校正等。
6.光栅化(Rasterization)
在OpenGL中,光栅化(Rasterization)是图形渲染管线中的一个关键阶段,位于顶点处理之后和片段处理之前。它的主要作用是将几何图元(如点、线、三角形等)转换为片段(Fragment),即屏幕上的像素候选。光栅化是连接几何处理和像素处理的桥梁,决定了图元如何在屏幕上显示。
光栅化的作用:
- 图元到片段的转换:将几何图元(如三角形)分解为片段,每个片段对应屏幕上的一个像素候选。片段包含颜色、深度、纹理坐标等插值属性。
- 插值计算:对图元的顶点属性(如颜色、纹理坐标、法线等)进行插值,生成每个片段的属性值。插值是基于片段的屏幕位置和顶点的属性值计算的。
- 片段生成:确定哪些像素位于图元内部或边缘,并生成相应的片段。对于部分覆盖图元的像素,光栅化会生成多个片段。
为片段处理做准备:生成的片段会传递给片段着色器进行进一步处理。