【EQ-R】在安卓中使用filament(sceneform)材质(二)

EQ-R

简介

EQ-Renderer是EQ基于sceneform(filament)扩展的一个用于安卓端的三维AR渲染器。

主要功能

它包含sceneform_v1.16.0中九成接口(剔除了如sfb资源加载等已弃用的内容),扩展了视频背景视图、解决了sceneform模型加载的内存泄漏问题、集成了AREngine和ORB-SLAM3、添加了场景坐标与地理坐标系(CGCS-2000)的转换方法。

注:由于精力有限,文档和示例都不完善。sceneform相关请直接参考谷歌官方文档,扩展部分接口说明请移步git联系。

相关链接

Git仓库
码云
EQ-R相关文档

Filament材质

注:本节内容源于filament材质文档,更多详情请转至原链接查看。

相关文档

概述

Filament是一个基于物理的渲染(PBR)引擎, 用于Android. Filament提供了一个可定制的材质系统, 你可以用它来创建简单材质和复杂材质. 本文档介绍材质支持的所有功能以及如何创建自己的材质.

核心概念

材质: 材质定义了表面的视觉外观. 为完整描述和渲染表面, 材质提供以下信息:

  • 材质模型
  • 一组用户可控制的命名参数
  • 光栅状态(混合模式, 背面剔除等)
  • 顶点着色器代码
  • 片段着色器代码

材质模型: 也称 着色模型 或 光照模型, 材质模型定义表面的内在特性. 这些特性直接影响光照的计算方式, 从而影响表面的外观.

材质定义: 描述材质所需的所有信息的文本文件. 这是你可以直接编写以创建新材质的文件.

材质包: 在运行时, 从 材质包 中加载材质, 材质包是使用matc工具根据材质的定义编译得到的. 材质包含了描述材质所需的所有信息, 以及为目标运行时平台生成的着色器. 这是必要的, 因为不同的平台(Android, macOS, Linux等)使用不同的图形API, 或相似图形API的不同变体(例如OpenGL与OpenGL ES).

材质实例: 一个材质实例是对材质的引用, 以及对应该材质的不同参数的一组值. 本文档不包括材质实例, 因为可以直接使用Filament代码创建和操控它们。

材质模型

Filament支持以下材质模型:

  • 光亮(或标准)
  • 次表面
  • 布料
  • 无光亮
  • 镜面光泽(用于以前的模型)

材质定义

一个材质定义是描述材质所需的所有信息的一个文本文件:

  • 名称
  • 用户参数
  • 材质模型
  • 必需属性
  • 插值(称为 变量)
  • 光栅状态(混合模式等)
  • 着色器代码(片段着色器, 可选的顶点着色器)

材质编译

matc工具

可以使用名为matc的命令行工具从材质定义编译材质包. 使用matc的最简单的方法是, 指定一个输入材质定义(下面示例中的car_paint.mat)和一个输出材质包(下面示例中的car_paint.filamat):

matc.exe工具编译过程请参考在安卓中使用filament(sceneform)材质(一)

matc -o ./materials/bin/car_paint.filamat ./materials/src/car_paint.mat
批量编译
  1. 在window电脑创建一个"genfilamat.bat"文件,使用编辑器打开,输入以下内容。
@echo off
if not exist out mkdir out
for /R %%G in (*.mat) do matc --optimize-size --platform=mobile -o "out\%%~nG.filamat" "%%G"

@echo off
echo success!
pause

  1. 将多个材质文件(*.mat) 拷贝至 “genfilamat.bat” 的同级目录。
  2. 运行 “genfilamat.bat” ,输出结果在同级目录的/out文件夹中。

材质调用

下文将通过一个材质示例,来讲述如何在【EQ-R】中调用filament材质实现法线贴图

编写材质

现要创建一个支持法线贴图的材质文件,步骤如下:

  1. 创建名为“eq_opaque_mat.mat”的文件
  2. 通过编辑器(记事本)打开mat文件,填写如下内容。
material {
    name : "EQ Opaque Mat",

    parameters : [
        {
           type : sampler2d,
           name : texture
        },
        {
           type : sampler2d,
           name : normalMap
        },
        {
           type : float,
           name : metallic
        },
        {
            type : float,
            name : roughness
        },
        {
            type : float,
            name : reflectance
        },
        {
            type : float4,
            name : emissive
        }
    ],
    requires : [
        position,
        uv0
    ],
    shadingModel : lit,
    blending : opaque
}
fragment {
    void material(inout MaterialInputs material) {
        // 获取切线空间中的法线,normal属性必须在prepareMaterial()前调用
        vec3 normal = texture(materialParams_normalMap, getUV0()).xyz;
        material.normal = normal * 2.0 - 1.0;
        prepareMaterial(material);
        //基色
        material.baseColor = texture(materialParams_texture, getUV0());
        //金属度
        material.metallic = materialParams.metallic;
        //粗糙度
        material.roughness = materialParams.roughness;
        //反射率
        material.reflectance = materialParams.reflectance;
        //自发光
        material.emissive = materialParams.emissive;
    }
}

上述的文本内容可以根据filament材质文档做修改,标准模型的材质参数范围和类型如下:

baseColor 基色float4[0…1]预乘的线性RGB
metallic 金属度float[0…1]应为0或1
roughness 粗糙度float[0…1]
reflectance 反射率float[0…1]首选值 > 0.35
clearCoat 涂层float[0…1]应为0或1
clearCoatRoughness 涂层粗糙度float[0…1]重新映射到[0…0.6]
anisotropy 各向异性度float[−1…1]当此值为正时, 各向异性位于切线方向
anisotropyDirection 各向异性方向float3[0…1]线性RGB, 编码切线空间中的方向向量
ambientOcclusion 环境光遮蔽float[0…1]
normal 法线float3[0…1]线性RGB, 编码切线空间中的方向向量
clearCoatNormal 涂层法线float3[0…1]线性RGB, 编码切线空间中的方向向量
emissive 自发光float4rgb=[0…1], a=[-n…n]Alpha为是曝光补偿
postLightingColor 后处理光照颜色float4[0…1]预乘的线性RGB

编译材质

通过matc工具编译得到(“eq_opaque_mat.filamat”)文件

调用材质

以下内容均在AndroidStudio中操作,使用Java接口

  1. 将“eq_opaque_mat.filamat“文件拷贝至项目模块的/res/raw目录下(这里我在res目录下创建了名为raw的文件夹,创建其它名称也可,只要能通过资源ID找到这个文件即可)
  2. 编写代码调用材质。
        Bitmap normalMap = loadBitmapFromAsstes("MATERIALS/org_fur/normal.png");
        Bitmap srcBm = loadBitmapFromAsstes("MATERIALS/org_fur/basecolor.png");

        Material.builder()
                .setSource(context, LoadHelper.rawResourceNameToIdentifier(context, "eq_opaque_mat"))
                .build().thenAccept(new Consumer<Material>() {
                    @Override
                    public void accept(Material mat) {
                        material = mat;
                        material.setFloat("reflectance",0.1f);
                        material.setFloat("roughness",0.6f);
                        material.setFloat("metallic",0.0f);
                        Texture.builder()
                                .setSource(normalMap)
                                .build().thenAccept(new Consumer<Texture>() {
                                    @Override
                                    public void accept(Texture normalMapTexture) {
                                        material.setTexture("normalMap", normalMapTexture);
                                    }
                                });
                        Texture.builder()
                                .setSource(srcBm)
                                .build().thenAccept(new Consumer<Texture>() {
                                    @Override
                                    public void accept(Texture srcMapTexture) {
                                        material.setTexture("texture",srcMapTexture);
                                    }
                                });
                    }
                });

此外,之前的“eq_opaque_mat.filamat“文件也可以放于其它能访问到的路径。

通过以下方式进行访问。

Material.builder().setSource(this,Uri.fromFile(new File(path)));
  1. 修改材质参数

​ 在材质build之后,可以通过material.setXX相关方法动态地对参数进行修改。参数名为“编写材质”步骤中的“parameters”对应的name

材质示例

Opaque Colored

material {
    "name" : "Opaque Colored",

    "parameters" : [
        {
           "type" : "float3",
           "name" : "color"
        },
        {
           "type" : "float",
           "name" : "metallic"
        },
        {
            "type" : "float",
            "name" : "roughness"
        },
        {
            "type" : "float",
            "name" : "reflectance"
        },
        {
            "type" : "float4",
            "name" : "emissive"
        }
    ],
    "requires" : [
        "position",
        "uv0"
    ],
    "shadingModel" : "lit",
    "blending" : "opaque",
    doubleSided : true
}
fragment {
    void material(inout MaterialInputs material) {
        prepareMaterial(material);
        material.baseColor.rgb = materialParams.color;
        material.metallic = materialParams.metallic;
        material.roughness = materialParams.roughness;
        material.reflectance = materialParams.reflectance;
        material.emissive = materialParams.emissive;
    }
}

Opaque Textured

material {
    "name" : "Opaque Textured",

    "parameters" : [
        {
           "type" : "sampler2d",
           "name" : "texture"
        },
        {
           "type" : "float",
           "name" : "metallic"
        },
        {
            "type" : "float",
            "name" : "roughness"
        },
        {
            "type" : "float",
            "name" : "reflectance"
        },
        {
            "type" : "float4",
            "name" : "emissive"
        }
    ],
    "requires" : [
        "position",
        "uv0"
    ],
    "shadingModel" : "lit",
    "blending" : "opaque",
    doubleSided : true
}
fragment {
    void material(inout MaterialInputs material) {
        prepareMaterial(material);
        material.baseColor = texture(materialParams_texture, getUV0());
        material.metallic = materialParams.metallic;
        material.roughness = materialParams.roughness;
        material.reflectance = materialParams.reflectance;
        material.emissive = materialParams.emissive;
    }
}

Transparent Colored

material {
    "name" : "Transparent Colored",

    "parameters" : [
        {
           "type" : "float4",
           "name" : "color"
        },
        {
           "type" : "float",
           "name" : "metallic"
        },
        {
            "type" : "float",
            "name" : "roughness"
        },
        {
            "type" : "float",
            "name" : "reflectance"
        },
        {
            "type" : "float4",
            "name" : "emissive"
        }
    ],
    "requires" : [
        "position",
        "uv0"
    ],
    "shadingModel" : "lit",
    "blending" : "transparent"
}
fragment {
    void material(inout MaterialInputs material) {
        prepareMaterial(material);
        material.baseColor = materialParams.color;
        material.metallic = materialParams.metallic;
        material.roughness = materialParams.roughness;
        material.reflectance = materialParams.reflectance;
        material.emissive = materialParams.emissive;
    }
}

Transparent Textured

material {
    "name" : "Transparent Textured",

    "parameters" : [
        {
           "type" : "sampler2d",
           "name" : "texture"
        },
        {
           "type" : "float",
           "name" : "metallic"
        },
        {
            "type" : "float",
            "name" : "roughness"
        },
        {
            "type" : "float",
            "name" : "reflectance"
        },
        {
            "type" : "float4",
            "name" : "emissive"
        }
    ],
    "requires" : [
        "position",
        "uv0"
    ],
    "shadingModel" : "lit",
    "blending" : "transparent"
}
fragment {
    void material(inout MaterialInputs material) {
        prepareMaterial(material);
        material.baseColor = texture(materialParams_texture, getUV0());
        material.metallic = materialParams.metallic;
        material.roughness = materialParams.roughness;
        material.reflectance = materialParams.reflectance;
        material.emissive = materialParams.emissive;
    }
}

View

material {
    "name" : "View",
    "parameters" : [
        {
           "type" : "samplerExternal",
           "name" : "viewTexture"
        },
        {
            "type" : "float2",
            "name" : "offsetUv"
        },
        {
            "type" : "float4",
            "name" : "emissive"
        }
    ],
    "requires" : [
        "position",
        "uv0"
    ],
    "shadingModel" : "unlit",
    "blending" : "transparent",
    "doubleSided" : true
}

fragment {
    void material(inout MaterialInputs material) {
        prepareMaterial(material);

        vec2 uv = getUV0();

        if (!gl_FrontFacing) {
          uv.x = 1.0 - uv.x;
        }

        // Set offsetUv if we want to invert around an axis.
        // In front facing camera, set offsetUv.x to 1 and offsetUv.y to 0.
        uv.x = uv.x + materialParams.offsetUv.x * (1.0 - 2.0 * uv.x);
        uv.y = uv.y + materialParams.offsetUv.y * (1.0 - 2.0 * uv.y);

        material.baseColor = texture(materialParams_viewTexture, uv);
        material.baseColor.rgb = inverseTonemapSRGB(material.baseColor.rgb);
        material.emissive = materialParams.emissive;
    }
}

Camera

material {
    "name" : "Camera",

    "parameters" : [
        {
           "type" : "samplerExternal",
           "name" : "cameraTexture"
        }
    ],
    "requires" : [
        "uv0"
    ],
    "vertexDomain" : "device",
    "depthWrite" : false,
    "shadingModel" : "unlit",
    "doubleSided" : true
}
fragment {
    void material(inout MaterialInputs material) {
        prepareMaterial(material);

        vec4 color = texture(materialParams_cameraTexture, getUV0());
        material.baseColor.rgb = inverseTonemapSRGB(color.rgb);
    }
}

  • 11
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
编译FilamentAndroid版本程序需要以下步骤: 1. 下载并安装Android Studio:访问Android开发者网站(developer.android.com),下载并安装最新版本的Android Studio。这是一个集成开发环境(IDE),提供了丰富的工具和库编译Android应用程序。 2. 克隆Filament仓库:在命令行或Git Bash使用命令`git clone https://github.com/google/filament.git`克隆Filament的Git仓库到本地。 3. 打开Android Studio并导入项目:启动Android Studio,点击“File”菜单,选择“Open”选项,然后导航到刚刚克隆的Filament目录并选择“build.gradle”文件。点击“OK”来导入项目。 4. 配置编译选项:等待Android Studio完成导入过程后,点击“File”菜单,选择“Project Structure”选项。在弹出的对话框,选择“SDK Location”并确认已正确设置Android SDK的路径。 5. 构建项目:在Android Studio的工具栏上找到“Sync Project with Gradle Files”的按钮,并点击它来同步Gradle构造文件。然后再点击工具栏上的“Build”按钮,选择“Build Bundle(s) / APK(s)”选项。这将编译并构建Filament应用程序。 6. 安装和运行:编译成功后,在构建输出目录找到生成的APK文件。将手机通过USB连接到计算机,并在开发者选项启用USB调试模式。使用ADB(Android Debug Bridge)命令,将APK文件安装到手机上。运行应用程序并验证其正常工作。 以上是在Windows系统上编译FilamentAndroid版本程序的基本步骤。尽管这里提供了一个大致的指南,但具体的操作可能会因为系统配置和软件版本的不同而有所不同。为了更好地理解和完成这个过程,建议查阅Filament的官方文档和与Android开发相关的文档。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EQ-雪梨蛋花汤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值