我是靠谱客的博主 虚拟犀牛,最近开发中收集的这篇文章主要介绍matlab z变换离散化_光栅化渲染器的实现,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

引言

图形渲染管线到底干了什么?这是任何一个学习图形学的人都无法逃避的问题。

现代的API(如OpenGL,DirectX等)都将其具体过程封装好了,使用的时候只需传入相应参数,调用函数即可达到渲染的目的。尽管不了解它的原理并不影响使用,但为了编程可持续发展(雾),最好还是自己手动实现一下光栅化渲染器

以下我简单地阐述图形渲染管线的流程(以OpenGL辅以理解),我会用整体->细节的结构去阐述这个流程

正文

整体

首先是一张流传甚广的图片:

3e06ae39ec8ef2a93d38d909847dfd36.png

这是OpenGL的图形渲染管线(蓝色底代表可编程)示意图,从上我们可以知道图形渲染管线的功能是什么:输入顶点数据,输出屏幕上我们看到的东西。

更加具体一点:输入顶点数据至顶点着色器,接着进行图元装配,(几何着色器可选),然后光栅化(将连续的顶点映射至屏幕,由于屏幕是一个一个的像素(离散的),所以称之为光栅化),接着进行着色,最后进行各种测试和混合(深度测试、模板测试,颜色混合之类的)。

由此,我们知道了图形渲染管线的大致流程,下面开始深入讲解细节。

细节

同样是以一张图开局

e0aa643402791fcd17edfa5001df0e58.png

我们先抛开OpenGL中的那些人为划定的Shader,直接来看渲染管线干了些什么。

Application 这是完全由开发者控制的阶段,通常在CPU上运行,一般是执行一些碰撞之类的计算。此阶段不可再分。

Geometry 这个阶段分为四个小流程,分别是:vertex shadingoptional vertex processingclippingscreen mapping

Rasterization 这个阶段有两个部分,primitive setupprimitive traversal

Pixel Processing 分为Pixel ShadingMerging


Geometry

vertex shading

此阶段有两个任务:计算顶点位置,计算其他属性的值(如法线、纹理坐标,颜色等)。

  • 计算顶点的位置。我们所熟知的model->view->projection在这里计算。

具体地说。model变换由三个变换组成:缩放(scale),旋转(rotate),平移(translate),通过矩阵乘法来执行这些操作。(注:rotate用的是四元数而非欧拉角的方式实现,因为欧拉角会导致Gimbal Lock的问题:具体参照 Bonus,四元数和欧拉角之间的转化可以参照图书《3D数学基础:图形与游戏开发》或者quaternion。

接着是view矩阵(即摄像机)。

最后是projection投影矩阵,这个矩阵的推导较为冗长,这里我给出两个推导的链接:深入探索透视投影变换,OpenGL projection matrix,写的都很好。

  • 计算顶点其他属性的值。在计算的过程中要注意透视纹理映射的问题,具体参考:深入探索透视纹理映射(上), 深入探索透视纹理映射(下)。

optional vertex processing

这个阶段是可选的,有曲面细分,几何着色和流输出(图元装配在曲面细分里面),这不是我们阐述的重点。

clipping

裁剪过程发生在裁剪空间里面(在执行了model->view->projection变换之后,顶点的坐标所处的空间称为裁剪空间)。我们不妨将投影后的点设为

,此时,不符合

的点将会被裁去(裁去之后依据裁剪情况重新组合图元)。

为什么是这个范围?:很简单,在裁剪之后会进行透视除法,将原本perspective构建的视锥体变换到CVV空间(CVV空间中的坐标系称之NDC)中。经过透视除法之后的点(x, y, z,w)变成(x/w, y/w, z/w, 1),我们知道他们应当处于CVV内,即取值范围为[-1, 1](z在DirectX中是[0, 1],在OpenGL中是[-1, 1]),我们将这个取值范围逆着推回来即可。此外透视除法会产生近大远小的效果。

裁剪之后便会进行透视除法,将视锥体变成长方体(OpenGL中是特殊一点的长方体,即正方体),同时产生近大远小的效果。我们也可以说透视除法是要把齐次坐标转回欧式坐标。

screen mapping

将处于CVV空间的

坐标映射到屏幕(视口)上(Z坐标作为深度值存储到深度缓冲中)。

这里我们可以知道,如果Perspective的视锥体的Aspect不为1,透视除法之后会失真,而映射到屏幕(视口)上之后会复原(因此我们要把视口的长宽比设置为PerspectiveAspect一致,这样子映射之后才不会失真)。

Rasterization

光栅化有三角形建立和三角形遍历两个阶段。

  1. primitive setup(三角形(图元)建立):三角形通过传入三个点得以建立。
  2. primitive traversal(三角形(遍历)):遍历三角形内的片元(fragment),送至下一个阶段。

Pixel Processing

  1. pixel shading:所有逐像素的计算都在这里完成,光照,纹理,颜色值都是在这里计算。
  2. merging:执行深度测试,模板测试,混合测试等过程。

总结

写完了光栅化渲染器,对OpenGL中的图形渲染管线(pipeline)有了初步的理解和认知,尽管实现的只是一个最简单的光栅化渲染器,但以后面对封装好的图形库、游戏引擎的时候总不至于两眼一抹黑。

路还长着呢。

拓展知识

  1. Directx在坐标运算中全程采用的是左手坐标系,OpenGLNDC是左手坐标系,其他时候都是右手坐标系。
  2. 为什么坐标的运算要用到齐次坐标?可以参考这个回答:关于齐次坐标的理解(经典),此外也有另外一种角度,参考:深入探索透视投影变换的开头部分。

参考资料

  1. Bonus
  2. quaternion
  3. 3D图形固定短线(这个专栏讲的是真的好)
  4. OpenGL projection matrix
  5. RTR 4th阅读笔记 Chapter2
  6. GPU在进行vertex shading之后,rasterization之前,是怎么剪裁的?——徐行的回答
  7. 在透视投影中要进行透视除法。对于这一步 有没有更具体的解释或更形象的类比 让人容易理解?——milo yip的回答

最后

以上就是虚拟犀牛为你收集整理的matlab z变换离散化_光栅化渲染器的实现的全部内容,希望文章能够帮你解决matlab z变换离散化_光栅化渲染器的实现所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(38)

评论列表共有 0 条评论

立即
投稿
返回
顶部