# How to cast shadows in 3d google map?

**URL:** <https://discourse.threejs.org/t/how-to-cast-shadows-in-3d-google-map/31619>\
**Category:** Questions\
**Tags:** shadows\
**Created:** [November 9, 2021, 7:58am UTC](https://discourse.threejs.org/t/how-to-cast-shadows-in-3d-google-map/31619 "2021-11-09T07:58:20Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![yosan\_melese](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/yosan_melese/32/73152_2.png) [@yosan\_melese](https://discourse.threejs.org/u/yosan_melese)\
**Post date:** [November 9, 2021, 7:58am UTC](https://discourse.threejs.org/t/how-to-cast-shadows-in-3d-google-map/31619/1 "2021-11-09T07:58:20Z")

</div>

Hello. I want to load a ThreeJs scene to a Google map using the WebGL overlay [API](https://developers.google.com/maps/documentation/javascript/webgl/webgl-overlay-view)

It seems to me that the map API doesn’t give access to its Light source. so this might not be possible. I was wondering if you can point me the way to achieve this. it doesn’t matter even if I need to go down to WebGL-GPU.

---

<div class="post-metadata">

**Author:** ![Mugen87](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/mugen87/32/5645_2.png) [@Mugen87](https://discourse.threejs.org/u/Mugen87)\
**Post date:** [November 9, 2021, 8:30am UTC](https://discourse.threejs.org/t/how-to-cast-shadows-in-3d-google-map/31619/2 "2021-11-09T08:30:40Z")

</div>

/cc

> <https://stackoverflow.com/questions/69894168/webgl-overlay-google-map-how-to-cast-shadows>

---

<div class="post-metadata">

**Author:** ![ah72king](https://avatars.discourse-cdn.com/v4/letter/a/8797f3/32.png) [@ah72king](https://discourse.threejs.org/u/ah72king)\
**Post date:** [November 26, 2021, 1:05pm UTC](https://discourse.threejs.org/t/how-to-cast-shadows-in-3d-google-map/31619/3 "2021-11-26T13:05:50Z")

</div>

++  
Update:  
[stackoverflow](https://stackoverflow.com/questions/69894168/webgl-overlay-google-map-how-to-cast-shadows/)  
i have edit my answer after @ [yosan\_melese](https://discourse.threejs.org/u/yosan_melese) comment on [stackoverflow](https://stackoverflow.com/questions/69894168/webgl-overlay-google-map-how-to-cast-shadows/)

Hi @yosan_melese , basically we do not have access to google map layer in Threejs  
shadow depend on plane and google map layer is not a plane

I achieve the shadow by adding a custom plane of same color of google map skin below 3D object  
and added directional light from this i get shadow of object

Here is my code

```javascript

import { Loader } from '@googlemaps/js-api-loader';
import * as THREE from 'three';
import {FBXLoader} from 'three/examples/jsm/loaders/FBXLoader.js';

const apiOptions = {
  apiKey: 'A *********** 8',
  version: "beta",
  map_ids: [""]
};
let directionalLight = '';
const mapOptions = {
  "tilt": 0,
  "heading": 0,
  "zoom": 18,
  "center": { lat: 33.57404, lng: 73.1637 },
  "mapId": "" ,
  "mapTypeId": 'roadmap'
}
/*
roadmap: the default map that you usually see.
satellite: satellite view of Google Maps and Google Earth, when available.
hybrid: a mixture of roadmap and satellite view.
terrain: a map based on terrain information, such as mountains and valleys.
*/
async function initMap() {    
  const mapDiv = document.getElementById("map");
  const apiLoader = new Loader(apiOptions);
  await apiLoader.load();
  return new google.maps.Map(mapDiv, mapOptions);
}

let scene, renderer, camera, loader,loader1,controls;
function initWebglOverlayView(map) {  
  
  const webglOverlayView = new google.maps.WebglOverlayView();
  
  webglOverlayView.onAdd = () => {   
    // set up the scene
    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera();

    const ambientLight = new THREE.AmbientLight( 0xffffff, 0.75 ); // soft white light
    scene.add(ambientLight);

    directionalLight = new THREE.DirectionalLight(0xffffff, 1);
    directionalLight.position.x += (-90)
    directionalLight.position.y += 0
    directionalLight.position.z += 20
    directionalLight.castShadow = true
    const d = 100;
    directionalLight.shadow.camera.left = - d;
    directionalLight.shadow.camera.right = d;
    directionalLight.shadow.camera.top = d;
    directionalLight.shadow.camera.bottom = - d;
    scene.add(directionalLight);
    scene.add( new THREE.CameraHelper( directionalLight.shadow.camera ) );

    // FLOOR
    const plane = new THREE.Mesh(new THREE.PlaneGeometry(2050, 2200, 300),
    new THREE.MeshPhongMaterial({ color: 0xF3F4F5, opacity: 0.3, transparent: true}));
    plane.rotation.x = 0;
    plane.rotation.y = 0;
    plane.rotation.z = 0;
    plane.castShadow = true
    plane.receiveShadow = true
    scene.add(plane);

    loader = new FBXLoader();
    loader.load( 'model/imaratlowpoly.fbx', function ( object ) {
      object.scale.set( 1, 1, 1 );
      object.rotation.x = 1.480;
      object.rotation.y = 0.950;
      object.rotation.z = 0.070;
      object.castShadow = true;
      object.receiveShadow = true;
      object.name = "ir_model"; 
      object.traverse( function ( child ) {
        if(child.isMesh ) {
          child.castShadow = true;
          child.receiveShadow = true;
        }
      });
      scene.add( object );
    });
  
  }
  
  webglOverlayView.onContextRestored = (gl) => {        
    // create the three.js renderer, using the
    // maps's WebGL rendering context.
    renderer = new THREE.WebGLRenderer({
      canvas: gl.canvas,
      context: gl,
      ...gl.getContextAttributes(),
    });
    renderer.autoClear = false;
    renderer.shadowMap.enabled = true;
    renderer.shadowMap.type = THREE.PCFSoftShadowMap;
    renderer.receiveShadow = true;
    renderer.castShadow = true;
    
  }

  webglOverlayView.onDraw = (gl, coordinateTransformer) => {
    // update camera matrix to ensure the model is georeferenced correctly on the map     
    const matrix = coordinateTransformer.fromLatLngAltitude(mapOptions.center, 10);
    camera.projectionMatrix = new THREE.Matrix4().fromArray(matrix);
    webglOverlayView.requestRedraw();
    renderer.render(scene, camera);
    // always reset the GL state
    renderer.resetState();

  }
  webglOverlayView.setMap(map);

}

(async () => {        
  const map = await initMap();
  initWebglOverlayView(map);    
})();

```

 ![google_plane2](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/6/e/6e2a97f33b902e0f9b75ccd9813f299f3072391b.jpeg)  
 ![color_plane](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/5/d/5df53bb2638d9305027ed2390babf19e2cfc167d.jpeg)
