three-js-post-processing
Javascript Web Development

Logo with GodRays Effect | Three.js Postprocessing Tutorial

In this tutorial, we’re going to show to how to create a batman logo with god rays background using JavaScript and Three.js in just a few minutes. Let’s check it out!

Importing 3D Model

In previous tutorial, we have showed you how to import 3D car model into the webpage using Three.js. This tutorial is going to reuse that code to import the Batman logo model.

add-3d-model-website-2

Next I’m going to find a suitable model for bat logo. I found a free version on Sketchfab so let’s download it.

Now here is the code from previous tutorial. Let’s replace the car model with the batman logo and change the model scaling size from 0.5 to 100.

let loader = new THREE.GLTFLoader();
loader.load('scene.gltf', function(gltf){
  let bat = gltf.scene.children[0];
  bat.scale.set(100,100,100);
  scene.add(gltf.scene);
  animate();
});

3D-batman-logo-Godrays-1

Scene Setup

Let’s change the scene background to black and change the camera position and angle. I’ll also increase the FOV angle and viewing range.

scene.background = new THREE.Color(0x020202);

camera = new THREE.PerspectiveCamera(60,window.innerWidth/window.innerHeight,1,50000);
camera.position.y = 310;
camera.position.z = 500;

3D-batman-logo-Godrays-2

Next we’re going adjust the light source. We already have multiple light sources from previous tutorial. Now we only need just one directional light from background. I’ll set the light color to warm yellow and reduce the intensity. Also change the direction to make the glowing background.

let directionalLight = new THREE.DirectionalLight(0xffccaa,3);
directionalLight.position.set(0,0,-1);
scene.add(directionalLight);

Now to create a volumetric light or god rays, we need to create a shape of the light source. Let’s create a circle shape. The color of the god rays effect is determined by the color of the light source material. I’m going to set to yellow. I’ll place it some distance behind the bat logo. Also add a small horizontal scale to create an ellipse shape.

let circleGeo = new THREE.CircleGeometry(220,50);
let circleMat = new THREE.MeshBasicMaterial({color: 0xffccaa});
let circle = new THREE.Mesh(circleGeo, circleMat);
circle.position.set(0 ,100 ,-500);
circle.scale.setX(1.2);
scene.add(circle);

3D-batman-logo-Godrays-3

Post-Processing

Scene is ready. The next step is to add a god rays post-processing effect to the shape we have just created. There is a nice post-processing library for Three.js that will do the heavy lifting for you. Just download the latest release from github or use npm install command, it’s up to you!

Once downloaded, copy the postprocessing.js and include it to your page with script tag.

<script src="postprocessing.min.js"></script>

Next create an effect object using god rays effect constructor. We’ll pass the camera and the our circle shape. And the last one is option object which we can customize the god rays characteristic.

let godraysEffect = new POSTPROCESSING.GodRaysEffect(camera, circle, {
  resolutionScale: 1,
  density: 0.8,
  decay: 0.95,
  weight: 0.9,
  samples: 100
});

There is no actual formula for these numbers. It depends on how you want your light to be. Try out the official demo of the library to understand more about each property.

Alright the effect object is ready. Next step is to create the pass. Pass is how we utilize the shader with the post-processing. The first pass we need is a renderPass. Normally, we’ll use our WebGL render to render the scene. But as want to apply the post-processing, we’ll have to use renderPass instead.

let renderPass = new POSTPROCESSING.RenderPass(scene, camera);

Next is effectPass. This is where you’ll pass the god rays effect object that we created. You can add more than one effect to the pass. We also need to set the render to screen property to true to enable it.

let effectPass = new POSTPROCESSING.EffectPass(camera,godraysEffect);
effectPass.renderToScreen = true;

The final step is to create an effect composer, this is where you’ll add all the passes to it. You’ll need to pass your normal renderer to the constructor. Then use addPass to add all your passes.

composer = new POSTPROCESSING.EffectComposer(renderer);
composer.addPass(renderPass);
composer.addPass(effectPass);

Then render the scene with composer instead.

function animate() {
    composer.render(0.1);
    requestAnimationFrame(animate);
}

3D-batman-logo-Godrays-4

That looks good but if you look closely you’ll see jagged edge.

3D-batman-logo-Godrays-5

We can fix this problem by adding anti aliasing effect. Using SMAApass provided in this library.

let areaImage = new Image();
    areaImage.src = POSTPROCESSING.SMAAEffect.areaImageDataURL;
let searchImage = new Image();
    searchImage.src = POSTPROCESSING.SMAAEffect.searchImageDataURL;
let smaaEffect = new POSTPROCESSING.SMAAEffect(searchImage,areaImage,1);

let effectPass = new POSTPROCESSING.EffectPass(camera,smaaEffect,godraysEffect);

You can see the final result in this video

And that’s all for this Three.js tutorial. Hope it helps! Like our Facebook and subscribe our Youtube Channel to stay connected if you love to see more. See you next time!

Source Code

HTML/JS

<!DOCTYPE html>
<html>
  <head>
    <meta charset=UTF-8 />
    <link rel="stylesheet" type="text/css" href="styles.css" />
  </head>
  <body>
    <script src="three.min.js"></script>
    <script src="GLTFLoader.js"></script>
    <script src="OrbitControls.js"></script>
    <script src="postprocessing.min.js"></script>
    <script>
      let scene, camera, renderer, composer,controls;

      function init() {

        scene = new THREE.Scene();
        scene.background = new THREE.Color(0x020202);

        camera = new THREE.PerspectiveCamera(60,window.innerWidth/window.innerHeight,1,50000);
        camera.position.y = 510;
        camera.position.z = 500;

        controls = new THREE.OrbitControls(camera);
        controls.addEventListener('change', renderer);
        controls.panSpeed = 0.1;
        controls.rotateSpeed = 0.1;
        controls.update();

        let directionalLight = new THREE.DirectionalLight(0xffccaa,3);
        directionalLight.position.set(0,0,-1);
        scene.add(directionalLight);

        renderer = new THREE.WebGLRenderer({antialias:true});
        renderer.setSize(window.innerWidth,window.innerHeight);
        document.body.appendChild(renderer.domElement);

        let circleGeo = new THREE.CircleGeometry(220,50);
        let circleMat = new THREE.MeshBasicMaterial({color: 0xffccaa});
        let circle = new THREE.Mesh(circleGeo, circleMat);
        circle.position.set(0 ,100 ,-500);
        circle.scale.setX(1.2);
        scene.add(circle);

        let areaImage = new Image();
            areaImage.src = POSTPROCESSING.SMAAEffect.areaImageDataURL;
        let searchImage = new Image();
            searchImage.src = POSTPROCESSING.SMAAEffect.searchImageDataURL;
        let smaaEffect = new POSTPROCESSING.SMAAEffect(searchImage,areaImage,1);

        let godraysEffect = new POSTPROCESSING.GodRaysEffect(camera, circle, {
          resolutionScale: 1,
          density: 0.8,
          decay: 0.95,
          weight: 0.9,
          samples: 100
        });

        let renderPass = new POSTPROCESSING.RenderPass(scene, camera);
        let effectPass = new POSTPROCESSING.EffectPass(camera,godraysEffect);
        effectPass.renderToScreen = true;

        composer = new POSTPROCESSING.EffectComposer(renderer);
        composer.addPass(renderPass);
        composer.addPass(effectPass);

        let loader = new THREE.GLTFLoader();
        loader.load('scene.gltf', function(gltf){
          let bat = gltf.scene.children[0];
          bat.scale.set(100,100,100);
          scene.add(gltf.scene);
          animate();
        });
      }
      function animate() {
        composer.render(0.1);
        requestAnimationFrame(animate);
      }
      init();
    </script>

  </body>
</html>

CSS

body {
  width: 100vw;
  height: 100vh;
  margin: 0;
  background: black;
  overflow: hidden;
}

3 comments

  1. I have dumb noob question: Why is nothing showing up on my website?
    I am uploading these files to my webhoster:
    index.html
    OrbitControls.js
    WebGL.js
    css (folder)
    scene.bin (downloaded)
    scene ( 3d file )
    js ( folder with three.js , GLTFloader.js , three.min.js )
    textures ( folder )

    What I am doing wrong?

  2. How do you get those light intensity sliders, or sliders in general for the user to make changes too?

Leave a Reply

Your email address will not be published. Required fields are marked *

error: