c#如何使用反射去创建一个委托_SakuraRender(三)--场景和编辑器反射

2335ce91401cb60cf7714060c438dc66.png

考试周终于结束辣, 复习的时候见缝插针的给Sakura写了下场景部分以及编辑器反射的部分, 这篇文章大致写一下已经实现的这些东西。

c364d237c2d71afc9c476afaa0be4b9e.png

照例放仓库地址, 目前最新的提交在SakuraScene分支。

Sakura​github.com

场景部分

场景部分采用了轻量级引擎普遍采用的Node方案, 提供了带Transform的Node以及NodeProperty两个小型结构:

a8832ec64f199f8733bafc11119cd538.png

场景整体组成一棵树, 每个节点均带有Transform, 这也方便对场景进行组合性的导入/导出, 通过树结构可以让序列化等工作变得非常清晰。

1f0124699d3ce8b768583a0651b04069.png

Scene作为一种特殊的Node, 存储着导出/入场景时的一些附加信息, 导出时会将主node包被成为Scene, 在导入时再进行向下的转换, 并链接入场景树。

在场景和渲染模块的对接上, 建立了一块黑板RenderScene(没错从ue来的)。所有的VB和IB以及材质等一系列资源由上文完成的ResourceManager创建并保持。

需要渲染的node持有资源引用, 将对应的引用提交到RenderScene中创建出RenderItem, 再由GraphicsManager进行收集, 即可进行绘制。

1b0a48b3587e137049247ec2002c8b5c.png

这样在场景导入导出上也十分方便, 用assimp读通用格式文件, 再进行节点信息的收集以及mesh Geometry的导入即可。

编辑器反射

由于C++20反射还没有纳入标准, 甚至连实验性特性也没有纳入, 所以目前只能使用动态反射的方案了。我个人还是有些洁癖, 但只在编辑器下用用非侵入性的动态反射还算是可以接受。反射实现起来倒是不难, 但因为已经有非常成熟的开源库, 这里就不再重复造轮了, 直接用了rttr:

RTTR​github.com

支持继承, 也可以添加meta, 用来写编辑器绰绰有余了。引擎本身不会依赖反射, 保持相对静态的结构就可以了。

5534f48b20ed09309d0504c64aec070f.png

RTTR在使用上也比较简单漂亮, 不需要像侵入式方案一样写大量扭曲的宏, 在.cpp进行注册就可以辣:

536e52938e429269841e47476b81c80a.png

由于RTTR支持反射, 我们只需要利用继承虚表把注册宏的类名存进类成员里, 这样又可以很方便的通过接口拿到对象的终极类名, 如此就能轻松获取并遍历属性字段了。

由于要拉编辑器, 并且需要跨dll进行交接, 因此还是需要确定下基本类型。大致如下分类:

  • bool, float, int, uint, string, vector3/4, color等作为基础类型, 需要拉对应的控件;
  • vector, map等容器;
  • 嵌套的反射类对象。

属性字段

8951edaa34e9e7190f98a824f9a799ec.png

包含属性字段的一些信息, 方便处理。PropertyData涵盖上面的所有类型, 也可以通过里面的obj指针进行成员嵌套。

属性字段遍历

397bb166f973f02dce8b17ed20f7f9de.png

有了反射库基本没什么好说, 遍历属性字段并且把属性数组导出就好了。比较坑的是std::string不能像float一样, 没有公共语言运行时支持, 也不能直接传char*出去, 需要写个wrapper来包一下。

fd524cd266bad49a9054c24d95612779.png

C#端用同样的wrapper接住:

65821ce426b6c8937f35aced19927cdf.png

再直接new string(sbyte*)就可以完成交接了。还要注意要确实的在传入的C#引用上直接操作, 这样才能让C#的GC顺利接盘, 不然很容易泄露。不过不得不说C++配C#还是很舒爽, 写起来完全没有违和感。

基本类型/容器/对象嵌套

7c8410c1d548b548eab716c879405961.png

基本类型需要写全套的set和get接口并导出dll。C#端遍历对象的属性字段并按类型进行dll调用就可以进行get/set了。这些类型的控件也需要每样拉一个并提供一个公共接口。

653003707737dd9839257945b1e8d038.png

容器和对象嵌套上也是同样的道理, 直接解析容器返回字段数组/对象就可以嘞。完成之后的编辑器界面基本像下面这个样子:

7f95f2d8961788a03105cde91b0dfa58.png

可扩展管线的方案

因为下一步要写多着色模型, 所以构思了一下管线扩展的方案, 大致有这样两种:

  • shaderlab式的shadergraph, 组合pass进行多样化的绘制, 即好多好多种shader。坏处是需要写套shader graph和方便的parameter收集机制, 不然需要写很大量的重复hlsl和srv绑定代码;
  • 为renderer指定固定的shadingmodel, 通过扩展shadingmodel来获取多样性。坏处是比较呆不够灵活, 只能通过在管线上开天窗(类如ue的材质编辑器, 好多好多种材质)或者硬写新管线来完成扩展;
  • 我全都要...

现在还是考虑用第二种思路, 因为已经写了FG了, 只需要把FG露出来就可以很方便的加pass和注册新的着色模型了。

2020年拉, 大家新年快乐~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值