游戏引擎Flax Engine源码分析(十一)渲染

2021SC@SDUSC


一、概述

        这篇博客继续分析2D渲染的后续内容。

二、分析

        函数DrawBezier()绘制贝塞尔曲线。参数:p1起点、p2第一个控制点、p3第二个控制点、终点、color线条颜色、thickness线条粗细。

static void DrawBezier(const Vector2& p1, const Vector2& p2, const Vector2& p3, const Vector2& p4, const Color& color, float thickness = 1.0f);

   以下内容转载自:链接:https://www.jianshu.com/p/4966455cfcaa      

  贝赛尔曲线是应用于二维图形应用程序的数学曲线。贝兹曲线由线段节点组成,节点是可拖动的支点,线段像可伸缩的皮筋。它通过控制曲线上的四个点(起始点、终止点以及两个相互分离的中间点)来创造、编辑图形。其中起重要作用的是位于曲线中央的控制线。这条线是虚拟的,中间与贝塞尔曲线交叉,两端是控制端点。移动两端的端点时贝塞尔曲线改变曲线的曲率(弯曲的程度);移动中间点(也就是移动虚拟的控制线)时,贝塞尔曲线在起始点和终止点锁定的情况下做均匀移动。    

        下面是Flax Engine绘制贝赛尔曲线的方法:

  •         查找要使用的段数。
  •         绘制分段曲线。
void Render2D::DrawBezier(const Vector2& p1, const Vector2& p2, const Vector2& p3, const Vector2& p4, const Color& color, float thickness)
{
    RENDER2D_CHECK_RENDERING_STATE;

    const Vector2 d1 = p2 - p1;
    const Vector2 d2 = p3 - p2;
    const Vector2 d3 = p4 - p3;
    const float len = d1.Length() + d2.Length() + d3.Length();
    const int32 segmentCount = Math::Clamp(Math::CeilToInt(len * 0.05f), 1, 100);
    const float segmentCountInv = 1.0f / segmentCount;

    Vector2 p;
    AnimationUtils::Bezier(p1, p2, p3, p4, 0, p);
    Lines2.Clear();
    Lines2.Add(p);
    for (int32 i = 1; i <= segmentCount; i++)
    {
        const float t = i * segmentCountInv;
        AnimationUtils::Bezier(p1, p2, p3, p4, t, p);
        Lines2.Add(p);
    }
    DrawLines(Lines2.Get(), Lines2.Count(), color, color, thickness);
}

         2D渲染服务剩余的一些函数如下:

static void DrawMaterial(MaterialBase* material, const Rectangle& rect, const Color& color);
static void DrawBlur(const Rectangle& rect, float blurStrength);
static void DrawTexturedTriangles(GPUTexture* t, const Span<Vector2>& vertices, const Span<Vector2>& uvs);
static void DrawTexturedTriangles(GPUTexture* t, const Span<Vector2>& vertices, const Span<Vector2>& uvs, const Color& color);
static void DrawTexturedTriangles(GPUTexture* t, const Span<Vector2>& vertices, const Span<Vector2>& uvs, const Span<Color>& colors);
static void FillTriangles(const Span<Vector2>& vertices, const Span<Color>& colors, bool useAlpha);
static void FillTriangle(const Vector2& p0, const Vector2& p1, const Vector2& p2, const Color& color);
};

        这里我们只介绍函数的具体作用以及参数的含义,而具体的实现则通过其中一到两个举例。(1) DrawMaterial绘制 GUI 材质。

  • "material"要渲染的材料。 必须是 GUI 材质类型。
  •  "rect"要绘制的目标矩形。
  • "color"要使用的颜色。

(2)DrawBlur 绘制背景模糊。

  • "rect"要绘制的目标矩形(模糊其背景)
  •  "blurStrength"模糊强度定义了背景的模糊程度。 较大的数字会增加模糊,从而导致 GPU 上的运行时成本更高。

(3)DrawTexturedTriangles绘制顶点数组。

  • "t"纹理。
  • "vertices"顶点数组。
  • "uvs"uvs 数组。(Span<>任意内存连续区域的通用表示。)
  • colors"颜色数组
  • "useAlpha"如果真正的 alpha 混合将被启用。

(4)FillTriangle填充三角形区域。

  • 参数分别是第一二三个顶点以及颜色

 

        以DrawMaterial为例:

void Render2D::DrawMaterial(MaterialBase* material, const Rectangle& rect, const Color& color)
{
    RENDER2D_CHECK_RENDERING_STATE;
    if (material == nullptr || !material->IsReady() || !material->IsGUI())
        return;

    Render2DDrawCall& drawCall = DrawCalls.AddOne();
    drawCall.Type = DrawCallType::Material;
    drawCall.StartIB = IBIndex;
    drawCall.CountIB = 6;
    drawCall.AsMaterial.Mat = material;
    WriteRect(rect, color);
}

        仍然是在进行一些参数有效性判断后对2D绘图调用进行设置,然后再使用之前我们分析过的诸如WriteRect(),WriteTri()等方法进行具体计算。

        再比如FillTriangles()方法:

void Render2D::FillTriangles(const Span<Vector2>& vertices, const Span<Color>& colors, bool useAlpha)
{
    CHECK(vertices.Length() == colors.Length());
    RENDER2D_CHECK_RENDERING_STATE;

    Render2DDrawCall& drawCall = DrawCalls.AddOne();
    drawCall.Type = useAlpha ? DrawCallType::FillRect : DrawCallType::FillRectNoAlpha;
    drawCall.StartIB = IBIndex;
    drawCall.CountIB = vertices.Length();

    for (int32 i = 0; i < vertices.Length(); i += 3)
        WriteTri(vertices[i], vertices[i + 1], vertices[i + 2], colors[i], colors[i + 1], colors[i + 2]);
}

三、总结 

        到这里,有关Render2D.h和Render2D.cpp大部分内容都已经分析完毕,可以看到在这个部分基本完成了2D渲染的大部分操作,关于2D渲染的其他部分,还有字体以及Sprite图集等,之后的博客会针对这些部分再做分析。

        由于游戏引擎太过庞大,Flax Engine更像Unity和UE4(虚幻)的结合,所以其源码量也是较大,有关3D渲染的部分可能在这次分析中不再涉及,但是在分析完2D渲染的剩余内容后可能对3D渲染的源代码进行一个大体的分析。

        好了这次分析就到这里,感谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值