Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate Alpha curve from Color curve in the Particle Process input + add emission curve #6779

Closed
QbieShay opened this issue Apr 30, 2023 · 5 comments

Comments

@QbieShay
Copy link

QbieShay commented Apr 30, 2023

Describe the project you are working on

Various VFX

Describe the problem or limitation you are having in your project

Working with merged alpha and rgb in VFX is very annoying. There's multiple ways this could be solved within Godot.
Please read below my solution to it.

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

I work on a variety of VFX in a professional setting. For the type of VFX that I make, I often end up using alpha dissolve/erosion in my shaders (dissolve from now on).
Example:
https://user-images.githubusercontent.com/7917475/235350251-5f789a5c-4440-4f30-8e81-ca55a96092f1.mp4

Sometimes, I want to change the color palette of an effect to "reskin" it for another purpose. The colors being intrinsically tied to the alpha makes it clunky and makes the palettes non-reusable across multiple VFX.

Color as in the rgb component, is a key part for the effect's palette and personality. We use color to convey the substance effects are made of. Think of classical fire and water, entirely different palettes!

Alpha, in particles, is related to motion and timing. It informs of how long the effect stays on screen, how long it lingers.
This can vary a lot in a single VFX! Some elements are very instantaneous while others linger.

The way I need to manipulate timing across different particle systems within the same effects, makes it impossible to reuse a combined alpha+color gradient even inside the same VFX, just because i need particles to disappear at different rates and with different curves.

This is when things get tricky. Suddenly I don't have a single color gradient anymore, but rather I start having one per different particle systems. And particle systems count go up very very fast. So then, to reskin an effect in term of color, i suddenly need to edit 5, 10, 20 gradients. It doesn't scale at all.

For example, this "simple" hit effect (simple in the sense that in a game this is one of the smallest/simplest VFX you'd have)

2023-04-02.17-53-58.mp4

Is made of those emitters:

2023-04-02.18-39-51.mp4

image

Imagine a bigger explosion .. :D

Ideally, I'd like to be able to have my "lava palette" and my "water palette" of colors (rgb) in a way that I can apply it to multiple particle systems: this way, the concept of "color" is entirely decoupled for the timing of the effect.

Initial gradients don't cut it here because very often effects have a "hot color" and a "cold color" respectively for when the effect is at the height of the energy, and when the energy disperses. Think of explosions: they start bright yellow, go to red, then grey smoke. If i was using a start gradient, some particle would spawn "hot color" and stay hot and some particle would spawn "cold color" and be cold at the beginning of the explosion!

Gradient textures having the possibility to separate alpha and emission from color would be an improvement but would still not solve the highlighted problems with workflow and reusability of color palettes.

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

In the color section of particles
image
add the following properties

  • split alpha
  • (if split alpha is on) a curve for alpha
  • split emission
  • (if split emission is on) a curve for emission

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

It could be done by a special gradient texture , but it would significantly worsen the proposed workflow

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

see above.

@Calinou
Copy link
Member

Calinou commented Apr 30, 2023

This could be done by adding a Curve property to GradientTexture that acts as an alpha multiplier. For your use case, the main gradient would be fully opaque but you'd use the curve property to multiply the gradient's opacity. A more flexible alternative would be to implement #5524, which would make this possible using the Multiply blend mode and a second GradientTexture that is fully white (but with varying alpha values).

Adjusting emission independently doesn't sound feasible without using a custom shader though. In BaseMaterial3D, vertex color data is only for albedo, not emission. We could probably have additional modes in BaseMaterial3D to interpret vertex color differently (including the increasingly popular ambient occlusion), but you probably want more flexibility for your use case since you want to adjust both albedo and emission based on vertex color. This likely entails using a scheme where the first 4 bits of a vertex color channel are interpeted as albedo and the last 4 bits are interpreted as emission.

@QbieShay
Copy link
Author

QbieShay commented May 1, 2023

I mentioned the possibility of a solution with GradientTexture

Gradient textures having the possibility to separate alpha and emission from color would be an improvement but would still not solve the highlighted problems with workflow and reusability of color palettes.

But that would not be as ideal (and I think even more complicated to implement?) than having it directly in the particle system, and I think UI wise you'd also have an extra nesting layer in the inspector because it would be another sub-resource.

The way I imagined this working is the following.
You have these 3 elements, color gradient, alpha curve, emission curve.

Inside of the particle shader, you combine them (color gradient's alpha should be multiplied by alpha curve's alpha)

In the shader/material, you can separate them by doing the following:

  • emission intensity is the maximum between r, g and b
  • alpha is alpha
  • rgb is rgb divided by emisssion when emission is above 1
  • srgb conversion is performed after emission is extracted

This would add a built-in EMISSION_INTENSITY to the shader materials.

What do you think?

@reduz
Copy link
Member

reduz commented Jul 17, 2023

Emission curve in process material is not possible because there is no way to pass this information to the material shader. IMO this should go somewhere in the material shader using the lifetime value that you get from the particle to control emission.

@QbieShay
Copy link
Author

I have a functional prototype in godotengine/godot#79527

@QbieShay
Copy link
Author

Closed by godotengine/godot#79527

@Calinou Calinou added this to the 4.2 milestone Oct 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Development

No branches or pull requests

4 participants