如何在实体/组件系统中处理物料


13

我的E / C实现是一种基本的实现,其中实体只是ID,组件是数据,系统根据数据进行操作。现在,我在处理对象材质和渲染时遇到了麻烦。对于简单的objetc,我有一个ModelComponent与绑定的RenderSystemModelComponent具有渲染系统使用的顶点缓冲区ID。一个简单的对象MaterialComponent可能具有颜色或镜面反射强度等,但是我希望它具有足够的灵活性,以允许多个渲染过程和一般的“效果”,而这些效果不如的简单变量那么容易MaterialComponent

为了解决这些问题,我想出了两种解决方案:

1-超通用材料组件

像这样:

struct Material : public Component
{
    ShaderData* shader;
    std::vector<std::pair<std::string, boost::any>> uniforms;
    [...]
};

在渲染系统中,我将循环并将制服传递给着色器。我想这会很慢,但对于我的目的来说足够快了。

2-另一层抽象,MaterialData

有一个包装特定材料的类,该类可以由任何专门的材料继承,基类将具有类似的东西,void set_shader_constants(ShaderData* d)但是实现取决于每个类,并且MaterialComponent将具有一个指向MaterialData对象的指针。

我不确定我会选择哪种方法,但是这些方法都不涉及多次通过或其他复杂的渲染技术。

关于如何做到这一点的任何想法?

Answers:


26

材质是一种图形概念,属于您的渲染器。渲染器的底层架构太低,无法在实体系统之上构建。实体系统应该用于更高级别的游戏对象。并非所有事物都需要成为一个组件,实际上,试图将所有事物强制成这样的单一范例通常是一个坏主意。它创建了一个最小公分母的解决方案。

因此,我建议您采用其他方法:

  • 材质只是渲染器中的另一种类型。
  • 渲染器的类型表示“要绘制到屏幕上的东西”。通常将它们称为“渲染实例”或“可渲染对象”,甚至称为“模型”。此类型引用在绘制时将使用的材质,并提供公共API以允许渲染器的使用者将材质设置为所需的任何材质。

这本质上是在要求您ModelComponent对它进行重命名Model,删除对实体/组件层的依赖,从而将其移至较低的抽象层,以及渲染器的其余部分。

然后,您执行以下操作:

  • 在与其他组件相同的抽象层中,您具有某种“方面组件”,用于表示实体的视觉表示。该组件仅包含对某些可渲染对象的引用(如上所述),而后者又包含对材质的引用。该组件可以提供用于暴露可渲染对象的API(从而允许客户端对其进行操作),也可以包装可渲染对象的API以控制曝光。这取决于你。

通过将模型和材料都作为组件,可以解决您遇到的组件相互依赖性问题。实体应该具有一个方面,也可以不具有一个方面,并且该方面应该能够对有关实体表示的所有内容(包括材料)进行编码。

这也使您可以灵活地对材质对象采取其他方法,因为与其他渲染系统抽象缺乏奇偶性,因此很难将该对象用作组件。

允许更复杂的效果和多次传递的问题主要是可以通过在材质中解决,方法是公开要查询的函数并设置材质的着色器文件公开的命名着色器常量。如果您使用的效果文件(在D3D中)支持多次通过等,则尤其如此。即使您没有使用效果文件,您也可以从材质中暴露出多次通过的想法,每一次都有不同的着色器,并允许材质API为此提供操纵器。由于材料现在处于相同的抽象级别,因此最有可能更轻松,更干净地集成到呈现API中。


1
感谢您的回答,这个问题困扰了我一段时间,但是创建不受E / C约束的渲染器要容易得多。
路加B.13年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.