Filament 渲染引擎剖析 之 创建渲染对象 1

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 copied
    Entity(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 compared
    bool operator==(Entity e) const { return e.mIdentity == mIdentity; }
    bool operator!=(Entity e) const { return e.mIdentity != mIdentity; }

    // Entities can be sorted
    bool 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 material
    const UniformInterfaceBlock& getUniformInterfaceBlock() const noexcept {
        return mUniformInterfaceBlock;
    }

    // return the uniform interface block for this material
    const SamplerInterfaceBlock& getSamplerInterfaceBlock() const noexcept {
        return mSamplerInterfaceBlock;
    }

    // Create an instance of this material
    FMaterialInstance* 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 use
    mutable 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);

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Filament引擎是一种现代化的渲染引擎,用于实时渲染图形,特别是用于移动设备和虚拟现实平台。它是由Google公司开发的,旨在为开发者提供高质量、高性能的渲染功能。 Filament引擎的一个重要特点是其卓越的可视效果。它使用基于物理的材质系统,能够模拟光照、阴影、反射等视觉效果,使得渲染出来的图像更加逼真和细腻。同时,Filament引擎还支持更高级的图形功能,如屏幕空间反射、全局光照和泛光效果等,以提供更出色的视觉体验。 除了可视效果外,Filament引擎还注重性能。它采用了先进的渲染技术和算法,以提高渲染速度和效率。该引擎能够在移动设备和虚拟现实平台上运行,而不影响用户体验,并且可以自动适应不同硬件设备的性能和功能。 另外,Filament引擎还提供了灵活的工具和API,使开发者能够更轻松地创建和定制渲染效果。开发者可以使用Filament的材质编辑器和场景编辑器来调整和优化图形效果,也可以通过使用Filament的C++ API来实现更高级的自定义需求。 总之,Filament引擎是一款功能强大、易于使用且性能优越的渲染引擎。它将高质量的视觉效果和高性能相结合,为开发者提供了创建令人惊叹的实时渲染图形的能力。无论是用于移动游戏、虚拟现实应用还是其他图形渲染需求,Filament引擎都能够发挥重要作用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值