WebGL / Support DPR > 1 in linestring shader

A u_pixelRatio uniform was added to be used in the shaders. this is necessary
since we're relying on the builtin gl_FragCoord vector, which will be scaled
relative to the u_sizePx uniform in case of a device pixel ratio != 1.

Also added tests for computed uniform values, instead of just testing
that they were indeed set.
This commit is contained in:
Olivier Guyot
2022-06-07 21:43:01 +02:00
parent 9e35acaa0a
commit f603ce7456
3 changed files with 63 additions and 1 deletions

View File

@@ -100,6 +100,7 @@ class WebGLLayer extends Layer {
}`, }`,
lineStringFragmentShader: ` lineStringFragmentShader: `
precision mediump float; precision mediump float;
uniform float u_pixelRatio;
varying vec2 v_segmentStart; varying vec2 v_segmentStart;
varying vec2 v_segmentEnd; varying vec2 v_segmentEnd;
varying float v_angleStart; varying float v_angleStart;
@@ -118,8 +119,9 @@ class WebGLLayer extends Layer {
float lineWidth = 1.5; float lineWidth = 1.5;
void main(void) { void main(void) {
vec2 v_currentPoint = gl_FragCoord.xy / u_pixelRatio;
gl_FragColor = vec4(v_color.rgb * 0.75, 1.0); gl_FragColor = vec4(v_color.rgb * 0.75, 1.0);
gl_FragColor *= segmentDistanceField(gl_FragCoord.xy, v_segmentStart, v_segmentEnd, lineWidth); gl_FragColor *= segmentDistanceField(v_currentPoint, v_segmentStart, v_segmentEnd, lineWidth);
}`, }`,
pointVertexShader: ` pointVertexShader: `
precision mediump float; precision mediump float;

View File

@@ -50,6 +50,7 @@ export const DefaultUniform = {
ZOOM: 'u_zoom', ZOOM: 'u_zoom',
RESOLUTION: 'u_resolution', RESOLUTION: 'u_resolution',
SIZE_PX: 'u_sizePx', SIZE_PX: 'u_sizePx',
PIXEL_RATIO: 'u_pixelRatio',
}; };
/** /**
@@ -666,6 +667,7 @@ class WebGLHelper extends Disposable {
applyFrameState(frameState) { applyFrameState(frameState) {
const size = frameState.size; const size = frameState.size;
const rotation = frameState.viewState.rotation; const rotation = frameState.viewState.rotation;
const pixelRatio = frameState.pixelRatio;
const offsetScaleMatrix = resetTransform(this.offsetScaleMatrix_); const offsetScaleMatrix = resetTransform(this.offsetScaleMatrix_);
scaleTransform(offsetScaleMatrix, 2 / size[0], 2 / size[1]); scaleTransform(offsetScaleMatrix, 2 / size[0], 2 / size[1]);
@@ -693,6 +695,7 @@ class WebGLHelper extends Disposable {
DefaultUniform.RESOLUTION, DefaultUniform.RESOLUTION,
frameState.viewState.resolution frameState.viewState.resolution
); );
this.setUniformFloatValue(DefaultUniform.PIXEL_RATIO, pixelRatio);
this.setUniformFloatVec2(DefaultUniform.SIZE_PX, [size[0], size[1]]); this.setUniformFloatVec2(DefaultUniform.SIZE_PX, [size[0], size[1]]);
} }

View File

@@ -63,6 +63,7 @@ const SAMPLE_FRAMESTATE = {
rotation: 0.4, rotation: 0.4,
resolution: 2, resolution: 2,
center: [10, 20], center: [10, 20],
zoom: 3,
}, },
}; };
@@ -154,6 +155,16 @@ describe('ol/webgl/WebGLHelper', function () {
h.uniformLocations_[DefaultUniform.OFFSET_SCALE_MATRIX] h.uniformLocations_[DefaultUniform.OFFSET_SCALE_MATRIX]
).not.to.eql(undefined); ).not.to.eql(undefined);
expect(h.uniformLocations_[DefaultUniform.TIME]).not.to.eql(undefined); expect(h.uniformLocations_[DefaultUniform.TIME]).not.to.eql(undefined);
expect(h.uniformLocations_[DefaultUniform.ZOOM]).not.to.eql(undefined);
expect(h.uniformLocations_[DefaultUniform.RESOLUTION]).not.to.eql(
undefined
);
expect(h.uniformLocations_[DefaultUniform.SIZE_PX]).not.to.eql(
undefined
);
expect(h.uniformLocations_[DefaultUniform.PIXEL_RATIO]).not.to.eql(
undefined
);
}); });
it('has processed uniforms', function () { it('has processed uniforms', function () {
@@ -413,4 +424,50 @@ describe('ol/webgl/WebGLHelper', function () {
expect(spy.getCall(2).args[4]).to.eql(5 * bytesPerFloat); expect(spy.getCall(2).args[4]).to.eql(5 * bytesPerFloat);
}); });
}); });
describe('#applyFrameState', function () {
let stubMatrix, stubFloat, stubVec2, stubTime;
beforeEach(function () {
stubTime = sinon.stub(Date, 'now');
stubTime.returns(1000);
h = new WebGLHelper();
stubMatrix = sinon.stub(h, 'setUniformMatrixValue');
stubFloat = sinon.stub(h, 'setUniformFloatValue');
stubVec2 = sinon.stub(h, 'setUniformFloatVec2');
stubTime.returns(2000);
h.applyFrameState({...SAMPLE_FRAMESTATE, pixelRatio: 2});
});
afterEach(function () {
stubTime.restore();
});
it('sets the default uniforms according the frame state', function () {
expect(stubMatrix.getCall(0).args).to.eql([
DefaultUniform.OFFSET_SCALE_MATRIX,
[
0.9210609940028851, -0.3894183423086505, 0, 0, 0.3894183423086505,
0.9210609940028851, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
],
]);
expect(stubMatrix.getCall(1).args).to.eql([
DefaultUniform.OFFSET_ROTATION_MATRIX,
[
0.9210609940028851, -0.3894183423086505, 0, 0, 0.3894183423086505,
0.9210609940028851, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
],
]);
expect(stubFloat.getCall(0).args).to.eql([DefaultUniform.TIME, 1]);
expect(stubFloat.getCall(1).args).to.eql([DefaultUniform.ZOOM, 3]);
expect(stubFloat.getCall(2).args).to.eql([DefaultUniform.RESOLUTION, 2]);
expect(stubFloat.getCall(3).args).to.eql([DefaultUniform.PIXEL_RATIO, 2]);
expect(stubVec2.getCall(0).args).to.eql([
DefaultUniform.SIZE_PX,
[100, 150],
]);
});
});
}); });