[c++][SDL]图形学菜鸡的软渲染之路1-渲染流程概述

渲染流程概览

参考了很多大佬的博客,最终也成功写出了自己的软渲染器,这里记录一下自己的学习心得,有错的话希望大家可以指正。

此节参考资料:LearnOpenGL CN 坐标系统
项目github地址:SoftRenderer

1.效果

图像渲染的过程就是将三维空间中面片数据的映射到二维空间中,并对这一面片进行着色的过程。软渲染就是用软件模拟硬件中的各种操作,完成这一过程。

我们的所有模型都可以用很多个三角面片进行近似,本文中软渲染器也用三角面片为渲染的基本单位。(下面是用我的软渲染器实现的效果)

图片 描述
在这里插入图片描述 只渲染三角面片的边获得的图像
s 使用各种贴图进行三角形光栅化后得到的图像

2.模型变换

让我们来粗略的模拟一下一个三角面片变成屏幕像素的过程:

ps:这里使用和openGL相同的右手坐标系进行演示。数学相关的细节之后会讲到这里只做概念介绍

首先,我们从模型中得到了三个顶点ABC,它们组成了一个三角面片,此时三角形面片位于局部坐标系,也就是建模时使用的坐标系。
在这里插入图片描述

我们在场景中摆放模型时,常常需要对它进行平移旋转缩放等操作,将模型放在我们需要的位置。这时需要使用
模型矩阵(MODEL MATRIX)局部坐标系(Local Coordinate) 转换到 世界坐标系(World Coordinate) 下。

在这里插入图片描述

3.视图变换

接下来我们需要一个摄像机,将 世界坐标系(World Coordinate) 下的三角面片转换到 观察坐标系(View Coordinate)(也被叫做摄像机空间(Camera Space)或视觉空间(Eye Space)),为了更好的理解这一步是在做什么,这里先现在演示一种最简单的情况。

我们有一个摄像机在z轴上,看向z轴负方向。此时世界坐标系与观察坐标系方向相同,我们可以通过令所有顶点的z值为0简单的得到三角面片到xoy平面的投影。(为什么z轴朝向摄像机后方?这里是因为openGL里z轴是由屏幕里面指向自己的,只是个规定。)
在这里插入图片描述
此时摄像机的视野是这样的,只需令顶点的z值为0,我们其实已经很简单的完成了三维空间到二维平面的转换。
在这里插入图片描述

但是因为真实世界中还有近大远小的透视效果,我们的摄像机也不总能恰好在z轴且指向z轴负方向,所以我们还需要对三角形顶点继续进行运算,但是通过这个例子我们可以了解到,视图变换可以方便后面进行投影。
在这里插入图片描述

对于任意位置的摄像机,我们都可以使用 观察矩阵(VIEW MATRIX) 将 世界坐标系(World Coordinate) 的坐标转换到 观察坐标系(View Coordinate) 下,此次变换后,z轴就存储了顶点距离摄像机的位置信息,我们可以利用这一数据,通过透视矩阵实现近大远小的效果。

4.投影变换

只有一个三角形面片很难用图片演示透视变换,接下来请允许我换一种表达方式。透视变换会通过一些参数定义一个视锥(决定了摄像机可以看到那些地方),然后将这个视锥变换成一个立方体(xyz范围在[-w,w]),然后通过透视除法将这个立方体变为标准设备坐标系(xyz范围在[-1,1])。

在这里插入图片描述

效果如图:
红色为视锥,蓝色为我们的模型
在这里插入图片描述

变换后视锥会变成立方体,其中的内容会被跟随视锥进行缩放。
在这里插入图片描述

至此,我们通过使用 投影矩阵(PROJECTION MATRIX)观察坐标系(View Coordinate) 转换到了 裁剪坐标系(Clip Coordinate) 下。
在这里插入图片描述

之所以叫做裁切坐标系,是因为我们希望这一步后,所有不在投影(红色)范围内的模型都被裁切掉(齐次裁切)。裁剪后我们需要根据剩下的顶点重写构建三角形。

5.标准设备变换

在投影变换后,我们进行 透视除法(Perspective Division) ,将裁剪坐标系(Clip Coordinate) 转换到 标准设备坐标系(ndc Coordinate) ,标准设备坐标系中xyz都在[-1,1]范围中,方面我们将其坐标映射到屏幕。
在这里插入图片描述

6.视窗变换

得到了ndc坐标,我们就可以通过 视窗变换(Viewport Transform) 将顶点坐标转换到 屏幕坐标系(Screen Coordinate) 上了。
****视窗变换****

7.光栅化

至此,我们的3维坐标已经转换到了二维屏幕坐标。接下来的工作就是讲连续的图元变成离散的像素点,即光栅化。假设我们的屏幕为24x16像素。
在这里插入图片描述

这里用黑色对三角形的边进行光栅化,结果将类似与下图:
在这里插入图片描述

这个效果可以用直线光栅化算法,如Bresenham实现。除了对边进行光栅化,我们还可以用扫描线算法,重心坐标算法等算法对整个三角形进行光栅化。当我们把变换到屏幕坐标的三角形栅格化后,整个渲染流程就走完一半了。

在实际实现的时候,现在这个框架会将模型背面看不见的三角形面片也会被计算一遍,效率很低。而且因为面片绘制顺序和空间位置无关,有可能背面的面会后绘制,从而遮挡已经绘制好了的在前面的面,出现各种奇怪的效果。
在这里插入图片描述

如果后期要使用材质贴图,我们还要处理透视变形(地板贴图没有正确显示)的问题。
在这里插入图片描述

而且这个框架没有计算任何光照数据。但此时的功能已经可以帮助我们实现线框模型的正确渲染了。

猜你喜欢

转载自blog.csdn.net/weixin_43153753/article/details/107643321