Godot PointMesh 实战:3 行代码搞定粒子点渲染,附点云与动态点大小
【免费下载链接】godot-docsGodot Engine official documentation项目地址: https://gitcode.com/GitHub_Trending/go/godot-docs
渲染上千个粒子时帧率暴跌,多半是因为每个粒子还是一整块网格。在 Godot 里,你可以把每个粒子画成一个点就完事——这正是 PointMesh 的设计用途:一种“单点”图元网格,不依赖三角形,在屏幕上被画成恒定像素大小的矩形,是粒子系统、点云可视化与 billboard 点精灵(billboard sprite,始终面向相机的贴片)最省事的渲染方案。
三行代码画出第一个 Godot PointMesh
先看效果,再聊原理。把下面这段放进任意 3D 节点的_ready()里:
var mesh_instance := MeshInstance3D.new() var point_mesh := PointMesh.new() var mat := StandardMaterial3D.new() mat.use_point_size = true mat.point_size = 8.0 point_mesh.material = mat mesh_instance.mesh = point_mesh add_child(mesh_instance)跑起来,场景里会多出一个 8 像素见方的小点——一个 Godot PointMesh 就成了。C# 用户等价写法:new PointMesh()、mat.UsePointSize = true、mat.PointSize = 8f,逻辑完全一致。更多细节见 PointMesh 类参考。
一个点为什么够用:恒定像素、天然正对相机
你可能会觉得只给一个顶点太寒酸,但点渲染的“寒酸”恰恰是卖点:
- 恒定像素大小。点的大小由材质或着色器以像素直接给定,和相机距离无关;三角形网格近大远小的透视缩放,点在屏幕上不会发生。
- 天然正对相机。GPU 把点栅格化为一个屏幕对齐的矩形,这本身就是 billboard 精灵(billboard,即始终面向相机的对象)的效果——地图标记、远景特效这类“永远朝脸”的小图标,不用开
billboard_mode就白嫖了朝向。 - 零三角形。没有面、没有法线、没有正反面,一堆顶点级材质属性对它直接失效(后文坑位见)。这正是它能轻松扛住海量实例的底气。
Godot 点大小怎么设置:两个开关与一棵决策树
先回答唯一的关键问题:你用的是哪种材质?
用内置 StandardMaterial3D:打开 use_point_size
不写着色器、直接拿StandardMaterial3D时,只有两个开关,都挂在BaseMaterial3D上:
use_point_size(bool,默认false):总开关,不开的话point_size设置多少都白搭;point_size(float,默认1.0):单位是像素,1 像素在屏幕上基本不可见,建议从 4.0 起步再调。
类参考里特意强调了:该开关只对“基于点”的几何体生效,对三角形网格无效,别指望它让普通网格的点变大。
用 ShaderMaterial:在 vertex 阶段写 POINT_SIZE
如果你已经用了自定义ShaderMaterial,材质开关帮不上忙,要在顶点着色器里写内置变量POINT_SIZE(inout float)。它还能和片段阶段的POINT_COORD(点矩形内的归一化坐标,范围 0.0~1.0)搭配做形状裁剪,比如把方点剪成圆点:
shader_type spatial; void vertex() { POINT_SIZE = 16.0; // 点直径,单位像素 } void fragment() { vec2 d = POINT_COORD - vec2(0.5); if (dot(d, d) > 0.25) { discard; // 超出半径的片段丢掉,留下圆形 } ALBEDO = vec3(0.8, 0.4, 0.9); }从 GLSL 迁移的话,把gl_PointSize换成POINT_SIZE即可,别的不用动。变量清单可查空间着色器参考文档。
用 Godot PointMesh 必踩的 6 个坑
⚠️ 都是“代码看着对、效果就是不对”的类型,过一遍能省不少排查时间:
- 点看不见:
use_point_size默认关闭且point_size只有 1.0 像素;对策是显式打开开关并调到 4.0 以上。 billboard_mode/grow/cull_mode无效:点天然正对相机,且没有表面与法线、没有正反面;对策是不必设置,设了也没有作用。- 远处的点不缩小:点大小以像素为单位,不走透视缩放;若想要近大远小,在着色器里按深度自行计算
POINT_SIZE(见进阶玩法)。 - 点是方的:GPU 点图元栅格化出来就是矩形;要圆形就在片段阶段用
POINT_COORD配合discard裁剪。 - CSG 节点用不了它:
PointMesh是非流形(non-manifold,面与边不封闭)图元,布尔运算无从下手;CSG 场景请改用BoxMesh、SphereMesh等。 - 着色器偏移顶点后点消失:视锥剔除(frustum culling,把视野外的物体不送去渲染)仍按原始位置的包围盒判断,会误杀;对策是用
custom_aabb把包围盒扩到偏移范围。
同一个点,两种进阶玩法
点云可视化:MultiMesh 批量实例化 5000 个点
要把几千个采样点画成点云,千万别逐点建节点。把同一个PointMesh交给MultiMesh,用实例化(instancing,一次绘制调用画上千份副本)扛住数量,每个实例只换变换:
var mat := StandardMaterial3D.new() mat.use_point_size = true mat.point_size = 4.0 var pm := PointMesh.new() pm.material = mat var mm := MultiMesh.new() mm.mesh = pm mm.instance_count = 5000 for i in 5000: var t := Transform3D() t.origin = Vector3(randf_range(-10, 10), randf_range(-5, 5), randf_range(-10, 10)) mm.set_instance_transform(i, t)再建一个MultiMeshInstance3D,把mm赋给它的multimesh属性并加入场景,一片点云就铺满了。所有实例共享同一份PointMesh资源,只有位置不同,GPU 侧开销远低于逐实例提交。
着色器动态点大小:让远处的点自动缩小
“恒定像素”既是特性也是限制。想要近大远小,就在顶点阶段把顶点投影到裁剪空间,取深度反推像素大小:
shader_type spatial; void vertex() { vec4 clip = PROJECTION_MATRIX * (MODELVIEW_MATRIX * vec4(VERTEX, 1.0)); // clip.w 是视图空间下到相机的距离,越远点越小 POINT_SIZE = clamp(80.0 / max(clip.w, 0.5), 2.0, 16.0); }改完之后,PointMesh也能有透视感,适合密度不均的点云和远景粒子。
Godot PointMesh 适合什么:能力边界与延伸阅读
一句话划界:适合海量、恒定像素、不关心法线与光照的点(粒子、点云、小图标);不适合需要真实光照、背面剔除或 CSG 布尔运算的几何体。需要透视缩放与贴图细节时,换QuadMesh或SphereMesh,别硬掰 PointMesh。
想继续往下挖:
- 空间着色器内置变量:
POINT_SIZE、POINT_COORD及相关矩阵变量一览; - 3D 粒子系统教程:用 Draw Pass 搭完整粒子系统,把网格换成 PointMesh 只需改一行。
【免费下载链接】godot-docsGodot Engine official documentation项目地址: https://gitcode.com/GitHub_Trending/go/godot-docs
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考