Filament 渲染对象的创建

Filament 将实体(Entity)属性看成组件(component)的形式,实体可以是相机,光源,可绘制实体, 全局光照(IBL)实体等类型。一个场景包含最多、最主要的是可绘制实体对象。可绘制实体主要包含两种属性 可绘制属性Renderable 和 变换属性Transform,Renderable 与 Transform 被看作两种组件。Filament 的对象和组件都是通过各自的Manager创建和管理的, Filament 有自己的内存管理模块,类实例通过句柄 handle 可以映射到对应的内存地址上。组件在内部以实例instance的方式存在。

创建一个可渲染对象主要经过以下三个过程:

(1)创建 Enitity 对象

Entity 对象只是包含一个全局唯一标识符的对象,相当于实例对象的句柄, 下面给出 Entity 类定义:

class Entity {
public:// this can be used to create an array of to-be-filled entities (see create())Entity() noexcept = default;// Entities can be copiedEntity(const Entity& e) noexcept = default;Entity(Entity&& e) noexcept = default;Entity& operator=(const Entity& e) noexcept = default;Entity& operator=(Entity&& e) noexcept = default;// Entities can be comparedbool operator==(Entity e) const { return e.mIdentity == mIdentity; }bool operator!=(Entity e) const { return e.mIdentity != mIdentity; }// Entities can be sortedbool operator<(Entity e) const { return e.mIdentity < mIdentity; }bool isNull() const noexcept {return mIdentity == 0;}uint32_t getId() const noexcept {return mIdentity;}explicit operator bool() const noexcept { return !isNull(); }private:friend class EntityManager;friend class EntityManagerImpl;friend struct std::hash<Entity>;using Type = uint32_t;explicit Entity(Type identity) noexcept : mIdentity(identity) { }Type mIdentity = 0;
};

Filament 创建 Entity 示例:

Entity rootEntity;

EntityManager::get().create(1, &rootEntity);

(2)准备渲染所需的对象资源 VertexBuffer, IndexBuffer, Material

  • 创建 VBO
// 构建 Builder 并描述所需 VBO 状态
VertexBuffer::Builder vertexBufferBuilder = VertexBuffer::Builder().vertexCount((uint32_t)asset.positions.size()).bufferCount(4).attribute(VertexAttribute::POSITION,     0, VertexBuffer::AttributeType::HALF4).attribute(VertexAttribute::TANGENTS,     1, VertexBuffer::AttributeType::SHORT4).normalized(VertexAttribute::TANGENTS);// Builder 通过 build 方法创建 VertexBuffer
mVertexBuffer = vertexBufferBuilder.build(mEngine);// 设置 VBO 数据
mVertexBuffer->setBufferAt(mEngine, 0,VertexBuffer::BufferDescriptor(ps->data(), ps->size(), State<half4>::free, ps));
  • 创建 EBO 与 VBO 创建 大同小异, 只是数据结构简单,填充图元索引数据。
mIndexBuffer = IndexBuffer::Builder().indexCount(uint32_t(is->size())).build(mEngine);mIndexBuffer->setBuffer(mEngine,IndexBuffer::BufferDescriptor(is->data(), is->size(), State<uint32_t>::free, is));
  • 创建 Material 实例 MaterialInstance

Filament 基于物理渲染, 支持自定义shader , 材质以脚本形式定义,并通过材质解析器读取JSON 格式的材质文件进行解析的。我们可将Material 看做是材质模版, 具体到渲染对象使用材质时是通过材质对象创建instance实例绑定到实体的Renderable组件来描述渲染对象的外观。

Material 材质模版的定义:

class FMaterial : public Material {
public:FMaterial(FEngine& engine, const Material::Builder& builder);~FMaterial() noexcept;class DefaultMaterialBuilder : public Material::Builder {public:DefaultMaterialBuilder();};void terminate(FEngine& engine);// return the uniform interface block for this materialconst UniformInterfaceBlock& getUniformInterfaceBlock() const noexcept {return mUniformInterfaceBlock;}// return the uniform interface block for this materialconst SamplerInterfaceBlock& getSamplerInterfaceBlock() const noexcept {return mSamplerInterfaceBlock;}// Create an instance of this materialFMaterialInstance* createInstance() const noexcept;bool hasParameter(const char* name) const noexcept;FMaterialInstance const* getDefaultInstance() const noexcept { return &mDefaultInstance; }FMaterialInstance* getDefaultInstance() noexcept { return &mDefaultInstance; }FEngine& getEngine() const noexcept  { return mEngine; }backend::Handle<backend::HwProgram> getProgramSlow(uint8_t variantKey) const noexcept;backend::Handle<backend::HwProgram> getSurfaceProgramSlow(uint8_t variantKey) const noexcept;backend::Handle<backend::HwProgram> getPostProcessProgramSlow(uint8_t variantKey) const noexcept;backend::Handle<backend::HwProgram> getProgram(uint8_t variantKey) const noexcept {backend::Handle<backend::HwProgram> const entry = mCachedPrograms[variantKey];return UTILS_LIKELY(entry) ? entry : getProgramSlow(variantKey);}backend::Program getProgramBuilderWithVariants(uint8_t variantKey, uint8_t vertexVariantKey,uint8_t fragmentVariantKey) const noexcept;backend::Handle<backend::HwProgram> createAndCacheProgram(backend::Program&& p,uint8_t variantKey) const noexcept;bool isVariantLit() const noexcept { return mIsVariantLit; }const utils::CString& getName() const noexcept { return mName; }backend::RasterState getRasterState() const noexcept  { return mRasterState; }uint32_t getId() const noexcept { return mMaterialId; }Shading getShading() const noexcept { return mShading; }Interpolation getInterpolation() const noexcept { return mInterpolation; }BlendingMode getBlendingMode() const noexcept { return mBlendingMode; }BlendingMode getRenderBlendingMode() const noexcept { return mRenderBlendingMode; }VertexDomain getVertexDomain() const noexcept { return mVertexDomain; }MaterialDomain getMaterialDomain() const noexcept { return mMaterialDomain; }CullingMode getCullingMode() const noexcept { return mCullingMode; }TransparencyMode getTransparencyMode() const noexcept { return mTransparencyMode; }bool isColorWriteEnabled() const noexcept { return mRasterState.colorWrite; }bool isDepthWriteEnabled() const noexcept { return mRasterState.depthWrite; }bool isDepthCullingEnabled() const noexcept {return mRasterState.depthFunc != backend::RasterState::DepthFunc::A;}bool isDoubleSided() const noexcept { return mDoubleSided; }bool hasDoubleSidedCapability() const noexcept { return mDoubleSidedCapability; }float getMaskThreshold() const noexcept { return mMaskThreshold; }bool hasShadowMultiplier() const noexcept { return mHasShadowMultiplier; }AttributeBitset getRequiredAttributes() const noexcept { return mRequiredAttributes; }bool hasSpecularAntiAliasing() const noexcept { return mSpecularAntiAliasing; }float getSpecularAntiAliasingVariance() const noexcept { return mSpecularAntiAliasingVariance; }float getSpecularAntiAliasingThreshold() const noexcept { return mSpecularAntiAliasingThreshold; }size_t getParameterCount() const noexcept {return mUniformInterfaceBlock.getUniformInfoList().size() +mSamplerInterfaceBlock.getSamplerInfoList().size();}size_t getParameters(ParameterInfo* parameters, size_t count) const noexcept;uint32_t generateMaterialInstanceId() const noexcept { return mMaterialInstanceId++; }private:// try to order by frequency of usemutable std::array<backend::Handle<backend::HwProgram>, VARIANT_COUNT> mCachedPrograms;backend::RasterState mRasterState;BlendingMode mRenderBlendingMode;TransparencyMode mTransparencyMode;bool mIsVariantLit;Shading mShading;BlendingMode mBlendingMode;Interpolation mInterpolation;VertexDomain mVertexDomain;MaterialDomain mMaterialDomain;CullingMode mCullingMode;AttributeBitset mRequiredAttributes;float mMaskThreshold = 0.4f;float mSpecularAntiAliasingVariance;float mSpecularAntiAliasingThreshold;bool mDoubleSided;bool mDoubleSidedCapability = false;bool mHasShadowMultiplier = false;bool mHasCustomDepthShader = false;bool mIsDefaultMaterial = false;bool mSpecularAntiAliasing = false;FMaterialInstance mDefaultInstance;SamplerInterfaceBlock mSamplerInterfaceBlock;UniformInterfaceBlock mUniformInterfaceBlock;SamplerBindingMap mSamplerBindings;utils::CString mName;FEngine& mEngine;const uint32_t mMaterialId;mutable uint32_t mMaterialInstanceId = 0;MaterialParser* mMaterialParser = nullptr;
};

Material 定义了各种渲染属性,双面光照,背面剔除,图元插值方式(smooth, flat), 混合模式,反走样,纹理采样,着色器及uniform buffer对外界口。Filament 常量的交互是通过组织成uniform buffer 的形式,着在现代图形引擎中使用UBO更高效。Filament 支持 Vulkan , OpenGLES 类型的 shader, 对材质的转换也提供了相应的工具 matc (mateiral converter), shader 压缩工具 glslminifier。

MaterialInstance 是 Material 的实例和接口类,负责设置shader参数与渲染状态参数。当Material 被创建时,默认会创建一个相关的实例对象, 每一个可渲染对象 Renderable 都可以 关联一个材质实例对象 materialInstance。

VBO , EBO, Material 数据将用来设置Renderable组件,Renderable 组件管理渲染对象几何数据 与 材质。

(3)创建 Renderable 组件实例 Instance,将渲染数据关联到 Instance,最后通过build 方法将 Instance 与 Entity 实例关联

RenderableManager::Builder(1).boundingBox({{ 0, 0, 0 },{ 1, 1, 1 }}).material(0, mMaterialInstanceSolid).geometry(0, RenderableManager::PrimitiveType::TRIANGLES, mVertexBuffer, mIndexBuffer, 0, 3*2*6).priority(7).culling(culling).build(engine, entity);

RenderableManager::Builder 的成员函数 geometry 是渲染数据设置接口, 我们可以看到对一个可渲染的数据,包括包围盒设置、材质设置、图元设置、优先级设置、剔除设置, build 成员方法将 Renderable 组件 与 entity 关联。在引擎内部, 组件都是以实例(instance)的形式存在,通过map 关联起来。

(4)创建 Transform 组件实例 Instance, 通过TransformManager.create(utils::Entity entity, Instance parent = {}, const math::mat4f& localTransform = {}) 方法关联到实体对象上。Transform组件是可选的,如果对象不需要矩阵变换可以不创建, 默认是单位矩阵。

TransformManager& tcm = Engine.getTransformManager();
//Add transform instance to entity
tcm.create(entity, TransformManager::Instance{}, mat4f());

Transform 组件 与 Renderable 组件的关联方式不一样,它是通过create方法创建instance并与entity 关联的。

(5)将渲染实体添加到场景图中

Filament 的 scene 负责场景对象的组织和管理,scene 的创建工作由 Engine 负责。

FScene& scene = view.getScene();void FScene::addEntity(Entity entity) {mEntities.insert(entity);
}void FScene::addEntities(const Entity* entities, size_t count) {mEntities.insert(entities, entities + count);
}// 创建 Scene、添加渲染实体、并由 view 管理 scene.
mScene = mEngine->createScene();mScene->addEntity(cameraCube->getWireFrameRenderable());view->setScene(mScene);

Filament 渲染引擎剖析 之 创建渲染对象 1相关推荐

  1. Filament 渲染引擎剖析 之 多线程渲染 2

    Filament 渲染一帧流程 Filament 是一款针对多核硬件系统开发的并行渲染引擎,内部通过多线程的合理调度,尤其在android移动平台上针对大小核心架构做了很多优化设计,比如通过设置线程亲 ...

  2. Filament 渲染引擎剖析 之 FrameGraph 1 虚拟资源的定义与创建

    Filament 使用了可扩展渲染管线(FrameGraph)来组织渲染通道和管理渲染资源,网上也搜了下可扩展渲染管线的相关的文章,一般认为可扩展渲染管线是次时代渲染引擎应该具备的比较先进的管线组织架 ...

  3. pyqt创建窗口没有句柄_Filament 渲染引擎剖析 之 FrameGraph 1 虚拟资源的定义与创建...

    Filament 使用了可扩展渲染管线(FrameGraph)来组织渲染通道和管理渲染资源,网上也搜了下可扩展渲染管线的相关的文章,一般认为可扩展渲染管线是次时代渲染引擎应该具备的比较先进的管线组织架 ...

  4. Filament渲染引擎剖析 之 通过图元构建几何体

    Filament渲染引擎剖析 之 通过图元构建几何体 什么是图元 filament可绘制的图元类型 构建图元的工具 VertexBuffer IndexBuffer Primitive 什么是图元 图 ...

  5. Filament 渲染引擎剖析 之 FrameGraph 2 动态构建渲染管线

    一.渲染通道的设计与实现 1 Frostbite 构建FrameGraph的准则 我们先看下Frostbite 构建FrameGraph原则,包括三个阶段: 设置阶段 setup.编译阶段compil ...

  6. 高性能跨平台渲染引擎系列一: 跨平台渲染引擎简介

    引言: 一直工作比较忙,很久就想写点东西做个备忘,拖延至今.本系列也期望督促自己坚持记录分享,文中如有笔误或者理解偏差,欢迎各位指正交流.也期望未来基于该系列文章的相关代码同步到git上,最终完成一款 ...

  7. Cryengine渲染引擎剖析

    ms,OpenGPU这些天又冷下去了, 转篇Napoleon314 大牛的分析,排版好乱,见谅,耐心读,这是个好东西,注意看他自己的实现,是个技术狂人啊,Ogre焕发次时代的光芒啊~~~努力 ---- ...

  8. Filament 渲染引擎剖析 之 ECS模式

    一.什么是 ECS 模式 ECS Entity-Component-System(实体-组件-系统) 是基于组合优于继承原则的一种模式,每一渲染对象都是一个实体,每个实体由一个或者多个组件构成,每个组 ...

  9. webGL、webGPU、封装、渲染引擎 three.js、游戏引擎,定位是游戏开发,在前面的渲染引擎基础上,还提供了骨骼动画、物理引擎、AI、GUI 等功能,以及可视化编辑器来设计关卡,支撑大型游戏

    https://zhuanlan.zhihu.com/p/162878354 如何选择 WebGL 框架和引擎? ​ 知道得越多,不知道的就更多了 数据可视化Sugar-百度智能云 ​cloud.ba ...

最新文章

  1. LeetCode简单题之打折购买糖果的最小开销
  2. 回应关于《BCH五月硬分叉是伪需求》的疑问
  3. c语言队列(顺序队列,循环队列,链式队列)
  4. Xcode 6 allows VECTOR image assets… any idea how to use them?
  5. Airflow 中文文档:安装
  6. Java设计模式(十二)----享元模式
  7. 6.1 统计学基本原理
  8. 20180805:求出字典d = {'a':1,b:2,c:3,d:4,e:4}中的最大的字母,并打印出来
  9. 6. Manage the driver for browser and the script for Hub
  10. wow Warlock shushia PVP DZ
  11. 工业计算机英语作文,工业计算机,Industrial Computer,音标,读音,翻译,英文例句,英语词典...
  12. 17_1.Excel股票分析工具-开盘前涨停数据
  13. 4K显示器和防蓝光眼镜膜
  14. PaddlePaddle入门-1
  15. Kubernetes--k8s--进阶--全面了解HPA--部署HPA实现高可用和成本控制
  16. 2.2.2 定点数的移位运算
  17. 如何在一个月内写完论文?
  18. 用Dreamweaver实现ASP动态网站建设
  19. 基于微信小程序的旧书置换二手书交易系统的设计与实现#毕业设计
  20. CH4-面向对象下 (8个案例实现)

热门文章

  1. chmod +x 与chmod 777的区别
  2. Linux 文件系统原理 / 虚拟文件系统VFS
  3. Ubuntu下彻底卸载mysql、安装mysql、及MySQLdb模块
  4. OpenCV cvBoundingRect应用举例
  5. GlobalWoZ: 面向全球通用的人机对话系统——快速构建多语对话能力初探
  6. Python异步: 什么时候使用异步?(3)
  7. 程序员必读书籍一览表
  8. java队名_求JAVA团队名称
  9. python分析股票主力_筹码分布及计算原理
  10. 致远SPM国资企业解决方案之工会管理