Particle sun rendering in computer graphics

Babylon.js is Javascript's open-source framework that allows us to build interactive 3D experiences on the web. Having such features makes it a potential library for rendering 3D objects in space.

Babylon.js logo
Babylon.js logo

In this Answer, we will use Babylon.js to create a fascinating 3D rendering of the sun by employing advanced features like particle systems and visualizing various effects, surface textures, flares, and corona particles.

Note: Particle systems in Babylon.js are dynamic visual effects that we can use simulate lots of small elements within a scene. For instance, fire, smoke, rain, etc.

Visualizing the sun
Visualizing the sun

Code walkthrough

We will go through the code in chunks and understand how various components come together to render a sun in three dimensions using Babylon.js. Let's get started!

Importing Babylon.js CDN files

<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
<script src="https://assets.babylonjs.com/generated/Assets.js"></script>
<script src="https://cdn.babylonjs.com/recast.js"></script>
<script src="https://cdn.babylonjs.com/ammo.js"></script>
<script src="https://cdn.babylonjs.com/havok/HavokPhysics_umd.js"></script>
<script src="https://cdn.babylonjs.com/cannon.js"></script>
<script src="https://cdn.babylonjs.com/Oimo.js"></script>
<script src="https://cdn.babylonjs.com/earcut.min.js"></script>
<script src="https://cdn.babylonjs.com/babylon.js"></script>
<script src="https://cdn.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script>
<script src="https://cdn.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script>
<script src="https://cdn.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js"></script>
<script src="https://cdn.babylonjs.com/loaders/babylonjs.loaders.js"></script>
<script src="https://cdn.babylonjs.com/serializers/babylonjs.serializers.min.js"></script>
<script src="https://cdn.babylonjs.com/gui/babylon.gui.min.js"></script>
<script src="https://cdn.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
  • In this section, we import external libraries and dependencies required for Babylon.js and its 3D visualizations.

Style options

<style>
html, body {
overflow: hidden;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#canvasClass {
width: 100%;
height: 100%;
touch-action: none;
}
#canvasArea {
width: 100%;
height: 100%;
}
</style>
  • We define our style <style> properties to control the appearance of the HTML and body elements. This is mainly done to see the sun's visualization in full screen.

HTML canvas

<div id="canvasArea">
<canvas id="canvasClass"></canvas>
</div>
  • This canvas will serve as the rendering surface for the 3D scene. We give it the ID of "canvasClass".

Engine and scene creation

var canvas = document.getElementById("canvasClass");
var startRenderLoop = function(sunEngine, canvas) {
sunEngine.runRenderLoop(function() {
if (sceneToRender && sceneToRender.activeCamera) {
sceneToRender.render();
}
});
}
var sunEngine = null;
var sunScene = null;
var sceneToRender = null;
var createDefaultEngine = function() {
return new BABYLON.Engine(canvas, true, {
preserveDrawingBuffer: true,
stencil: true,
disableWebGL2Support: false
});
};
  • Here, we retrieve the HTML element with the ID "canvasClass" using the document.getElementById method. This element will serve as our rendering canvas, where the 3D scene will be displayed.

  • We define a function called startRenderLoop, which takes two parameters: sunEngine and canvas. Inside this function, we use the runRenderLoop method provided by sunEngine to create a continuous rendering loop. Within the loop, we check if sceneToRender exists and if its active camera is set. If these conditions are met, we render the current scene using sceneToRender.render().

  • We declare three variables: sunEngine, sunScene, and sceneToRender which are null at the start. These variables will be used to manage both the scene and the engine behind it.

  • We define a function called createDefaultEngine, where we create a new instance of Babylon's Engine class and configure it accordingly.

Scene customization

var createScene = function() {
var sunScene = new BABYLON.Scene(sunEngine);
var camera = new BABYLON.ArcRotateCamera("ArcRotateCamera", 1, 0.8, 5, new BABYLON.Vector3(0, 0, 0), sunScene);
camera.attachControl(canvas, true);
sunScene.clearColor = new BABYLON.Color3(0.0, 0.0, 0.0);
var stars = BABYLON.Mesh.CreateBox("emitter", 1, sunScene);
var surfaceParticles = new BABYLON.ParticleSystem("surfaceParticles", 1600, sunScene);
var flareParticles = new BABYLON.ParticleSystem("flareParticles", 20, sunScene);
var coronaParticles = new BABYLON.ParticleSystem("coronaParticles", 600, sunScene);
var starsParticles = new BABYLON.ParticleSystem("starsParticles", 500, sunScene);
surfaceParticles.particleTexture = new BABYLON.Texture("https://raw.githubusercontent.com/PatrickRyanMS/BabylonJStextures/master/ParticleSystems/Sun/T_SunSurface.png", sunScene);
flareParticles.particleTexture = new BABYLON.Texture("https://raw.githubusercontent.com/PatrickRyanMS/BabylonJStextures/master/ParticleSystems/Sun/T_SunFlare.png", sunScene);
coronaParticles.particleTexture = new BABYLON.Texture("https://raw.githubusercontent.com/PatrickRyanMS/BabylonJStextures/master/ParticleSystems/Sun/T_Star.png", sunScene);
starsParticles.particleTexture = new BABYLON.Texture("https://raw.githubusercontent.com/PatrickRyanMS/BabylonJStextures/master/ParticleSystems/Sun/T_Star.png", sunScene);
var coreSphere = BABYLON.MeshBuilder.CreateSphere("coreSphere", {
diameter: 2.01,
segments: 64
}, sunScene);
var coreMat = new BABYLON.StandardMaterial("coreMat", sunScene)
coreMat.emissiveColor = new BABYLON.Color3(0.3773, 0.0930, 0.0266);
coreSphere.material = coreMat;
var sunEmitter = new BABYLON.SphereParticleEmitter();
sunEmitter.radius = 1;
sunEmitter.radiusRange = 0;
var starsEmitter = new BABYLON.SphereParticleEmitter();
starsEmitter.radius = 20;
starsEmitter.radiusRange = 0;
surfaceParticles.emitter = coreSphere;
surfaceParticles.particleEmitterType = sunEmitter;
flareParticles.emitter = coreSphere;
flareParticles.particleEmitterType = sunEmitter;
coronaParticles.emitter = coreSphere;
coronaParticles.particleEmitterType = sunEmitter;
starsParticles.emitter = stars;
starsParticles.particleEmitterType = starsEmitter;
starsParticles.color1 = new BABYLON.Color4(0.898, 0.737, 0.718, 1.0);
starsParticles.color2 = new BABYLON.Color4(0.584, 0.831, 0.894, 1.0);
surfaceParticles.addColorGradient(0, new BABYLON.Color4(0.8509, 0.4784, 0.1019, 0.0));
surfaceParticles.addColorGradient(0.4, new BABYLON.Color4(0.6259, 0.3056, 0.0619, 0.5));
surfaceParticles.addColorGradient(0.5, new BABYLON.Color4(0.6039, 0.2887, 0.0579, 0.5));
surfaceParticles.addColorGradient(1.0, new BABYLON.Color4(0.3207, 0.0713, 0.0075, 0.0));
flareParticles.addColorGradient(0, new BABYLON.Color4(1, 0.9612, 0.5141, 0.0));
flareParticles.addColorGradient(0.25, new BABYLON.Color4(0.9058, 0.7152, 0.3825, 1.0));
flareParticles.addColorGradient(1.0, new BABYLON.Color4(0.6320, 0.0, 0.0, 0.0));
coronaParticles.addColorGradient(0, new BABYLON.Color4(0.8509, 0.4784, 0.1019, 0.0));
coronaParticles.addColorGradient(0.5, new BABYLON.Color4(0.6039, 0.2887, 0.0579, 0.12));
coronaParticles.addColorGradient(1.0, new BABYLON.Color4(0.3207, 0.0713, 0.0075, 0.0));
surfaceParticles.minSize = 0.3;
surfaceParticles.maxSize = 0.8;
flareParticles.minScaleX = 0.3;
flareParticles.minScaleY = 0.6;
flareParticles.maxScaleX = 1;
flareParticles.maxScaleY = 1;
coronaParticles.minScaleX = 0.3;
coronaParticles.minScaleY = 0.8;
coronaParticles.maxScaleX = 1.5;
coronaParticles.maxScaleY = 2.5;
starsParticles.minSize = 0.1;
starsParticles.maxSize = 0.35;
flareParticles.addSizeGradient(0, 0);
flareParticles.addSizeGradient(1, 1);
surfaceParticles.minLifeTime = 7;
surfaceParticles.maxLifeTime = 7;
flareParticles.minLifeTime = 10;
flareParticles.maxLifeTime = 10;
coronaParticles.minLifeTime = 3;
coronaParticles.maxLifeTime = 3;
starsParticles.minLifeTime = 1000000;
starsParticles.maxLifeTime = 1000000;
surfaceParticles.emitRate = 250;
flareParticles.emitRate = 2;
coronaParticles.emitRate = 250;
starsParticles.manualEmitCount = 1000;
starsParticles.maxEmitPower = 0;
surfaceParticles.blendMode = BABYLON.ParticleSystem.BLENDMODE_ADD;
flareParticles.blendMode = BABYLON.ParticleSystem.BLENDMODE_ADD;
coronaParticles.blendMode = BABYLON.ParticleSystem.BLENDMODE_ADD;
starsParticles.blendMode = BABYLON.ParticleSystem.BLENDMODE_STANDARD;
surfaceParticles.minAngularSpeed = -0.4;
surfaceParticles.maxAngularSpeed = 0.4;
flareParticles.minAngularSpeed = 0.0;
flareParticles.maxAngularSpeed = 0.0;
coronaParticles.minAngularSpeed = 0.0;
coronaParticles.maxAngularSpeed = 0.0;
starsParticles.minAngularSpeed = 0.0;
starsParticles.maxAngularSpeed = 0.0;
surfaceParticles.minEmitPower = 0;
surfaceParticles.maxEmitPower = 0;
surfaceParticles.updateSpeed = 0.005;
flareParticles.minEmitPower = 0.001;
flareParticles.maxEmitPower = 0.01;
coronaParticles.minEmitPower = 0.0;
coronaParticles.maxEmitPower = 0.0;
starsParticles.minEmitPower = 0.0;
starsParticles.maxAngularSpeed = 0.0;
surfaceParticles.isBillboardBased = false;
flareParticles.isBillboardBased = true;
coronaParticles.isBillboardBased = true;
starsParticles.isBillboardBased = true;
starsParticles.start();
surfaceParticles.start();
flareParticles.start();
coronaParticles.start();
return sunScene;
}

This is the code where the 3D sun is actually configured, and the scene is returned. Let's go through it in detail.

  • We start by creating a new Babylon.js scene called sunScene, using sunEngine as the rendering engine.

  • We create ArcRotateCamera to control the camera's position and movement.

  • The camera's controls are attached to the canvas using attachControl so that we can interact with the scene by dragging and zooming.

  • We create a mesh emitter to serve as the source for particle emission.

  • Four particle systems are created for different visual effects

    • surfaceParticles

    • flareParticles

    • coronaParticles

    • starsParticles

  • Each particle system is then assigned a particle texture to depict close to accurate phenomenons.

  • We now create the sun! A spherical mesh, coreSphere, is generated using BABYLON.MeshBuilder.CreateSphere and represents the sun's core.

  • The material of coreSphere is defined using BABYLON.StandardMaterial and configured to emit a color like the sun.

  • Sphere emitters, sunEmitter and starsEmitter, are set up for the particle systems. These emitters determine where particles originate.

  • This is where most of the customizations reside as particle properties and behavior are configured:

    • emitter assignment using .emitter

    • emitter type using particleEmitterType

    • colors using BABYLON.COLOR and .addColorGradient

    • sizes using minSize, maxSize, minScaleX, minScaleY and .addSizeGradient

    • lifetimes using .minLifeTime and .maxLifeTime

    • emit rates using .emitRate

    • blending modes using .blendMode

    • angular speeds using minAngularSpeed and maxAngularSpeed

  • Next, the particle systems are started using start() functions.

  • Finally, our configured sunScene is returned.

Complete scene initialization

window.initFunction = async function() {
var asyncEngineCreation = async function() {
return createDefaultEngine();
}
window.sunEngine = await asyncEngineCreation();
startRenderLoop(sunEngine, canvas);
window.sunScene = createScene();
};
initFunction().then(() => {
sceneToRender = sunScene
});
window.addEventListener("resize", function() {
sunEngine.resize();
});
  • We start by defining a function named initFunction, which will handle the initialization of our rendering environment. The asyncEngineCreation function returns a default engine, the result of which is saved in window.sunEngine.

  • We use the startRenderLoop(sunEngine, canvas) function to begin the rendering loop. This function repeatedly renders the scene using sunEngine and our HTML canvas element canvas.

  • Then we call createScene() to create the 3D scene. The result, sunScene, is assigned to window.sunScene.

  • We initiate the scene rendering and set the rendered scene to sceneToRender. We also ensure the rendering engine is resized if the window dimensions change.

Executable code

Congratulations, we're done with the code! It all comes together to form this final executable HTML file. Feel free to experiment with it and click "Run" once done.

Note: Since we are importing CDNdistributed group of servers files, please ensure that you're connected to the internet when running this HTML file.

3D sun rendering demonstration

How our sun is customized makes it start rendering from a simple red circle depicting a sun. It starts warming up and reaches its final hot state a few seconds after the code executes.

Interact with the output below and enjoy the realistic rendering!

Prewarmed sun code addition

To render a sun that is already hot, we can add the code below. preWarmStepOffset and preWarmCycles have to be defined accordingly.

surfaceParticles.preWarmStepOffset = 10;
surfaceParticles.preWarmCycles = 100;
flareParticles.preWarmStepOffset = 10;
flareParticles.preWarmCycles = 100;
coronaParticles.preWarmStepOffset = 10;
coronaParticles.preWarmCycles = 100;

The output looks like the following:

Applications of 3D sun visualization

Such visualizations can be employed in various applications in the real world, as the following table represents.

Real world applications

Astronomy related interactive learning

Virtual planetariums or science centers

Scientific research

Space simulations

Art visualizations

How well do you know 3D sun visualization in Babylon.js?

Q

To change the speed of the sun’s flares, what property do we configure?

A)

minFlareSpeed and maxFlareSpeed

B)

minAngularSpeed and maxAngularSpeed

C)

minRotationSpeed and maxRotationSpeed

Free Resources

Copyright ©2025 Educative, Inc. All rights reserved