你点开一个星系漫游应用,手指滑动,屏幕上的视角随即在银河里穿行。数万颗独立的星星按距离实时变暗,每一颗都不是贴图,而是即时计算亮度的三维光点。这个活生生的场景背后,并没有什么庞大的游戏引擎,渲染代码完全放在一个共享的 Kotlin 模块里。更令人意外的是,它故意把前两代项目的分层结构反了过来。
在做星系应用之前,作者先完成了两次 3D 国际象棋开发。第一次用 Compose Multiplatform 做壳,第二次换成 React Native。两次实践中,下棋规则、走法合法性、将军检测这些核心逻辑通通写在共享的 Kotlin 代码里,而三维渲染器则按平台分别实现。共享逻辑成了严格唯一的事实来源。共享核心引擎直接从 Compose Multiplatform 仓库以 Maven 坐标 `io.github.ber4444:chess-core` 发布,React Native 项目通过一层很薄的包装类引用它,两个项目之间没有一行重复的 Kotlin 代码。甚至 React Native 端的 TypeScript 类型绑定,也是利用 Kotlin 的 `@JsExport` 声明自动生成,保证类型定义永远同步。
![]()
这就是前两篇文章的思路:有价值的代码丢进共享层,渲染只是交付物。但星系渲染器的故事把整个思路翻转了过来。
这款应用要实时渲染银河系的立体环境,用户在成千上万颗恒星之间飞行,每颗星根据距离实时计算亮度衰减。一张静态背景图根本行不通,核心卖点就是可导航、可交互的活场景。渲染器成了绝对的资产——它定制程度极高,决定了应用所有视觉特性,也正是那种谁都不想重复写两遍的代码。既然图形调用都是平台特有的绑定,而非通用 API,要保住这层代码就必须回答一个新问题:能不能把图形 API 隔离在一个接缝面之下,让渲染器本身住进 `commonMain`?
答案是能。新的分层图景里,顶层原生应用只剩极薄的一层胶水和手势输入传递,iOS 侧用 Swift,Android 侧用 Kotlin,渲染器模块根本看不见 `View` 或 `ViewController`。中间移进共享 Kotlin 核心的部分,不再只是业务规则,而是完整的渲染器、着色器资源、相机运动数学以及视觉叠加元素。堆栈的底部,一个 GL 外观层把共享核心与平台驱动隔开,在 Android 上直接路由到图形 API,在 iOS 上则通过一个翻译层桥接下去。同一个 Kotlin 语言,承担重量的模块换到了完全不同的位置。
共享核心的合约也随之明确:所有绘制逻辑都落在 `commonMain`,包括渲染器本身、相机数学、数据解析器,以及一份单源维护常量的约定文件。`androidMain` 和 `iosMain` 只负责平台专属的 API 委托和图像解码器,没有任何渲染策略掺杂其中。
从国际象棋到星系漫游,转变的不仅是应用类型,更是对“哪些代码值得共享”这一问题的重新回答。前一个项目把规则引擎高高托起,把渲染视作耗材;这一次,渲染器成了主权代码,平台层则被削薄成透明的转接头。两种架构指向同一个结论:Kotlin Multiplatform 里,真正的分层不是固定配方,而是由核心资产的位置决定的。重头戏挪到共享层的那一刻,平台端反而变得轻盈,维护负担也随之收窄。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.