基于Filament Android为GLB现有材质应用几何着色器
Filament Android 自定义着色器实现气流动画指南
核心实现流程
要给GLB模型的现有材质替换自定义着色器并实现气流动画,核心分为三步:
- 创建带自定义着色逻辑的Filament材质
- 替换GLB模型中原有的材质实例
- 动态更新材质参数驱动动画
关键步骤与代码示例
1. 创建带气流动画的自定义材质
使用MaterialBuilder构建自定义材质,添加动画所需的动态参数(如时间、法线贴图),并在材质代码中实现气流相关的视觉逻辑:
val matPackage = MaterialBuilder() .platform(MaterialBuilder.Platform.MOBILE) // 适配Android平台 .name("AirFlow Animated Material") // 调试用名称 .shading(MaterialBuilder.Shading.LIT) // 保持与GLB默认材质一致的着色模型 // 定义动态参数:基础色、时间、法线贴图 .uniformParameter(MaterialBuilder.UniformType.FLOAT3, "baseColor") .uniformParameter(MaterialBuilder.UniformType.FLOAT, "time") .uniformParameter(MaterialBuilder.UniformType.SAMPLER_2D, "normalMap") // 自定义着色逻辑:实现气流动画 .material("void material(inout MaterialInputs material) {\n" + " prepareMaterial(material);\n" + " // 1. 基础色随时间波动模拟气流变色\n" + " float colorWave = sin(materialParams.time * 2.0) * 0.2 + 0.8;\n" + " material.baseColor.rgb = materialParams.baseColor * colorWave;\n" + " // 2. 法线贴图UV偏移模拟气流扰动\n" + " vec2 uvShift = vec2(sin(materialParams.time * 1.5), cos(materialParams.time * 1.2)) * 0.01;\n" + " vec3 perturbedNormal = texture(materialParams.normalMap, material.uv + uvShift).rgb * 2.0 - 1.0;\n" + " material.normal = normalize(perturbedNormal);\n" + " // 3. 自发光随时间闪烁增强气流氛围感\n" + " material.emissive = vec3(sin(materialParams.time * 3.0)) * 0.5;\n" + " // 固定材质属性(可根据需求调整)\n" + " material.roughness = 0.65;\n" + " material.metallic = 1.0;\n" + " material.clearCoat = 1.0;\n" + "}\n") .optimization(MaterialBuilder.Optimization.NONE) // 适配filamat lite版本 .build(engine)
2. 替换GLB模型的原有材质
加载GLB模型后,遍历其RenderableInstance,将自定义材质实例替换掉模型原有的材质:
// 假设已通过Filament的AssetLoader加载得到modelEntity engine.renderableManager.forEachRenderable(modelEntity) { instance -> // 创建自定义材质实例 val customMatInstance = matPackage.createInstance() // 设置初始参数:基础色、法线贴图(需提前加载纹理资源) customMatInstance.setParameter("baseColor", floatArrayOf(0.2f, 0.6f, 0.8f)) customMatInstance.setParameter("normalMap", normalTexture) // 替换模型的第一个子材质(索引0,可根据模型结构调整) engine.renderableManager.setMaterialInstance(instance, 0, customMatInstance) }
3. 动态更新参数实现动画
在Filament的渲染循环中,每一帧更新时间参数,驱动着色器中的动画逻辑:
private var animationTime = 0f // 在Filament的FrameCallback中更新 engine.sceneView.renderer.registerFrameCallback { deltaTime -> animationTime += deltaTime // 遍历所有自定义材质实例,更新时间参数 customMatInstance.setParameter("time", animationTime) }
注意事项
- 必须调用
prepareMaterial(material):这是Filament内置管线的入口,缺失会导致材质渲染异常 - 匹配着色模型:尽量选择与GLB原材质一致的着色模型(如LIT),避免渲染风格差异
- 纹理资源处理:法线贴图等纹理需通过Filament的
TextureManager正确加载,确保格式兼容 - 性能优化:复杂动画逻辑可通过降低时间乘数、简化数学运算减少GPU负载
内容的提问来源于stack exchange,提问作者Test Label
相关产品推荐
相关产品推荐

