两层不同的点形状

问题描述 投票:1回答:1

我在地图上绘制webgl点,目前工作正常。现在我想在地图上再加一层。我正试图找出最好的方法来实现这个目标。因为我的代码是这样写的,我给gl绘制函数发送了一个长数组,格式如下。

[lat, lng, r, g, b, a, id, lat, lng, r, g, b, a, id, etc...] //where id is used for selecting the marker.

这些点是用以下格式绘制的

this.delegate.gl.drawArrays(this.delegate.gl.POINTS, 0, numPoints);

当添加额外的图层时,我希望一个图层显示为圆形,另一个图层显示为方形。我的想法是在数组中添加另一个元素,该元素的代码是绘制圆形还是方形,即0或1,所以现在数组的步长是8。

[lat, lng, r, g, b, a, id, code, lat, lng, r, g, b, a, id, code etc...]

着色器代码就会决定是画圆还是画方块。这可能吗?我不知道如何将形状代码属性传递给着色器来决定绘制哪种形状.下面是着色器代码,目前有两个片段着色器程序。一个画圆,一个画方块。

 <script id="vshader" type="x-shader/x-vertex">
      uniform mat4 u_matrix;
      attribute vec4 a_vertex;
      attribute float a_pointSize;
      attribute vec4 a_color;
      varying vec4 v_color;

      void main() {
        gl_PointSize =  a_pointSize;
        gl_Position = u_matrix * a_vertex;
        v_color = a_color;
      }
    </script>

    <script id="fshader" type="x-shader/x-fragment">
      precision mediump float;
      varying vec4 v_color;

      void main() {
        float border = 0.05;
        float radius = 0.5;

        vec2 m = gl_PointCoord.xy - vec2(0.5, 0.5);
        float dist = radius - sqrt(m.x * m.x + m.y * m.y);

        float t = 0.0;
        if (dist > border)
        t = 1.0;
        else if (dist > 0.0)
        t = dist / border;
        gl_FragColor = mix(vec4(0), v_color, t);

      }
    </script>
      <script id="fshader-square" type="x-shader/x-fragment">
        precision mediump float;
        varying vec4 v_color;
        void main() {
          gl_FragColor = v_color;  
        }

    </script>

我的属性指针是这样设置的。

this.gl.vertexAttribPointer(vertLoc, 2, this.gl.FLOAT, false, fsize*7, 0); 我的属性指针是这样设置的: /vertex

this.gl.vertexAttribPointer(colorLoc, 4, this.gl.FLOAT, true, fsize*7, fsize*2); /肤色

javascript glsl webgl
1个回答
1
投票

绘制不同形状的点最常用的方法是使用纹理,这样你的设计师可以使 记号笔 等。

不画也是常见的 POINTS 但却要画出四边形,由 TRIANGLES. 谷歌地图和Mapbox都没有使用 POINTS (你可以 验证自己)

POINTS 有两个问题

  1. 规范说,你可以画一个POINT的最大尺寸是取决于实现的,可以只是1像素。

  2. 当点的中心点离开屏幕时,点是否会立即消失取决于实现(这不是规范的一部分,但不幸的是这是事实

  3. POINTS只能是对齐的正方形。

    如果你想画的形状又高又细,你需要浪费一堆纹理空间,并且或过多地画一个足够大的正方形来容纳你想画的高细矩形。同样如果你想旋转图像,用三角形比用点来做要容易得多。

至于实现方式那就全靠你了。一些随机的想法

  • 使用 POINTS,增加一个 imageId 每点。使用 imageIdgl_PointCoord 从纹理图谱中选择图像

    假设所有的图像都是相同大小

    uniform vec2 textureAtlasSize;  // eg 64x32
    uniform vec2 imageSize;         // eg 16x16
    
    float imagesAcross = floor(textureAtlasSize.x / imageSize.x);
    vec2 imageCoord = vec2(mod(imageId, imagesAcross), floor(imageId / imagesAcross));
    vec2 uv = (imageCoord + imageSize * gl_PointCoord) / textureAtlasSize;
    
    gl_FragColor = texture2D(textureAtlas, uv);
    

注意,如果你将imageIds设为vec2而不是float,并将id作为imageCoord传入,那么你就不需要在shader中使用imageCoord数学。

  • 在着色器中使用 POINTS纹理图谱,以及每个点的vec2偏移量,vec2范围。

    现在,图像的大小不需要相同,但你需要为每个点设置适当的偏移和范围。

    gl_FragColor = texture2D(textureAtlas, offset + range * gl_PointCoord);
    
  • 使用 TRIANGLES实例图

    这其实和上面没有什么不同,只是你创建了一个单一的2个三角形四边形,然后使用 drawArrayInstanceddrawElementsInstanced. 您需要将引用改为 gl_PointCoord 用你自己的纹理坐标,你需要计算顶点着色器中的点。

    attribute vec2 reusedPosition;  // the 6 points (1, -1)
    
    ... all the attributes you had before ...
    
    uniform vec2 outputResolution;  // gl.canvas.width, gl.canvas.height
    
    varying vec2 ourPointCoord;
    
    void main() {
       ... -- insert code that you had before above this line -- ...
    
       // now take gl_Position and convert to point
       float ourPointSize = ???
       gl_Position.xy += reusedPosition * ourPointSize / outputResolution * gl_Position.w;
    
       ourPointCoord = reusedPosition * 0.5 + 0.5;
    
  • 使用 TRIANGLES 与合并的几何体。

    这只是意味着每个点需要4个(如果有索引)或6个顶点,而不是一个顶点。

  • 使用 TRIANGLES 只有一个id,把数据放在textures中。

    如果更新4到6个顶点来移动一个点太费劲了(提示:可能不是)。那么你可以把数据放在纹理中,根据一个id来查找每个点的数据。所以你把每个点的4个id加上一些顶点id放在某个缓冲区(即id0,0,0,0,1,1,1,1,2,2,2,3,3,3,3,4,4,4,顶点id0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3),然后你就可以用这些来计算四边形坐标、纹理坐标和vs,在纹理中查找每个点的数据。优点是,如果你想移动一个点,你只需要更新每个点的一个值,而不是每个点的4到6个值。

注意:以上所有的情况都是假设你想在一次绘制调用中绘制1000个点。如果你要画250个或更少的点,甚至是1000-2000个点,用正常的方式在每个绘图调用中画一个点也许就可以了。 例如

for each point
  setup uniforms
  gl.drawXXX

不是积分,只是举例说明 WebGL水族馆 正在使用该循环。它没有以任何方式使用实例化或合并几何体。下面是另一个例子 只不过是每一次抽签都要抽一次

© www.soinside.com 2019 - 2024. All rights reserved.