Наложение WebGL на карту Google: Как отбрасывать тени?

#google-maps #google-maps-api-3 #three.js #webgl #webgloverlayview

Вопрос:

Как я могу сделать так, чтобы 3D-объекты, которые я загружаю на карту, используя WebGL overlay API, отбрасывали тени на плитки карты и на другие загруженные объекты?

Мне кажется, что это еще не поддерживается (или эта функция удалена), так есть ли какое-либо обходное решение?

Предпочитаемый фреймворк WebGL: ThreeJS

Комментарии:

1. Кто-нибудь получил ответ на этот вопрос?

Ответ №1:

Обходным решением с помощью ThreeJS было бы поместить на землю тонкую рамку (с которой она не будет работать planeGeometry ), которая полностью прозрачна, но получает тень. это может быть достигнуто с помощью shadowMaterial

Примечание: при этом будут отображаться только тени от сеток, добавленных в webgloverlay, а не от зданий на карте

Ответ №2:

У нас пока нет этой опции на карте Google, потому что наложение карты, которую мы получаем из «webgloverlayview», не имеет опции получения тени.

Я попытался создать свою собственную плоскость поверх карты Google и добиться непрозрачности тени, непрозрачность моей плоскости очень легкая, как 0,3. Я также добавил изображение ниже в цветной плоскости, чтобы объяснить.

Пожалуйста, обратитесь к @yosan_melese, ответьте префекту, чтобы использовать ShadowMaterial

вот пример кода

     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);
 */

//after yosan_melese answer i am using ShadowMaterial 

const geometry = new THREE.PlaneGeometry( 2000, 2000 );
geometry.rotateX( - Math.PI / 2 );

const material = new THREE.ShadowMaterial();
material.opacity = 0.5;

const plane = new THREE.Mesh( geometry, material );
plane.rotation.x = 2;
plane.position.x = 0;
plane.position.y = 0;
plane.position.z = 0;
plane.receiveShadow = true;
scene.add( plane );   
    
        loader = new FBXLoader();
        loader.load( 'model/name_model.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 = "name_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);    
    })();
 

непрозрачность 0,3 плоскости над слоем карты Google

например, с помощью цветной плоскости

после кода @yosan_melese
введите описание изображения здесь

Комментарии:

1. попробуйте использовать shadowmaterial