EQ-R
简介
EQ-Renderer是EQ基于sceneform(filament)扩展的一个用于安卓端的三维AR渲染器。
主要功能
它包含sceneform_v1.16.0中九成接口(剔除了如sfb资源加载等已弃用的内容),扩展了视频背景视图、解决了sceneform模型加载的内存泄漏问题、集成了AREngine和ORB-SLAM3、添加了场景坐标与地理坐标系(CGCS-2000)的转换方法。
注:由于精力有限,文档和示例都不完善。sceneform相关请直接参考谷歌官方文档,扩展部分接口说明请移步git联系。
相关链接
Git仓库
- EQ-Renderer的示例工程
码云
- EQ-Renderer的示例工程
EQ-R相关文档
- 文档目录
Filament材质
注:本节内容源于filament材质文档,更多详情请转至原链接查看。
相关文档
-
filament官方文档
-
sceneform自定义材质文档
-
中文文档(Jerkwin译)
概述
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
批量编译
- 在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
- 将多个材质文件(*.mat) 拷贝至 “genfilamat.bat” 的同级目录。
- 运行 “genfilamat.bat” ,输出结果在同级目录的/out文件夹中。
材质调用
下文将通过一个材质示例,来讲述如何在【EQ-R】中调用filament材质实现法线贴图
编写材质
现要创建一个支持法线贴图的材质文件,步骤如下:
- 创建名为“eq_opaque_mat.mat”的文件
- 通过编辑器(记事本)打开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 自发光 | float4 | rgb=[0…1], a=[-n…n] | Alpha为是曝光补偿 |
postLightingColor 后处理光照颜色 | float4 | [0…1] | 预乘的线性RGB |
编译材质
通过matc工具编译得到(“eq_opaque_mat.filamat”)文件
调用材质
以下内容均在AndroidStudio中操作,使用Java接口
- 将“eq_opaque_mat.filamat“文件拷贝至项目模块的/res/raw目录下(这里我在res目录下创建了名为raw的文件夹,创建其它名称也可,只要能通过资源ID找到这个文件即可)
- 编写代码调用材质。
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“文件也可以放于其它能访问到的路径。
通过以下方式进行访问。文章来源:https://www.toymoban.com/news/detail-838710.html
Material.builder().setSource(this,Uri.fromFile(new File(path)));
- 修改材质参数
在材质build之后,可以通过material.setXX相关方法动态地对参数进行修改。参数名为“编写材质”步骤中的“parameters”对应的name文章来源地址https://www.toymoban.com/news/detail-838710.html
材质示例
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);
}
}
到了这里,关于【EQ-R】在安卓中使用filament(sceneform)材质(二)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!