You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
这几天在做游戏 demo 以及 (#199) 时感觉,目前修改可渲染对象的材质是一件非常麻烦的事情。计划在未来做一个好用的系统封装其中麻烦的部分,下面是一些想法:
动机
修改单个 entity 的材质,因为涉及渲染对象的内部数据结构,处于不暴露内部结构的想法,封装了一组 api 去访问 ecs 中的对应数据。即
local imaterial = ecs.require "ant.render|material"
这个 ecs 模块,使用imaterial.set_property(e, name, data)
进行修改。但我总觉得在 ecs 框架下封装这样的函数味道不对。我希望 ecs 保持更存粹的数据。修改 prefab 的材质需要遍历 prefab instance 的所有 entity ,挑选出场景对象。这个过程非常繁琐,易出错。这是因为,prefab 是一组 entity 的集合。只有 prefab 的创造者最清楚材质变化意味着什么:例如,把整个 prefab 变成半透明状态到底应该把哪些部件的材质改变一下。
改变材质
每个可渲染对象都有一个材质,在 Wiki:材质 小节有更多介绍。当文中提到改变材质,一般指的是修改材质的 properties ,即着色器的属性。这些属性原本设计目的就是留在运行时修改的。引擎目前不允许渲染对象更换材质对象本身。如有这个需求,通常建议更换整个 entity 。
着色器的属性通常是只写不读的。所以,可以修改材质看成是向渲染层发送了一个指令,最终是在渲染阶段生效。在同一帧中修改同一材质多次,只有最后一次有效。
广义上说,修改一个对象的可见性也属于修改材质。只是因为可见性判断涉及优化(不可见的对象不需要提交渲染),并没有使用着色器的属性开关来完成。
在场景树中,我们往往需要传播材质的修改。比如,修改场景中一个节点的可见性,应该传播到它的子树。
虚拟材质系统
我觉得可以做一个虚拟材质系统解决上面提到的问题。
这个系统是一个独立于 ecs 之外的系统,每创建一个虚拟材质对象,就赋予它一个唯一 id 。而在 ecs 中记录的每个实际材质中记录这个虚拟材质 id 。
虚拟材质可以定义一系列属性,它可以和真实材质保持一致,也可以做一次名字映射。它管理树层次结构,它可以定义自己继承哪些父节点的属性。
向虚拟材质对象设置属性时,系统将其记录下来,并在渲染阶段前传播到子节点。在渲染阶段可以读取当前帧变更的属性值,然后清空状态。即,虚拟材质系统只保存当前帧的属性变更信息,不持久保存属性数据。
和 ECS 结合
Beta Was this translation helpful? Give feedback.
All reactions