当前位置: 首页
AI教程
Horse3D游戏引擎材质系统:从JSON配置到GPU Uniform

Horse3D游戏引擎材质系统:从JSON配置到GPU Uniform

热心网友 时间:2026-07-21
转载

Horse3D引擎将材质抽象为JSON格式的 material文件,统一管理着色器、顶点属性和Uniform值,实现解耦。模块分为Percheron(资源定义)、Diligencier(构建解析)和Dragon(渲染层),MaterialBuilder缓存Shader程序避免重复编译,渲染线程与显示端均通过Material::bind release使用材质

Bilibili 同步视频

一、为什么需要材质系统

回顾最初的三角形示例,顶点着色器与片段着色器被直接嵌入C++字符串中。虽然能正常运行,但每次调整颜色或新增Uniform都需要重新编译整个项目,更不用说多个物体共享Shader时带来的重复编译开销了。

因此,将“材质”提升为引擎中的一等公民是明智之举。一个材质文件即可清晰定义三要素:所使用的着色器阶段、顶点属性布局方式以及默认Uniform值(包括颜色、标量、向量、矩阵和纹理)。这样,美术或策划人员只需修改JSON和GLSL文件,无需接触C++代码,实现了真正的解耦。

二、.material 文件格式

材质文件统一存放于 Materials/ 目录,采用JSON格式描述。以下以三角形材质为例:

{"Attributes": [{ "Name": "aPos", "Dimension": 3 },{ "Name": "aTexCoord", "Dimension": 2 }],"Uniforms": [{ "Name": "u_texture", "Type": "Texture2D", "Value": "Triangle.jpeg" }],"Shaders": [{ "ShaderEnum": "Vertex", "SourceFile": "triangle.vert" },{ "ShaderEnum": "Fragment", "SourceFile": "triangle.frag" }]}

对应的片段着色器同样简洁,仅包含一个纹理采样操作:

uniform sampler2D u_texture;void main(){fragColor = texture(u_texture, vTexCoord);}

三、模块划分

材质相关代码被拆分为两个子项目,依赖关系必须明确:

flowchart TBsubgraph Dragon["Dragon(渲染层)"]RT[RenderThread]OB[Object3D]BR[Brush]CA[Camera]IS[IScreen]endsubgraph Diligencier["Diligencier(工具层)"]MB[MaterialBuilder]TL[TextureLoader]FK[FileKit]endsubgraph Percheron["Percheron(资源层)"]MA[Material]IU[IUniform]TX[Texture2D]endRT --> OBOB --> MAOB --> BR & CAIS --> MAMB --> MA & FK & TLTL --> TXMA --> IUIU --> TX

  • Percheron:仅依赖Qt,负责定义 MaterialUniformTexture2D 等基础资源类型。
  • Diligencier:依赖 Percheron,负责解析 .material 文件、编译Shader及加载纹理。
  • Dragon:依赖前两者,在渲染线程中实际使用材质。

通过这种分层设计,即使未来更换构建工具链,Percheron 中的资源定义也无需任何改动。

四、核心类关系

classDiagramIAsset <|-- MaterialIAsset <|-- ITextureITexture <|-- Texture2DMaterial o-- IUniformMaterial o-- Texture2DIUniform <|-- ColorUniformIUniform <|-- FloatUniformIUniform <|-- IntUniformIUniform <|-- Vector2UniformIUniform <|-- Vector3UniformIUniform <|-- Vector4UniformIUniform <|-- Matrix4x4UniformIUniform <|-- Texture2DUniformTexture2DUniform --> Texture2DMaterialBuilder ..> Material : buildsTextureLoader ..> Texture2D : loadsFileKit ..> MaterialBuilder : reads JSON

4.1 Material

Material 是运行时核心容器,其关键特性如下:

  • 持有指向 QOpenGLShaderProgram 的指针(由 MaterialBuilder 缓存并复用,材质本身不负责其生命周期)。
  • 拥有根据 JSON 创建的 IUniform 集合与 Texture2D 列表。
  • bind() 方法负责绑定着色器程序并遍历所有 Uniform 上传;release() 则解绑程序并释放占用的纹理单元。

4.2 Uniform 体系

IUniform 仅暴露一个 useUniform(program) 接口,各子类负责将具体值上传至GPU:

  • ColorUniformFloatUniformVector*UniformMatrix4x4Uniform:直接调用 setUniformValue 方法。
  • Texture2DUniform:激活指定纹理单元,绑定 QOpenGLTexture,并将采样器 Uniform 设置为该单元索引。

这样一来,Material::bind() 无需关心 Uniform 的具体类型,只需统一遍历调用接口,扩展性极佳。

4.3 MaterialBuilder

MaterialBuilder 采用单例模式,核心职责包括以下三项:

  1. 读取 .material 文件中的 JSON 配置;
  2. 按规范路径缓存已编译的 QOpenGLShaderProgram,避免重复编译;
  3. 根据 Uniforms 字段为 Material 填充 Uniform 和纹理。

相对路径统一以 .material 文件所在目录为基准进行解析,因此材质资源可以整体打包移动,极大提升便利性。

4.4 TextureLoader & FileKit

  • FileKit::readText 负责读取文本文件(如 JSON、GLSL)。
  • TextureLoaderQImage 转换为 QOpenGLTexture,并执行垂直翻转(mirrored())以适配 OpenGL 坐标原点。

五、运行时流程

5.1 材质加载

sequenceDiagramparticipant RT as RenderThreadparticipant MB as MaterialBuilderparticipant FK as FileKitparticipant TL as TextureLoaderparticipant MA as MaterialRT->>MB: initializeMaterial(material)MB->>FK: readText(.material)FK-->>MB: JSONMB->>MB: parseShaderSourcesMB->>FK: readText(.vert / .frag)FK-->>MB: source codeMB->>MB: compileAndLinkMB-->>MA: QOpenGLShaderProgramMB->>MB: parseUniformsMB->>TL: loadTexture2D(image)TL-->>MB: Texture2DMB-->>MA: Uniforms & Textures

5.2 一帧渲染

flowchart LRA[Object3D::render] --> B[Material::bind]B --> C[program->bind]C --> D[遍历 Uniform
useUniform 上传]D --> E[设置 u_model]E --> F[Camera::apply
u_view / u_projection]F --> G[Brush::drawGeometry]G --> H[Material::release]

渲染线程将材质和几何体打包到 Object3D 后,每帧只需调用 Object3D::render(camera)。对于镜像地板等需要动态纹理的渲染通道,额外传入运行时纹理ID,由 Object3D 设置 u_mirrorTexture 并绑定。

GUI 线程中的 IScreen 同样使用材质系统,区别在于它仅将渲染线程生成的共享纹理绘制到一个全屏四边形上。

六、设计取舍与踩坑

  1. 程序缓存 vs. 材质拥有
    MaterialBuilder 缓存 QOpenGLShaderProgram,多个 Material 共享同一份程序;Material 析构时仅删除自己的 Uniform 和纹理,避免重复释放。

  2. 纹理单元分配
    目前按 Uniform 出现顺序依次分配 0, 1, 2...,在演示中足够使用,但后续肯定需要独立的纹理单元管理器。

  3. JSON 解析容错
    遇到不认识的 Uniform 类型会直接跳过;编译或链接失败时打印 shader 日志。生产环境建议加入更严格的验证和默认回退纹理。

  4. QImage 原点
    QImage 原点位于左上角,而 OpenGL 纹理原点在左下角,加载时必须使用 image.mirrored() 进行翻转,否则纹理将显示颠倒。

七、当前成果

  • 着色器完全外置,通过 .material 文件的 JSON 配置加载。
  • Material 统一管理 Shader、Uniform 和纹理。
  • MaterialBuilder 提供程序缓存,避免重复编译。
  • 渲染线程和显示端均通过统一的 Material::bind/release 接口使用材质。
  • 依赖关系清晰:Percheron 定义资源,Diligencier 负责构建,Dragon 负责渲染。

八、下一步

  • 支持材质实例化:共享同一 ShaderProgram,但拥有不同的 Uniform 值。
  • 引入 Uniform Buffer Object(UBO),批量上传每帧变化的矩阵。
  • 实现材质热重载:监听 .material.vert/.frag 文件变化,运行时自动重新编译。
  • Attributes 段的描述真正投入使用,由 MaterialBuilder 驱动顶点属性布局。

本系列文章记录了 Horse3D 游戏引擎从零开始的研发历程。

来源:https://juejin.cn/post/7663165474499592230

游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

同类文章
更多
TalkVisions实时视频翻译应用,消除语言障碍

TalkVisions实时视频翻译应用,消除语言障碍

TalkVisions是一款实时视频翻译应用,能将视频中的口语实时转录为文本并翻译成用户所选语言,以字幕形式叠加在画面上,支持多语言、低延迟,还可保存录制视频,有效消除跨语言沟通障碍。

时间:2026-07-25 22:26
AI驱动的日历管理工具Ipso

AI驱动的日历管理工具Ipso

IpsoAI是一款专为专业人士及助手打造的AI日历管理工具,能够自动协调多方日程、智能草拟邮件,并通过快速安排会议、提供智能建议及自动化工作流程,显著减少琐碎操作,帮助用户高效管理时间、提升工作效率。

时间:2026-07-25 22:25
Spectate企业级专业高效监控与事故管理一体化平台

Spectate企业级专业高效监控与事故管理一体化平台

Spectate是一款高效监控和事故管理工具,能在30秒内检测故障并推送告警。它支持Slack、PagerDuty等主流集成,提供自定义状态页面和全球性能监控。系统自动更新状态并推送修复建议,帮助团队减少沟通成本,快速解决问题。

时间:2026-07-25 22:25
阿里云通义千问2.5大模型发布 多项能力赶超GPT-4

阿里云通义千问2.5大模型发布 多项能力赶超GPT-4

通义千问2 5大模型发布,多项能力宣称赶超GPT-4,中文语境下文本理解、生成、知识问答等表现优异。相比2 1版本,理解提升9%、逻辑推理提升16%、指令遵循提升19%。开源1100亿参数模型超越Llama-3-70B,获评开源最强。已服务超9万家企业,与小米、微博等达成合作。

时间:2026-07-25 22:25
万知个人AI工作站:一站式智能阅读创作分享平台

万知个人AI工作站:一站式智能阅读创作分享平台

万知是集成多种AI能力的个人工作站,支持自然语言交互、文档快速阅读与摘要生成、PPT自动设计与优化,覆盖学术研究、商务报告、写作辅助及日常问答等场景,全方位提升工作效率。

时间:2026-07-25 22:25
热门专题
更多
刀塔传奇破解版无限钻石下载大全 刀塔传奇破解版无限钻石下载大全
洛克王国正式正版手游下载安装大全 洛克王国正式正版手游下载安装大全
思美人手游下载专区 思美人手游下载专区
好玩的阿拉德之怒游戏下载合集 好玩的阿拉德之怒游戏下载合集
不思议迷宫手游下载合集 不思议迷宫手游下载合集
百宝袋汉化组游戏最新合集 百宝袋汉化组游戏最新合集
jsk游戏合集30款游戏大全 jsk游戏合集30款游戏大全
宾果消消消原版下载大全 宾果消消消原版下载大全
  • 热门数据榜