4、Kanzi 2D/3D渲染:2D图形绘制、3D场景搭建、粒子系统与特效
好,咱们今天聊聊Kanzi的渲染能力。说实话,很多做车载HMI的朋友一开始都以为Kanzi只是个2D UI工具,其实它的3D能力被严重低估了。我在几个量产项目里,都用Kanzi直接搭建了3D场景,效果不比Unity差多少,关键是和2D UI的融合度极高。
4.1 2D图形绘制:矩形、圆形与渐变
2D绘制是基础中的基础。Kanzi里绘制图形,我习惯用两种方式:一种是直接用预制控件,另一种是用Canvas自己画。
4.1.1 矩形与圆角矩形
矩形最简单,拖一个Image2D控件,设置背景色就行。但圆角矩形呢?很多人去切图,其实没必要。
// 在Kanzi Studio中,通过属性面板设置
// 或者代码里这样写
Image2D image = new Image2D();
image.BackgroundBrush = new SolidColorBrush(Color.Red);
image.CornerRadius = new Thickness(10, 10, 10, 10); // 四个角统一圆角
嗯,这里要注意:CornerRadius可以分别设置四个角。我在项目中遇到过一个问题——只给左上角设圆角,其他三个角是直角,结果渲染出来边缘有锯齿。后来发现是抗锯齿没开,在渲染设置里把AntiAliasing打开就好了。
4.1.2 圆形与椭圆
圆形其实就是特殊的圆角矩形。把宽高设成一样,圆角设成宽度的一半,就是个正圆。
Ellipse2D控件。它比Image2D更轻量,性能更好。
4.1.3 渐变绘制
渐变这块,Kanzi支持线性渐变和径向渐变。我个人更常用线性渐变,比如仪表盘的背景光效。
// 线性渐变示例
LinearGradientBrush gradient = new LinearGradientBrush();
gradient.StartPoint = new Point(0, 0);
gradient.EndPoint = new Point(1, 1); // 对角线渐变
gradient.GradientStops.Add(new GradientStop(Color.FromArgb(255, 0, 120, 255), 0.0f));
gradient.GradientStops.Add(new GradientStop(Color.FromArgb(255, 0, 200, 255), 0.5f));
gradient.GradientStops.Add(new GradientStop(Color.FromArgb(255, 0, 50, 150), 1.0f));
image.BackgroundBrush = gradient;
我曾经踩过一个坑:渐变颜色在编辑器里看着挺好,一上真机颜色就偏了。后来发现是颜色空间的问题。Kanzi默认用sRGB,但有些硬件用线性空间。解决办法是在Project Settings里明确指定颜色空间。
4.2 3D场景搭建:相机、灯光与模型导入
3D场景搭建,说白了就是搭一个虚拟的摄影棚。你需要相机(Camera)、灯光(Light)和模型(Model)。
4.2.1 相机设置
相机决定了用户看到什么。Kanzi里相机分两种:透视相机和正交相机。车载HMI里,透视相机用得最多,因为它有近大远小的效果,更真实。
// 创建透视相机
PerspectiveCamera camera = new PerspectiveCamera();
camera.FieldOfView = 60.0f; // 视野角度,我一般用45-60度
camera.NearPlane = 0.1f;
camera.FarPlane = 1000.0f;
camera.Position = new Vector3(0, 0, 5); // 相机位置
camera.LookAt = new Vector3(0, 0, 0); // 看向原点
你想想看,如果视野角度设太大,画面会变形;设太小,又像望远镜。我建议在45-60度之间调试,这个范围最接近人眼视角。
4.2.2 灯光系统
灯光是3D场景的灵魂。没有灯光,模型就是一片黑。Kanzi支持三种灯光:方向光、点光源和聚光灯。
| 灯光类型 | 适用场景 | 性能开销 |
|---|---|---|
| 方向光 | 模拟太阳光,全局照明 | 低 |
| 点光源 | 模拟灯泡,局部照明 | 中 |
| 聚光灯 | 模拟车灯,聚焦效果 | 高 |
我个人习惯用两盏方向光:一盏主光,一盏补光。主光从左上角打下来,补光从右下角补一点。这样模型立体感最强,而且性能开销最小。
4.2.3 模型导入
模型导入这块,Kanzi支持FBX、glTF、OBJ等格式。我强烈推荐用glTF格式,它是Khronos Group的标准,压缩率高,加载快。
// 加载glTF模型
Model3D model = new Model3D();
model.Source = "resource://Models/car_body.gltf";
model.Position = new Vector3(0, -0.5, 0);
model.Scale = new Vector3(0.01f, 0.01f, 0.01f); // 模型太大,缩小100倍
嗯,这里有个坑:模型导入后位置不对。我遇到过模型跑到地底下去了,或者旋转轴不对。解决办法是在3D建模软件里就把模型原点设在中心,导出前检查一下坐标轴。
4.3 粒子系统与特效
粒子系统是HMI的点睛之笔。比如充电时的流光效果、空调出风口的粒子动画、启动时的光晕特效,都靠它。
4.3.1 粒子系统基础
Kanzi的粒子系统基于ParticleEmitter组件。你需要设置几个关键参数:发射速率、生命周期、速度、大小、颜色。
// 创建一个简单的粒子发射器
ParticleEmitter emitter = new ParticleEmitter();
emitter.EmissionRate = 50; // 每秒发射50个粒子
emitter.ParticleLifetime = 2.0f; // 每个粒子存活2秒
emitter.Speed = new Vector3(0, 1, 0); // 向上运动
emitter.Size = new Vector2(10, 10); // 粒子大小
emitter.Color = Color.FromArgb(255, 0, 150, 255); // 蓝色粒子
你想想看,如果发射速率设成1000,粒子会像喷泉一样喷出来。但性能也会爆炸。我建议发射速率控制在100以内,除非你特别需要密集效果。
4.3.2 粒子纹理与动画
粒子不一定是小圆点。你可以用纹理贴图,比如星星、火花、光晕。我常用一张渐变圆点的纹理,配合颜色变化,做出流光效果。
// 使用纹理
emitter.Texture = new Texture2D("resource://Textures/glow.png");
emitter.ColorOverLifetime = new Gradient(); // 颜色随时间变化
emitter.ColorOverLifetime.AddStop(0.0f, Color.White);
emitter.ColorOverLifetime.AddStop(1.0f, Color.Transparent); // 逐渐消失
我曾经做过一个充电特效:粒子从充电口飞出,沿着曲线路径飞到电池图标。这个用粒子系统的Path属性就能实现,不需要写复杂的脚本。
4.3.3 特效优化
粒子系统是性能杀手。我总结了几条优化原则:
- 控制粒子数量:同时存在的粒子不要超过500个
- 使用小纹理:纹理尺寸不要超过64x64
- 禁用碰撞:粒子碰撞计算很耗CPU,非必要不用
- 合并发射器:多个小发射器不如一个大发射器
好了,这一章的内容就这些。下一章我们会聊Kanzi的动画系统,包括关键帧动画、路径动画和状态机动画。到时候我会分享一些我在动画调优上的血泪史,敬请期待。