Avoid rendering outside WebGL layer and source extent
This commit is contained in:
@@ -96,12 +96,22 @@ function parseStyle(style, bandCount) {
|
|||||||
const vertexShader = `
|
const vertexShader = `
|
||||||
attribute vec2 ${Attributes.TEXTURE_COORD};
|
attribute vec2 ${Attributes.TEXTURE_COORD};
|
||||||
uniform mat4 ${Uniforms.TILE_TRANSFORM};
|
uniform mat4 ${Uniforms.TILE_TRANSFORM};
|
||||||
|
uniform float ${Uniforms.TEXTURE_PIXEL_WIDTH};
|
||||||
|
uniform float ${Uniforms.TEXTURE_PIXEL_HEIGHT};
|
||||||
|
uniform float ${Uniforms.TEXTURE_RESOLUTION};
|
||||||
|
uniform float ${Uniforms.TEXTURE_ORIGIN_X};
|
||||||
|
uniform float ${Uniforms.TEXTURE_ORIGIN_Y};
|
||||||
uniform float ${Uniforms.DEPTH};
|
uniform float ${Uniforms.DEPTH};
|
||||||
|
|
||||||
varying vec2 v_textureCoord;
|
varying vec2 v_textureCoord;
|
||||||
|
varying vec2 v_mapCoord;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
v_textureCoord = ${Attributes.TEXTURE_COORD};
|
v_textureCoord = ${Attributes.TEXTURE_COORD};
|
||||||
|
v_mapCoord = vec2(
|
||||||
|
${Uniforms.TEXTURE_ORIGIN_X} + ${Uniforms.TEXTURE_RESOLUTION} * ${Uniforms.TEXTURE_PIXEL_WIDTH} * v_textureCoord[0],
|
||||||
|
${Uniforms.TEXTURE_ORIGIN_Y} - ${Uniforms.TEXTURE_RESOLUTION} * ${Uniforms.TEXTURE_PIXEL_HEIGHT} * v_textureCoord[1]
|
||||||
|
);
|
||||||
gl_Position = ${Uniforms.TILE_TRANSFORM} * vec4(${Attributes.TEXTURE_COORD}, ${Uniforms.DEPTH}, 1.0);
|
gl_Position = ${Uniforms.TILE_TRANSFORM} * vec4(${Attributes.TEXTURE_COORD}, ${Uniforms.DEPTH}, 1.0);
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@@ -237,6 +247,8 @@ function parseStyle(style, bandCount) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
varying vec2 v_textureCoord;
|
varying vec2 v_textureCoord;
|
||||||
|
varying vec2 v_mapCoord;
|
||||||
|
uniform vec4 ${Uniforms.RENDER_EXTENT};
|
||||||
uniform float ${Uniforms.TRANSITION_ALPHA};
|
uniform float ${Uniforms.TRANSITION_ALPHA};
|
||||||
uniform float ${Uniforms.TEXTURE_PIXEL_WIDTH};
|
uniform float ${Uniforms.TEXTURE_PIXEL_WIDTH};
|
||||||
uniform float ${Uniforms.TEXTURE_PIXEL_HEIGHT};
|
uniform float ${Uniforms.TEXTURE_PIXEL_HEIGHT};
|
||||||
@@ -248,6 +260,15 @@ function parseStyle(style, bandCount) {
|
|||||||
${functionDefintions.join('\n')}
|
${functionDefintions.join('\n')}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
if (
|
||||||
|
v_mapCoord[0] < ${Uniforms.RENDER_EXTENT}[0] ||
|
||||||
|
v_mapCoord[1] < ${Uniforms.RENDER_EXTENT}[1] ||
|
||||||
|
v_mapCoord[0] > ${Uniforms.RENDER_EXTENT}[2] ||
|
||||||
|
v_mapCoord[1] > ${Uniforms.RENDER_EXTENT}[3]
|
||||||
|
) {
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
|
||||||
vec4 color = texture2D(${
|
vec4 color = texture2D(${
|
||||||
Uniforms.TILE_TEXTURE_ARRAY
|
Uniforms.TILE_TEXTURE_ARRAY
|
||||||
}[0], v_textureCoord);
|
}[0], v_textureCoord);
|
||||||
|
|||||||
@@ -35,6 +35,10 @@ export const Uniforms = {
|
|||||||
DEPTH: 'u_depth',
|
DEPTH: 'u_depth',
|
||||||
TEXTURE_PIXEL_WIDTH: 'u_texturePixelWidth',
|
TEXTURE_PIXEL_WIDTH: 'u_texturePixelWidth',
|
||||||
TEXTURE_PIXEL_HEIGHT: 'u_texturePixelHeight',
|
TEXTURE_PIXEL_HEIGHT: 'u_texturePixelHeight',
|
||||||
|
TEXTURE_RESOLUTION: 'u_textureResolution', // map units per texture pixel
|
||||||
|
TEXTURE_ORIGIN_X: 'u_textureOriginX', // map x coordinate of left edge of texture
|
||||||
|
TEXTURE_ORIGIN_Y: 'u_textureOriginY', // map y coordinate of top edge of texture
|
||||||
|
RENDER_EXTENT: 'u_renderExtent', // intersection of layer, source, and view extent
|
||||||
RESOLUTION: 'u_resolution',
|
RESOLUTION: 'u_resolution',
|
||||||
ZOOM: 'u_zoom',
|
ZOOM: 'u_zoom',
|
||||||
};
|
};
|
||||||
@@ -150,7 +154,7 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
|
|||||||
this.renderComplete = false;
|
this.renderComplete = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This transform converts tile i, j coordinates to screen coordinates.
|
* This transform converts texture coordinates to screen coordinates.
|
||||||
* @type {import("../../transform.js").Transform}
|
* @type {import("../../transform.js").Transform}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
@@ -581,6 +585,19 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
|
|||||||
Uniforms.TEXTURE_PIXEL_HEIGHT,
|
Uniforms.TEXTURE_PIXEL_HEIGHT,
|
||||||
tileSize[1]
|
tileSize[1]
|
||||||
);
|
);
|
||||||
|
this.helper.setUniformFloatValue(
|
||||||
|
Uniforms.TEXTURE_RESOLUTION,
|
||||||
|
tileResolution
|
||||||
|
);
|
||||||
|
this.helper.setUniformFloatValue(
|
||||||
|
Uniforms.TEXTURE_ORIGIN_X,
|
||||||
|
tileOrigin[0] + tileCenterI * tileSize[0] * tileResolution
|
||||||
|
);
|
||||||
|
this.helper.setUniformFloatValue(
|
||||||
|
Uniforms.TEXTURE_ORIGIN_Y,
|
||||||
|
tileOrigin[1] - tileCenterJ * tileSize[1] * tileResolution
|
||||||
|
);
|
||||||
|
this.helper.setUniformFloatVec4(Uniforms.RENDER_EXTENT, extent);
|
||||||
this.helper.setUniformFloatValue(
|
this.helper.setUniformFloatValue(
|
||||||
Uniforms.RESOLUTION,
|
Uniforms.RESOLUTION,
|
||||||
viewState.resolution
|
viewState.resolution
|
||||||
|
|||||||
@@ -962,6 +962,15 @@ class WebGLHelper extends Disposable {
|
|||||||
this.getGL().uniform1f(this.getUniformLocation(uniform), value);
|
this.getGL().uniform1f(this.getUniformLocation(uniform), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Give a value for a vec4 uniform
|
||||||
|
* @param {string} uniform Uniform name
|
||||||
|
* @param {Array<number>} value Array of length 4.
|
||||||
|
*/
|
||||||
|
setUniformFloatVec4(uniform, value) {
|
||||||
|
this.getGL().uniform4fv(this.getUniformLocation(uniform), value);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Give a value for a standard matrix4 uniform
|
* Give a value for a standard matrix4 uniform
|
||||||
* @param {string} uniform Uniform name
|
* @param {string} uniform Uniform name
|
||||||
|
|||||||
@@ -87,7 +87,11 @@ describe('ol/layer/WebGLTile', function () {
|
|||||||
#else
|
#else
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
varying vec2 v_textureCoord;
|
varying vec2 v_textureCoord;
|
||||||
|
varying vec2 v_mapCoord;
|
||||||
|
|
||||||
|
uniform vec4 u_renderExtent;
|
||||||
uniform float u_transitionAlpha;
|
uniform float u_transitionAlpha;
|
||||||
uniform float u_texturePixelWidth;
|
uniform float u_texturePixelWidth;
|
||||||
uniform float u_texturePixelHeight;
|
uniform float u_texturePixelHeight;
|
||||||
@@ -97,7 +101,16 @@ describe('ol/layer/WebGLTile', function () {
|
|||||||
uniform float u_var_g;
|
uniform float u_var_g;
|
||||||
uniform float u_var_b;
|
uniform float u_var_b;
|
||||||
uniform sampler2D u_tileTextures[1];
|
uniform sampler2D u_tileTextures[1];
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
if (
|
||||||
|
v_mapCoord[0] < u_renderExtent[0] ||
|
||||||
|
v_mapCoord[1] < u_renderExtent[1] ||
|
||||||
|
v_mapCoord[0] > u_renderExtent[2] ||
|
||||||
|
v_mapCoord[1] > u_renderExtent[3]
|
||||||
|
) {
|
||||||
|
discard;
|
||||||
|
}
|
||||||
vec4 color = texture2D(u_tileTextures[0], v_textureCoord);
|
vec4 color = texture2D(u_tileTextures[0], v_textureCoord);
|
||||||
color = vec4(u_var_r / 255.0, u_var_g / 255.0, u_var_b / 255.0, 1.0);
|
color = vec4(u_var_r / 255.0, u_var_g / 255.0, u_var_b / 255.0, 1.0);
|
||||||
if (color.a == 0.0) {
|
if (color.a == 0.0) {
|
||||||
@@ -112,12 +125,24 @@ describe('ol/layer/WebGLTile', function () {
|
|||||||
expect(compileShaderSpy.getCall(1).args[0].replace(/[ \n]+/g, ' ')).to.be(
|
expect(compileShaderSpy.getCall(1).args[0].replace(/[ \n]+/g, ' ')).to.be(
|
||||||
`
|
`
|
||||||
attribute vec2 a_textureCoord;
|
attribute vec2 a_textureCoord;
|
||||||
|
|
||||||
uniform mat4 u_tileTransform;
|
uniform mat4 u_tileTransform;
|
||||||
|
uniform float u_texturePixelWidth;
|
||||||
|
uniform float u_texturePixelHeight;
|
||||||
|
uniform float u_textureResolution;
|
||||||
|
uniform float u_textureOriginX;
|
||||||
|
uniform float u_textureOriginY;
|
||||||
uniform float u_depth;
|
uniform float u_depth;
|
||||||
|
|
||||||
varying vec2 v_textureCoord;
|
varying vec2 v_textureCoord;
|
||||||
|
varying vec2 v_mapCoord;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
v_textureCoord = a_textureCoord;
|
v_textureCoord = a_textureCoord;
|
||||||
|
v_mapCoord = vec2(
|
||||||
|
u_textureOriginX + u_textureResolution * u_texturePixelWidth * v_textureCoord[0],
|
||||||
|
u_textureOriginY - u_textureResolution * u_texturePixelHeight * v_textureCoord[1]
|
||||||
|
);
|
||||||
gl_Position = u_tileTransform * vec4(a_textureCoord, u_depth, 1.0);
|
gl_Position = u_tileTransform * vec4(a_textureCoord, u_depth, 1.0);
|
||||||
}
|
}
|
||||||
`.replace(/[ \n]+/g, ' ')
|
`.replace(/[ \n]+/g, ' ')
|
||||||
@@ -163,6 +188,10 @@ describe('ol/layer/WebGLTile', function () {
|
|||||||
#else
|
#else
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
#endif varying vec2 v_textureCoord;
|
#endif varying vec2 v_textureCoord;
|
||||||
|
|
||||||
|
varying vec2 v_mapCoord;
|
||||||
|
|
||||||
|
uniform vec4 u_renderExtent;
|
||||||
uniform float u_transitionAlpha;
|
uniform float u_transitionAlpha;
|
||||||
uniform float u_texturePixelWidth;
|
uniform float u_texturePixelWidth;
|
||||||
uniform float u_texturePixelHeight;
|
uniform float u_texturePixelHeight;
|
||||||
@@ -188,6 +217,14 @@ describe('ol/layer/WebGLTile', function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
if (
|
||||||
|
v_mapCoord[0] < u_renderExtent[0] ||
|
||||||
|
v_mapCoord[1] < u_renderExtent[1] ||
|
||||||
|
v_mapCoord[0] > u_renderExtent[2] ||
|
||||||
|
v_mapCoord[1] > u_renderExtent[3]
|
||||||
|
) {
|
||||||
|
discard;
|
||||||
|
}
|
||||||
vec4 color = texture2D(u_tileTextures[0], v_textureCoord);
|
vec4 color = texture2D(u_tileTextures[0], v_textureCoord);
|
||||||
color = vec4((getBandValue(4.0, 0.0, 0.0) / 3000.0), (getBandValue(1.0, 0.0, 0.0) / 3000.0), (getBandValue(2.0, 0.0, 0.0) / 3000.0), 1.0);
|
color = vec4((getBandValue(4.0, 0.0, 0.0) / 3000.0), (getBandValue(1.0, 0.0, 0.0) / 3000.0), (getBandValue(2.0, 0.0, 0.0) / 3000.0), 1.0);
|
||||||
if (color.a == 0.0) {
|
if (color.a == 0.0) {
|
||||||
|
|||||||
BIN
test/rendering/cases/webgl-layer-extent/expected.png
Normal file
BIN
test/rendering/cases/webgl-layer-extent/expected.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
28
test/rendering/cases/webgl-layer-extent/main.js
Normal file
28
test/rendering/cases/webgl-layer-extent/main.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import Map from '../../../../src/ol/Map.js';
|
||||||
|
import TileLayer from '../../../../src/ol/layer/WebGLTile.js';
|
||||||
|
import View from '../../../../src/ol/View.js';
|
||||||
|
import XYZ from '../../../../src/ol/source/XYZ.js';
|
||||||
|
import {useGeographic} from '../../../../src/ol/proj.js';
|
||||||
|
useGeographic();
|
||||||
|
|
||||||
|
new Map({
|
||||||
|
layers: [
|
||||||
|
new TileLayer({
|
||||||
|
extent: [-100, -30, 50, 50],
|
||||||
|
source: new XYZ({
|
||||||
|
url: '/data/tiles/satellite/{z}/{x}/{y}.jpg',
|
||||||
|
transition: 0,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
target: 'map',
|
||||||
|
view: new View({
|
||||||
|
center: [0, 0],
|
||||||
|
zoom: 0,
|
||||||
|
rotation: Math.PI / 5,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
render({
|
||||||
|
message: 'data outside the layer extent is not rendered',
|
||||||
|
});
|
||||||
BIN
test/rendering/cases/webgl-source-extent/expected.png
Normal file
BIN
test/rendering/cases/webgl-source-extent/expected.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 51 KiB |
58
test/rendering/cases/webgl-source-extent/main.js
Normal file
58
test/rendering/cases/webgl-source-extent/main.js
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import Map from '../../../../src/ol/Map.js';
|
||||||
|
import TileGrid from '../../../../src/ol/tilegrid/TileGrid.js';
|
||||||
|
import TileLayer from '../../../../src/ol/layer/WebGLTile.js';
|
||||||
|
import View from '../../../../src/ol/View.js';
|
||||||
|
import XYZ from '../../../../src/ol/source/XYZ.js';
|
||||||
|
import {getHeight, getWidth} from '../../../../src/ol/extent.js';
|
||||||
|
import {get as getProjection} from '../../../../src/ol/proj.js';
|
||||||
|
|
||||||
|
const fullExtent = getProjection('EPSG:3857').getExtent();
|
||||||
|
const width = getWidth(fullExtent);
|
||||||
|
const height = getHeight(fullExtent);
|
||||||
|
|
||||||
|
const partialExtent = [
|
||||||
|
fullExtent[0],
|
||||||
|
fullExtent[1] + 0.4 * height,
|
||||||
|
fullExtent[2] - 0.4 * width,
|
||||||
|
fullExtent[3],
|
||||||
|
];
|
||||||
|
|
||||||
|
function resolutionsFromExtent(extent, maxZoom) {
|
||||||
|
const height = getHeight(extent);
|
||||||
|
const width = getWidth(extent);
|
||||||
|
|
||||||
|
const maxResolution = Math.max(width / 256, height / 256);
|
||||||
|
|
||||||
|
const length = maxZoom + 1;
|
||||||
|
const resolutions = new Array(length);
|
||||||
|
for (let z = 0; z < length; ++z) {
|
||||||
|
resolutions[z] = maxResolution / Math.pow(2, z);
|
||||||
|
}
|
||||||
|
return resolutions;
|
||||||
|
}
|
||||||
|
|
||||||
|
new Map({
|
||||||
|
layers: [
|
||||||
|
new TileLayer({
|
||||||
|
source: new XYZ({
|
||||||
|
wrapX: false,
|
||||||
|
url: '/data/tiles/satellite/{z}/{x}/{y}.jpg',
|
||||||
|
transition: 0,
|
||||||
|
tileGrid: new TileGrid({
|
||||||
|
extent: partialExtent,
|
||||||
|
resolutions: resolutionsFromExtent(fullExtent, 10),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
target: 'map',
|
||||||
|
view: new View({
|
||||||
|
center: [0, 0],
|
||||||
|
zoom: 0,
|
||||||
|
rotation: -Math.PI / 8,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
render({
|
||||||
|
message: 'data outside the source tile grid extent is not rendered',
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user