我的这个3D渲染器是模仿D3D11的流水线的,不过我的渲染器是固定渲染流水线的。
3D渲染流水线
我的流水线如下所示:
放出我的渲染函数代码,跟上面流水线图(没给出具体的实现细节)差不多:
void UpdateScene()
{
//进行输入的更新
InputUpdate();
//赋予顶点缓存数据
PointList_Mem = PointList;
//重新获取世界矩阵
worldMatrix = BuildIdentityMatrix();
//移动世界矩阵
Matrix translateMa = BuildTranslateMatrix(0.0, 0.0f, 0.0f);
worldMatrix = MatrixMultiply(&translateMa, &worldMatrix);
//更新旋转矩阵的
static float y =0.0f;
y += 0.5f;
if (y >= 360.0f)
y = 0.0f;
static float x = 0.0f;
x += 0.5f;
if (x >= 360.0f)
x = 0.0f;
//获取X和Y旋转矩阵
Matrix RotateYMa = BuildRotateYMatrix(y);
Matrix RotateXMa = BuildRotateXMatrix(x);
//更新世界矩阵
worldMatrix = MatrixMultiply(&RotateYMa, &worldMatrix);
worldMatrix = MatrixMultiply(&RotateXMa, &worldMatrix);
//将所有顶点的法向量变换到世界空间,这里是变换顶点的法向量
TransormObjectNormalToWorld(PointList_Mem, &worldMatrix);
//对所有顶点进行世界变换,这里是变换顶点的位置
ObjectTransform(PointList_Mem, &worldMatrix);
//对所有顶点进行相机变换
ObjectTransform(PointList_Mem, &ViewMatrix);
//对所有顶点进行透视投影变换
ObjectTransform(PointList_Mem, &ProjMatrix);
//进行CVV裁剪算法
CVVClip(PointList_Mem);
//对所有顶点进行透视除法
PerspectiveDivede(PointList_Mem);
//对所有顶点进行视口变换
ObjectTransform(PointList_Mem, &ViewPortMatrix);
//进行背面剔除
BackCull(PointList_Mem);
}
坐标系的选择
3D图形学里D3D11的为左手坐标系,OpenGL的为右手坐标系,先来看看来两种坐标系的区别:
(1)左手坐标系
(2)右手坐标系
那么怎么区分左手和右手呢?
方法有两种:方法一,非常直观的看到,左手坐标系的Z坐标是往纸内的,而右手坐标系的Z坐标是往纸外的。
方法二,用我们的左手和右手,如下面图所示,左边的图那只手为左手,四指从X轴饶向Y轴,拇指指向为左手坐标系的Z轴方向,
右边的图那只手为右手,四指从X轴饶向Y轴,拇指指向为右手坐标系的Z轴方向。
上面说了那么多,我只想说一句:我的3D渲染器是使用与DX11一样的坐标系的,也就是局部空间,世界空间,相机空间都是左手坐标系。这里顺便说下OpenGL的局部空间,世界空间都是右手坐标系。