godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.12k stars 69 forks source link

Add billboard transform align settings to CPUParticles3D (like in GPUParticles3D) #6172

Open lostminds opened 1 year ago

lostminds commented 1 year ago

Describe the project you are working on

A particle effect with billboarded shaded quads in a 3D environment

Describe the problem or limitation you are having in your project

I'm making a sparkling particle effect in 3d, where I want to have little billboarded quads that use a simple custom shader I've made. I've tried using GPUParticles3D as this has an easy to set up billboaring setting that works great. But unfortunately it also has alot of other stability issues that means I've now abandoned it in favor of the more stable GPUParticles3D. It works much better, but for some reason it's missing an option to billboard the meshes towards the camera.

The only way to achieve billboarding on CPUParticles3D seems to be to use a material with a vertex shader (like the standard material has I assume), but this is very complex and restrictive in my mind compared to simply having the particle system orienting all the particles to face the camera and then allowing you to apply any basic shader or material to them like you can in the GPUParticles3D case.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

GPUParticles3D has a transform align setting (in the drawing section) that lets you align the meshes (simple quads in my case) to billboard them towards the camera. Basically, the way GPUParticles3D currently handles billboaring seems a lot better in my mind, and both for consistency and as an improvement I'd propose that this functionality should work the same in CPUParticles3D. Making this change should also be backward compatible since just not using the setting would work the same as the current implementation. And hopefully, since this is already implemented in GPUParticles3D there should be code that can be reused.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

Add the same transform align setting that is currently implemented in GPUParticles3D to CPUParticles3D. While there will of course be changes needed, hopefully a lot of the code used to align the particles on the GPU version can be reused on the CPU version.

If this enhancement will not be used often, can it be worked around with a few lines of script?

There is the workaround using the standard materials billboarding setting, but this is restrictive as you then need to use the standard material. It's also inconsistent with GPUParticles and hard to understand (since it seems backward to have the material of the mesh be responsible for the orientation of the particles)

Is there a reason why this should be core and not an add-on in the asset library?

CPU and GPU particle nodes are part of the core, and I think they should (as far as possible) be consistent in their use and functionality in the core.

Calinou commented 1 year ago

This is probably not feasible in a way that doesn't involve modifying the material. Billboarding each each particle on the CPU individually is likely not viable for performance reasons.

There is the workaround using the standard materials billboarding setting, but this is restrictive as you then need to use the standard material.

ShaderMaterials can also use billboarding by converting a BaseMaterial3D with billboarding enabled to a ShaderMaterial, or copying the appropriate lines that are generated by BaseMaterial3D to the shader's vertex() function:

https://github.com/godotengine/godot/blob/10d22a4b35b33ad89f626c261ef7f1aeae81daf3/scene/resources/material.cpp#L937-L981

Particles billboard also requires the following uniforms to be added in the shader:

https://github.com/godotengine/godot/blob/10d22a4b35b33ad89f626c261ef7f1aeae81daf3/scene/resources/material.cpp#L815-L819

lostminds commented 1 year ago

Billboarding each each particle on the CPU individually is likely not viable for performance reasons.

I see. I did not expect that this would be a performance issue since the CPUParticles already do such a lot of modifications to the transform properties of each particle, and the billboarding would just require the addition of getting the angle to the camera.

If this is performance intensive it probably doesn't need to be done each frame, and in many cases it could probably be good enough to just orient the meshes towards the camera when they're spawned and then not rotate them.

I did investige if I could do a workaround script for this to basically figure out the camera direction and set the initial orientation of particles, but there only seems to be a single Angle property value (not separate x,y,z angles or an axis vector) along with the basic Mesh X,Y or Z orientation that can be set.

Calinou commented 1 year ago

Maybe it's actually fine to billboard each particle on the CPU, but probably only a few hundred at most. There are definitely many older engines that do particle billboarding on the CPU; it's just a less efficient approach to do.

lostminds commented 1 year ago

Yes, it will most definitely be less performant to do it on the CPU of course, but that's I guess why Godot also has the GPU version of the particle system. But I think like you say for more basic cases where performance isn't critical the same type of billboarding functionality would be good to have in the CPUParticles3D as well as long as that's still in the engine.