Sparking Light Fixture Effect in VR Corridor (Updated Scene)

(Edit: I’ve been slowly updating this scene, adding a little more architecture. The “sparking effect” is in a corridor behind the camera, so you have to rotate around with the thumbstick or mouse, and then move forward by teleporting (VR) or using the arrow keys (PC). This scene is part of a larger project, and is in its infancy–so there’s no physics added yet.)

Good afternoon! I’m working on a webXR project (work in progress) with dilapidated, run-down corridors, and wanted to show a broken light fixture with wires hanging down, shorting out and throwing sparks, just like the light fixtures in my own house. I wanted it to be erratic, so I experimented with a few ideas I had in mind, only to accidentally stumble upon something that worked better than I expected. I included the rough “sparking” code below the link. There’s probably a more elegant way to do it, but I’m not an elegant person…:smiley:

I’m only using two lights in the scene–a hemispheric light for general lighting, and a green-glowing point light underneath the small box that emits the sparks. The rest is mostly baked lighting and materials. My intention was to have both the point light and sparks turn off and on in a randomized way. Each of the five “on” states was supposed to set the light to a different intensity while turning on the particle emitter and having them both run for a few seconds (using settimeout). And each of the “off” states was supposed to turn off the light and the sparks for a different length of time before switching to the “on” state again. I set the timeout to one or several seconds just to test whether or not the timeout and randomized “on” and “off” states would work. When I tried it, however, I was surprised to discover that the code worked exactly as I intended it to. Somehow the code is both acknowledging the timeouts while running right past them at the same time, causing the rapid yet erratic sparking effect. lol.

Anyway, here’s the link (a page on my website) and the code. The demo has no sound and is intended for VR (webXR), but it can be viewed on a PC, using the mouse for turning and arrow keys. (Edit: The camera starts off facing a small cube and has to be rotated with the thumbstick (or mouse) to face the corridor)
.:
https://secrettreasurepath.com/Hidden/ClearTheRubbleUrbexXR.html:

.

            // Default intensity is 1. Let's dim the light a small amount
            light.intensity = 6.0;
            light.diffuse = new BABYLON.Color3(0.55, 0.37, 0.67);
            light.setEnabled(true);
            let lightOffMesh = 1;
            let lightFlicker = 0;

           var lightPoint = new BABYLON.PointLight("light", new BABYLON.Vector3(0.14,5.97,24.55), scene);
	   lightPoint.diffuse = new BABYLON.Color3(0.09,0.94,0.45);
	   //lightPoint.specular = new BABYLON.Color3(0, 1, 0);
           lightPoint.intensity = 0;
           lightPoint.setEnabled(false);
        
               // Create a particle system
              const particleSystem = new BABYLON.ParticleSystem("particles", 4000);

              particleSystem.particleTexture = new BABYLON.Texture("ParticleGreen.png", scene);
              particleSystem.blendMode = BABYLON.ParticleSystem.BLENDMODE_STANDARD;

              // Position where the particles are emiited from
              particleSystem.emitter = boxSparkSource;
              particleSystem.minEmitBox = new BABYLON.Vector3(-0.1, -0.1, -0.1); // Starting all from
              particleSystem.maxEmitBox = new BABYLON.Vector3(0.1, 0.1, 0.1);
              particleSystem.emitRate = 100;

              particleSystem.minScaleX = 0.04;
              particleSystem.maxScaleX = 0.06;

              particleSystem.minScaleY = 0.04;
              particleSystem.maxScaleY = 0.06;

              particleSystem.direction1 = new BABYLON.Vector3(0, -4, 0).normalize();
              particleSystem.direction2 = new BABYLON.Vector3(0, -4, 0).normalize();

              particleSystem.minAngularSpeed = 0;
              particleSystem.maxAngularSpeed = Math.PI;

              particleSystem.minEmitPower = 4;
              particleSystem.maxEmitPower = 6;

              particleSystem.stop();


           scene.actionManager.registerAction(  
           new BABYLON.ExecuteCodeAction({
               trigger: BABYLON.ActionManager.OnEveryFrameTrigger
               },
               function(){
                   let SMGR = scene.getMeshByName("ShadowMeshGateRusted");                   
                   if (lightOffMesh == 1){
                       light.excludeMeshes = [SMGR, boxSparkSource];
                       lightOffMesh = 2;
                   }
                   else if (lightOffMesh == 2){
                       lightFlicker = 1;
                       lightOffMesh = 3;
                   }
               }//ends function
               
            )
        );//ends everyframe trig

            //boxSparkSource.emissiveTexture = new BABYLON.Texture("GreenGlow.png", scene); 
            boxSparkSource.material = new BABYLON.StandardMaterial('myMaterial', scene);
           scene.actionManager.registerAction(  
           new BABYLON.ExecuteCodeAction({
               trigger: BABYLON.ActionManager.OnEveryFrameTrigger
               },
               function(){
                   if (lightFlicker == 1){
                      lightPoint.setEnabled(true);
                      //light.setEnabled(false);
                      lightPoint.intensity = 50;
                      boxSparkSource.material.emissiveColor = BABYLON.Color3.Green();
                      particleSystem.start();
                      setTimeout(function(){
                        lightPointOff();        
                      }, 2000);
                      //lightFlicker = 0;                      
                   }
                   else if (lightFlicker == 2){
                      lightPoint.setEnabled(true);
                      //light.setEnabled(false);
                      lightPoint.intensity = 30;
                      boxSparkSource.material.emissiveColor = BABYLON.Color3.Green();
                      particleSystem.start();
                      setTimeout(function(){
                        lightPointOff();        
                      }, 1000);
                      //lightFlicker = 0;     
                   }
                   else if (lightFlicker == 3){
                      lightPoint.setEnabled(true);
                      //light.setEnabled(false);
                      lightPoint.intensity = 70;
                      boxSparkSource.material.emissiveColor = BABYLON.Color3.Green();
                      particleSystem.start();
                      setTimeout(function(){
                        lightPointOff();        
                      }, 4000);
                      //lightFlicker = 0;
                   }
                   else if (lightFlicker == 4){
                      lightPoint.setEnabled(true);
                      //light.setEnabled(false);
                      lightPoint.intensity = 100;
                      boxSparkSource.material.emissiveColor = BABYLON.Color3.Green();
                      particleSystem.start();
                      setTimeout(function(){
                        lightPointOff();        
                      }, 2000);
                      //lightFlicker = 0;
                   }
                   else if (lightFlicker == 5){
                      lightPoint.setEnabled(true);
                      //light.setEnabled(false);
                      lightPoint.intensity = 70;
                      boxSparkSource.material.emissiveColor = BABYLON.Color3.Green();
                      particleSystem.start();
                      setTimeout(function(){
                        lightPointOff();        
                      }, 10000);
                      //lightFlicker = 0;
                   }
                   else if (lightFlicker == 6){
                       //light.setEnabled(true);
                       lightPoint.setEnabled(false);
                       boxSparkSource.material.emissiveColor = BABYLON.Color3.Black();
                       particleSystem.stop();
                      setTimeout(function(){
                        lightPointOn();        
                      }, 3000);
                      //lightFlicker = 0;
                           
                   }
                   else if (lightFlicker == 7){
                       //light.setEnabled(true);
                       lightPoint.setEnabled(false);
                       boxSparkSource.material.emissiveColor = BABYLON.Color3.Black();
                       particleSystem.stop();
                      setTimeout(function(){
                        lightPointOn();        
                      }, 20000);
                      //lightFlicker = 0;
                   }
                   else if (lightFlicker == 8){
                       //light.setEnabled(true);
                       lightPoint.setEnabled(false);
                       boxSparkSource.material.emissiveColor = BABYLON.Color3.Black();
                       particleSystem.stop();
                      setTimeout(function(){
                        lightPointOn();        
                      }, 2000);
                      //lightFlicker = 0;
                   }
                   else if (lightFlicker == 9){
                       //light.setEnabled(true);
                       lightPoint.setEnabled(false);
                       boxSparkSource.material.emissiveColor = BABYLON.Color3.Black();
                       particleSystem.stop();
                      setTimeout(function(){
                        lightPointOn();        
                      }, 1000);
                      //lightFlicker = 0;
                   }
                   else if (lightFlicker == 10){
                       //light.setEnabled(true);
                       lightPoint.setEnabled(false);
                       boxSparkSource.material.emissiveColor = BABYLON.Color3.Black();
                       particleSystem.stop();
                      setTimeout(function(){
                        lightPointOn();        
                      }, 1000);
                      //lightFlicker = 0;
                   }
               }//ends function
               
            )
        );//ends everyframe trig

        function lightPointOn(){
            lightFlicker = Math.floor(Math.random() * (5 - 1 + 1) ) + 5;
        }
        function lightPointOff(){
            lightFlicker = Math.floor(Math.random() * (10 - 6 + 1) ) + 10;
        }
1 Like

Very cool! Sometimes when coding we get those “happy accidents” :rofl:

2 Likes

Thanks for the comment! I showed this to a friend, on Quest 2, and he said, “Those aren’t sparks; they’re little green balls.” I said, “Those are sparks!” He said, “Green balls!” We went back and forth like that for fifteen minutes before I finally conceded that they’re little green balls… :pensive:

Right now they’re just dropping straight down. Eventually I’ll have them shoot out to the sides a little bit before dropping down.

A few days ago I arranged the “grounds” to align with the corridors and rooms. I also added a gliding motion (besides the teleportation). It’s based on a post by Owen and a series of answers to that post and code snippets by @RaananW. To glide over the floors, just point either controller at any spot on the floor, and press the front trigger.

Maybe scaling the particles to be something like 2x longer on the y axis would make them “sparkier” than “ballier”? :laughing: and I agree that shooting them a bit to the side would be a nice touch :slight_smile:

1 Like

Yes, that’s good. Kind of like motion blur simulation. :slightly_smiling_face: