URasterizer实现(1):框架搭建和矩阵构造
2024-02-08 02:29:10
在探索游戏图形技术过程中,若对底层的实现略知一二,就会发现简单而强大的实现往往离不开一些很深奥的数学知识。软光栅化作为如今高精度光栅化的雏形,从原理上说,也不存在太大的难度,如果说有什么晦涩难懂的东西,我想就是其中所蕴含的那些数学知识。
本文将基于Unity引擎创建一个软光栅实现的项目,并分成三个系列文章进行详细阐述:
- 项目的框架搭建和模型视图投影矩阵的构造;
- 栅格化与光栅化算法;
- 其他功能的实现(例如Z-buffer、纹理贴图、光照等)。
本文重点关注项目的框架搭建以及模型视图投影矩阵的构造。
框架搭建
新建Unity项目,项目命名为URasterizer,创建Assets文件夹下的Scenes、Scripts、Shaders三个子文件夹,分别用于存放场景、脚本和着色器。
1. 场景搭建
新建场景main,在场景中创建一个名为Camera的主摄像机,并设置其位置和朝向。
2. 脚本编写
在Scripts文件夹下创建URasterizer脚本,用于控制光栅化的过程。URasterizer脚本主要包含以下几个函数:
- Start() :在场景开始时调用,用于初始化相关变量。
- Update() :在每一帧调用,用于更新光栅化的过程。
- OnRenderImage() :在每一帧渲染图像时调用,用于执行光栅化算法。
3. 着色器编写
在Shaders文件夹下创建VertexShader和FragmentShader两个着色器文件,用于处理顶点和片元。
VertexShader着色器主要用于将顶点坐标从模型空间变换到裁剪空间,其代码如下:
#pragma vertex vert
struct appdata {
float4 position : POSITION;
};
struct v2f {
float4 position : SV_POSITION;
};
v2f vert(appdata v) {
v2f o;
o.position = mul(UNITY_MATRIX_MVP, v.position);
return o;
}
FragmentShader着色器主要用于将片元颜色从裁剪空间变换到屏幕空间,其代码如下:
#pragma fragment frag
struct v2f {
float4 position : SV_POSITION;
};
fixed4 frag(v2f i) : SV_TARGET {
return fixed4(1, 0, 0, 1);
}
矩阵构造
在URasterizer脚本中,我们使用Unity提供的矩阵函数来构造模型视图投影矩阵。模型视图投影矩阵由模型矩阵、视图矩阵和投影矩阵相乘得到。
1. 模型矩阵
模型矩阵用于将模型坐标变换到世界坐标。模型矩阵的构造非常简单,只需要使用Matrix4x4.TRS(position, rotation, scale)
函数即可。
// 模型矩阵
Matrix4x4 modelMatrix = Matrix4x4.TRS(modelPosition, modelRotation, modelScale);
2. 视图矩阵
视图矩阵用于将世界坐标变换到摄像机坐标。视图矩阵的构造也比较简单,只需要使用Camera.main.worldToCameraMatrix
属性即可。
// 视图矩阵
Matrix4x4 viewMatrix = Camera.main.worldToCameraMatrix;
3. 投影矩阵
投影矩阵用于将摄像机坐标变换到裁剪空间。投影矩阵的构造稍微复杂一些,我们需要使用Matrix4x4.Perspective(fieldOfView, aspect, near, far)
函数。
// 投影矩阵
Matrix4x4 projectionMatrix = Matrix4x4.Perspective(60, (float)Screen.width / (float)Screen.height, 0.1f, 1000f);
4. 模型视图投影矩阵
模型视图投影矩阵由模型矩阵、视图矩阵和投影矩阵相乘得到。
// 模型视图投影矩阵
Matrix4x4 mvpMatrix = projectionMatrix * viewMatrix * modelMatrix;
在URasterizer脚本中,我们将模型视图投影矩阵传递给顶点着色器,以便顶点着色器能够将顶点坐标从模型空间变换到裁剪空间。
以上就是基于Unity的软光栅实现项目框架的搭建和模型视图投影矩阵的构造过程。在下一篇博文中,我们将介绍光栅化与栅格化算法。