)
示例工程【免费下载链接】godot-demo-projectsDemonstration and Template Projects项目地址https://gitcode.com/GitHub_Trending/go/godot-demo-projects点击查看免费下载导读本指南以 compute/post_shader 演示项目为依托系统讲解 Godot 4 中全新的合成器特效Compositor Effects系统即如何利用计算着色器Compute Shader在渲染管线末端实现全屏后处理。你将学会如何创建CompositorEffect资源子类、如何将其挂载到WorldEnvironment或Camera3D的Compositor上、如何通过_render_callback在渲染线程提交计算指令以及模板注入式与文件预编译式两种着色器组织方式的取舍。读完本文你可以独立写出自己的全屏模糊、描边、色彩校正等后处理效果并理解其与 2DCanvasItem着色器的本质差异。适用前提本功能仅在基于渲染设备render device的渲染器中可用即 Forward 渲染器项目配置见 project.godot 中的config/featuresPackedStringArray(4.7, Forward Plus)。演示语言为 GDScript。一、合成器特效系统概述为什么需要它传统的 Godot 2D 后处理如CanvasItem上的CanvasGroup、屏幕空间着色器在 3D 渲染管线中缺乏统一的接入点。合成器特效系统解决了这一问题它把渲染完一帧画面后、在写回屏幕之前的这段时间开放给开发者允许你在该阶段提交任意渲染指令包括计算着色器调度。从 README.md 的技术描述可以提炼出三条核心规则特效即资源一个后处理特效必须先实现为CompositorEffect资源的子类。挂载点有二该资源实例可加入Compositor而Compositor既可以放在WorldEnvironment节点上也可以放在Camera3D节点上本演示使用前者见 main.tscn 中WorldEnvironment节点的compositor SubResource(Compositor_xxhi4)。回调即入口在视口渲染过程中资源的_render_callback会在配置好的阶段stage被调用开发者可在其中提交额外的渲染命令。项目中的两个示例都以tool脚本实现因此在编辑器和运行时都能生效——你在编辑器中调整着色器代码可以立即看到 3D 视口的变化无需进入播放模式。二、两种实现路径模板注入 vs 文件预编译演示项目同时提供了两个CompositorEffect子类对应两种着色器组织策略这是整个 demo 最值得理解的设计对比。2.1 模板注入式post_process_shader.gd该方案将着色器代码保存在特效资源的属性中运行时把用户代码注入到一段 GLSL 模板里再编译。核心代码如下脚本头部通过class_name PostProcessShader extends CompositorEffect声明为合成器特效资源并以tool启用编辑器内运行定义了一个TEMPLATE_SHADER字符串常量内含#version 450、#include godot/scene_data_inc.glsl、layout(local_size_x 8, local_size_y 8, local_size_z 1) in;等基础设施并预留#COMPUTE_CODE占位符模板中声明了三个关键绑定set 0, binding 0的场景数据统一缓冲SceneDataBlock、binding 1的rgba16f颜色图像、binding 2的深度纹理采样器以及一组与脚本端推送常量严格对齐的Paramsvec2 raster_size; float view; float pad;注释明确要求必须按 16 字节对齐用户代码通过export_multiline var shader_code: String暴露其 setter 在加锁后把shader_is_dirty置为真触发重新编译。运行时代码注入与重编译流程渲染线程区域#region Code in this region runs on the rendering thread_check_shader()在互斥锁保护下检查shader_is_dirty标记若需要更新用TEMPLATE_SHADER.replace(#COMPUTE_CODE, new_shader_code)拼接完整着色器源码调用rd.shader_compile_spirv_from_source()把 GLSL 编译为 SPIR-V若compile_error_compute非空则通过push_error输出错误依次创建着色器 RID 与计算管线rd.compute_pipeline_create(shader)。这种方式能在运行时随属性变化重新编译着色器你可以拖动滑条或在代码中修改注入片段效果实时更新。但 README 明确指出了两个限制无法有效利用着色器缓存shader caching某些平台可能不支持例如要求着色器预编译的控制台平台consoles。在 main.tscn 中这个特效资源携带了一段默认注入代码——将深度反投影unproject后的世界坐标映射为 RGB 颜色的伪深度可视化片段// Unproject vec4 unproj vec4(uv_norm * 2.0 - 1.0, depth, 1.0); mat4 inv_projection_matrix scene_data_block.data.inv_projection_matrix_view[view]; vec4 vertex inv_projection_matrix * unproj; vertex.xyz vertex.xyz / vertex.w; color.rgb clamp(vec3(vertex.x/20.0, vertex.y/20.0, -vertex.z/20.0), 0.0, 1.0);注意它通过scene_data_block访问了视图专属的逆投影矩阵这正是模板中引入#include godot/scene_data_inc.glsl与SceneDataBlock的原因。2.2 文件预编译式post_process_grayscale.gd该方案把着色器代码存成独立文件 post_process_grayscale.glsl在初始化阶段一次性编译func _init() - void: effect_callback_type EFFECT_CALLBACK_TYPE_POST_TRANSPARENT rd RenderingServer.get_rendering_device() RenderingServer.call_on_render_thread(_initialize_compute)通过load(res://post_process_grayscale.glsl)加载着色器文件其导入类型为RDShaderFile见 post_process_grayscale.glsl.import 中的importerglsl、typeRDShaderFile调用shader_file.get_spirv()直接取得引擎预编译好的 SPIR-V再创建着色器与计算管线编译过程发生在初始化阶段因此编辑glsl文件后需要重新加载场景才能看到效果。该方式的优势正如 README 所述Godot 可以对glsl文件进行预编译precompile从而获得更好的平台兼容性与启动性能。两种方式的取舍可以总结为下表维度模板注入式post_process_shader.gd文件预编译式post_process_grayscale.gd着色器来源资源属性shader_codeexport_multiline独立.glsl文件编译时机属性变化时运行时重编译初始化时编译一次修改生效方式运行时实时生效需重新加载场景着色器缓存无法有效利用支持 Godot 预编译平台兼容性部分要求预编译的控制台平台可能不支持更广三、着色器与脚本的协作细节3.1 灰度计算着色器剖析post_process_grayscale.glsl 是一段标准的计算着色器麻雀虽小五脏俱全#[compute] #version 450 layout(local_size_x 8, local_size_y 8, local_size_z 1) in; layout(rgba16f, set 0, binding 0) uniform image2D color_image; layout(push_constant, std430) uniform Params { vec2 raster_size; vec2 reserved; } params; void main() { ivec2 uv ivec2(gl_GlobalInvocationID.xy); ivec2 size ivec2(params.raster_size); // Prevent reading/writing out of bounds. if (uv.x size.x || uv.y size.y) { return; } // Read from our color buffer. vec4 color imageLoad(color_image, uv); // Apply our changes. float gray color.r * 0.2125 color.g * 0.7154 color.b * 0.0721; color.rgb vec3(gray); // Write back to our color buffer. imageStore(color_image, uv, color); }要点说明工作组尺寸为8 x 8 x 1与脚本端_render_callback中的派发数量严格对应见下文rgba16f说明颜色缓冲是 16 位浮点格式这是 HDR 渲染管线的标配灰度权重0.2125 / 0.7154 / 0.0721是标准的 Rec.709 亮度系数比简单取平均更符合人眼感知越界保护uv.x size.x || uv.y size.y是必须的因为(size.x - 1) / 8 1的向上取整可能导致工作组覆盖超出实际图像尺寸。3.2 渲染线程回调_render_callback 的完整调用链两个脚本的_render_callback结构高度一致这里以功能更完整的 post_process_shader.gd 为例梳理完整流程阶段校验p_effect_callback_type EFFECT_CALLBACK_TYPE_POST_TRANSPARENT即仅在透明物体渲染后的阶段触发该枚举值4也固化在 main.tscn 的effect_callback_type 4中获取渲染缓冲p_render_data.get_render_scene_buffers()返回RenderSceneBuffers注释提醒不同渲染器的实现不同因此需要类型转换读取内部尺寸render_scene_buffers.get_internal_size()得到的是3D 渲染分辨率而非窗口分辨率若为 0 则提前返回计算工作组数量x_groups (size.x - 1) / 8 1向上取整y_groups同理z_groups 1构造推送常量PackedFloat32Array([size.x, size.y, 0.0, 0.0])注释强调必须与着色器中Params的字段顺序一致并保持 16 字节对齐创建最近邻采样器SAMPLER_FILTER_NEAREST供深度纹理采样使用只在无效时重建一次遍历所有视图render_scene_buffers.get_view_count()兼容立体渲染VR单目渲染时循环只有一次、无额外开销构建统一集合使用UniformSetCacheRD.get_cache(shader, 0, [...])——该缓存会在视口配置变化时自动清理派发计算compute_list_begin → compute_list_bind_compute_pipeline → compute_list_bind_uniform_set → compute_list_set_push_constant → compute_list_dispatch → compute_list_end这是 RenderingDevice 提交计算任务的完整序列。此外脚本在_notification中响应NOTIFICATION_PREDELETE负责释放着色器 RID注释说明释放着色器会连带释放依赖它的管线与采样器 RID这是避免渲染资源泄漏的关键细节。3.3 两种脚本的差异post_process_shader.gd额外绑定了深度纹理binding 2因此能实现依赖深度信息的后处理如反投影可视化post_process_grayscale.gd只绑定颜色图像binding 0结构更精简也展示了单图像读写这一最常见的最小用例前者使用Mutex保护跨线程共享的shader_code状态后者无需此机制因为着色器在初始化时一次性编译完成。四、场景组织与交互控制4.1 场景树结构main.tscn 展示了一个最小可复用的场景模板Main (Node3D, main.gd) ├── DirectionalLight3D (shadow_enabled) ├── WorldEnvironment │ └── compositor Compositor(compositor_effects [Grayscale特效, Shader特效]) ├── Camera3D (fov 60) ├── Ground (PlaneMesh, 棋盘格纹理 pattern.png) ├── Sphere / Box (彩色棋盘格材质) ├── Info (Label) —— 显示两个特效的开关状态 └── Help (Label) —— 提示按键 G / S环境使用ProceduralSkyMaterial天空并开启glow_enabled为后处理效果提供了足够丰富的色彩输入。两个CompositorEffect子资源在Compositor中按数组顺序排列索引 0 是灰度特效默认enabled true索引 1 是着色器注入特效默认enabled false。4.2 运行时开关main.gd 通过输入动作切换两个特效的enabled属性extends Node3D onready var compositor: Compositor $WorldEnvironment.compositor func _input(input_event: InputEvent) - void: if input_event.is_action_pressed(toggle_grayscale_effect): compositor.compositor_effects[0].enabled not compositor.compositor_effects[0].enabled update_info_text() if input_event.is_action_pressed(toggle_shader_effect): compositor.compositor_effects[1].enabled not compositor.compositor_effects[1].enabled update_info_text()对应的输入映射定义在 project.godot 的[input]段toggle_grayscale_effect绑定物理键71G 键、toggle_shader_effect绑定物理键83S 键。Info标签会实时显示Grayscale effect: Enabled/Disabled与Shader effect: Enabled/Disabled方便对比开启前后画面差异。这种通过compositor_effects[i].enabled动态启停的机制意味着你可以在玩法代码中随时切换特效例如只在低血量时开启画面灰度或者按场景切换色调映射方案。五、在编辑器中的可视化调试由于两个脚本均以tool标注在编辑器中选中WorldEnvironment节点即可在 Inspector 中直接编辑shader_code多行文本3D 视口会同步反映效果变化。项目截图screenshots/post_process_shader.webp展示了编辑器内启用灰度特效后的场景棋盘格地面、立方体与球体整体呈现灰度Inspector 中可看到PostProcessShader资源、Enabled开关与Effect Callback Type: Post Transparent等参数。六、迁移到自己的项目实操清单如果你想把该方案复用到自己的 Godot 4.x 项目按以下步骤操作确认渲染器在项目设置中选择 Forwardconfig/features含Forward PlusMobile/Compatibility 等非渲染设备后端不支持此功能编写特效脚本新建脚本继承CompositorEffect在_init中设置effect_callback_type EFFECT_CALLBACK_TYPE_POST_TRANSPARENT或EFFECT_CALLBACK_TYPE_POST_OPAQUE等更早阶段获取RenderingServer.get_rendering_device()选择着色器组织方式原型调试 / 参数动态变化采用模板注入式把用户代码放入export_multiline属性正式发布 / 追求缓存与平台兼容采用文件预编译式把 GLSL 存为*.glsl文件并load()后get_spirv()挂载合成器在场景中创建WorldEnvironment或Camera3D在属性面板添加Compositor再向compositor_effects数组添加特效资源实例编写回调在_render_callback中获取RenderSceneBuffers以get_internal_size()计算派发组数构造 16 字节对齐的推送常量最后用UniformSetCacheRDcompute_list_*提交计算任务记得清理在_notification(NOTIFICATION_PREDELETE)中释放着色器与采样器 RID。七、小结compute/post_shader演示的核心价值在于它把 Godot 4 合成器特效系统的完整链路——资源子类、挂载方式、渲染回调、SPIR-V 编译、计算派发、双平台着色器策略——浓缩在两个约两百行的脚本中。无论你是要做风格化渲染、深度可视化还是性能分析工具这条链路都是 3D 后处理扩展的起点。唯一需要牢记的限制是它只服务于 Forward 这类基于渲染设备的渲染器且模板注入方案在需要着色器预编译的平台上可能无法工作——选择文件预编译方案则能获得更广的兼容面。如果你希望继续深入可以在仓库中找到更多相关的计算着色器示例compute/heightmap计算着色器生成高度图与 compute/texture计算纹理处理它们与本文共享RenderingDevice的编译与派发基础设施可以交叉印证。赞分享示例工程【免费下载链接】godot-demo-projectsDemonstration and Template Projects项目地址https://gitcode.com/GitHub_Trending/go/godot-demo-projects点击查看免费下载相关推荐Godot-demo-projects中的着色器示例2D与3D特效实现教程Godot demo projects中的着色器示例2D与3D特效实现教程 引言告别特效实现困境 你是否还在为Godot引擎中着色器 Shader 的复杂语示例工程godot-demo-projects 2D 示例合集GDScript、着色器与渲染器选型的实战指南godot demo projects 2D 示例合集GDScript、着色器与渲染器选型的实战指南 本文基于 godot demo projects 仓库的示例工程Godot 4 物理光照与相机单位实战基于 godot-demo-projects 的 Physical Light and Camera Units 演示Godot 4 物理光照与相机单位实战基于 godot demo projects 的 Physical Light and Camera Units 演示示例工程上一篇【亲测免费】 PHP_CodeSniffer 使用常见问题解决方案下一篇Laravel Prompts 终极指南解决 CLI 表单开发中的 7 大常见问题创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考