diff --git a/include/Engine/Rendering/ExplosionEffectJob.h b/include/Engine/Rendering/ExplosionEffectJob.h index a86b59af..62cc0d59 100644 --- a/include/Engine/Rendering/ExplosionEffectJob.h +++ b/include/Engine/Rendering/ExplosionEffectJob.h @@ -27,6 +27,8 @@ struct ExplosionEffectJob : ModelJob Velocity = (glm::vec2)explosionEffectComponent["Velocity"]; ColorByDistance = (bool)explosionEffectComponent["ColorByDistance"]; ExponentialAccelaration = (bool)explosionEffectComponent["ExponentialAccelaration"]; + Reverse = (bool)explosionEffectComponent["Reverse"]; + ColorDistanceScalar = (double)explosionEffectComponent["ColorDistanceScalar"]; }; glm::vec3 ExplosionOrigin; @@ -38,12 +40,14 @@ struct ExplosionEffectJob : ModelJob glm::vec4 EndColor; bool Randomness = false; - float RandomnessScalar = 1.f; + double RandomnessScalar = 1.f; glm::vec2 Velocity; bool ColorByDistance = false; //bool ReverseAnimation = false; //bool Wireframe = false; bool ExponentialAccelaration = false; + bool Reverse = false; + double ColorDistanceScalar = 1.f; std::array RandomNumbers = { 0.3257552917701f, diff --git a/include/Game/Systems/ExplosionEffectSystem.h b/include/Game/Systems/ExplosionEffectSystem.h index 24eee955..d2eafa15 100644 --- a/include/Game/Systems/ExplosionEffectSystem.h +++ b/include/Game/Systems/ExplosionEffectSystem.h @@ -3,6 +3,7 @@ #include "Common.h" #include "Core/System.h" +#include "Engine/GLM.h" class ExplosionEffectSystem : public PureSystem { diff --git a/resources/Schema/Components/ExplosionEffect.xml b/resources/Schema/Components/ExplosionEffect.xml index 0b4a44c4..80022738 100644 --- a/resources/Schema/Components/ExplosionEffect.xml +++ b/resources/Schema/Components/ExplosionEffect.xml @@ -1,19 +1,21 @@ - 0 - 2 + 0.0 + 2.0 1 0 - 0 - 1 + false + 1.0 - 0 - + false - 0 + false + false + false + 1.0 \ No newline at end of file diff --git a/resources/Schema/Components/ExplosionEffect.xsd b/resources/Schema/Components/ExplosionEffect.xsd index bd29b2ed..f0edcc8e 100644 --- a/resources/Schema/Components/ExplosionEffect.xsd +++ b/resources/Schema/Components/ExplosionEffect.xsd @@ -44,15 +44,21 @@ Change the color by its moved distance instead of by its time - Linear/Exponential accelaration + + Pulsate the effect + + + Reverse the effect + + + Scale the distance of the color change + diff --git a/resources/Shaders/ExplosionEffect.geom.glsl b/resources/Shaders/ExplosionEffect.geom.glsl index 19944cac..420bbaae 100644 --- a/resources/Shaders/ExplosionEffect.geom.glsl +++ b/resources/Shaders/ExplosionEffect.geom.glsl @@ -15,6 +15,11 @@ uniform float RandomnessScalar; uniform vec2 Velocity; uniform bool ColorByDistance; uniform bool ExponentialAccelaration; +uniform bool Reverse; +uniform float ColorDistanceScalar; +//uniform bool Gravity; +//uniform bool Rotation; +//uniform bool MaxRadius; in VertexData{ vec3 Position; @@ -41,169 +46,136 @@ out VertexData{ layout(triangles) in; layout(triangle_strip, max_vertices = 3) out; +float EqualTo(float x, float y) { + return 1.0 - abs(sign(x - y)); +} + +float NotEqualTo(float x, float y) { + return abs(sign(x - y)); +} + +float GreaterThan(float x, float y) { + return max(sign(x - y), 0.0); +} + +float LessThan(float x, float y) { + return max(sign(y - x), 0.0); +} + +float GreaterEqualTo(float x, float y) { + return 1.0 - LessThan(x, y); +} + +float LessEqualTo(float x, float y) { + return 1.0 - GreaterThan(x, y); +} + // returns a "random" number based on input parameter float GetRandomNumber(int polygon_index) { - int randomIndex = int(mod(polygon_index, 50)); - - return RandomNumbers[randomIndex]; + return RandomNumbers[int(mod(polygon_index, 50))]; } -float randomNumber = 0.0; -float randomDistance = 0.0; - -void main() +vec3 CalcCenterOfTriangle(vec3 vertex0, vec3 vertex1, vec3 vertex2) { // calculate middle of vectors - vec3 v1 = Input[1].Position - Input[0].Position; - vec3 v2 = Input[2].Position - Input[0].Position; - vec3 v3 = Input[2].Position - (v1 / 2); - vec3 v4 = Input[1].Position - (v2 / 2); + vec3 dir1 = normalize(vertex1 - vertex0); + vec3 dir2 = normalize(vertex2 - vertex0); - // calculate intersection - - // normalize direction - vec3 dir1 = normalize(v1); - vec3 dir2 = normalize(v2); - - vec3 vecA = Input[2].Position - Input[1].Position; //o2 - o1 + vec3 vecA = vertex2 - vertex1; //o2 - o1 vec3 vecB = cross(dir1, dir2); mat3 matrisA = mat3(vecA, dir2, vecB); float lengthA = length(vecB); lengthA = lengthA * lengthA; - + float s = determinant(matrisA) / lengthA; // center position of triangle - vec3 centerOfTriangle = Input[1].Position + (s * dir1); - + return vertex1 + (s * dir1); +} + +void PassThingsThrough(int index) +{ + // pass through vertex data + Output.Normal = Input[index].Normal; + Output.Position = Input[index].Position; + Output.TextureCoordinate = Input[index].TextureCoordinate; + Output.Tangent = Input[index].Tangent; + Output.BiTangent = Input[index].BiTangent; + Output.ExplosionColor = EndColor; +} + +void main() +{ + vec3 centerOfTriangle = CalcCenterOfTriangle(Input[0].Position, Input[1].Position, Input[2].Position); + // center position of triangle to origin vector vec3 origin2TriangleCenterVector = centerOfTriangle - ExplosionOrigin; vec3 normalizedOrigin2TriangleCenterVector = normalize(origin2TriangleCenterVector); + // distance between origin and the center of the current triangle + float origin2TriangleCenterDistance = length(origin2TriangleCenterVector); + // time percentage until end of explosion (0.0-1.0) float timePercetage = TimeSinceDeath / ExplosionDuration; - // get a random number if randomness is enabled, otherwise the random number will be zero and won't affect the other algorithms - if (Randomness == true) - { - randomDistance = GetRandomNumber(gl_PrimitiveIDIn) * RandomnessScalar; - } + // get a random number if randomness is enabled, otherwise the random distance will be zero and won't affect the other algorithms + float randomDistance = float(Randomness) * GetRandomNumber(gl_PrimitiveIDIn) * RandomnessScalar; vec2 randomVelocity = Velocity * (randomDistance + 1.0); // accelaration to use on current frame. is a interpolation between start and end value float currentVelocity = mix(randomVelocity.x, randomVelocity.y, timePercetage); - if (ExponentialAccelaration == true) - { - currentVelocity = pow(currentVelocity, 2) / 2.0; - } + // if the accelaration should be exponential + currentVelocity = currentVelocity * max(currentVelocity * float(ExponentialAccelaration), 1.0); - // distance between origin and the center of the current triangle - float origin2TriangleCenterDistance = length(origin2TriangleCenterVector); + // the distance the blast has moved since the beginning, i.e. its radius + float blastWave = TimeSinceDeath * currentVelocity; // the distance from origin to the triangle center with eventual randomness added - float fullDistanceWithRandomness = origin2TriangleCenterDistance + randomDistance; - - // vector from the triangle center to the explosion's shockwave - vec3 triangleCenter2ExplosionRadius = (normalizedOrigin2TriangleCenterVector * (TimeSinceDeath * currentVelocity)) - (normalizedOrigin2TriangleCenterVector * fullDistanceWithRandomness); + float origin2TriangleCenterDistanceWithRandomness = origin2TriangleCenterDistance + randomDistance; - // if the triangle is inside the blast radius... - if (fullDistanceWithRandomness <= (TimeSinceDeath * currentVelocity)) + vec3 triangleCenter2ExplosionRadius = (normalizedOrigin2TriangleCenterVector * blastWave) - (normalizedOrigin2TriangleCenterVector * origin2TriangleCenterDistanceWithRandomness); + + // if the triangle is inside the blast's radius... + float isInsideBlastRadius = LessEqualTo(origin2TriangleCenterDistanceWithRandomness, blastWave); + + // calculate the max distance (s) the triangle will move + float accelaration = (randomVelocity.y - randomVelocity.x) / ExplosionDuration; + float maxDistance = (randomVelocity.x * ExplosionDuration) + (0.5 * accelaration * ExplosionDuration * ExplosionDuration); + + // if explosion color should be affected by distance instead of time... + if (ColorByDistance == true) { - float maxRadius = max(TimeSinceDeath * currentVelocity, (ExplosionDuration * currentVelocity)); - - float a = (randomVelocity.y - randomVelocity.x) / ExplosionDuration; - //float t = sqrt((2 * origin2TriangleCenterDistance) / a); - - // if explosion color should be affected by distance instead of time... - if (ColorByDistance == true) - { - // calculate the max distance (s) the triangle will move - float s = (randomVelocity.x * ExplosionDuration) + (0.5 * a * pow(ExplosionDuration, 2)); - float te = (length(triangleCenter2ExplosionRadius) / s); - - Output.ExplosionColor = EndColor; - Output.ExplosionPercentageElapsed = te; - - } - else - { - Output.ExplosionColor = EndColor; - Output.ExplosionPercentageElapsed = timePercetage; - - } - - // for every vertex on the triangle... - for (int i = 0; i < gl_in.length(); i++) - { - // move the triangle to the blast radius - vec3 ExplodedPosition = Input[i].Position + triangleCenter2ExplosionRadius; - - // pass through vertex data - Output.Normal = Input[i].Normal; - Output.Position = Input[i].Position; - Output.TextureCoordinate = Input[i].TextureCoordinate; - Output.Tangent = Input[i].Tangent; - Output.BiTangent = Input[i].BiTangent; - for (int j = 0; j < MAX_SPLITS; j++) - { - Output.PositionLightSpace[j] = Input[i].PositionLightSpace[j]; - } - - // convert to model space for the gravity to always be in -y - vec4 ExplodedPositionInModelSpace = M * vec4(ExplodedPosition, 1.0); - - // if there is gravity, apply it - //if (Gravity == true) - //{ - // // ---DO THIS----> //ExplodedPositionInModelSpace.y = ExplodedPositionInModelSpace.y - TimeSinceHit; - // - // ExplodedPositionInModelSpace.y = ExplodedPositionInModelSpace.y - pow(TimeSinceDeath, 2); - //} - - // convert to screen space - gl_Position = P*V * ExplodedPositionInModelSpace; - EmitVertex(); - } + Output.ExplosionPercentageElapsed = (length(triangleCenter2ExplosionRadius) / maxDistance) * isInsideBlastRadius * ColorDistanceScalar; } else { - // if explosion color should be affected by distance instead of time... - if (ColorByDistance == true) - { - Output.ExplosionColor = EndColor; - Output.ExplosionPercentageElapsed = 0.0; - } - else - { - Output.ExplosionColor = EndColor; - Output.ExplosionPercentageElapsed = timePercetage; + Output.ExplosionPercentageElapsed = timePercetage; + } + + vec3 ExplodedPosition; + for (int i = 0; i < gl_in.length(); i++) + { + // move the triangle to the blast radius + ExplodedPosition = Input[i].Position + (triangleCenter2ExplosionRadius * isInsideBlastRadius); - } - - // for every vertex on the triangle... - for(int i = 0; i < gl_in.length(); i++) - { - // pass through vertex data - Output.Normal = Input[i].Normal; - Output.Position = Input[i].Position; - Output.TextureCoordinate = Input[i].TextureCoordinate; - Output.Tangent = Input[i].Tangent; - Output.BiTangent = Input[i].BiTangent; + // pass through vertex data + PassThingsThrough(i); for (int j = 0; j < MAX_SPLITS; j++) { Output.PositionLightSpace[j] = Input[i].PositionLightSpace[j]; } - - // no change in position, pass through vertex - gl_Position = gl_in[i].gl_Position; - EmitVertex(); - } + for (int j = 0; j < MAX_SPLITS; j++) + { + Output.PositionLightSpace[j] = Input[i].PositionLightSpace[j]; + } + + // convert to window space + gl_Position = P * V * M * vec4(ExplodedPosition, 1.0); + EmitVertex(); } - - //EndPrimitive(); -} +} \ No newline at end of file diff --git a/src/Engine/Rendering/DrawFinalPass.cpp b/src/Engine/Rendering/DrawFinalPass.cpp index d03b0c2b..6ab4bb3c 100644 --- a/src/Engine/Rendering/DrawFinalPass.cpp +++ b/src/Engine/Rendering/DrawFinalPass.cpp @@ -1333,7 +1333,12 @@ void DrawFinalPass::BindExplosionUniforms(GLuint shaderHandle, std::shared_ptrExplosionOrigin)); GLERROR("Bind 6 uniform"); - glUniform1f(glGetUniformLocation(shaderHandle, "TimeSinceDeath"), job->TimeSinceDeath); + if (job->Reverse == false) { + glUniform1f(glGetUniformLocation(shaderHandle, "TimeSinceDeath"), job->TimeSinceDeath); + } + else { + glUniform1f(glGetUniformLocation(shaderHandle, "TimeSinceDeath"), (job->ExplosionDuration - job->TimeSinceDeath)); + } GLERROR("Bind 7 uniform"); glUniform1f(glGetUniformLocation(shaderHandle, "ExplosionDuration"), job->ExplosionDuration); GLERROR("Bind 8 uniform"); @@ -1351,6 +1356,10 @@ void DrawFinalPass::BindExplosionUniforms(GLuint shaderHandle, std::shared_ptrExponentialAccelaration); GLERROR("Bind 15 uniform"); + glUniform1i(glGetUniformLocation(shaderHandle, "Reverse"), job->Reverse); + GLERROR("Bind 15-2 uniform"); + glUniform1f(glGetUniformLocation(shaderHandle, "ColorDistanceScalar"), job->ColorDistanceScalar); + GLERROR("Bind 15-3 uniform"); glUniform4fv(glGetUniformLocation(shaderHandle, "Color"), 1, glm::value_ptr(job->Color)); GLERROR("Bind 16 uniform"); diff --git a/src/Game/Systems/ExplosionEffectSystem.cpp b/src/Game/Systems/ExplosionEffectSystem.cpp index 71de192a..e75ebb24 100644 --- a/src/Game/Systems/ExplosionEffectSystem.cpp +++ b/src/Game/Systems/ExplosionEffectSystem.cpp @@ -7,12 +7,15 @@ void ExplosionEffectSystem::UpdateComponent(EntityWrapper& entity, ComponentWrap delay = std::max(0.0, delay - dt); } - if (delay <= 0) { - double& timeSinceDeath = component["TimeSinceDeath"]; - timeSinceDeath += (double)component["Speed"] * dt; - if (timeSinceDeath < 0 || timeSinceDeath > (double)component["ExplosionDuration"]) { - timeSinceDeath = 0.0; - } - } + if (delay <= 0) { + double& timeSinceDeath = component["TimeSinceDeath"]; + timeSinceDeath += (double)component["Speed"] * dt; + if (timeSinceDeath < 0) { + timeSinceDeath = 0.0; + } + else if (timeSinceDeath >(double)component["ExplosionDuration"]) { + timeSinceDeath = (double)component["ExplosionDuration"]; + } + } }