2021SC@SDUSC
一、简述
这篇博客继续上一篇未分析完的部分继续分析,分析2D渲染服务。
二、分析
我们先看一下我们曾在Render2D.h这个头文件中介绍过的开始渲染函数,其有多个重载:
API_FUNCTION() static void Begin(GPUContext* context, GPUTexture* output, GPUTexture* depthBuffer = nullptr);
API_FUNCTION() static void Begin(GPUContext* context, GPUTexture* output, GPUTexture* depthBuffer, API_PARAM(Ref) const Matrix& viewProjection);
API_FUNCTION() static void Begin(GPUContext* context, GPUTextureView* output, GPUTextureView* depthBuffer, API_PARAM(Ref) const Viewport& viewport);
API_FUNCTION() static void Begin(GPUContext* context, GPUTextureView* output, GPUTextureView* depthBuffer, API_PARAM(Ref) const Viewport& viewport, API_PARAM(Ref) const Matrix& viewProjection);
(1)从最简单的,含有三个参数包括要使用的 GPU 命令上下文、输出目标和深度缓冲区:
ASSERT(output != nullptr);
Begin(context, output->View(), depthBuffer ? depthBuffer->View() : nullptr, Viewport(output->Size()));
对输出目标进行了判断,关于ASSERT这个预定义宏,目的是执行表达式的硬断言, 使引擎崩溃并在表达式失败时插入调试器中断。
调用Begin()的重载, Viewpoint为输出视点,关于这个重载函数的实现我们在下面分析,在此之前我们先看第二个函数。
(2)增加的一个参数viewProjection:视图*投影矩阵。,允许以 3D 或自定义转换呈现 GUI。
ASSERT(output != nullptr);
Begin(context, output->View(), depthBuffer ? depthBuffer->View() : nullptr, Viewport(output->Size()), viewProjection);
这里调用的是另一个Begin()的重载。
(3)这里我们看关于(1)中所调用的Begin()的重载函数的实现(这里仅截取部分代码用于分析):
Matrix::OrthoOffCenter(-halfWidth, halfWidth, halfHeight, -halfHeight, zNear, zFar, projection);
Matrix::Translation(-halfWidth, -halfHeight, 0, view);
Matrix::Multiply(view, projection, viewProjection);
Begin(context, output, depthBuffer, viewport, viewProjection);
halfWith,halfHeight为视点宽度和高度的一半,zNear和zFar分别为浮点数的0和1。view, projection, viewProjection为Matrix类型,表示一个 4x4 的数学矩阵。
OrthoOffCenter创建一个左手的、自定义的正交投影矩阵。参数含义依次为观测量的最小 x 值、观测量的最大 x 值、观测量的最小 y 值、观测量的最大 y 值、观测量的最小 z 值、观测量的最大 z 值、当方法完成时,包含创建的投影矩阵。
Translation使用指定的偏移量创建平移矩阵。参数依次为X 坐标偏移、Y 坐标偏移、Z 坐标偏移、当方法完成时,包含创建的投影矩阵。
Multiply计算两个矩阵的乘积。参数依次为矩阵1(左)、矩阵2(右)、结果。
然后再调用最后一个重载函数。
(4)这里我们介绍最后一个重载的Begin(),也就是上述几个Begin()函数调用的最底层:
ASSERT(Context == nullptr && Output == nullptr);
ASSERT(context != nullptr && output != nullptr);
先对 命名空间内预先声明的GPUContext*(代码中的Context)和GPUTextureView*(Output)是否为空进行判断;同时判断形参是否有内容。
设置:
Context = context;
Output = output;
DepthBuffer = depthBuffer;
View = viewport;
ViewProjection = viewProjection;
DrawCalls.Clear();
初始化默认转换,清空转换层堆栈,再将默认转换压入栈中:
const Matrix3x3 defaultTransform = Matrix3x3::Identity;
TransformLayersStack.Clear();
TransformLayersStack.Push(defaultTransform);
TransformCached = defaultTransform;
初始化默认剪辑蒙版:
const Rectangle defaultBounds(viewport.Location, viewport.Size);
const RotatedRectangle defaultMask(defaultBounds);
ClipLayersStack.Clear();
ClipLayersStack.Add({ defaultMask, defaultBounds });
初始化默认色调堆栈 :
TintLayersStack.Clear();
TintLayersStack.Add({ 1, 1, 1, 1 });
只能为 2D 正投影启用剪刀,因此此处设置为false:
IsScissorsRectEnabled = false;
重置几何缓冲区:
VB.Clear();
IB.Clear();
VBIndex = 0;
IBIndex = 0;
到这里,开始渲染的整个流程已经分析结束,下一篇博客将关注结束时所作的工作以及其他2D渲染操作。