一、结果
二、代码
根据瓦片行列号计算单个瓦片范围
/**
* 根据行列号计算瓦片
* @param {*} x
* @param {*} y
* @param {*} zoom
*/
export function computeBound(x, y, zoom) {
//根据级别计算当前有多少瓦片
const xNumber = Math.pow(2, zoom)
const yNumber = Math.pow(2, zoom - 1)
//计算每个瓦片经纬度宽度
const xWidth = 360 / xNumber
const yWidth = 180 / yNumber
const minLng = tile2lng(x, zoom)
const maxLng = tile2lng(x + 1, zoom)
const minLat = tile2lat(y, 4)
const maxLat = tile2lat(y + 1, 4)
return {
minLng,
maxLng,
minLat,
maxLat
}
}
// 墨卡托下瓦片编号转经纬度
function tile2lng(x, z) {
return (x / Math.pow(2, z) * 360 - 180);
}
function tile2lat(y, z) {
var n = Math.PI - 2 * Math.PI * y / Math.pow(2, z);
return (180 / Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))));
}
构建mesh
import { BufferGeometry } from './BufferGeometry.js'
import { computeBound } from '../core/Math.js'
import { Cartesian3 } from '../core/Math.js'
export default class TileGeometry extends BufferGeometry {
constructor({
x,
y,
zoom,
}) {
super()
this._bound = computeBound(x, y, zoom)
console.log(this._bound)
this.initGeometry()
}
initGeometry() {
//划分为16*16的 格子
//计算每个格子宽度
const rangeLng = (this._bound.maxLng - this._bound.minLng) / 16
const rangeLat = (this._bound.maxLat - this._bound.minLat) / 16
const rangeUV = 1.0 / 16
const positions = []
const uvs = []
const indexes = []
for (let i = 0; i < 17; i++) {
const lat = this._bound.maxLat - rangeLat * i
const v = 1 - rangeUV * i
//行数
for (let j = 0; j < 17; j++) {
const lng = this._bound.minLng + rangeLng * j
const position = Cartesian3.fromDegrees(lng, lat, 0.001)
positions.push(position.x, position.y, position.z)
const u = rangeUV * j
uvs.push(u, v)
if (i < 16 && j < 16) {
const current = i * 17 + j
indexes.push(current, current + 17, current + 1)
indexes.push(current + 1, current + 17, current + 18)
}
}
}
console.log(positions, uvs, indexes)
super.create({ positions, indexes, uvs }, gl.TRIANGLES)
}
}
调用代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>绘制线</title>
<style>
body {
margin: 0px;
padding: 0px;
text-align: center;
}
#canvas {
margin: 0;
position: absolute;
width: 100%;
height: 100%;
left: 0px;
top: 0px;
}
</style>
<script src="/lib/webgl-utils.js"></script>
<script src="/lib/webgl-debug.js"></script>
<script src="/lib/cuon-utils.js"></script>
<script src="/lib/cuon-matrix.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.3.4/axios.js"></script>
</head>
<body>
<canvas id="canvas"></canvas>
</body>
<script type="module">
import { SphereGeometry } from "/geometry/SphereGeometry.js"
import { Texture2D } from './texture/Texture2D.js'
import { Program } from './core/Program.js'
import { toRadian, Cartesian3 } from './core/Math.js'
import { Material } from './material/Material.js'
import { Control } from './core/Control.js'
import { Object3D } from './core/Object3D.js'
import { Scene } from './core/Scene.js'
import { Camera } from './core/Camera.js'
import { Renderer } from './core/Renderer.js'
import { earthVS, earthFS } from './material/shaders/Earth.js'
import TileGeometry from './geometry/TileGeometry.js'
const VS =/*glsl*/`
attribute vec3 a_Position;
attribute vec2 a_Uv;
uniform mat4 u_ModelMatrix;
uniform mat4 u_ViewMatrix;
uniform mat4 u_ProjectMatrix;
varying vec2 v_Uv;
void main(){
mat4 mvpMatrix=u_ProjectMatrix*u_ViewMatrix*u_ModelMatrix;
v_Uv=a_Uv;
gl_Position=mvpMatrix*vec4(a_Position,1.0);
}
`
const FS = /*glsl*/`
#ifdef GL_ES
precision mediump float;
#endif
uniform sampler2D u_Texture;
varying vec2 v_Uv;
void main(){
vec4 baseColor=texture2D(u_Texture,v_Uv);
gl_FragColor=baseColor;
}`;
//声明js需要的相关变量
var canvas = document.getElementById("canvas");
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
window.gl = getWebGLContext(canvas);
const scene = new Scene()
const camera = new Camera(30, canvas.width / canvas.height, 0.1, 10)
// var projMatrix = camera.projectMatrix
//设置视角矩阵的相关信息(视点,视线,上方向)
var viewMatrix = camera.viewMatrix
const renderer = new Renderer()
main()
async function main() {
if (!gl) {
console.log("你的浏览器不支持WebGL");
return;
}
const earthProgram = new Program(earthVS, earthFS)
//绘制球形
const sphereGeometry = new SphereGeometry(gl, 1, 180, 90)
//绘制纹理
const texture = Texture2D.initTexture('./image/earth.jpg', 0)
const sphereMaterial = new Material({
program: earthProgram,
uniforms: {
texture: texture,
normalTexture: null,
test: 1.0
},
})
const earth = new Object3D(sphereGeometry, sphereMaterial)
scene.add(earth)
const program = new Program(VS, FS)
for (let i = 11; i <= 14; i++) {
for (let j = 7; j <= 8; j++) {
const tileGeomtry = new TileGeometry({
x: i,
y: j,
zoom: 4
})
//绘制纹理
const texture1 = Texture2D.initTexture(`./image/tiles/4-${j}-${i}.jpg`, 0)
const tileMaterial = new Material({
program: program,
uniforms: {
texture: texture1,
},
})
const tile = new Object3D(tileGeomtry, tileMaterial)
scene.add(tile)
}
}
const control = new Control(viewMatrix, canvas)
var tick = function () {
//设置底色
gl.clearColor(0.0, 0.0, 0.0, 1.0);
control.update()
renderer.render(scene, camera)
requestAnimationFrame(tick)
}
tick()
// Control.registerMouseEvent(canvas)
}
</script>
</html>