ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

Bevy 着色器迁移到 WESL:从 naga_oil 预处理到原生着色器模块

Bevy 着色器迁移到 WESL:从 naga_oil 预处理到原生着色器模块 Bevy 着色器迁移到 WESL从 naga_oil 预处理到原生着色器模块【免费下载链接】bevyA refreshingly simple>项目地址: https://gitcode.com/GitHub_Trending/be/bevyBevy 的着色器已从 naga_oil 预处理器方言全面切换到 WESL完整覆盖新旧语法对照、模块命名规则、着色器定义shader defs的映射方式并结合 bevy_shader 源码 与 着色器缓存实现 讲解 WESL 在 Bevy 中的编译、解析与缓存机制帮助你安全完成自定义着色器的迁移。核心变化WESL 取代 naga_oilBevy 引擎内置的所有着色器现在都直接用 WESL 编写naga_oil预处理器被彻底移除。迁移指南给出的结论是使用 naga_oil 方言的自定义着色器必须翻译成 WESL并将扩展名从.wgsl改为.wesl不含任何预处理指令的纯 WGSL 文件可以继续原样使用无需改动。这一判断的依据可以在加载器源码中得到印证ShaderLoader 按扩展名分派到三种Source变体——spv走Shader::from_spirv、wgsl走Shader::from_wgsl、wesl走Shader::from_wesl三者分别对应 Source 枚举 中的SpirV、Wgsl、Wesl。也就是说纯 WGSL 文件进入缓存后会被原样交给渲染器编译完全绕开 WESL 管线。同时有两条加载规则值得注意shader.rs L288-L293只有.wesl文件支持 shader defs。如果给.wgsl/.spv着色器附加了shader_defsBevy 会打印警告 “Tried to load a non-wesl shader with shader defs, this isnt supported” 并忽略这些定义不支持的扩展名会直接 panicunhandled extension加载器声明的合法扩展名为[spv, wgsl, wesl]。语法对照BEFORE / AFTER 逐行解析迁移指南给出的新旧对照示例是本次迁移的核心参照这里完整保留并逐条解释// BEFOREnaga_oil 方言 #import bevy_pbr::forward_io::VertexOutput #import shaders/util.wgsl::hsv_to_rgb #ifdef VERTEX_COLORS varprivate tint: vec4f32; #endif group(2) binding(#{MATERIAL_BINDING}) varuniform color: vec4f32; // AFTERWESL import bevy_pbr::render::forward_io::VertexOutput; import super::util::hsv_to_rgb; if(VERTEX_COLORS) varprivate tint: vec4f32; group(2) binding(constants::MATERIAL_BINDING) varuniform color: vec4f32;映射关系可归纳为四类naga_oil 写法WESL 写法说明#import a::b::Cimport a::b::C;import 以分号结尾且必须置于文件最前#ifdef X…#endifif(X)无结束标记条件编译直接附着在声明上#{NAME}constants::NAME数值定义变成可读常量#define_import_path移除导入路径由文件位置自动推导1. import 语句位置与分号规则WESL 的import必须以分号结尾并且必须位于文件开头出现在任何声明或enable指令之前。这与 Rust 的use风格一致也和仓库中引擎自带着色器的实际写法吻合例如 bevy_pbr 的 pbr.wesl 开篇就是一组importimport package::{ render::{ pbr_types, pbr_functions::alpha_discard, pbr_fragment::pbr_input_from_standard_material, }, decal::clustered::apply_decals, };此外 WESL 支持跨 crate 的具名导入如import bevy_core_pipeline::oit::draw::oit_draw;见 pbr.wesl。2. 模块名与着色器在 crate 中的路径一致指南指出模块名现在必须与着色器文件在其 crate 中的路径匹配。由于 Bevy 引擎的着色器被重组进了子目录一批旧路径发生了平移例如bevy_pbr::mesh_view_bindings→bevy_pbr::render::mesh_view_bindings对应 crates/bevy_pbr/src/render/mesh_view_bindings.weslbevy_pbr::prepass_utils→bevy_pbr::prepass::utils。这条规则的底层逻辑在 Shader::from_wesl 中非常清晰对于embedded://前缀的路径Bevy 去掉协议前缀与文件扩展名后把路径按/拆分成::分隔的模块名——embedded://bevy_foo/bar.wesl因此成为可导入的bevy_foo::bar非内嵌着色器则生成以/开头的资产路径ShaderImport::AssetPath即指南所说的 “anything else at its asset path”其余着色器按资产路径导入。对于项目内自定义着色器指南示例中的import super::util::hsv_to_rgb;展示了相对引用写法shaders/util.wesl这样的本地文件可以用super::util相对模块名导入替代过去#import shaders/util.wgsl::hsv_to_rgb的字符串路径。3. 条件编译if 附着在语言元素上if/elif/else直接附着在完整的声明、结构体成员、函数参数、import 乃至单条语句上不再需要#ifdef/#endif包裹块。引擎着色器中的真实用例覆盖了指南提到的所有附着位置附着结构体成员forward_io.wesl 中UncompressedVertex的每个顶点属性都按能力开关裁掉struct UncompressedVertex { builtin(instance_index) instance_index: u32, if(VERTEX_POSITIONS) location(0) position: vec3f32, if(VERTEX_NORMALS) location(1) normal: vec3f32, ... if(VERTEX_COLORS) location(5) color: vec4f32, };附着函数参数pbr.wesl的 fragment 入口按管线阶段裁剪入参if(MESHLET_MESH_MATERIAL_PASS)控制frag_coord是否存在附着 importpbr.wesl中 prepass 与 forward 两条管线引用不同的输入输出类型if(PREPASS_PIPELINE) import package::{ prepass::io::{VertexOutput, FragmentOutput}, deferred::functions::deferred_output, }; else import package::render::{ forward_io::{VertexOutput, FragmentOutput}, ... };附着语句pbr.wesl的 fragment 体内用if(...)包裹逐语句逻辑。4. shader defs布尔变开关、数值变常量指南的关键一条布尔型着色器定义Bool变成条件编译开关Int/UInt定义则同时可读作constants::NAME常量并启用一个同名开关。例如binding(#{MATERIAL_BINDING})改为binding(constants::MATERIAL_BINDING)值在编译期由 Bevy 注入。这一机制在 ShaderCache::get 中有完整实现。编译一个 WESL 着色器时收集定义闭包L229-L247从当前着色器出发沿imports图做 BFS把依赖链上每个库着色器自带的shader_defs一并纳入closure_defs——这意味着库着色器里写死的constants::取值会随依赖自动传播分流处理L248-L280Bool(key, v)写入compiler_options.features.flags作为if开关Int/UInt除了启用同名开关外还会把keyvalue追加进一张常量表生成虚拟constants模块常量表被拼成const NAME value;形式的源码L277-L280由 ShaderResolver::resolve_source 在解析到模块名constants时注入因此constants::MATERIAL_BINDING在文本上就是普通 WGSL 的常量引用编译输出 WGSLwesl::compile_sourcemap以imports: true, condcomp: true的 CompileOptions 把模块及其依赖拼成最终 WGSL 源再交给渲染器编译。Int/UInt定义的常量用法在单元测试 constants_module 中得到验证——group(constants::MATERIAL_BIND_GROUP)与arrayvec4f32, constants::BATCH_SIZE在给定ShaderDefVal::UInt后编译产物中确实出现了对应的 2;与 4;。5.#define_import_path移除路径即身份过去 naga_oil 需要#define_import_path手动声明着色器的导入名现在该指令不复存在导入路径完全由文件来源决定从embedded://加载的着色器按其crate 名 文件路径可导入embedded://bevy_foo/bar.wesl即bevy_foo::bar其他着色器按其资产路径可导入。对应的代码证据是 scan_wesl_imports它解析 WESL 源码中的每条import把Package来源的模块路径拼回crate::module::item形式的ShaderImport::Custom把Absolute来源拼回/a/b/c形式的ShaderImport::AssetPath从而让资产系统能自动跟踪导入依赖加载器中的依赖收集逻辑 会为每个AssetPath导入load_context.load一份强引用防止被引用文件提前释放。特性开关与兼容边界指南末尾给出了三条框架级变化逐条对应源码事实shader_format_weslcargo feature 已移除WESL 支持始终启用。WESL 是 bevy_shader 的无条件依赖wesl { version 0.4.2, features [naga-ext] }不再有任何开关GLSL 支持一并移除着色器源只保留Source::{Wgsl, Wesl, SpirV}三种形态SPIR-V 直通passthrough保持不变.spv文件依旧按字节直传ShaderLoader 分派但如前所述SPIR-V 着色器不支持 shader defs且 ValidateShader 文档中说明对不受信任的 SPIR-V 启用运行期校验会 panic。从源码结构看缓存、重试与失效理解 WESL 管线的一个隐藏重点是导入解析的时序。着色器资产按加载先后入缓存若某个import的目标尚未加载完成get() 会返回ShaderImportNotYetAvailable下一帧重试import_retry 测试 验证了这一“先失败、后成功”的流程。其他几个单测也很有参考价值library_def_scoping两个库着色器各自定义不同BATCH_SIZE3 与 7根着色器分别引用后各自的编译产物只含自己的常量——说明常量闭包是按依赖图精确收集的不会串值cyclic_import_invalidation循环导入的模块被替换后依赖它的管线会全部被标记重编译缓存失效传播是闭环的import_resolution库着色器热替换后引用它的根着色器自动进入重编译队列。迁移操作清单结合指南与源码一个自定义着色器例如仓库 assets/shaders/custom_material.wesl 这类项目内文件的迁移步骤可以归纳为判断是否需要迁移文件中不含#import/#ifdef/#{...}等预处理指令时保留.wgsl原样即可否则执行后续步骤重命名.wgsl→.wesl同步更新 Rust 侧加载路径ShaderRef/AssetPath中的扩展名翻译指令#import X→import X;移到文件顶部、加分号#ifdef X ... #endif→ 在声明前加if(X)无结束标记#{NAME}→constants::NAME修正模块名引擎内置着色器按“crate 内文件路径”重命名导入如bevy_pbr::render::forward_io本地文件用相对模块名super::util或资产路径引用删除所有#define_import_path核对 shader defs确认布尔定义用于if开关数值定义ShaderDefVal::Int/UInt通过constants::NAME读取验证着色器源在 ShaderCache::get 中经wesl::compile_sourcemap产出 WGSL若导入缺失会输出 “Shader...has an unresolved import” 警告每个着色器只告警一次见 L297-L305语法问题则以ProcessShaderError报错并附带可读的诊断位置信息。小结这次迁移的本质是Bevy 把着色器的模块系统、条件编译和常量注入从外部预处理器naga_oil内化到了 WESL 语言本身import走资产系统、if走 WESL 条件编译、constants::走虚拟常量模块。纯 WGSL 与 SPIR-V 两条通路保持不变但只有 WESL 能享受 defs 与导入追踪能力。对引擎作者而言bevy_pbr等模块的.wesl文件是现成的、带注释的迁移范本对使用者而言照上文对照表逐条替换并核对模块路径即可完成迁移。【免费下载链接】bevyA refreshingly simple>项目地址: https://gitcode.com/GitHub_Trending/be/bevy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表