mirror of
https://github.com/overte-org/overte.git
synced 2025-08-03 23:43:30 +02:00
Fix particle radius and rgba start, middle, finish interpolation
Bezier interpolation of 3 points doesn't intersect the middle value. Instead, use separate Bezier interpolations for start-middle and middle- finish, so that the interpolated values intersect the middle value as a user would expect.
This commit is contained in:
parent
fc4ece5671
commit
58f1371eba
2 changed files with 45 additions and 7 deletions
|
@ -71,7 +71,7 @@
|
|||
Entities.editEntity(particles, {
|
||||
radiusSpread: 0.0,
|
||||
radiusStart: 0.0,
|
||||
particleRadius: 2 * PARTICLE_RADIUS, // Bezier interpolation used means that middle value isn't intersected
|
||||
particleRadius: PARTICLE_RADIUS,
|
||||
radiusFinish: 0.0
|
||||
});
|
||||
break;
|
||||
|
|
|
@ -56,13 +56,51 @@ float bezierInterpolate(float y1, float y2, float y3, float u) {
|
|||
return (1.0 - u) * (1.0 - u) * y1 + 2.0 * (1.0 - u) * u * y2 + u * u * y3;
|
||||
}
|
||||
|
||||
vec4 interpolate3Vec4(vec4 y1, vec4 y2, vec4 y3, float u) {
|
||||
return vec4(bezierInterpolate(y1.x, y2.x, y3.x, u),
|
||||
bezierInterpolate(y1.y, y2.y, y3.y, u),
|
||||
bezierInterpolate(y1.z, y2.z, y3.z, u),
|
||||
bezierInterpolate(y1.w, y2.w, y3.w, u));
|
||||
float interpolate3Points(float y1, float y2, float y3, float u) {
|
||||
// Makes the interpolated values intersect the middle value.
|
||||
|
||||
if ((u <= 0.5f && y1 == y2) || (u >= 0.5f && y2 == y3)) {
|
||||
// Flat line.
|
||||
return y2;
|
||||
}
|
||||
|
||||
if ((y2 >= y1 && y2 >= y3) || (y2 <= y1 && y2 <= y3)) {
|
||||
// U or inverted-U shape.
|
||||
// Make the slope at y2 = 0, which means that the control points half way between the value points have the value y2.
|
||||
if (u <= 0.5f) {
|
||||
return bezierInterpolate(y1, y2, y2, 2.0f * u);
|
||||
} else {
|
||||
return bezierInterpolate(y2, y2, y3, 2.0f * u - 1.0f);
|
||||
}
|
||||
|
||||
} else {
|
||||
// L or inverted and/or mirrored L shape.
|
||||
// Make the slope at y2 be the slope between y1 and y3, up to a maximum of double the minimum of the slopes between y1
|
||||
// and y2, and y2 and y3. Use this slope to calculate the control points half way between the value points.
|
||||
// Note: The maximum ensures that the control points and therefore the interpolated values stay between y1 and y3.
|
||||
float slope = y3 - y1;
|
||||
float slope12 = y2 - y1;
|
||||
float slope23 = y3 - y2;
|
||||
if (abs(slope) > abs(2.0f * slope12)) {
|
||||
slope = 2.0f * slope12;
|
||||
} else if (abs(slope) > abs(2.0f * slope23)) {
|
||||
slope = 2.0f * slope23;
|
||||
}
|
||||
|
||||
if (u <= 0.5f) {
|
||||
return bezierInterpolate(y1, y2 - slope / 2.0f, y2, 2.0f * u);
|
||||
} else {
|
||||
return bezierInterpolate(y2, y2 + slope / 2.0f, y3, 2.0f * u - 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vec4 interpolate3Vec4(vec4 y1, vec4 y2, vec4 y3, float u) {
|
||||
return vec4(interpolate3Points(y1.x, y2.x, y3.x, u),
|
||||
interpolate3Points(y1.y, y2.y, y3.y, u),
|
||||
interpolate3Points(y1.z, y2.z, y3.z, u),
|
||||
interpolate3Points(y1.w, y2.w, y3.w, u));
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
TransformCamera cam = getTransformCamera();
|
||||
|
@ -82,7 +120,7 @@ void main(void) {
|
|||
varColor = interpolate3Vec4(particle.color.start, particle.color.middle, particle.color.finish, age);
|
||||
|
||||
// anchor point in eye space
|
||||
float radius = bezierInterpolate(particle.radius.start, particle.radius.middle, particle.radius.finish, age);
|
||||
float radius = interpolate3Points(particle.radius.start, particle.radius.middle, particle.radius.finish, age);
|
||||
vec4 quadPos = radius * UNIT_QUAD[twoTriID];
|
||||
|
||||
vec4 anchorPoint;
|
||||
|
|
Loading…
Reference in a new issue