Allow sampling data from neighboring pixels
This commit is contained in:
@@ -13,3 +13,4 @@ export {default as Vector} from './layer/Vector.js';
|
||||
export {default as VectorImage} from './layer/VectorImage.js';
|
||||
export {default as VectorTile} from './layer/VectorTile.js';
|
||||
export {default as WebGLPoints} from './layer/WebGLPoints.js';
|
||||
export {default as WebGLTile} from './layer/WebGLTile.js';
|
||||
|
||||
@@ -215,6 +215,10 @@ function parseStyle(style, bandCount) {
|
||||
|
||||
varying vec2 v_textureCoord;
|
||||
uniform float ${Uniforms.TRANSITION_ALPHA};
|
||||
uniform float ${Uniforms.TEXTURE_PIXEL_WIDTH};
|
||||
uniform float ${Uniforms.TEXTURE_PIXEL_HEIGHT};
|
||||
uniform float ${Uniforms.RESOLUTION};
|
||||
uniform float ${Uniforms.ZOOM};
|
||||
|
||||
${uniformDeclarations.join('\n')}
|
||||
|
||||
|
||||
@@ -35,6 +35,10 @@ export const Uniforms = {
|
||||
TILE_TRANSFORM: 'u_tileTransform',
|
||||
TRANSITION_ALPHA: 'u_transitionAlpha',
|
||||
DEPTH: 'u_depth',
|
||||
TEXTURE_PIXEL_WIDTH: 'u_texturePixelWidth',
|
||||
TEXTURE_PIXEL_HEIGHT: 'u_texturePixelHeight',
|
||||
RESOLUTION: 'u_resolution',
|
||||
ZOOM: 'u_zoom',
|
||||
};
|
||||
|
||||
export const Attributes = {
|
||||
@@ -75,6 +79,23 @@ function addTileTextureToLookup(tileTexturesByZ, tileTexture, z) {
|
||||
tileTexturesByZ[z].push(tileTexture);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {import("../../PluggableMap.js").FrameState} frameState Frame state.
|
||||
* @return {import("../../extent.js").Extent} Extent.
|
||||
*/
|
||||
function getRenderExtent(frameState) {
|
||||
const layerState = frameState.layerStatesArray[frameState.layerIndex];
|
||||
let extent = frameState.extent;
|
||||
if (layerState.extent) {
|
||||
extent = getIntersection(
|
||||
extent,
|
||||
fromUserExtent(layerState.extent, frameState.viewState.projection)
|
||||
);
|
||||
}
|
||||
return extent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {string} vertexShader Vertex shader source.
|
||||
@@ -183,6 +204,9 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
|
||||
* @return {boolean} Layer is ready to be rendered.
|
||||
*/
|
||||
prepareFrame(frameState) {
|
||||
if (isEmpty(getRenderExtent(frameState))) {
|
||||
return false;
|
||||
}
|
||||
const source = this.getLayer().getSource();
|
||||
if (!source) {
|
||||
return false;
|
||||
@@ -198,20 +222,9 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
|
||||
renderFrame(frameState) {
|
||||
this.preRender(frameState);
|
||||
|
||||
const layerState = frameState.layerStatesArray[frameState.layerIndex];
|
||||
const viewState = frameState.viewState;
|
||||
|
||||
let extent = frameState.extent;
|
||||
if (layerState.extent) {
|
||||
extent = getIntersection(
|
||||
extent,
|
||||
fromUserExtent(layerState.extent, viewState.projection)
|
||||
);
|
||||
}
|
||||
if (isEmpty(extent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const layerState = frameState.layerStatesArray[frameState.layerIndex];
|
||||
const extent = getRenderExtent(frameState);
|
||||
const tileLayer = this.getLayer();
|
||||
const tileSource = tileLayer.getSource();
|
||||
const tileGrid = tileSource.getTileGridForProjection(viewState.projection);
|
||||
@@ -421,6 +434,19 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
|
||||
|
||||
this.helper.setUniformFloatValue(Uniforms.TRANSITION_ALPHA, alpha);
|
||||
this.helper.setUniformFloatValue(Uniforms.DEPTH, depth);
|
||||
this.helper.setUniformFloatValue(
|
||||
Uniforms.TEXTURE_PIXEL_WIDTH,
|
||||
tileSize[0]
|
||||
);
|
||||
this.helper.setUniformFloatValue(
|
||||
Uniforms.TEXTURE_PIXEL_HEIGHT,
|
||||
tileSize[1]
|
||||
);
|
||||
this.helper.setUniformFloatValue(
|
||||
Uniforms.RESOLUTION,
|
||||
viewState.resolution
|
||||
);
|
||||
this.helper.setUniformFloatValue(Uniforms.ZOOM, viewState.zoom);
|
||||
|
||||
this.helper.drawElements(0, this.indices_.getSize());
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
export {default as BingMaps} from './source/BingMaps.js';
|
||||
export {default as CartoDB} from './source/CartoDB.js';
|
||||
export {default as Cluster} from './source/Cluster.js';
|
||||
export {default as DataTile} from './source/DataTile.js';
|
||||
export {default as GeoTIFF} from './source/GeoTIFF.js';
|
||||
export {default as IIIF} from './source/IIIF.js';
|
||||
export {default as Image} from './source/Image.js';
|
||||
export {default as ImageArcGISRest} from './source/ImageArcGISRest.js';
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @module ol/style/expressions
|
||||
*/
|
||||
|
||||
import {Uniforms} from '../renderer/webgl/TileLayer.js';
|
||||
import {asArray, isStringColor} from '../color.js';
|
||||
|
||||
/**
|
||||
@@ -12,12 +13,13 @@ import {asArray, isStringColor} from '../color.js';
|
||||
* The following operators can be used:
|
||||
*
|
||||
* * Reading operators:
|
||||
* * `['band', bandIndex]` fetches a pixel value from band `bandIndex` of the source's data. The first
|
||||
* `bandIndex` of the source data is `1`. Fetched values are in the 0..1 range.
|
||||
* {@link import("../source/TileImage.js").default} sources have 4 bands: red, green, blue and alpha.
|
||||
* {@link import("../source/DataTile.js").default} sources can have any number of bands, depending on
|
||||
* the underlying data source and
|
||||
* {@link import("../source/GeoTIFF.js").Options configuration}.
|
||||
* * `['band', bandIndex, xOffset, yOffset]` For tile layers only. Fetches pixel values from band
|
||||
* `bandIndex` of the source's data. The first `bandIndex` of the source data is `1`. Fetched values
|
||||
* are in the 0..1 range. {@link import("../source/TileImage.js").default} sources have 4 bands: red,
|
||||
* green, blue and alpha. {@link import("../source/DataTile.js").default} sources can have any number
|
||||
* of bands, depending on the underlying data source and
|
||||
* {@link import("../source/GeoTIFF.js").Options configuration}. `xOffset` and `yOffset` are optional
|
||||
* and allow specifying pixel offsets for x and y. This is used for sampling data from neighboring pixels.
|
||||
* * `['get', 'attributeName']` fetches a feature attribute (it will be prefixed by `a_` in the shader)
|
||||
* Note: those will be taken from the attributes provided to the renderer
|
||||
* * `['resolution']` returns the current resolution
|
||||
@@ -34,6 +36,9 @@ import {asArray, isStringColor} from '../color.js';
|
||||
* * `['%', value1, value2]` returns the result of `value1 % value2` (modulo)
|
||||
* * `['^', value1, value2]` returns the value of `value1` raised to the `value2` power
|
||||
* * `['abs', value1]` returns the absolute value of `value1`
|
||||
* * `['sin', value1]` returns the sine of `value1`
|
||||
* * `['cos', value1]` returns the cosine of `value1`
|
||||
* * `['atan', value1, value2]` returns `atan2(value1, value2)`. If `value2` is not provided, returns `atan(value1)`
|
||||
*
|
||||
* * Transform operators:
|
||||
* * `['case', condition1, output1, ...conditionN, outputN, fallback]` selects the first output whose corresponding
|
||||
@@ -416,7 +421,8 @@ Operators['band'] = {
|
||||
return ValueTypes.NUMBER;
|
||||
},
|
||||
toGlsl: function (context, args) {
|
||||
assertArgsCount(args, 1);
|
||||
assertArgsMinCount(args, 1);
|
||||
assertArgsMaxCount(args, 3);
|
||||
const band = args[0];
|
||||
if (typeof band !== 'number') {
|
||||
throw new Error('Band index must be a number');
|
||||
@@ -428,7 +434,22 @@ Operators['band'] = {
|
||||
// LUMINANCE_ALPHA - band 1 assigned to rgb and band 2 assigned to alpha
|
||||
bandIndex = 3;
|
||||
}
|
||||
return `color${colorIndex}[${bandIndex}]`;
|
||||
if (args.length === 1) {
|
||||
return `color${colorIndex}[${bandIndex}]`;
|
||||
} else {
|
||||
const xOffset = args[1];
|
||||
const yOffset = args[2] || 0;
|
||||
assertNumber(xOffset);
|
||||
assertNumber(yOffset);
|
||||
const uniformName = Uniforms.TILE_TEXTURE_PREFIX + colorIndex;
|
||||
return `texture2D(${uniformName}, v_textureCoord + vec2(${expressionToGlsl(
|
||||
context,
|
||||
xOffset
|
||||
)} / ${Uniforms.TEXTURE_PIXEL_WIDTH}, ${expressionToGlsl(
|
||||
context,
|
||||
yOffset
|
||||
)} / ${Uniforms.TEXTURE_PIXEL_HEIGHT}))[${bandIndex}]`;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -570,6 +591,45 @@ Operators['abs'] = {
|
||||
},
|
||||
};
|
||||
|
||||
Operators['sin'] = {
|
||||
getReturnType: function (args) {
|
||||
return ValueTypes.NUMBER;
|
||||
},
|
||||
toGlsl: function (context, args) {
|
||||
assertArgsCount(args, 1);
|
||||
assertNumbers(args);
|
||||
return `sin(${expressionToGlsl(context, args[0])})`;
|
||||
},
|
||||
};
|
||||
|
||||
Operators['cos'] = {
|
||||
getReturnType: function (args) {
|
||||
return ValueTypes.NUMBER;
|
||||
},
|
||||
toGlsl: function (context, args) {
|
||||
assertArgsCount(args, 1);
|
||||
assertNumbers(args);
|
||||
return `cos(${expressionToGlsl(context, args[0])})`;
|
||||
},
|
||||
};
|
||||
|
||||
Operators['atan'] = {
|
||||
getReturnType: function (args) {
|
||||
return ValueTypes.NUMBER;
|
||||
},
|
||||
toGlsl: function (context, args) {
|
||||
assertArgsMinCount(args, 1);
|
||||
assertArgsMaxCount(args, 2);
|
||||
assertNumbers(args);
|
||||
return args.length === 2
|
||||
? `atan(${expressionToGlsl(context, args[0])}, ${expressionToGlsl(
|
||||
context,
|
||||
args[1]
|
||||
)})`
|
||||
: `atan(${expressionToGlsl(context, args[0])})`;
|
||||
},
|
||||
};
|
||||
|
||||
Operators['>'] = {
|
||||
getReturnType: function (args) {
|
||||
return ValueTypes.BOOLEAN;
|
||||
|
||||
Reference in New Issue
Block a user