Minimal working text renderer
This commit is contained in:
@@ -142,7 +142,8 @@ if (ol.ENABLE_WEBGL) {
|
|||||||
* @return {ol.render.webgl.circlereplay.defaultshader.Locations|
|
* @return {ol.render.webgl.circlereplay.defaultshader.Locations|
|
||||||
ol.render.webgl.imagereplay.defaultshader.Locations|
|
ol.render.webgl.imagereplay.defaultshader.Locations|
|
||||||
ol.render.webgl.linestringreplay.defaultshader.Locations|
|
ol.render.webgl.linestringreplay.defaultshader.Locations|
|
||||||
ol.render.webgl.polygonreplay.defaultshader.Locations} Locations.
|
ol.render.webgl.polygonreplay.defaultshader.Locations|
|
||||||
|
ol.render.webgl.textreplay.defaultshader.Locations} Locations.
|
||||||
*/
|
*/
|
||||||
ol.render.webgl.Replay.prototype.setUpProgram = function(gl, context, size, pixelRatio) {};
|
ol.render.webgl.Replay.prototype.setUpProgram = function(gl, context, size, pixelRatio) {};
|
||||||
|
|
||||||
@@ -154,7 +155,8 @@ if (ol.ENABLE_WEBGL) {
|
|||||||
* @param {ol.render.webgl.circlereplay.defaultshader.Locations|
|
* @param {ol.render.webgl.circlereplay.defaultshader.Locations|
|
||||||
ol.render.webgl.imagereplay.defaultshader.Locations|
|
ol.render.webgl.imagereplay.defaultshader.Locations|
|
||||||
ol.render.webgl.linestringreplay.defaultshader.Locations|
|
ol.render.webgl.linestringreplay.defaultshader.Locations|
|
||||||
ol.render.webgl.polygonreplay.defaultshader.Locations} locations Locations.
|
ol.render.webgl.polygonreplay.defaultshader.Locations|
|
||||||
|
ol.render.webgl.textreplay.defaultshader.Locations} locations Locations.
|
||||||
*/
|
*/
|
||||||
ol.render.webgl.Replay.prototype.shutDownProgram = function(gl, locations) {};
|
ol.render.webgl.Replay.prototype.shutDownProgram = function(gl, locations) {};
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,14 @@ goog.provide('ol.render.webgl.TextReplay');
|
|||||||
|
|
||||||
goog.require('ol');
|
goog.require('ol');
|
||||||
goog.require('ol.colorlike');
|
goog.require('ol.colorlike');
|
||||||
|
goog.require('ol.dom');
|
||||||
|
goog.require('ol.extent');
|
||||||
goog.require('ol.has');
|
goog.require('ol.has');
|
||||||
goog.require('ol.render.webgl');
|
goog.require('ol.render.webgl');
|
||||||
goog.require('ol.render.webgl.imagereplay.defaultshader');
|
goog.require('ol.render.webgl.textreplay.defaultshader');
|
||||||
goog.require('ol.render.webgl.Replay');
|
goog.require('ol.render.webgl.Replay');
|
||||||
goog.require('ol.webgl');
|
goog.require('ol.webgl');
|
||||||
|
goog.require('ol.webgl.Buffer');
|
||||||
goog.require('ol.webgl.Context');
|
goog.require('ol.webgl.Context');
|
||||||
|
|
||||||
|
|
||||||
@@ -24,7 +27,7 @@ if (ol.ENABLE_WEBGL) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {ol.render.webgl.imagereplay.defaultshader.Locations}
|
* @type {ol.render.webgl.textreplay.defaultshader.Locations}
|
||||||
*/
|
*/
|
||||||
this.defaultLocations_ = null;
|
this.defaultLocations_ = null;
|
||||||
|
|
||||||
@@ -52,6 +55,12 @@ if (ol.ENABLE_WEBGL) {
|
|||||||
*/
|
*/
|
||||||
this.textures_ = [];
|
this.textures_ = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {HTMLCanvasElement}
|
||||||
|
*/
|
||||||
|
this.measureCanvas_ = ol.dom.createCanvasContext2D(0, 0).canvas;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {{strokeColor: (ol.ColorLike|null),
|
* @type {{strokeColor: (ol.ColorLike|null),
|
||||||
@@ -59,7 +68,7 @@ if (ol.ENABLE_WEBGL) {
|
|||||||
* lineDash: Array.<number>,
|
* lineDash: Array.<number>,
|
||||||
* lineDashOffset: (number|undefined),
|
* lineDashOffset: (number|undefined),
|
||||||
* lineJoin: (string|undefined),
|
* lineJoin: (string|undefined),
|
||||||
* lineWidth: (number|undefined),
|
* lineWidth: number,
|
||||||
* miterLimit: (number|undefined),
|
* miterLimit: (number|undefined),
|
||||||
* fillColor: (ol.ColorLike|null),
|
* fillColor: (ol.ColorLike|null),
|
||||||
* text: string,
|
* text: string,
|
||||||
@@ -70,7 +79,9 @@ if (ol.ENABLE_WEBGL) {
|
|||||||
* offsetY: (number|undefined),
|
* offsetY: (number|undefined),
|
||||||
* scale: (number|undefined),
|
* scale: (number|undefined),
|
||||||
* rotation: (number|undefined),
|
* rotation: (number|undefined),
|
||||||
* rotateWithView: (boolean|undefined)}
|
* rotateWithView: (boolean|undefined),
|
||||||
|
* height: (number|undefined),
|
||||||
|
* width: (number|undefined)}}
|
||||||
*/
|
*/
|
||||||
this.state_ = {
|
this.state_ = {
|
||||||
strokeColor: null,
|
strokeColor: null,
|
||||||
@@ -78,7 +89,7 @@ if (ol.ENABLE_WEBGL) {
|
|||||||
lineDash: null,
|
lineDash: null,
|
||||||
lineDashOffset: undefined,
|
lineDashOffset: undefined,
|
||||||
lineJoin: undefined,
|
lineJoin: undefined,
|
||||||
lineWidth: undefined,
|
lineWidth: 0,
|
||||||
miterLimit: undefined,
|
miterLimit: undefined,
|
||||||
fillColor: null,
|
fillColor: null,
|
||||||
text: '',
|
text: '',
|
||||||
@@ -89,19 +100,17 @@ if (ol.ENABLE_WEBGL) {
|
|||||||
offsetY: undefined,
|
offsetY: undefined,
|
||||||
scale: undefined,
|
scale: undefined,
|
||||||
rotation: undefined,
|
rotation: undefined,
|
||||||
rotateWithView: undefined
|
rotateWithView: undefined,
|
||||||
|
height: undefined,
|
||||||
|
width: undefined
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
ol.inherits(ol.render.webgl.TextReplay, ol.render.webgl.Replay);
|
ol.inherits(ol.render.webgl.TextReplay, ol.render.webgl.Replay);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
* @inheritDoc
|
||||||
* @param {number} offset Offset.
|
|
||||||
* @param {number} end End.
|
|
||||||
* @param {number} stride Stride.
|
|
||||||
* @param {ol.geom.Geometry|ol.render.Feature} geometry Geometry.
|
|
||||||
* @param {ol.Feature|ol.render.Feature} feature Feature.
|
|
||||||
*/
|
*/
|
||||||
ol.render.webgl.TextReplay.prototype.drawText = function(flatCoordinates, offset,
|
ol.render.webgl.TextReplay.prototype.drawText = function(flatCoordinates, offset,
|
||||||
end, stride, geometry, feature) {
|
end, stride, geometry, feature) {
|
||||||
@@ -109,35 +118,46 @@ if (ol.ENABLE_WEBGL) {
|
|||||||
//TODO: speed up rendering with SDF, or at least glyph atlases
|
//TODO: speed up rendering with SDF, or at least glyph atlases
|
||||||
var state = this.state_;
|
var state = this.state_;
|
||||||
if (state.text && (state.fillColor || state.strokeColor)) {
|
if (state.text && (state.fillColor || state.strokeColor)) {
|
||||||
|
this.startIndices.push(this.indices.length);
|
||||||
|
this.startIndicesFeature.push(feature);
|
||||||
|
|
||||||
this.images_.push(this.createTextImage_());
|
this.images_.push(this.createTextImage_());
|
||||||
|
this.drawCoordinates_(
|
||||||
|
flatCoordinates, offset, end, stride);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @return {HTMLCanvasElement} Text image.
|
* @return {HTMLCanvasElement} Text image.
|
||||||
*/
|
*/
|
||||||
ol.render.webgl.TextReplay.prototype.createTextImage_ = function() {
|
ol.render.webgl.TextReplay.prototype.createTextImage_ = function() {
|
||||||
var state = this.state_;
|
var state = this.state_;
|
||||||
var canvas = document.createElement('canvas');
|
|
||||||
|
|
||||||
var ctx = canvas.getContext('2d');
|
//Measure text dimensions
|
||||||
ctx.font = state.font;
|
var mCtx = this.measureCanvas_.getContext('2d');
|
||||||
var lineHeight = Math.round(ctx.measureText('M').width * 1.5 + state.lineWidth * 2);
|
mCtx.font = state.font;
|
||||||
|
var lineHeight = Math.round(mCtx.measureText('M').width * 1.2 + state.lineWidth * 2);
|
||||||
var lines = state.text.split('\n');
|
var lines = state.text.split('\n');
|
||||||
//FIXME: use pixelRatio
|
//FIXME: use pixelRatio
|
||||||
var textHeight = Math.ceil(lineHeight * lines.length * state.scale);
|
var textHeight = Math.ceil(lineHeight * lines.length * state.scale);
|
||||||
|
state.height = textHeight;
|
||||||
var longestLine = lines.map(function(str) {
|
var longestLine = lines.map(function(str) {
|
||||||
return ctx.measureText(str).width;
|
return mCtx.measureText(str).width;
|
||||||
}).reduce(function(max, curr) {
|
}).reduce(function(max, curr) {
|
||||||
return Math.max(max, curr);
|
return Math.max(max, curr);
|
||||||
});
|
});
|
||||||
//FIXME: use pixelRatio
|
//FIXME: use pixelRatio
|
||||||
var textWidth = Math.ceil((longestLine + state.lineWidth * 2) * state.scale);
|
var textWidth = Math.ceil((longestLine + state.lineWidth * 2) * state.scale);
|
||||||
|
state.width = textWidth;
|
||||||
|
|
||||||
|
//Create a canvas
|
||||||
|
var ctx = ol.dom.createCanvasContext2D(textWidth, textHeight);
|
||||||
|
var canvas = ctx.canvas;
|
||||||
|
|
||||||
//Parameterize the canvas
|
//Parameterize the canvas
|
||||||
canvas.width = textWidth;
|
ctx.font = state.font;
|
||||||
canvas.height = textHeight;
|
|
||||||
ctx.fillStyle = state.fillColor;
|
ctx.fillStyle = state.fillColor;
|
||||||
ctx.strokeStyle = state.strokeColor;
|
ctx.strokeStyle = state.strokeColor;
|
||||||
ctx.lineWidth = state.lineWidth;
|
ctx.lineWidth = state.lineWidth;
|
||||||
@@ -146,7 +166,7 @@ if (ol.ENABLE_WEBGL) {
|
|||||||
ctx.miterLimit = state.miterLimit;
|
ctx.miterLimit = state.miterLimit;
|
||||||
ctx.textAlign = 'left';
|
ctx.textAlign = 'left';
|
||||||
ctx.textBaseline = 'top';
|
ctx.textBaseline = 'top';
|
||||||
if (ol.has.CANVAS_LINE_DASH) {
|
if (ol.has.CANVAS_LINE_DASH && state.lineDash) {
|
||||||
//FIXME: use pixelRatio
|
//FIXME: use pixelRatio
|
||||||
ctx.setLineDash(state.lineDash);
|
ctx.setLineDash(state.lineDash);
|
||||||
ctx.lineDashOffset = state.lineDashOffset;
|
ctx.lineDashOffset = state.lineDashOffset;
|
||||||
@@ -168,14 +188,282 @@ if (ol.ENABLE_WEBGL) {
|
|||||||
lineY += lineHeight;
|
lineY += lineHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
return canvas;
|
return /** @type {HTMLCanvasElement} */ (canvas);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @abstract
|
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||||
* @param {ol.webgl.Context} context Context.
|
* @param {number} offset Offset.
|
||||||
|
* @param {number} end End.
|
||||||
|
* @param {number} stride Stride.
|
||||||
|
* @return {number} My end.
|
||||||
|
* @private
|
||||||
*/
|
*/
|
||||||
ol.render.webgl.TextReplay.prototype.finish = function(context) {};
|
ol.render.webgl.TextReplay.prototype.drawCoordinates_ = function(flatCoordinates, offset, end, stride) {
|
||||||
|
var state = this.state_;
|
||||||
|
var anchorX, anchorY;
|
||||||
|
var height = /** @type {number} */ (state.height);
|
||||||
|
var width = /** @type {number} */ (state.width);
|
||||||
|
switch (state.textAlign) {
|
||||||
|
default:
|
||||||
|
anchorX = width / 2;
|
||||||
|
break;
|
||||||
|
case 'left': case 'end':
|
||||||
|
anchorX = 0;
|
||||||
|
break;
|
||||||
|
case 'right': case 'start':
|
||||||
|
anchorX = width;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (state.textBaseline) {
|
||||||
|
default:
|
||||||
|
anchorY = height / 2;
|
||||||
|
break;
|
||||||
|
case 'top':
|
||||||
|
anchorY = 0;
|
||||||
|
break;
|
||||||
|
case 'bottom':
|
||||||
|
anchorY = height;
|
||||||
|
break;
|
||||||
|
case 'hanging':
|
||||||
|
anchorY = height * 0.2;
|
||||||
|
break;
|
||||||
|
case 'alphabetic': case 'ideographic':
|
||||||
|
anchorY = height * 0.8;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
var rotateWithView = state.rotateWithView ? 1.0 : 0.0;
|
||||||
|
// this.rotation_ is anti-clockwise, but rotation is clockwise
|
||||||
|
var rotation = /** @type {number} */ (-state.rotation);
|
||||||
|
var cos = Math.cos(rotation);
|
||||||
|
var sin = Math.sin(rotation);
|
||||||
|
var numIndices = this.indices.length;
|
||||||
|
var numVertices = this.vertices.length;
|
||||||
|
var i, n, offsetX, offsetY, x, y;
|
||||||
|
for (i = offset; i < end; i += stride) {
|
||||||
|
x = flatCoordinates[i] - this.origin[0];
|
||||||
|
y = flatCoordinates[i + 1] - this.origin[1];
|
||||||
|
|
||||||
|
// There are 4 vertices per [x, y] point, one for each corner of the
|
||||||
|
// rectangle we're going to draw. We'd use 1 vertex per [x, y] point if
|
||||||
|
// WebGL supported Geometry Shaders (which can emit new vertices), but that
|
||||||
|
// is not currently the case.
|
||||||
|
//
|
||||||
|
// And each vertex includes 7 values: the x and y coordinates, the x and
|
||||||
|
// y offsets used to calculate the position of the corner, the u and
|
||||||
|
// v texture coordinates for the corner, and whether the
|
||||||
|
// the image should be rotated with the view (rotateWithView).
|
||||||
|
|
||||||
|
n = numVertices / 7;
|
||||||
|
|
||||||
|
// bottom-left corner
|
||||||
|
offsetX = -anchorX;
|
||||||
|
offsetY = -(height - anchorY);
|
||||||
|
this.vertices[numVertices++] = x;
|
||||||
|
this.vertices[numVertices++] = y;
|
||||||
|
this.vertices[numVertices++] = offsetX * cos - offsetY * sin;
|
||||||
|
this.vertices[numVertices++] = offsetX * sin + offsetY * cos;
|
||||||
|
this.vertices[numVertices++] = 0;
|
||||||
|
this.vertices[numVertices++] = 1;
|
||||||
|
this.vertices[numVertices++] = rotateWithView;
|
||||||
|
|
||||||
|
// bottom-right corner
|
||||||
|
offsetX = width - anchorX;
|
||||||
|
offsetY = -(height - anchorY);
|
||||||
|
this.vertices[numVertices++] = x;
|
||||||
|
this.vertices[numVertices++] = y;
|
||||||
|
this.vertices[numVertices++] = offsetX * cos - offsetY * sin;
|
||||||
|
this.vertices[numVertices++] = offsetX * sin + offsetY * cos;
|
||||||
|
this.vertices[numVertices++] = 1;
|
||||||
|
this.vertices[numVertices++] = 1;
|
||||||
|
this.vertices[numVertices++] = rotateWithView;
|
||||||
|
|
||||||
|
// top-right corner
|
||||||
|
offsetX = width - anchorX;
|
||||||
|
offsetY = anchorY;
|
||||||
|
this.vertices[numVertices++] = x;
|
||||||
|
this.vertices[numVertices++] = y;
|
||||||
|
this.vertices[numVertices++] = offsetX * cos - offsetY * sin;
|
||||||
|
this.vertices[numVertices++] = offsetX * sin + offsetY * cos;
|
||||||
|
this.vertices[numVertices++] = 1;
|
||||||
|
this.vertices[numVertices++] = 0;
|
||||||
|
this.vertices[numVertices++] = rotateWithView;
|
||||||
|
|
||||||
|
// top-left corner
|
||||||
|
offsetX = -anchorX;
|
||||||
|
offsetY = anchorY;
|
||||||
|
this.vertices[numVertices++] = x;
|
||||||
|
this.vertices[numVertices++] = y;
|
||||||
|
this.vertices[numVertices++] = offsetX * cos - offsetY * sin;
|
||||||
|
this.vertices[numVertices++] = offsetX * sin + offsetY * cos;
|
||||||
|
this.vertices[numVertices++] = 0;
|
||||||
|
this.vertices[numVertices++] = 0;
|
||||||
|
this.vertices[numVertices++] = rotateWithView;
|
||||||
|
|
||||||
|
this.indices[numIndices++] = n;
|
||||||
|
this.indices[numIndices++] = n + 1;
|
||||||
|
this.indices[numIndices++] = n + 2;
|
||||||
|
this.indices[numIndices++] = n;
|
||||||
|
this.indices[numIndices++] = n + 2;
|
||||||
|
this.indices[numIndices++] = n + 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
return numVertices;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
ol.render.webgl.TextReplay.prototype.finish = function(context) {
|
||||||
|
var gl = context.getGL();
|
||||||
|
|
||||||
|
this.startIndices.push(this.indices.length);
|
||||||
|
|
||||||
|
// create, bind, and populate the vertices buffer
|
||||||
|
this.verticesBuffer = new ol.webgl.Buffer(this.vertices);
|
||||||
|
|
||||||
|
// create, bind, and populate the indices buffer
|
||||||
|
this.indicesBuffer = new ol.webgl.Buffer(this.indices);
|
||||||
|
|
||||||
|
// create textures
|
||||||
|
this.createTextures_(gl);
|
||||||
|
|
||||||
|
this.images_ = [];
|
||||||
|
this.state_ = {
|
||||||
|
strokeColor: null,
|
||||||
|
lineCap: undefined,
|
||||||
|
lineDash: null,
|
||||||
|
lineDashOffset: undefined,
|
||||||
|
lineJoin: undefined,
|
||||||
|
lineWidth: 0,
|
||||||
|
miterLimit: undefined,
|
||||||
|
fillColor: null,
|
||||||
|
text: '',
|
||||||
|
font: undefined,
|
||||||
|
textAlign: undefined,
|
||||||
|
textBaseline: undefined,
|
||||||
|
offsetX: undefined,
|
||||||
|
offsetY: undefined,
|
||||||
|
scale: undefined,
|
||||||
|
rotation: undefined,
|
||||||
|
rotateWithView: undefined,
|
||||||
|
height: undefined,
|
||||||
|
width: undefined
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
ol.render.webgl.TextReplay.prototype.setUpProgram = function(gl, context, size, pixelRatio) {
|
||||||
|
// get the program
|
||||||
|
var fragmentShader = ol.render.webgl.textreplay.defaultshader.fragment;
|
||||||
|
var vertexShader = ol.render.webgl.textreplay.defaultshader.vertex;
|
||||||
|
var program = context.getProgram(fragmentShader, vertexShader);
|
||||||
|
|
||||||
|
// get the locations
|
||||||
|
var locations;
|
||||||
|
if (!this.defaultLocations_) {
|
||||||
|
// eslint-disable-next-line openlayers-internal/no-missing-requires
|
||||||
|
locations = new ol.render.webgl.textreplay.defaultshader.Locations(gl, program);
|
||||||
|
this.defaultLocations_ = locations;
|
||||||
|
} else {
|
||||||
|
locations = this.defaultLocations_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// use the program (FIXME: use the return value)
|
||||||
|
context.useProgram(program);
|
||||||
|
|
||||||
|
// enable the vertex attrib arrays
|
||||||
|
gl.enableVertexAttribArray(locations.a_position);
|
||||||
|
gl.vertexAttribPointer(locations.a_position, 2, ol.webgl.FLOAT,
|
||||||
|
false, 28, 0);
|
||||||
|
|
||||||
|
gl.enableVertexAttribArray(locations.a_offsets);
|
||||||
|
gl.vertexAttribPointer(locations.a_offsets, 2, ol.webgl.FLOAT,
|
||||||
|
false, 28, 8);
|
||||||
|
|
||||||
|
gl.enableVertexAttribArray(locations.a_texCoord);
|
||||||
|
gl.vertexAttribPointer(locations.a_texCoord, 2, ol.webgl.FLOAT,
|
||||||
|
false, 28, 16);
|
||||||
|
|
||||||
|
gl.enableVertexAttribArray(locations.a_rotateWithView);
|
||||||
|
gl.vertexAttribPointer(locations.a_rotateWithView, 1, ol.webgl.FLOAT,
|
||||||
|
false, 28, 24);
|
||||||
|
|
||||||
|
return locations;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
ol.render.webgl.TextReplay.prototype.shutDownProgram = function(gl, locations) {
|
||||||
|
gl.disableVertexAttribArray(locations.a_position);
|
||||||
|
gl.disableVertexAttribArray(locations.a_offsets);
|
||||||
|
gl.disableVertexAttribArray(locations.a_texCoord);
|
||||||
|
gl.disableVertexAttribArray(locations.a_rotateWithView);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
ol.render.webgl.TextReplay.prototype.drawReplay = function(gl, context, skippedFeaturesHash, hitDetection) {
|
||||||
|
var textures = this.textures_;
|
||||||
|
var startIndices = this.startIndices;
|
||||||
|
|
||||||
|
var i, ii, start, end, feature, featureUid;
|
||||||
|
for (i = 0, ii = textures.length, start = 0; i < ii; ++i) {
|
||||||
|
feature = this.startIndicesFeature[i];
|
||||||
|
featureUid = ol.getUid(feature).toString();
|
||||||
|
|
||||||
|
end = startIndices[i];
|
||||||
|
if (skippedFeaturesHash[featureUid] === undefined) {
|
||||||
|
gl.bindTexture(ol.webgl.TEXTURE_2D, textures[i]);
|
||||||
|
this.drawElements(gl, context, start, end);
|
||||||
|
}
|
||||||
|
start = end;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
ol.render.webgl.TextReplay.prototype.drawHitDetectionReplayOneByOne = function(gl, context, skippedFeaturesHash,
|
||||||
|
featureCallback, opt_hitExtent) {
|
||||||
|
var textures = this.textures_;
|
||||||
|
var startIndices = this.startIndices;
|
||||||
|
|
||||||
|
var i, start, end, feature, featureUid;
|
||||||
|
for (i = textures.length - 1; i >= 0; --i) {
|
||||||
|
feature = this.startIndicesFeature[i];
|
||||||
|
featureUid = ol.getUid(feature).toString();
|
||||||
|
|
||||||
|
start = (i > 0) ? startIndices[i - 1] : 0;
|
||||||
|
end = startIndices[i];
|
||||||
|
if (skippedFeaturesHash[featureUid] === undefined &&
|
||||||
|
feature.getGeometry() &&
|
||||||
|
(opt_hitExtent === undefined || ol.extent.intersects(
|
||||||
|
/** @type {Array<number>} */ (opt_hitExtent),
|
||||||
|
feature.getGeometry().getExtent()))) {
|
||||||
|
gl.bindTexture(ol.webgl.TEXTURE_2D, textures[i]);
|
||||||
|
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||||||
|
this.drawElements(gl, context, start, end);
|
||||||
|
|
||||||
|
var result = featureCallback(feature);
|
||||||
|
if (result) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
@@ -198,7 +486,20 @@ if (ol.ENABLE_WEBGL) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {ol.style.Text} textStyle Text style.
|
* @private
|
||||||
|
* @param {WebGLRenderingContext} gl Gl.
|
||||||
|
*/
|
||||||
|
ol.render.webgl.TextReplay.prototype.createTextures_ = function(gl) {
|
||||||
|
for (var i = 0, ii = this.images_.length; i < ii; ++i) {
|
||||||
|
var image = this.images_[i];
|
||||||
|
this.textures_.push(ol.webgl.Context.createTexture(
|
||||||
|
gl, image, ol.webgl.CLAMP_TO_EDGE, ol.webgl.CLAMP_TO_EDGE));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
ol.render.webgl.TextReplay.prototype.setTextStyle = function(textStyle) {
|
ol.render.webgl.TextReplay.prototype.setTextStyle = function(textStyle) {
|
||||||
var state = this.state_;
|
var state = this.state_;
|
||||||
@@ -216,16 +517,18 @@ if (ol.ENABLE_WEBGL) {
|
|||||||
var textStrokeStyle = textStyle.getStroke();
|
var textStrokeStyle = textStyle.getStroke();
|
||||||
if (!textStrokeStyle) {
|
if (!textStrokeStyle) {
|
||||||
state.strokeColor = null;
|
state.strokeColor = null;
|
||||||
|
state.lineWidth = 0;
|
||||||
} else {
|
} else {
|
||||||
var textStrokeStyleColor = textFillStyle.getColor();
|
var textStrokeStyleColor = textStrokeStyle.getColor();
|
||||||
state.strokeColor = ol.colorlike.asColorLike(textStrokeStyleColor ?
|
state.strokeColor = ol.colorlike.asColorLike(textStrokeStyleColor ?
|
||||||
textStrokeStyleColor : ol.render.webgl.defaultStrokeStyle);
|
textStrokeStyleColor : ol.render.webgl.defaultStrokeStyle);
|
||||||
state.lineWidth = textStrokeStyle.getWidth() || ol.render.webgl.defaultLineWidth;
|
state.lineWidth = textStrokeStyle.getWidth() || ol.render.webgl.defaultLineWidth;
|
||||||
state.lineCap = textStrokeStyle.getLineCap() || ol.render.webgl.defaultLineCap;
|
state.lineCap = textStrokeStyle.getLineCap() || ol.render.webgl.defaultLineCap;
|
||||||
state.lineDash = textStrokeStyle.getLineDash() || ol.render.webgl.defaultLineDash;
|
|
||||||
state.lineDashOffset = textStrokeStyle.getLineDashOffset() || ol.render.webgl.defaultLineDashOffset;
|
state.lineDashOffset = textStrokeStyle.getLineDashOffset() || ol.render.webgl.defaultLineDashOffset;
|
||||||
state.lineJoin = textStrokeStyle.getLineJoin() || ol.render.webgl.defaultLineJoin;
|
state.lineJoin = textStrokeStyle.getLineJoin() || ol.render.webgl.defaultLineJoin;
|
||||||
state.miterLimit = textStrokeStyle.getMiterLimit() || ol.render.webgl.defaultMiterLimit;
|
state.miterLimit = textStrokeStyle.getMiterLimit() || ol.render.webgl.defaultMiterLimit;
|
||||||
|
var lineDash = textStrokeStyle.getLineDash();
|
||||||
|
state.lineDash = lineDash ? lineDash.slice() : ol.render.webgl.defaultLineDash;
|
||||||
}
|
}
|
||||||
state.font = textStyle.getFont() || ol.render.webgl.defaultFont;
|
state.font = textStyle.getFont() || ol.render.webgl.defaultFont;
|
||||||
state.offsetX = textStyle.getOffsetX() || 0;
|
state.offsetX = textStyle.getOffsetX() || 0;
|
||||||
|
|||||||
41
src/ol/render/webgl/textreplay/defaultshader.glsl
Normal file
41
src/ol/render/webgl/textreplay/defaultshader.glsl
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
//! NAMESPACE=ol.render.webgl.textreplay.defaultshader
|
||||||
|
//! CLASS=ol.render.webgl.textreplay.defaultshader
|
||||||
|
|
||||||
|
|
||||||
|
//! COMMON
|
||||||
|
varying vec2 v_texCoord;
|
||||||
|
|
||||||
|
//! VERTEX
|
||||||
|
attribute vec2 a_position;
|
||||||
|
attribute vec2 a_texCoord;
|
||||||
|
attribute vec2 a_offsets;
|
||||||
|
attribute float a_rotateWithView;
|
||||||
|
|
||||||
|
uniform mat4 u_projectionMatrix;
|
||||||
|
uniform mat4 u_offsetScaleMatrix;
|
||||||
|
uniform mat4 u_offsetRotateMatrix;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
mat4 offsetMatrix = u_offsetScaleMatrix;
|
||||||
|
if (a_rotateWithView == 1.0) {
|
||||||
|
offsetMatrix = u_offsetScaleMatrix * u_offsetRotateMatrix;
|
||||||
|
}
|
||||||
|
vec4 offsets = offsetMatrix * vec4(a_offsets, 0.0, 0.0);
|
||||||
|
gl_Position = u_projectionMatrix * vec4(a_position, 0.0, 1.0) + offsets;
|
||||||
|
v_texCoord = a_texCoord;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! FRAGMENT
|
||||||
|
uniform float u_opacity;
|
||||||
|
uniform sampler2D u_image;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
vec4 texColor = texture2D(u_image, v_texCoord);
|
||||||
|
gl_FragColor.rgb = texColor.rgb;
|
||||||
|
float alpha = texColor.a * u_opacity;
|
||||||
|
if (alpha == 0.0) {
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
gl_FragColor.a = alpha;
|
||||||
|
}
|
||||||
148
src/ol/render/webgl/textreplay/defaultshader.js
Normal file
148
src/ol/render/webgl/textreplay/defaultshader.js
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
// This file is automatically generated, do not edit
|
||||||
|
/* eslint openlayers-internal/no-missing-requires: 0 */
|
||||||
|
goog.provide('ol.render.webgl.textreplay.defaultshader');
|
||||||
|
|
||||||
|
goog.require('ol');
|
||||||
|
goog.require('ol.webgl.Fragment');
|
||||||
|
goog.require('ol.webgl.Vertex');
|
||||||
|
|
||||||
|
if (ol.ENABLE_WEBGL) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @extends {ol.webgl.Fragment}
|
||||||
|
* @struct
|
||||||
|
*/
|
||||||
|
ol.render.webgl.textreplay.defaultshader.Fragment = function() {
|
||||||
|
ol.webgl.Fragment.call(this, ol.render.webgl.textreplay.defaultshader.Fragment.SOURCE);
|
||||||
|
};
|
||||||
|
ol.inherits(ol.render.webgl.textreplay.defaultshader.Fragment, ol.webgl.Fragment);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @const
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
ol.render.webgl.textreplay.defaultshader.Fragment.DEBUG_SOURCE = 'precision mediump float;\nvarying vec2 v_texCoord;\n\nuniform float u_opacity;\nuniform sampler2D u_image;\n\nvoid main(void) {\n vec4 texColor = texture2D(u_image, v_texCoord);\n gl_FragColor.rgb = texColor.rgb;\n float alpha = texColor.a * u_opacity;\n if (alpha == 0.0) {\n discard;\n }\n gl_FragColor.a = alpha;\n}\n';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @const
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
ol.render.webgl.textreplay.defaultshader.Fragment.OPTIMIZED_SOURCE = 'precision mediump float;varying vec2 a;uniform float i;uniform sampler2D j;void main(void){vec4 texColor=texture2D(j,a);gl_FragColor.rgb=texColor.rgb;float alpha=texColor.a*i;if(alpha==0.0){discard;}gl_FragColor.a=alpha;}';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @const
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
ol.render.webgl.textreplay.defaultshader.Fragment.SOURCE = ol.DEBUG_WEBGL ?
|
||||||
|
ol.render.webgl.textreplay.defaultshader.Fragment.DEBUG_SOURCE :
|
||||||
|
ol.render.webgl.textreplay.defaultshader.Fragment.OPTIMIZED_SOURCE;
|
||||||
|
|
||||||
|
|
||||||
|
ol.render.webgl.textreplay.defaultshader.fragment = new ol.render.webgl.textreplay.defaultshader.Fragment();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @extends {ol.webgl.Vertex}
|
||||||
|
* @struct
|
||||||
|
*/
|
||||||
|
ol.render.webgl.textreplay.defaultshader.Vertex = function() {
|
||||||
|
ol.webgl.Vertex.call(this, ol.render.webgl.textreplay.defaultshader.Vertex.SOURCE);
|
||||||
|
};
|
||||||
|
ol.inherits(ol.render.webgl.textreplay.defaultshader.Vertex, ol.webgl.Vertex);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @const
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
ol.render.webgl.textreplay.defaultshader.Vertex.DEBUG_SOURCE = 'varying vec2 v_texCoord;\n\nattribute vec2 a_position;\nattribute vec2 a_texCoord;\nattribute vec2 a_offsets;\nattribute float a_rotateWithView;\n\nuniform mat4 u_projectionMatrix;\nuniform mat4 u_offsetScaleMatrix;\nuniform mat4 u_offsetRotateMatrix;\n\nvoid main(void) {\n mat4 offsetMatrix = u_offsetScaleMatrix;\n if (a_rotateWithView == 1.0) {\n offsetMatrix = u_offsetScaleMatrix * u_offsetRotateMatrix;\n }\n vec4 offsets = offsetMatrix * vec4(a_offsets, 0.0, 0.0);\n gl_Position = u_projectionMatrix * vec4(a_position, 0.0, 1.0) + offsets;\n v_texCoord = a_texCoord;\n}\n\n\n';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @const
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
ol.render.webgl.textreplay.defaultshader.Vertex.OPTIMIZED_SOURCE = 'varying vec2 a;attribute vec2 b;attribute vec2 c;attribute vec2 d;attribute float e;uniform mat4 f;uniform mat4 g;uniform mat4 h;void main(void){mat4 offsetMatrix=g;if(e==1.0){offsetMatrix=g*h;}vec4 offsets=offsetMatrix*vec4(d,0.0,0.0);gl_Position=f*vec4(b,0.0,1.0)+offsets;a=c;}';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @const
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
ol.render.webgl.textreplay.defaultshader.Vertex.SOURCE = ol.DEBUG_WEBGL ?
|
||||||
|
ol.render.webgl.textreplay.defaultshader.Vertex.DEBUG_SOURCE :
|
||||||
|
ol.render.webgl.textreplay.defaultshader.Vertex.OPTIMIZED_SOURCE;
|
||||||
|
|
||||||
|
|
||||||
|
ol.render.webgl.textreplay.defaultshader.vertex = new ol.render.webgl.textreplay.defaultshader.Vertex();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @param {WebGLRenderingContext} gl GL.
|
||||||
|
* @param {WebGLProgram} program Program.
|
||||||
|
* @struct
|
||||||
|
*/
|
||||||
|
ol.render.webgl.textreplay.defaultshader.Locations = function(gl, program) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {WebGLUniformLocation}
|
||||||
|
*/
|
||||||
|
this.u_image = gl.getUniformLocation(
|
||||||
|
program, ol.DEBUG_WEBGL ? 'u_image' : 'j');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {WebGLUniformLocation}
|
||||||
|
*/
|
||||||
|
this.u_offsetRotateMatrix = gl.getUniformLocation(
|
||||||
|
program, ol.DEBUG_WEBGL ? 'u_offsetRotateMatrix' : 'h');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {WebGLUniformLocation}
|
||||||
|
*/
|
||||||
|
this.u_offsetScaleMatrix = gl.getUniformLocation(
|
||||||
|
program, ol.DEBUG_WEBGL ? 'u_offsetScaleMatrix' : 'g');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {WebGLUniformLocation}
|
||||||
|
*/
|
||||||
|
this.u_opacity = gl.getUniformLocation(
|
||||||
|
program, ol.DEBUG_WEBGL ? 'u_opacity' : 'i');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {WebGLUniformLocation}
|
||||||
|
*/
|
||||||
|
this.u_projectionMatrix = gl.getUniformLocation(
|
||||||
|
program, ol.DEBUG_WEBGL ? 'u_projectionMatrix' : 'f');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
|
this.a_offsets = gl.getAttribLocation(
|
||||||
|
program, ol.DEBUG_WEBGL ? 'a_offsets' : 'd');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
|
this.a_position = gl.getAttribLocation(
|
||||||
|
program, ol.DEBUG_WEBGL ? 'a_position' : 'b');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
|
this.a_rotateWithView = gl.getAttribLocation(
|
||||||
|
program, ol.DEBUG_WEBGL ? 'a_rotateWithView' : 'e');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
|
this.a_texCoord = gl.getAttribLocation(
|
||||||
|
program, ol.DEBUG_WEBGL ? 'a_texCoord' : 'c');
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user