תצוגת שכבת-על WebGL

הצגת דוגמה

בעזרת תצוגת שכבת-העל של WebGL, תוכל להוסיף תוכן למפות שלך ישירות באמצעות WebGL, או באמצעות ספריות גרפיקה פופולריות כמו Three.js. תצוגת שכבת-על של WebGL מספקת גישה ישירה לאותו הקשר לעיבוד WebGL שבו משתמשת הפלטפורמה של מפות Google כדי לעבד את המפה הבסיסית הווקטורית. השימוש בהקשר משותף של רינדור מספק יתרונות כמו הסתרה בעומק באמצעות גיאומטריה של בניינים בתלת ממד, והאפשרות לסנכרן תוכן דו-ממדי/תלת-ממדי עם עיבוד המפה הבסיסית. אובייקטים שמעובדים באמצעות תצוגת שכבת-העל WebGL יכולים להיות מקושרים גם לקואורדינטות של קווי אורך ורוחב, כך שהם נעים כשאתם גוררים, משנים את מרחק התצוגה, מזיזים את המפה או מטים אותה.

דרישות

על מנת להשתמש בתצוגת שכבת-על של WebGL, עליך לטעון את המפה באמצעות מזהה מפה שבו מופעלת מפת וקטור. אנו ממליצים מאוד להפעיל הטיה וסיבוב כאשר יוצרים את מזהה המפה, כדי לאפשר שליטה מלאה במצלמה בתלת ממד. פרטים נוספים זמינים בסקירה הכללית.

הוספת תצוגה של שכבת-על 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);

קטעי הוק (hooks) במחזור החיים

תצוגת שכבת-העל של WebGL מספקת קבוצה של קטעי הוק (hooks) שמופעלים בזמנים שונים במחזור החיים של הקשר הרינדור WebGL של המפה הבסיסית של הווקטור. קטעי ה-hook האלה במחזור החיים הם המקום שבו אתם מגדירים, משרטטים ומסירים כל דבר שרוצים לעבד בשכבת-העל.

  • מתבצעת קריאה ל-onAdd() במהלך היצירה של שכבת-העל. תוכלו להשתמש בו כדי לאחזר או ליצור מבני נתונים מתווכים לפני ציור שכבת-העל, שלא מחייבים גישה מיידית להקשר של עיבוד WebGL.
  • מתבצעת קריאה לפונקציה onContextRestored({gl}) ברגע שהקשר הרינדור זמין. אפשר להשתמש בו כדי לאתחל או לקשר כל מצב של WebGL, כמו תוכנות הצללה (shader), אובייקטים של מאגר נתונים ב-GL וכו'. onContextRestored() לוקחת מופע WebGLStateOptions, שיש לו שדה אחד:
    • gl הוא כינוי ל-WebGLRenderingContext שמשמש את המפה הבסיסית.
  • onDraw({gl, transformer}) מעבד את הסצנה במפה הבסיסית. הפרמטרים של onDraw() הם אובייקט WebGLDrawOptions, שיש בו שני שדות:
    • gl הוא כינוי ל-WebGLRenderingContext שמשמש את המפה הבסיסית.
    • transformer מספק פונקציות מסייעות להפוך מקואורדינטות של מפה למטריצת היטל-צפייה-מודל, ואפשר להשתמש בהן כדי לתרגם קואורדינטות של מפה למרחב בעולם, לשטח המצלמה ולחלל המסך.
  • הקריאה onContextLost() נקראת כאשר הקשר העיבוד אבד מסיבה כלשהי, וזהו המקום שבו צריך לנקות את כל מצבי ה-GL שכבר קיימים, כי אין יותר צורך בו.
  • onStateUpdate({gl}) מעדכן את מצב ה-GL מחוץ ללולאת העיבוד, והוא מופעל כשהקריאה ל-requestStateUpdate מתבצעת. הפונקציה לוקחת מופע WebGLStateOptions עם שדה אחד:
    • gl הוא כינוי ל-WebGLRenderingContext שמשמש את המפה הבסיסית.
  • קריאה ל-onRemove() מתבצעת כשמסירים את שכבת-העל מהמפה עם WebGLOverlayView.setMap(null), וזהו המקום שבו צריך להסיר את כל האובייקטים האמצעיים.

לדוגמה, זו דוגמה בסיסית של כל קטעי ה-hook של מחזור החיים:

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 מטופל בדרך כלל ב-hook של onDraw(). לדוגמה, Three.js מספק פונקציית עזר שמנקה את כל השינויים במצב ה-GL:

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

אם המפה או האובייקטים לא מוצגים, סביר מאוד להניח שמצב ה-GL לא אופס.

תיאום טרנספורמציות

המיקום של אובייקט במפה הווקטורית נקבע על ידי שילוב של קואורדינטות של קווי אורך ורוחב, וגם גובה. עם זאת, הגרפיקה התלת-ממדית מוגדרת במרחב העולמי, בשטח המצלמה או בשטח המסך. כדי להקל על שינוי קואורדינטות של מפה למרחבים שנמצאים בשימוש נפוץ יותר, תצוגת שכבת-העל של WebGL מספקת את הפונקציה המסייעת coordinateTransformer.fromLatLngAltitude(latLngAltitude, rotationArr, scalarArr) ב-hook של 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 פופולרית בקוד פתוח, כדי למקם אובייקט תלת-ממדי במפה. לקבלת הדרכה מפורטת בנושא השימוש בתצוגת שכבת-על של WebGL כדי ליצור את הדוגמה שמופיעה בחלק העליון של הדף הזה, נסו את Building WebGL-Accelerated Map Experiences codelab.

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