【问题标题】:WebGL Overlay Google map: How to cast Shadows?WebGL Overlay 谷歌地图:如何投射阴影?
【发布时间】:2021-12-21 22:11:05
【问题描述】:

如何制作使用 WebGL 叠加 API 加载到地图中的 3d 对象,以便在地图图块和其他加载的对象上投射阴影?

在我看来,这还不支持(或此功能已被删除)所以有什么解决方法吗?

首选 WebGL 框架:ThreeJs

【问题讨论】:

  • 有人回答了这个问题吗?

标签: google-maps google-maps-api-3 three.js webgl webgloverlayview


【解决方案1】:

使用threeJS 的一种解决方法是在完全透明但接收阴影的地面上放置一个薄盒子(它不适用于planeGeometry)。这可以通过shadowMaterial实现

注意:这只会显示添加到 webgoverlay 的网格的阴影,而不是地图上建筑物的阴影

【讨论】:

    【解决方案2】:

    我们在谷歌地图上还没有这个选项,因为我们从“webgloverlayview”获得的地图覆盖没有接收阴影选项。

    我尝试在谷歌地图上创建自己的飞机并实现阴影 我的平面不透明度很轻,像 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);    
        })();
    

    在@yosan_melese 代码之后

    【讨论】:

    • 尝试使用阴影材质
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-20
    • 2012-11-29
    • 1970-01-01
    • 2016-06-21
    相关资源
    最近更新 更多