Skip to content

WebGL Renderer: Misalignment When 'stroke-pattern-spacing' Values are Multiples #16396

Open
@nssang00

Description

@nssang00

Describe the bug
A clear and concise description of what the bug is.

I previously requested a 'stroke-pattern-start-offset' option in webgl.
#15944

There is also an issue with the WebGL renderer in OpenLayers when using stroke-pattern-spacing in LiteralStyle.
Specifically, when two different spacing values ​​for 'stroke-pattern-spacing' (e.g. 40 and 80) are applied to the same style, the alignment between patterns becomes inconsistent.
This causes rendering errors for stroke patterns.

class WebGLVectorTileLayer extends VectorTile {
  createRenderer() {
    return new WebGLVectorTileLayerRenderer(this, {
      className: this.getClassName(),
      style:  [{
        'stroke-pattern-src': 'bar.png',
        'stroke-width': 5,
        'stroke-offset': 0,
        'stroke-pattern-start-offset':20,
        'stroke-pattern-spacing': 40,
      },
      {
        'stroke-pattern-src': 'circle1.png',
        'stroke-width': 5,
        'stroke-offset': 0,
        'stroke-pattern-start-offset':17, 
        'stroke-pattern-spacing': 80,
      },
      {
        'stroke-pattern-src': 'circle2.png',
        'stroke-width': 5,
        'stroke-offset': 0,
        'stroke-pattern-start-offset':23,
        'stroke-pattern-spacing': 80,
      }],
    });
  }
}

image

The style with an interval of 40 should match the style with an interval of 80 for the second time, but an error occurs.
So I checked that the style with an interval of 40 matches the interval of 80 for the second time when I changed it to 37.5.
This is the result when the image width is 5, and if the width of the image changes, the interval will have an error again.
So at first, I tried to compensate for the error value, but then I changed it to calculate the interval regardless of the image size.

    let startOffsetExpression = '0.';
    if ('stroke-pattern-start-offset' in style) {
      startOffsetExpression = expressionToGlsl(
        fragContext,
        style['stroke-pattern-start-offset'],
        NumberType,
      );
    }
    fragContext.functions['sampleStrokePattern'] =
    `vec4 sampleStrokePattern(sampler2D texture, vec2 textureSize, vec2 textureOffset, vec2 sampleSize, float spacingPx, float startOffsetPx, float currentLengthPx, float currentRadiusRatio, float lineWidth) {
  float currentLengthScaled = currentLengthPx * sampleSize.y / lineWidth;
  float spacingScaled = spacingPx * sampleSize.y / lineWidth;
  float uCoordPx = mod(currentLengthScaled + startOffsetPx, spacingScaled);
  // make sure that we're not sampling too close to the borders to avoid interpolation with outside pixels
  uCoordPx = clamp(uCoordPx, 0.5, sampleSize.x - 0.5);
  if (uCoordPx > sampleSize.x - 1.0) {
    return vec4(0.0);
  }  
  float vCoordPx = (0.5 - currentRadiusRatio * 0.5) * sampleSize.y;
  vec2 texCoord = (vec2(uCoordPx, vCoordPx) + textureOffset) / textureSize;
  return samplePremultiplied(texture, texCoord);
}`;
    const textureName = `u_texture${textureId}`;
    let tintExpression = '1.';
    if ('stroke-color' in style) {
      tintExpression = builder.getStrokeColorExpression();
    }
    builder.setStrokeColorExpression(
      `${tintExpression} * sampleStrokePattern(${textureName}, ${sizeExpression}, ${offsetExpression}, ${sampleSizeExpression}, ${spacingExpression}, ${startOffsetExpression}, currentLengthPx, currentRadiusRatio, v_width)`,
    );
  }

The desired result was obtained as follows.
image

The issue was confirmed in 'stroke-line-dash'.
If there are no other issues with the code I wrote, please reflect it.

Thank you for solving the issue related to the filter related to 'geometry-type' that I wrote before.
#15805

To Reproduce
Steps to reproduce the behavior:

  1. Go to '...'
  2. Click on '....'
  3. See error

Expected behavior
A clear and concise description of what you expected to happen.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions