มุมมองการวางซ้อนของ WebGL

ดูตัวอย่าง

ด้วยมุมมองการวางซ้อน WebGL คุณสามารถเพิ่มเนื้อหาลงในแผนที่โดยใช้ WebGL โดยตรง หรือไลบรารีกราฟิกยอดนิยมอย่าง Three.js มุมมองการวางซ้อน WebGL ให้การเข้าถึง บริบทการแสดงผล WebGL เดียวกันที่ Google Maps Platform ใช้ในการแสดงผลแผนที่ฐานเวกเตอร์โดยตรง การใช้บริบทการแสดงผลร่วมกันนี้มีข้อดี เช่น การบดบังแบบเจาะลึกด้วยเรขาคณิตของสิ่งปลูกสร้าง 3 มิติ และความสามารถในการซิงค์เนื้อหา 2 มิติ/3 มิติกับการแสดงผลแผนที่ฐาน วัตถุที่แสดงผลด้วยมุมมองการวางซ้อน WebGL ยังสามารถเชื่อมโยงกับพิกัดละติจูด/ลองจิจูดเพื่อให้วัตถุเคลื่อนที่เมื่อคุณลาก ซูม เลื่อน หรือเอียงแผนที่

ข้อกำหนด

หากต้องการใช้มุมมองการวางซ้อน WebGL คุณต้องโหลดแผนที่โดยใช้รหัสแผนที่ที่เปิดใช้แผนที่เวกเตอร์ เราขอแนะนำให้เปิดใช้การเอียงและหมุนเมื่อคุณสร้างรหัสแผนที่เพื่อให้ควบคุมกล้อง 3 มิติได้อย่างเต็มที่ ดูรายละเอียดในภาพรวม

เพิ่มมุมมองการวางซ้อน WebGL

หากต้องการเพิ่มการวางซ้อนลงในแผนที่ ให้ใช้ google.maps.WebGLOverlayView จากนั้น ส่งต่ออินสแตนซ์ของแผนที่โดยใช้ setMap:

// Create a map instance.
const map = new google.maps.Map(mapDiv, mapOptions);

// Create a WebGL Overlay View instance.
const webglOverlayView = new google.maps.WebGLOverlayView();

// Add the overlay to the map.
webglOverlayView.setMap(map);

ขอเกี่ยวอายุการใช้งาน

มุมมองการวางซ้อน WebGL เป็นชุดฮุกที่มีการเรียกใช้หลายครั้งในวงจรการแสดงผล WebGL ของแผนที่ฐานเวกเตอร์ ฮุกวงจรเหล่านี้เป็นที่ที่คุณจะตั้งค่า วาด และแยกทุกอย่างที่คุณต้องการให้แสดงในการวางซ้อน

  • ระบบจะเรียกใช้ onAdd() เมื่อมีการสร้างการวางซ้อน ใช้รายงานนี้เพื่อดึงหรือสร้างโครงสร้างข้อมูลขั้นกลางก่อนวาดการวางซ้อนซึ่งไม่ต้องอาศัยการเข้าถึงบริบทการแสดงผล WebGL ในทันที
  • ระบบจะเรียกใช้ onContextRestored({gl}) เมื่อบริบทการแสดงผลพร้อมใช้งาน ใช้เครื่องมือนี้เพื่อเริ่มต้นหรือเชื่อมโยงสถานะ WebGL เช่น ตัวปรับแสงเงา ออบเจ็กต์บัฟเฟอร์ GL และอื่นๆ onContextRestored() ใช้อินสแตนซ์ WebGLStateOptions ซึ่งมีช่องเดียว
    • gl เป็นแฮนเดิลของ WebGLRenderingContext ที่แผนที่ฐานใช้
  • onDraw({gl, transformer}) แสดงผลฉากบนแผนที่ฐาน พารามิเตอร์ของ onDraw() คือออบเจ็กต์ WebGLDrawOptions ซึ่งมี 2 ช่องดังนี้
    • gl เป็นแฮนเดิลของ WebGLRenderingContext ที่แผนที่ฐานใช้
    • transformer มีฟังก์ชันตัวช่วยเพื่อเปลี่ยนจากพิกัดของแผนที่เป็นเมทริกซ์การฉายภาพในมุมมองโมเดล ซึ่งสามารถใช้เพื่อแปลพิกัดแผนที่ไปยังอวกาศในโลก พื้นที่กล้อง และพื้นที่หน้าจอ
  • ระบบจะเรียกใช้ onContextLost() เมื่อบริบทการแสดงผลหายไปไม่ว่าด้วยเหตุผลใดก็ตามและเป็นจุดที่คุณควรล้างสถานะ GL ที่มีอยู่ก่อนแล้ว เนื่องจากไม่จำเป็นต้องใช้อีกต่อไป
  • onStateUpdate({gl}) อัปเดตสถานะ GL นอกลูปการแสดงผลและจะมีการเรียกใช้เมื่อมีการเรียกใช้ requestStateUpdate โดยใช้อินสแตนซ์ WebGLStateOptions ซึ่งมีช่องเดียว
    • gl เป็นแฮนเดิลของ WebGLRenderingContext ที่แผนที่ฐานใช้
  • ระบบจะเรียกใช้ onRemove() เมื่อมีการนำการวางซ้อนออกจากแผนที่โดยใช้ WebGLOverlayView.setMap(null) และเป็นตำแหน่งที่คุณควรนำวัตถุระดับกลางทั้งหมดออก

ตัวอย่างต่อไปนี้เป็นการใช้งานพื้นฐานของฮุกตลอดอายุการใช้งานทั้งหมด

const webglOverlayView = new google.maps.WebGLOverlayView();

webglOverlayView.onAdd = () => {
  // Do setup that does not require access to rendering context.
}

webglOverlayView.onContextRestored = ({gl}) => {
  // Do setup that requires access to rendering context before onDraw call.
}

webglOverlayView.onStateUpdate = ({gl}) => {
  // Do GL state setup or updates outside of the render loop.
}

webglOverlayView.onDraw = ({gl, transformer}) => {
  // Render objects.
}

webglOverlayView.onContextLost = () => {
  // Clean up pre-existing GL state.
}

webglOverlayView.onRemove = () => {
  // Remove all intermediate objects.
}

webglOverlayView.setMap(map);

กำลังรีเซ็ตสถานะ GL

มุมมองการแสดงข้อมูล WebGL จะแสดงบริบทภาพของ WebGL ของแผนที่ฐาน ด้วยเหตุนี้ คุณจึงต้องรีเซ็ตสถานะ GL เป็นสถานะเดิมเมื่อแสดงผลออบเจ็กต์เสร็จแล้ว การรีเซ็ตสถานะ GL ไม่สำเร็จมีแนวโน้มที่จะส่งผลให้เกิดความขัดแย้งในสถานะ GL ซึ่งจะทำให้การแสดงผลทั้งแผนที่และออบเจ็กต์ที่คุณระบุล้มเหลว

โดยปกติการรีเซ็ตสถานะ GL จะทำในฮุก onDraw() ตัวอย่างเช่น Three.js มีฟังก์ชันตัวช่วยที่ล้างการเปลี่ยนแปลงสถานะ GL ดังนี้

webglOverlayView.onDraw = ({gl, transformer}) => {
  // Specify an object to render.
  renderer.render(scene, camera);
  renderer.resetState();
}

หากแผนที่หรือวัตถุของคุณแสดงผลไม่สำเร็จ อาจเป็นไปได้ว่าไม่ได้รีเซ็ตสถานะ GL

ประสานการแปลง

ตำแหน่งของวัตถุบนแผนที่เวกเตอร์จะระบุโดยการผสมระหว่างพิกัดละติจูดและลองจิจูด ตลอดจนระดับความสูง แต่กราฟิก 3 มิติ จะระบุอยู่ในพื้นที่โลก พื้นที่กล้อง หรือพื้นที่หน้าจอ เพื่อให้เปลี่ยนพิกัดแผนที่เป็นพื้นที่ที่ใช้กันโดยทั่วไปเหล่านี้ได้ง่ายขึ้น มุมมองการวางซ้อน WebGL มีฟังก์ชันตัวช่วย coordinateTransformer.fromLatLngAltitude(latLngAltitude, rotationArr, scalarArr) ในฮุก onDraw() โดยใช้ค่าต่อไปนี้และแสดงผล Float64Array

  • latLngAltitude: พิกัดละติจูด/ลองจิจูด/ระดับความสูง เป็น LatLngAltitude หรือ LatLngAltitudeLiteral
  • rotationArr: Float32Array ของมุมการหมุนในออยเลอร์ที่ระบุเป็นองศา
  • scalarArr: Float32Array ของสเกลาร์ที่จะใช้กับแกนคาร์ดินัล

ตัวอย่างต่อไปนี้ใช้ fromLatLngAltitude() เพื่อสร้างเมทริกซ์การฉายภาพของกล้องใน Three.js

const camera = new THREE.PerspectiveCamera();
const matrix = coordinateTransformer.fromLatLngAltitude({
    lat: mapOptions.center.lat,
    lng: mapOptions.center.lng,
    altitude: 120,
});
camera.projectionMatrix = new THREE.Matrix4().fromArray(matrix);

ตัวอย่าง

ต่อไปนี้เป็นตัวอย่างง่ายๆ ของการใช้ Three.js ซึ่งเป็นไลบรารีโอเพนซอร์สยอดนิยมของ WebGL เพื่อวางวัตถุ 3 มิติบนแผนที่ หากต้องการคำแนะนำแบบทีละขั้นเกี่ยวกับการใช้มุมมองการวางซ้อน WebGL เพื่อสร้างตัวอย่างที่คุณเห็นอยู่ที่ด้านบนของหน้านี้ ให้ลองใช้โค้ดห้องทดลองการสร้างประสบการณ์แผนที่แบบเร่งความเร็ว WebGL

const webglOverlayView = new google.maps.WebGLOverlayView();
let scene, renderer, camera, loader;

webglOverlayView.onAdd = () => {
  // Set up the Three.js scene.
  scene = new THREE.Scene();
  camera = new THREE.PerspectiveCamera();
  const ambientLight = new THREE.AmbientLight( 0xffffff, 0.75 ); // Soft white light.
  scene.add(ambientLight);

  // Load the 3D model with GLTF Loader from Three.js.
  loader = new GLTFLoader();
  loader.load("pin.gltf");
}

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;
}

webglOverlayView.onDraw = ({gl, transformer}) => {
  // Update camera matrix to ensure the model is georeferenced correctly on the map.
  const matrix = transformer.fromLatLngAltitude({
      lat: mapOptions.center.lat,
      lng: mapOptions.center.lng,
      altitude: 120,
  });
camera.projectionMatrix = new THREE.Matrix4().fromArray(matrix);

  // Request a redraw and render the scene.
  webglOverlayView.requestRedraw();
  renderer.render(scene, camera);

  // Always reset the GL state.
  renderer.resetState();
}

// Add the overlay to the map.
webglOverlayView.setMap(map);