Forráskód Böngészése

Merge pull request #8013 from CraigFeldspar/local-particles-gpu

Add local space support for GPU particles
David Catuhe 5 éve
szülő
commit
ced5b6dbb0

+ 3 - 0
dist/preview release/what's new.md

@@ -97,6 +97,9 @@
 
 - Added `Vector3.projectOnPlaneToRef` ([Deltakosh](https://github.com/deltakosh))
 
+### Particles
+- Added local space support for GPU particles ([CraigFeldpsar](https://github.com/craigfeldspar))
+
 ### Build
 
 - Fixed an issue with gulp webpack, webpack stream and the viewer ([RaananW](https://github.com/RaananW))

+ 17 - 10
src/Particles/gpuParticleSystem.ts

@@ -121,15 +121,8 @@ export class GPUParticleSystem extends BaseParticleSystem implements IDisposable
 
     /**
      * Specifies if the particles are updated in emitter local space or world space.
-     * This is always false for GPU particles
      */
-    public get isLocal() {
-        return false;
-    }
-
-    public set isLocal(value: boolean) {
-        // Ignore
-    }
+    public isLocal = false;
 
     /**
      * Is this system ready to be used/rendered
@@ -1065,6 +1058,10 @@ export class GPUParticleSystem extends BaseParticleSystem implements IDisposable
             defines += "\n#define NOISE";
         }
 
+        if (this.isLocal) {
+            defines += "\n#define LOCAL";
+        }
+
         if (this._updateEffect && this._updateEffectOptions.defines === defines) {
             return;
         }
@@ -1134,6 +1131,10 @@ export class GPUParticleSystem extends BaseParticleSystem implements IDisposable
             defines = "\n#define BLENDMULTIPLYMODE";
         }
 
+        if (this.isLocal) {
+            defines += "\n#define LOCAL";
+        }
+
         if (this._isBillboardBased) {
             defines += "\n#define BILLBOARD";
 
@@ -1167,7 +1168,7 @@ export class GPUParticleSystem extends BaseParticleSystem implements IDisposable
             return;
         }
 
-        var uniforms = ["worldOffset", "view", "projection", "colorDead", "invView", "vClipPlane", "vClipPlane2", "vClipPlane3", "vClipPlane4", "vClipPlane5", "vClipPlane6", "sheetInfos", "translationPivot", "eyePosition"];
+        var uniforms = ["emitterWM", "worldOffset", "view", "projection", "colorDead", "invView", "vClipPlane", "vClipPlane2", "vClipPlane3", "vClipPlane4", "vClipPlane5", "vClipPlane6", "sheetInfos", "translationPivot", "eyePosition"];
         var samplers = ["textureSampler", "colorGradientSampler"];
 
         if (ImageProcessingConfiguration) {
@@ -1377,7 +1378,10 @@ export class GPUParticleSystem extends BaseParticleSystem implements IDisposable
             var emitterPosition = (<Vector3>this.emitter);
             emitterWM = Matrix.Translation(emitterPosition.x, emitterPosition.y, emitterPosition.z);
         }
-        this._updateEffect.setMatrix("emitterWM", emitterWM);
+
+        if (!this.isLocal) {
+            this._updateEffect.setMatrix("emitterWM", emitterWM);
+        }
 
         // Bind source VAO
         this._engine.bindVertexArrayObject(this._updateVAO[this._targetIndex], null);
@@ -1400,6 +1404,9 @@ export class GPUParticleSystem extends BaseParticleSystem implements IDisposable
             this._renderEffect.setTexture("textureSampler", this.particleTexture);
             this._renderEffect.setVector2("translationPivot", this.translationPivot);
             this._renderEffect.setVector3("worldOffset", this.worldOffset);
+            if (this.isLocal) {
+                this._renderEffect.setMatrix("emitterWM", emitterWM);
+            }
             if (this._colorGradientsTexture) {
                 this._renderEffect.setTexture("colorGradientSampler", this._colorGradientsTexture);
             } else {

+ 18 - 4
src/Shaders/gpuRenderParticles.vertex.fx

@@ -4,6 +4,9 @@ uniform mat4 view;
 uniform mat4 projection;
 uniform vec2 translationPivot;
 uniform vec3 worldOffset;
+#ifdef LOCAL
+uniform mat4 emitterWM;
+#endif
 
 // Particles state
 in vec3 position;
@@ -58,8 +61,11 @@ vec3 rotate(vec3 yaxis, vec3 rotatedCorner) {
 	mat3 rotMatrix =  mat3(row0, row1, row2);
 
 	vec3 alignedCorner = rotMatrix * rotatedCorner;
-
-	return (position + worldOffset) + alignedCorner;
+	#ifdef LOCAL
+		return ((emitterWM * vec4(position, 1.0)).xyz + worldOffset) + alignedCorner;
+	#else
+		return (position + worldOffset) + alignedCorner;
+	#endif
 }
 
 #ifdef BILLBOARDSTRETCHED
@@ -75,7 +81,11 @@ vec3 rotateAlign(vec3 toCamera, vec3 rotatedCorner) {
 	mat3 rotMatrix =  mat3(row0, row1, row2);
 
 	vec3 alignedCorner = rotMatrix * rotatedCorner;
-	return (position + worldOffset) + alignedCorner;
+	#ifdef LOCAL
+		return ((emitterWM * vec4(position, 1.0)).xyz + worldOffset) + alignedCorner;
+	#else
+		return (position + worldOffset) + alignedCorner;
+	#endif
 }
 #endif
 
@@ -130,7 +140,11 @@ void main() {
 		rotatedCorner.z = 0.;
 
 		// Expand position
-		vec4 viewPosition = view * vec4((position + worldOffset), 1.0) + rotatedCorner;
+		#ifdef LOCAL
+			vec4 viewPosition = view * vec4(((emitterWM * vec4(position, 1.0)).xyz + worldOffset), 1.0) + rotatedCorner;
+		#else
+			vec4 viewPosition = view * vec4((position + worldOffset), 1.0) + rotatedCorner;
+		#endif
 	#endif
 
 #else

+ 12 - 4
src/Shaders/gpuUpdateParticles.vertex.fx

@@ -5,7 +5,9 @@
 uniform float currentCount;
 uniform float timeDelta;
 uniform float stopFactor;
+#ifndef LOCAL
 uniform mat4 emitterWM;
+#endif
 uniform vec2 lifeTime;
 uniform vec2 emitPower;
 uniform vec2 sizeRange;
@@ -322,7 +324,11 @@ void main() {
 
     float power = emitPower.x + (emitPower.y - emitPower.x) * randoms.a;
 
-    outPosition = (emitterWM * vec4(newPosition, 1.)).xyz;
+    #ifdef LOCAL
+        outPosition = newPosition;
+    #else
+        outPosition = (emitterWM * vec4(newPosition, 1.)).xyz;
+    #endif
 
 #ifdef CUSTOMEMITTER
     outDirection = direction;
@@ -330,7 +336,11 @@ void main() {
         outInitialDirection = direction;
     #endif
 #else
-    vec3 initial = (emitterWM * vec4(newDirection, 0.)).xyz;
+    #ifdef LOCAL
+        vec3 initial = newDirection;
+    #else 
+        vec3 initial = (emitterWM * vec4(newDirection, 0.)).xyz;
+    #endif
     outDirection = initial * power;
     #ifndef BILLBOARD        
         outInitialDirection = initial;
@@ -404,8 +414,6 @@ void main() {
     outDirection = updatedDirection;
 
     #ifdef NOISE
-        vec3 localPosition = outPosition - emitterWM[3].xyz;
-
         float fetchedR = texture(noiseSampler, vec2(noiseCoordinates1.x, noiseCoordinates1.y) * vec2(0.5) + vec2(0.5)).r;
         float fetchedG = texture(noiseSampler, vec2(noiseCoordinates1.z, noiseCoordinates2.x) * vec2(0.5) + vec2(0.5)).r;
         float fetchedB = texture(noiseSampler, vec2(noiseCoordinates2.y, noiseCoordinates2.z) * vec2(0.5) + vec2(0.5)).r;