custom layer -制作一个围墙

2 篇文章 0 订阅
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>Add a custom style layer</title>
  <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
  <link href="https://api.mapbox.com/mapbox-gl-js/v2.9.2/mapbox-gl.css" rel="stylesheet">
  <script src="https://api.mapbox.com/mapbox-gl-js/v2.9.2/mapbox-gl.js"></script>
  <style>
    body {
      margin: 0;
      padding: 0;
    }

    #map {
      position: absolute;
      top: 0;
      bottom: 0;
      width: 100%;
    }
  </style>
</head>

<body>
  <div id="map"></div>
  <script>
    mapboxgl.accessToken = 'pk.eyJ1IjoiaWxvdmVneXgxMzE0IiwiYSI6ImNpb2h6emI0ODAwNnR2ZWt4bDFncGI3ZjYifQ.Pu9l94qL1MEDdDim2-s6RA';
    const map = new mapboxgl.Map({
      container: 'map',
      zoom: 3,
      center: [7.5, 58],
      style: 'mapbox://styles/mapbox/light-v10',
      antialias: true // create the gl context with MSAA antialiasing, so custom layers are antialiased
    });

    // create a custom style layer to implement the WebGL content
    const highlightLayer = {
      id: 'highlight',
      type: 'custom',

      // method called when the layer is added to the map
      // https://docs.mapbox.com/mapbox-gl-js/api/#styleimageinterface#onadd
      onAdd: function (map, gl) {
        // create GLSL source for vertex shader
        const vertexSource = `
          uniform mat4 u_matrix;
          attribute vec3 a_pos;
          attribute vec2 aTextureCoords;
          varying vec2 vTextureCoords;
          void main() {
          gl_Position = u_matrix * vec4(a_pos, 1.0);
          vTextureCoords=aTextureCoords;
        }`;

        // create GLSL source for fragment shader
        const fragmentSource = `
        precision highp float;
        varying vec2 vTextureCoords;
        uniform sampler2D uTexture;
        void main() {
          gl_FragColor = texture2D(uTexture,vTextureCoords);
        }`;

        // create a vertex shader
        const vertexShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vertexShader, vertexSource);
        gl.compileShader(vertexShader);

        console.log('vertexShader', gl.getShaderInfoLog(vertexShader));
        console.log('fragShader', gl.getShaderInfoLog(vertexShader));

        // create a fragment shader
        const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fragmentShader, fragmentSource);
        gl.compileShader(fragmentShader);



        // link the two shaders into a WebGL program
        this.program = gl.createProgram();
        gl.attachShader(this.program, vertexShader);
        gl.attachShader(this.program, fragmentShader);
        gl.linkProgram(this.program);
        console.log(gl.getProgramInfoLog(this.program));

        this.aPos = gl.getAttribLocation(this.program, 'a_pos');
        this.aTextureCoords = gl.getAttribLocation(this.program, 'aTextureCoords');

        this.u_TextureLocation = gl.getUniformLocation(this.program, 'uTexture')

        // define vertices of the triangle to be rendered in the custom style layer
        const helsinki = mapboxgl.MercatorCoordinate.fromLngLat({
          lng: 25.004,
          lat: 60.239
        }, 1000000);
        const berlin = mapboxgl.MercatorCoordinate.fromLngLat({
          lng: 13.403,
          lat: 52.562
        }, 1000000);
        const kyiv = mapboxgl.MercatorCoordinate.fromLngLat({
          lng: 30.498,
          lat: 50.541
        }, 1000000);

        const vertices = new Float32Array([
          helsinki.x, helsinki.y, 0, 0, 0,
          helsinki.x, helsinki.y, 0.02, 0, 1,
          berlin.x, berlin.y, 0, 1, 0,
          berlin.x, berlin.y, 0.02, 1, 1,
          berlin.x, berlin.y, 0, 0, 0,
          berlin.x, berlin.y, 0.02, 0, 1,
          kyiv.x, kyiv.y, 0, 1, 0,
          kyiv.x, kyiv.y, 0.02, 1, 1,
          kyiv.x, kyiv.y, 0, 0, 0,
          kyiv.x, kyiv.y, 0.02, 0, 1,
          helsinki.x, helsinki.y, 0, 1, 0,
          helsinki.x, helsinki.y, 0.02, 1, 1
        ])

        console.log(vertices)


        // create and initialize a WebGLBuffer to store vertex and color data
        this.buffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
        gl.bufferData(
          gl.ARRAY_BUFFER,
          vertices,
          gl.STATIC_DRAW
        );

        // const indices = new Uint16Array([0, 1, 2,
        //   2, 1, 3, 3, 2, 4, 4, 3, 5, 5, 4, 0, 0, 5, 1])

        const indices = new Uint16Array([0, 2, 1,
          1, 2, 3,
          4, 5, 6, 6, 5, 7,
          8, 9, 10, 10, 9, 11
        ])
        this.indexbuffer = gl.createBuffer();
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexbuffer);
        gl.bufferData(
          gl.ELEMENT_ARRAY_BUFFER,
          indices,
          gl.STATIC_DRAW
        );

        this.texture = this.createTexture(gl, './test2.png');


      },


      createTexture (gl, data) {
        const texture = gl.createTexture();
        texture.image = new Image();
        var me = texture;
        texture.image.onload = function () {
          gl.activeTexture(gl.TEXTURE0);
          gl.bindTexture(gl.TEXTURE_2D, me);
          gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);

          gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, me.image);

          gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
          gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
          gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
          gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);

          gl.generateMipmap(gl.TEXTURE_2D);
          gl.bindTexture(gl.TEXTURE_2D, null);

        }

        texture.image.src = data

        return texture;
      },
      // method fired on each animation frame
      // https://docs.mapbox.com/mapbox-gl-js/api/#map.event:render
      render: function (gl, matrix) {
        gl.useProgram(this.program);
        gl.uniformMatrix4fv(
          gl.getUniformLocation(this.program, 'u_matrix'),
          false,
          matrix
        );
        gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexbuffer);
        gl.enableVertexAttribArray(this.aPos);
        gl.vertexAttribPointer(this.aPos, 3, gl.FLOAT, false, (3 + 2) * 4, 0);
        gl.enableVertexAttribArray(this.aTextureCoords);
        gl.vertexAttribPointer(this.aTextureCoords, 2, gl.FLOAT, false, (3 + 2) * 4, 3 * 4);
        gl.enable(gl.BLEND);
        gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
        if (this.texture) {
          gl.activeTexture(gl.TEXTURE0);
          // gl.activeTexture(this.texture);
          gl.bindTexture(gl.TEXTURE_2D, this.texture);
          gl.uniform1i(this.u_TextureLocation, 0);
        }
        // gl.drawArrays(gl.TRIANGLE_STRIP, 0, 3);
        gl.drawElements(gl.TRIANGLES, 18, gl.UNSIGNED_SHORT, 0)
      }
    };

    // add the custom style layer to the map
    map.on('load', () => {
      map.addLayer(highlightLayer, 'building');
    });
  </script>

</body>

</html>

效果
在这里插入图片描述
遇到的问题记录一下
1.glsl里面没有 precision highp float;这一句,好像纹理坐标就出现问题,无法加载纹理,黑乎乎一片
2.图片必须是2的幂,否则也会错误
3.就是

        gl.enableVertexAttribArray(this.aPos);
        gl.vertexAttribPointer(this.aPos, 3, gl.FLOAT, false, (3 + 2) * 4, 0);
        gl.enableVertexAttribArray(this.aTextureCoords);
        gl.vertexAttribPointer(this.aTextureCoords, 2, gl.FLOAT, false, (3 + 2) * 4, 3 * 4);

这里面的stride,offset问题;我用的是float32array,确认为是8字节
在这里插入图片描述
4.glsl中错误可以用 这两个函数获取

console.log(gl.getProgramInfoLog(this.program))
console.log('fragShader', gl.getShaderInfoLog(vertexShader))

5.关于一般polygon生成我已经写了一个,但是很粗,美化一下再放上来;

const polygoncoords=[....]//
//使用 mapboxgl.MercatorCoordinate.fromLngLat转换一下成NDC坐标?【存疑】;

let len = coords.length-1;//最后一点重复
const vertices=new Float32Array(len*4*3);//len个侧面*4个顶点*5个分量(顶点3+纹理2);这里考虑纹理坐标,所以有重复的顶点
const indices= new UInt16Array(len*2*3);//len个面,一个矩形面两个三角*三角三个索引

const vertexOffset=0;

for(let i = 0 ;i<len;i++){
	vertices[vertexOffset]=coords[i].x;
	vertices[vertexOffset+1]=coords[i].y;
	vertices[vertexOffset+2]=0;
	vertices[vertexOffset+3]=0;
	vertices[vertexOffset+4]=0;
	
	vertices[vertexOffset+5]=coords[i].x;
	vertices[vertexOffset+6]=coords[i].y;
	vertices[vertexOffset+7]=0.0003;
	vertices[vertexOffset+8]=0;
	vertices[vertexOffset+9]=1;

	vertices[vertexOffset+10]=coords[i].x;
	vertices[vertexOffset+11]=coords[i].y;
	vertices[vertexOffset+12]=0.0;
	vertices[vertexOffset+13]=1;
	vertices[vertexOffset+14]=0;

	vertices[vertexOffset+15]=coords[i].x;
	vertices[vertexOffset+16]=coords[i].y;
	vertices[vertexOffset+17]=0.0003;
	vertices[vertexOffset+18]=1;
	vertices[vertexOffset+19]=1;
	
	vertexOffset+=20;
}

let indexOffset=0;
//[2i,2i+1,2i+2,2i+3]
for(let i= 0;i<len;i++){
	indices[indexOffset]=2*(i+1);
	indices[indexOffset]=2*i+1;
	indices[indexOffset]=2*i;

	indices[indexOffset]=2*(i+1);
	indices[indexOffset]=2*i+1;
	indices[indexOffset]=2*(i+1)+1;
}









  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值