mirror of
https://github.com/godotengine/godot.git
synced 2024-12-21 10:25:24 +08:00
4226d56ca9
As of clang-format 6.0.1, putting the `/* clang-format off */` hint around our "invalid" `[vertex]` and `[shader]` statements isn't enough to prevent a bogus indent of the next comments and first valid statement, so we need to enclose that first valid statement in the unformatted chunk.
267 lines
5.2 KiB
GLSL
267 lines
5.2 KiB
GLSL
/* clang-format off */
|
|
[vertex]
|
|
|
|
layout(location = 0) in highp vec4 color;
|
|
/* clang-format on */
|
|
layout(location = 1) in highp vec4 velocity_active;
|
|
layout(location = 2) in highp vec4 custom;
|
|
layout(location = 3) in highp vec4 xform_1;
|
|
layout(location = 4) in highp vec4 xform_2;
|
|
layout(location = 5) in highp vec4 xform_3;
|
|
|
|
struct Attractor {
|
|
|
|
vec3 pos;
|
|
vec3 dir;
|
|
float radius;
|
|
float eat_radius;
|
|
float strength;
|
|
float attenuation;
|
|
};
|
|
|
|
#define MAX_ATTRACTORS 64
|
|
|
|
uniform bool emitting;
|
|
uniform float system_phase;
|
|
uniform float prev_system_phase;
|
|
uniform int total_particles;
|
|
uniform float explosiveness;
|
|
uniform float randomness;
|
|
uniform float time;
|
|
uniform float delta;
|
|
|
|
uniform int attractor_count;
|
|
uniform Attractor attractors[MAX_ATTRACTORS];
|
|
uniform bool clear;
|
|
uniform uint cycle;
|
|
uniform float lifetime;
|
|
uniform mat4 emission_transform;
|
|
uniform uint random_seed;
|
|
|
|
out highp vec4 out_color; //tfb:
|
|
out highp vec4 out_velocity_active; //tfb:
|
|
out highp vec4 out_custom; //tfb:
|
|
out highp vec4 out_xform_1; //tfb:
|
|
out highp vec4 out_xform_2; //tfb:
|
|
out highp vec4 out_xform_3; //tfb:
|
|
|
|
#if defined(USE_MATERIAL)
|
|
|
|
/* clang-format off */
|
|
layout(std140) uniform UniformData { //ubo:0
|
|
|
|
MATERIAL_UNIFORMS
|
|
|
|
};
|
|
/* clang-format on */
|
|
|
|
#endif
|
|
|
|
/* clang-format off */
|
|
|
|
VERTEX_SHADER_GLOBALS
|
|
|
|
/* clang-format on */
|
|
|
|
uint hash(uint x) {
|
|
|
|
x = ((x >> uint(16)) ^ x) * uint(0x45d9f3b);
|
|
x = ((x >> uint(16)) ^ x) * uint(0x45d9f3b);
|
|
x = (x >> uint(16)) ^ x;
|
|
return x;
|
|
}
|
|
|
|
void main() {
|
|
|
|
#ifdef PARTICLES_COPY
|
|
|
|
out_color = color;
|
|
out_velocity_active = velocity_active;
|
|
out_custom = custom;
|
|
out_xform_1 = xform_1;
|
|
out_xform_2 = xform_2;
|
|
out_xform_3 = xform_3;
|
|
|
|
#else
|
|
|
|
bool apply_forces = true;
|
|
bool apply_velocity = true;
|
|
float local_delta = delta;
|
|
|
|
float mass = 1.0;
|
|
|
|
float restart_phase = float(gl_VertexID) / float(total_particles);
|
|
|
|
if (randomness > 0.0) {
|
|
uint seed = cycle;
|
|
if (restart_phase >= system_phase) {
|
|
seed -= uint(1);
|
|
}
|
|
seed *= uint(total_particles);
|
|
seed += uint(gl_VertexID);
|
|
float random = float(hash(seed) % uint(65536)) / 65536.0;
|
|
restart_phase += randomness * random * 1.0 / float(total_particles);
|
|
}
|
|
|
|
restart_phase *= (1.0 - explosiveness);
|
|
bool restart = false;
|
|
bool shader_active = velocity_active.a > 0.5;
|
|
|
|
if (system_phase > prev_system_phase) {
|
|
// restart_phase >= prev_system_phase is used so particles emit in the first frame they are processed
|
|
|
|
if (restart_phase >= prev_system_phase && restart_phase < system_phase) {
|
|
restart = true;
|
|
#ifdef USE_FRACTIONAL_DELTA
|
|
local_delta = (system_phase - restart_phase) * lifetime;
|
|
#endif
|
|
}
|
|
|
|
} else {
|
|
if (restart_phase >= prev_system_phase) {
|
|
restart = true;
|
|
#ifdef USE_FRACTIONAL_DELTA
|
|
local_delta = (1.0 - restart_phase + system_phase) * lifetime;
|
|
#endif
|
|
} else if (restart_phase < system_phase) {
|
|
restart = true;
|
|
#ifdef USE_FRACTIONAL_DELTA
|
|
local_delta = (system_phase - restart_phase) * lifetime;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
uint current_cycle = cycle;
|
|
|
|
if (system_phase < restart_phase) {
|
|
current_cycle -= uint(1);
|
|
}
|
|
|
|
uint particle_number = current_cycle * uint(total_particles) + uint(gl_VertexID);
|
|
int index = int(gl_VertexID);
|
|
|
|
if (restart) {
|
|
shader_active = emitting;
|
|
}
|
|
|
|
mat4 xform;
|
|
|
|
#if defined(ENABLE_KEEP_DATA)
|
|
if (clear) {
|
|
#else
|
|
if (clear || restart) {
|
|
#endif
|
|
out_color = vec4(1.0);
|
|
out_velocity_active = vec4(0.0);
|
|
out_custom = vec4(0.0);
|
|
if (!restart)
|
|
shader_active = false;
|
|
|
|
xform = mat4(
|
|
vec4(1.0, 0.0, 0.0, 0.0),
|
|
vec4(0.0, 1.0, 0.0, 0.0),
|
|
vec4(0.0, 0.0, 1.0, 0.0),
|
|
vec4(0.0, 0.0, 0.0, 1.0));
|
|
} else {
|
|
out_color = color;
|
|
out_velocity_active = velocity_active;
|
|
out_custom = custom;
|
|
xform = transpose(mat4(xform_1, xform_2, xform_3, vec4(vec3(0.0), 1.0)));
|
|
}
|
|
|
|
if (shader_active) {
|
|
//execute shader
|
|
|
|
{
|
|
/* clang-format off */
|
|
|
|
VERTEX_SHADER_CODE
|
|
|
|
/* clang-format on */
|
|
}
|
|
|
|
#if !defined(DISABLE_FORCE)
|
|
|
|
if (false) {
|
|
|
|
vec3 force = vec3(0.0);
|
|
for (int i = 0; i < attractor_count; i++) {
|
|
|
|
vec3 rel_vec = xform[3].xyz - attractors[i].pos;
|
|
float dist = length(rel_vec);
|
|
if (attractors[i].radius < dist)
|
|
continue;
|
|
if (attractors[i].eat_radius > 0.0 && attractors[i].eat_radius > dist) {
|
|
out_velocity_active.a = 0.0;
|
|
}
|
|
|
|
rel_vec = normalize(rel_vec);
|
|
|
|
float attenuation = pow(dist / attractors[i].radius, attractors[i].attenuation);
|
|
|
|
if (attractors[i].dir == vec3(0.0)) {
|
|
//towards center
|
|
force += attractors[i].strength * rel_vec * attenuation * mass;
|
|
} else {
|
|
force += attractors[i].strength * attractors[i].dir * attenuation * mass;
|
|
}
|
|
}
|
|
|
|
out_velocity_active.xyz += force * local_delta;
|
|
}
|
|
#endif
|
|
|
|
#if !defined(DISABLE_VELOCITY)
|
|
|
|
if (true) {
|
|
|
|
xform[3].xyz += out_velocity_active.xyz * local_delta;
|
|
}
|
|
#endif
|
|
} else {
|
|
xform = mat4(0.0);
|
|
}
|
|
|
|
xform = transpose(xform);
|
|
|
|
out_velocity_active.a = mix(0.0, 1.0, shader_active);
|
|
|
|
out_xform_1 = xform[0];
|
|
out_xform_2 = xform[1];
|
|
out_xform_3 = xform[2];
|
|
|
|
#endif //PARTICLES_COPY
|
|
}
|
|
|
|
/* clang-format off */
|
|
[fragment]
|
|
|
|
//any code here is never executed, stuff is filled just so it works
|
|
|
|
#if defined(USE_MATERIAL)
|
|
|
|
layout(std140) uniform UniformData {
|
|
|
|
MATERIAL_UNIFORMS
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
FRAGMENT_SHADER_GLOBALS
|
|
|
|
void main() {
|
|
{
|
|
|
|
LIGHT_SHADER_CODE
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FRAGMENT_SHADER_CODE
|
|
|
|
}
|
|
}
|
|
/* clang-format on */
|