<head>
    <link href="https://fonts.googleapis.com/css2?family=Rajdhani:wght@500&display=swap" rel="stylesheet">
     <title>BABYLON js Template by Hitesh Sahu ๐ŸŽ„</title>
    </head>
<body>
    <div class="container"> 
      <div class="container"><canvas id="renderCanvas" class="container" /></div>
      <div class="footer"><a href = "https://hiteshsahu.com/lab">See More in Lab ๐Ÿงช</a></div> 
     <div class="header"><h3>Christmas Tree by Hitesh Sahu ๐ŸŽ„<h2></div>
</div>
</body>
<link href="https://fonts.googleapis.com/css2?family=Lobster&display=swap" rel="stylesheet">

#renderCanvas {
    position: absolute;
  width: 100%;
  height: 100%;
  touch-action: none;
   left:  0%;
  right: 0%;
  bottom:0%;
  top: 0%;
} 

 html, body {
  overflow: hidden;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
font-family: 'Rajdhani', sans-serif;
    color: white;
  font-size: large;

}

a:link, a:visited {
  background-color: #f44336;
  color: white;
  padding: 14px 25px;
  text-align: center;
  text-decoration: none;
  display: inline-block;
}

.container {
  position: relative;
  height: 100%;
  width: 100%;
}

.header {
  position: absolute;
  left:0;
  right:0;
  top:0;
  padding-left:10px;
    text-align: center;

}

.footer {
  position: absolute;
  right:0;
  bottom:0;
  margin:5px;
  padding:5px;
}

a:hover, a:active {
  background-color: red;
}

.center {
  position: absolute;
  background-color: #00bfa5;
  left:  0%;
  right: 0%;
  bottom:0%;
  top: 0%;
  margin:10px;
  padding:10px;
}

const GROUND_SIZE = 30
const TEXTURE_FOLDER = "https://www.babylonjs-playground.com/textures/"
const finalRadius = 3.5;
const finalHeight = 8;
const numberofHelix = 5
const numberOfLights = 35
const lightSize = 0.35
let lights = [];
let showWire = true
var lastClickedMesh = null

    //------------------- init Scene---------------------

    var canvas = document.getElementById("renderCanvas");
    var engine = new  BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true });

    var scene = new BABYLON.Scene(engine);
    scene.clearColor = BABYLON.Color3.FromHexString("#263238")

    // --------------------Add Camera--------------------
   var  camera = new BABYLON.ArcRotateCamera("Camera",
        Math.PI / 2, Math.PI / 2, 40, BABYLON.Vector3.Zero(), scene);
    camera.setTarget(BABYLON.Vector3.Zero());
    camera.attachControl(canvas, true);
    camera.lowerBetaLimit = 0.1;
    camera.upperBetaLimit = (Math.PI / 2) * 0.9;
    camera.lowerRadiusLimit = 3;
    camera.upperRadiusLimit = GROUND_SIZE * 2;
    camera.setPosition(new BABYLON.Vector3(GROUND_SIZE / 2, 5, GROUND_SIZE / 2))

    camera = new BABYLON.ArcRotateCamera("Camera", 0, 0, 10, new BABYLON.Vector3(0, 0, 0), scene);
    camera.setPosition(new BABYLON.Vector3(0, 0, 20));
    camera.attachControl(canvas, true);


    //-------------------- Lights -------------------------------

    //Light for Gtlf
    var ambientLight = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);
    ambientLight.intensity = 0.25;

    var sunLight = new BABYLON.SpotLight("sunLight",
             new BABYLON.Vector3(GROUND_SIZE/2 , GROUND_SIZE / 2, GROUND_SIZE/2),
               new BABYLON.Vector3(-1, -1, -1),
                                          Math.PI/2 , 1, scene);
    sunLight.diffuse =  BABYLON.Color3.FromHexString("#e25822")
    sunLight.diffuse = new BABYLON.Color3.FromHexString("#F96229"); //(1, 1, 1);
    sunLight.specular = new BABYLON.Color3.FromHexString("#FCE13D");
   sunLight.intensity = 5;

    //Imposter for sun
    var lightImposter = BABYLON.Mesh.CreateSphere("lightImposter", 10, 2, scene);
    var lightImposterMat = new BABYLON.StandardMaterial("lightImposterMat", scene);
    lightImposterMat.diffuseColor = new BABYLON.Color3(1, 1, 0);
    lightImposterMat.emissiveColor = new BABYLON.Color3(1, 1, 0);
    lightImposter.material = lightImposterMat
    lightImposter.position = sunLight.position;

    // Shadows
    var shadowGenerator = new BABYLON.ShadowGenerator(1024, sunLight);
    shadowGenerator.darkness = .25
    shadowGenerator.useExponentialShadowMap = true;

    //Make meshes glow
    new BABYLON.GlowLayer("glow", scene, {
        mainTextureFixedSize: 1024,
        blurKernelSize: 64
    });

 // Environment Texture
    var hdrTexture = BABYLON.CubeTexture.CreateFromPrefilteredData(TEXTURE_FOLDER + "environment.dds", scene);
    scene.imageProcessingConfiguration.exposure = 0.6;
    scene.imageProcessingConfiguration.contrast = 1.6;

    // Skybox
    var hdrSkybox = BABYLON.Mesh.CreateBox("hdrSkyBox", 1000.0, scene);
    var hdrSkyboxMaterial = new BABYLON.PBRMaterial("skyBox", scene);
    hdrSkyboxMaterial.backFaceCulling = false;
    hdrSkyboxMaterial.reflectionTexture = hdrTexture.clone();
    hdrSkyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
    hdrSkyboxMaterial.microSurface = 1.0;
    hdrSkyboxMaterial.disableLighting = true;
    hdrSkybox.material = hdrSkyboxMaterial;
    hdrSkybox.infiniteDistance = true;

    var camera = new BABYLON.ArcRotateCamera("Camera", 0, 0, 10, new BABYLON.Vector3(0, 0, 0), scene);
    camera.setPosition(new BABYLON.Vector3(0, 0, 20));
    camera.attachControl(canvas, true);

    var ambientLight = new BABYLON.HemisphericLight("light0", new BABYLON.Vector3(0, -1, 0), scene);
    ambientLight.intensity = 1;

    var light = new BABYLON.DirectionalLight("dir01", new BABYLON.Vector3(0, -1, -0.3), scene);
    light.position = new BABYLON.Vector3(20, 60, 30);
    light.intensity = 15

    new BABYLON.GlowLayer("glow", scene, {
        mainTextureFixedSize: 1024,
        blurKernelSize: 64
    });

    var lightMesh = BABYLON.Mesh.CreateSphere("Link", 16, lightSize, scene);
    lightMesh.isVisible = false;

   var woodPlank = BABYLON.MeshBuilder.CreateBox("plane", { width: 50, height: 1, depth: 50 }, scene);

    var wood = new BABYLON.PBRMaterial("wood", scene);
    wood.reflectionTexture = hdrTexture;
    wood.environmentIntensity = 1;
    wood.specularIntensity = 0.3;
    wood.reflectivityTexture = new BABYLON.Texture(TEXTURE_FOLDER + "reflectivity.png", scene);
    wood.reflectivityTexture.uScale = 5
    wood.reflectivityTexture.vScale = 5
    wood.useMicroSurfaceFromReflectivityMapAlpha = true;
    wood.albedoColor = BABYLON.Color3.White();
    wood.albedoTexture = new BABYLON.Texture(TEXTURE_FOLDER + "albedo.png", scene);
    woodPlank.material = wood;
    woodPlank.position.y = -5


    var plastic = new BABYLON.PBRMaterial("plastic", scene);
    plastic.reflectionTexture = hdrTexture;
    plastic.microSurface = 0.96;
    plastic.albedoColor = new BABYLON.Color3(0.206, 0.94, 1);
    plastic.reflectivityColor = new BABYLON.Color3(0.206, 0.94, 1);
    lightMesh.material = plastic;

    //Array of points to construct a spiral with lines
    var spiralPoints = [];
    let endRadian = 2 * Math.PI * numberofHelix;
    let radianStep = endRadian / numberOfLights
    let deltaR = finalRadius / numberOfLights
    var deltaY = finalHeight / numberOfLights;

    let radius = finalRadius
    let Y = 0;

    for (var radian = 0; radian < endRadian; radian += radianStep) {
        spiralPoints.push(new BABYLON.Vector3(
            radius * Math.cos(radian),
            Y,
            radius * Math.sin(radian)));
        Y += deltaY
        radius -= deltaR
    }

    var nodes = BABYLON.Curve3.CreateCatmullRomSpline(
        spiralPoints,
        10
    ).getPoints();

    if (showWire) {
        BABYLON.Mesh.CreateLines(
            "Wire",
            nodes,
            scene
        );
    }
 
    for (let index = 0; index < nodes.length; index += 5) {
        let light = lightMesh.createInstance("Link" + index);
        light.position = nodes[index];
        lights.push(light);
    }

    // Trees
    BABYLON.SceneLoader.ImportMesh("", "//www.babylonjs.com/assets/Tree/", "tree.babylon", scene,  (newMeshes)=> {
        newMeshes[0].position.y -= 4.8
        newMeshes.forEach(mesh => {
            mesh.scaling = new BABYLON.Vector3(30, 30, 30)
            mesh.material.opacityTexture = null;
            mesh.material.backFaceCulling = false;
        })
    });

 
engine.runRenderLoop(() => {
    if (scene) scene.render();
});

// Resize
window.addEventListener("resize", () => {
    engine.resize();
});


 

   var angle = 0, alpha=0;
    scene.registerAfterRender(function(){
        angle+=0.08;
        camera.alpha = angle
    })

    scene.onBeforeRenderObservable.add(function () {
        lights.forEach(mesh => {
            alpha += 0.001;
            mesh.material.emissiveColor = new BABYLON.Color3(Math.sin(alpha) * Math.random(), Math.cos(alpha), Math.sin(alpha));
        })
    });

      
       
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://code.jquery.com/pep/0.4.2/pep.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js
  3. https://preview.babylonjs.com/ammo.js
  4. https://preview.babylonjs.com/cannon.js
  5. https://preview.babylonjs.com/Oimo.js
  6. https://preview.babylonjs.com/libktx.js
  7. https://preview.babylonjs.com/earcut.min.js
  8. https://preview.babylonjs.com/babylon.js
  9. https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js
  10. https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js
  11. https://preview.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js
  12. https://preview.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js
  13. https://preview.babylonjs.com/loaders/babylonjs.loaders.js
  14. https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js
  15. https://preview.babylonjs.com/gui/babylon.gui.min.js