Add circle replay to WebGL renderer
This commit is contained in:
@@ -282,6 +282,7 @@ ol.render.canvas.ReplayGroup.prototype.replayHitDetection_ = function(
|
||||
* number, boolean)>}
|
||||
*/
|
||||
ol.render.canvas.ReplayGroup.BATCH_CONSTRUCTORS_ = {
|
||||
'Circle': ol.render.canvas.PolygonReplay,
|
||||
'Image': ol.render.canvas.ImageReplay,
|
||||
'LineString': ol.render.canvas.LineStringReplay,
|
||||
'Polygon': ol.render.canvas.PolygonReplay,
|
||||
|
||||
@@ -9,6 +9,7 @@ goog.require('ol.render.ReplayType');
|
||||
*/
|
||||
ol.render.replay.ORDER = [
|
||||
ol.render.ReplayType.POLYGON,
|
||||
ol.render.ReplayType.CIRCLE,
|
||||
ol.render.ReplayType.LINE_STRING,
|
||||
ol.render.ReplayType.IMAGE,
|
||||
ol.render.ReplayType.TEXT
|
||||
|
||||
@@ -5,6 +5,7 @@ goog.provide('ol.render.ReplayType');
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.render.ReplayType = {
|
||||
CIRCLE: 'Circle',
|
||||
IMAGE: 'Image',
|
||||
LINE_STRING: 'LineString',
|
||||
POLYGON: 'Polygon',
|
||||
|
||||
101
src/ol/render/webgl/circlereplay/defaultshader.glsl
Normal file
101
src/ol/render/webgl/circlereplay/defaultshader.glsl
Normal file
@@ -0,0 +1,101 @@
|
||||
//! NAMESPACE=ol.render.webgl.circlereplay.defaultshader
|
||||
//! CLASS=ol.render.webgl.circlereplay.defaultshader
|
||||
|
||||
|
||||
//! COMMON
|
||||
varying vec2 v_center;
|
||||
varying vec2 v_offset;
|
||||
varying float v_halfWidth;
|
||||
|
||||
|
||||
//! VERTEX
|
||||
attribute vec2 a_position;
|
||||
attribute float a_instruction;
|
||||
attribute float a_radius;
|
||||
|
||||
uniform mat4 u_projectionMatrix;
|
||||
uniform mat4 u_offsetScaleMatrix;
|
||||
uniform mat4 u_offsetRotateMatrix;
|
||||
uniform float u_lineWidth;
|
||||
|
||||
void main(void) {
|
||||
mat4 offsetMatrix = u_offsetScaleMatrix * u_offsetRotateMatrix;
|
||||
v_center = vec4(u_projectionMatrix * vec4(a_position, 0., 1.)).xy;
|
||||
float newX, newY;
|
||||
float lineWidth = u_lineWidth;
|
||||
if (lineWidth == 0.0) {
|
||||
lineWidth = 2.0;
|
||||
}
|
||||
v_halfWidth = u_lineWidth / 2.0;
|
||||
vec2 offset;
|
||||
// Radius with anitaliasing (roughly).
|
||||
float radius = a_radius + 3.0;
|
||||
// Until we get gl_VertexID in WebGL, we store an instruction.
|
||||
if (a_instruction == 0.0) {
|
||||
newX = a_position.x - radius;
|
||||
newY = a_position.y - radius;
|
||||
// Offsetting the edges of the triangle by lineWidth / 2 is necessary, however
|
||||
// we should also leave some space for the antialiasing, thus we offset by lineWidth.
|
||||
offset = vec2(-lineWidth, -lineWidth);
|
||||
} else {
|
||||
float sqrtVal = sqrt(2.0) + 1.0;
|
||||
if (a_instruction == 1.0) {
|
||||
newX = a_position.x + sqrtVal * radius;
|
||||
newY = a_position.y - radius;
|
||||
offset = vec2(lineWidth * sqrtVal, -lineWidth);
|
||||
} else {
|
||||
newX = a_position.x - radius;
|
||||
newY = a_position.y + sqrtVal * radius;
|
||||
offset = vec2(-lineWidth, lineWidth * sqrtVal);
|
||||
}
|
||||
}
|
||||
|
||||
gl_Position = u_projectionMatrix * vec4(newX, newY, 0., 1.) + offsetMatrix *
|
||||
vec4(offset, 0., 0.);
|
||||
v_offset = vec4(u_projectionMatrix * vec4(a_position.x + a_radius, a_position.y, 0., 1.)).xy;
|
||||
}
|
||||
|
||||
|
||||
//! FRAGMENT
|
||||
|
||||
uniform float u_opacity;
|
||||
uniform vec4 u_fillColor;
|
||||
uniform vec4 u_strokeColor;
|
||||
uniform vec2 u_size;
|
||||
uniform float u_pixelRatio;
|
||||
|
||||
void main(void) {
|
||||
vec2 windowCenter = vec2((v_center.x + 1.0) / 2.0 * u_size.x * u_pixelRatio,
|
||||
(v_center.y + 1.0) / 2.0 * u_size.y * u_pixelRatio);
|
||||
vec2 windowOffset = vec2((v_offset.x + 1.0) / 2.0 * u_size.x * u_pixelRatio,
|
||||
(v_offset.y + 1.0) / 2.0 * u_size.y * u_pixelRatio);
|
||||
float radius = length(windowCenter - windowOffset);
|
||||
float dist = length(windowCenter - gl_FragCoord.xy);
|
||||
if (dist > (radius + v_halfWidth) * u_pixelRatio) {
|
||||
if (u_strokeColor.a == 0.0) {
|
||||
gl_FragColor = u_fillColor;
|
||||
} else {
|
||||
gl_FragColor = u_strokeColor;
|
||||
}
|
||||
gl_FragColor.a = gl_FragColor.a - (dist - (radius + v_halfWidth) * u_pixelRatio);
|
||||
} else if (u_fillColor.a == 0.0) {
|
||||
// Hooray, no fill, just stroke. We can use real antialiasing.
|
||||
gl_FragColor = u_strokeColor;
|
||||
if (dist < (radius - v_halfWidth) * u_pixelRatio) {
|
||||
gl_FragColor.a = gl_FragColor.a - ((radius - v_halfWidth) * u_pixelRatio - dist);
|
||||
}
|
||||
} else {
|
||||
gl_FragColor = u_fillColor;
|
||||
float strokeDist = (radius - v_halfWidth) * u_pixelRatio;
|
||||
if (dist > strokeDist) {
|
||||
gl_FragColor = u_strokeColor;
|
||||
} else if (dist >= strokeDist - 2.0) {
|
||||
float step = smoothstep(strokeDist - 2.0, strokeDist, dist);
|
||||
gl_FragColor = mix(u_fillColor, u_strokeColor, step);
|
||||
}
|
||||
}
|
||||
gl_FragColor.a = gl_FragColor.a * u_opacity;
|
||||
if (gl_FragColor.a <= 0.0) {
|
||||
discard;
|
||||
}
|
||||
}
|
||||
162
src/ol/render/webgl/circlereplay/defaultshader.js
Normal file
162
src/ol/render/webgl/circlereplay/defaultshader.js
Normal file
@@ -0,0 +1,162 @@
|
||||
// This file is automatically generated, do not edit
|
||||
goog.provide('ol.render.webgl.circlereplay.defaultshader');
|
||||
|
||||
goog.require('ol');
|
||||
goog.require('ol.webgl.Fragment');
|
||||
goog.require('ol.webgl.Vertex');
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.webgl.Fragment}
|
||||
* @struct
|
||||
*/
|
||||
ol.render.webgl.circlereplay.defaultshader.Fragment = function() {
|
||||
ol.webgl.Fragment.call(this, ol.render.webgl.circlereplay.defaultshader.Fragment.SOURCE);
|
||||
};
|
||||
ol.inherits(ol.render.webgl.circlereplay.defaultshader.Fragment, ol.webgl.Fragment);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.render.webgl.circlereplay.defaultshader.Fragment.DEBUG_SOURCE = 'precision mediump float;\nvarying vec2 v_center;\nvarying vec2 v_offset;\nvarying float v_halfWidth;\n\n\n\nuniform float u_opacity;\nuniform vec4 u_fillColor;\nuniform vec4 u_strokeColor;\nuniform vec2 u_size;\nuniform float u_pixelRatio;\n\nvoid main(void) {\n vec2 windowCenter = vec2((v_center.x + 1.0) / 2.0 * u_size.x * u_pixelRatio,\n (v_center.y + 1.0) / 2.0 * u_size.y * u_pixelRatio);\n vec2 windowOffset = vec2((v_offset.x + 1.0) / 2.0 * u_size.x * u_pixelRatio,\n (v_offset.y + 1.0) / 2.0 * u_size.y * u_pixelRatio);\n float radius = length(windowCenter - windowOffset);\n float dist = length(windowCenter - gl_FragCoord.xy);\n if (dist > (radius + v_halfWidth) * u_pixelRatio) {\n if (u_strokeColor.a == 0.0) {\n gl_FragColor = u_fillColor;\n } else {\n gl_FragColor = u_strokeColor;\n }\n gl_FragColor.a = gl_FragColor.a - (dist - (radius + v_halfWidth) * u_pixelRatio);\n } else if (u_fillColor.a == 0.0) {\n // Hooray, no fill, just stroke. We can use real antialiasing.\n gl_FragColor = u_strokeColor;\n if (dist < (radius - v_halfWidth) * u_pixelRatio) {\n gl_FragColor.a = gl_FragColor.a - ((radius - v_halfWidth) * u_pixelRatio - dist);\n }\n } else {\n gl_FragColor = u_fillColor;\n float strokeDist = (radius - v_halfWidth) * u_pixelRatio;\n if (dist > strokeDist) {\n gl_FragColor = u_strokeColor;\n } else if (dist >= strokeDist - 2.0) {\n float step = smoothstep(strokeDist - 2.0, strokeDist, dist);\n gl_FragColor = mix(u_fillColor, u_strokeColor, step);\n }\n }\n gl_FragColor.a = gl_FragColor.a * u_opacity;\n if (gl_FragColor.a <= 0.0) {\n discard;\n }\n}\n';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.render.webgl.circlereplay.defaultshader.Fragment.OPTIMIZED_SOURCE = 'precision mediump float;varying vec2 a;varying vec2 b;varying float c;uniform float k;uniform vec4 l;uniform vec4 m;uniform vec2 n;uniform float o;void main(void){vec2 windowCenter=vec2((a.x+1.0)/2.0*n.x*o,(a.y+1.0)/2.0*n.y*o);vec2 windowOffset=vec2((b.x+1.0)/2.0*n.x*o,(b.y+1.0)/2.0*n.y*o);float radius=length(windowCenter-windowOffset);float dist=length(windowCenter-gl_FragCoord.xy);if(dist>(radius+c)*o){if(m.a==0.0){gl_FragColor=l;}else{gl_FragColor=m;}gl_FragColor.a=gl_FragColor.a-(dist-(radius+c)*o);}else if(l.a==0.0){gl_FragColor=m;if(dist<(radius-c)*o){gl_FragColor.a=gl_FragColor.a-((radius-c)*o-dist);}} else{gl_FragColor=l;float strokeDist=(radius-c)*o;if(dist>strokeDist){gl_FragColor=m;}else if(dist>=strokeDist-2.0){float step=smoothstep(strokeDist-2.0,strokeDist,dist);gl_FragColor=mix(l,m,step);}} gl_FragColor.a=gl_FragColor.a*k;if(gl_FragColor.a<=0.0){discard;}}';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.render.webgl.circlereplay.defaultshader.Fragment.SOURCE = ol.DEBUG ?
|
||||
ol.render.webgl.circlereplay.defaultshader.Fragment.DEBUG_SOURCE :
|
||||
ol.render.webgl.circlereplay.defaultshader.Fragment.OPTIMIZED_SOURCE;
|
||||
|
||||
|
||||
ol.render.webgl.circlereplay.defaultshader.fragment = new ol.render.webgl.circlereplay.defaultshader.Fragment();
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.webgl.Vertex}
|
||||
* @struct
|
||||
*/
|
||||
ol.render.webgl.circlereplay.defaultshader.Vertex = function() {
|
||||
ol.webgl.Vertex.call(this, ol.render.webgl.circlereplay.defaultshader.Vertex.SOURCE);
|
||||
};
|
||||
ol.inherits(ol.render.webgl.circlereplay.defaultshader.Vertex, ol.webgl.Vertex);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.render.webgl.circlereplay.defaultshader.Vertex.DEBUG_SOURCE = 'varying vec2 v_center;\nvarying vec2 v_offset;\nvarying float v_halfWidth;\n\n\nattribute vec2 a_position;\nattribute float a_instruction;\nattribute float a_radius;\n\nuniform mat4 u_projectionMatrix;\nuniform mat4 u_offsetScaleMatrix;\nuniform mat4 u_offsetRotateMatrix;\nuniform float u_lineWidth;\n\nvoid main(void) {\n mat4 offsetMatrix = u_offsetScaleMatrix * u_offsetRotateMatrix;\n v_center = vec4(u_projectionMatrix * vec4(a_position, 0., 1.)).xy;\n float newX, newY;\n float lineWidth = u_lineWidth;\n if (lineWidth == 0.0) {\n lineWidth = 2.0;\n }\n v_halfWidth = u_lineWidth / 2.0;\n vec2 offset;\n // Radius with anitaliasing (roughly).\n float radius = a_radius + 3.0;\n // Until we get gl_VertexID in WebGL, we store an instruction.\n if (a_instruction == 0.0) {\n newX = a_position.x - radius;\n newY = a_position.y - radius;\n // Offsetting the edges of the triangle by lineWidth / 2 is necessary, however\n // we should also leave some space for the antialiasing, thus we offset by lineWidth.\n offset = vec2(-lineWidth, -lineWidth);\n } else {\n float sqrtVal = sqrt(2.0) + 1.0;\n if (a_instruction == 1.0) {\n newX = a_position.x + sqrtVal * radius;\n newY = a_position.y - radius;\n offset = vec2(lineWidth * sqrtVal, -lineWidth);\n } else {\n newX = a_position.x - radius;\n newY = a_position.y + sqrtVal * radius;\n offset = vec2(-lineWidth, lineWidth * sqrtVal);\n }\n }\n\n gl_Position = u_projectionMatrix * vec4(newX, newY, 0., 1.) + offsetMatrix *\n vec4(offset, 0., 0.);\n v_offset = vec4(u_projectionMatrix * vec4(a_position.x + a_radius, a_position.y, 0., 1.)).xy;\n}\n\n\n';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.render.webgl.circlereplay.defaultshader.Vertex.OPTIMIZED_SOURCE = 'varying vec2 a;varying vec2 b;varying float c;attribute vec2 d;attribute float e;attribute float f;uniform mat4 g;uniform mat4 h;uniform mat4 i;uniform float j;void main(void){mat4 offsetMatrix=h*i;a=vec4(g*vec4(d,0.,1.)).xy;float newX,newY;float lineWidth=j;if(lineWidth==0.0){lineWidth=2.0;}c=j/2.0;vec2 offset;float radius=f+3.0;if(e==0.0){newX=d.x-radius;newY=d.y-radius;offset=vec2(-lineWidth,-lineWidth);}else{float sqrtVal=sqrt(2.0)+1.0;if(e==1.0){newX=d.x+sqrtVal*radius;newY=d.y-radius;offset=vec2(lineWidth*sqrtVal,-lineWidth);}else{newX=d.x-radius;newY=d.y+sqrtVal*radius;offset=vec2(-lineWidth,lineWidth*sqrtVal);}} gl_Position=g*vec4(newX,newY,0.,1.)+offsetMatrix*vec4(offset,0.,0.);b=vec4(g*vec4(d.x+f,d.y,0.,1.)).xy;}';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.render.webgl.circlereplay.defaultshader.Vertex.SOURCE = ol.DEBUG ?
|
||||
ol.render.webgl.circlereplay.defaultshader.Vertex.DEBUG_SOURCE :
|
||||
ol.render.webgl.circlereplay.defaultshader.Vertex.OPTIMIZED_SOURCE;
|
||||
|
||||
|
||||
ol.render.webgl.circlereplay.defaultshader.vertex = new ol.render.webgl.circlereplay.defaultshader.Vertex();
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {WebGLRenderingContext} gl GL.
|
||||
* @param {WebGLProgram} program Program.
|
||||
* @struct
|
||||
*/
|
||||
ol.render.webgl.circlereplay.defaultshader.Locations = function(gl, program) {
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_fillColor = gl.getUniformLocation(
|
||||
program, ol.DEBUG ? 'u_fillColor' : 'l');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_lineWidth = gl.getUniformLocation(
|
||||
program, ol.DEBUG ? 'u_lineWidth' : 'j');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_offsetRotateMatrix = gl.getUniformLocation(
|
||||
program, ol.DEBUG ? 'u_offsetRotateMatrix' : 'i');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_offsetScaleMatrix = gl.getUniformLocation(
|
||||
program, ol.DEBUG ? 'u_offsetScaleMatrix' : 'h');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_opacity = gl.getUniformLocation(
|
||||
program, ol.DEBUG ? 'u_opacity' : 'k');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_pixelRatio = gl.getUniformLocation(
|
||||
program, ol.DEBUG ? 'u_pixelRatio' : 'o');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_projectionMatrix = gl.getUniformLocation(
|
||||
program, ol.DEBUG ? 'u_projectionMatrix' : 'g');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_size = gl.getUniformLocation(
|
||||
program, ol.DEBUG ? 'u_size' : 'n');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_strokeColor = gl.getUniformLocation(
|
||||
program, ol.DEBUG ? 'u_strokeColor' : 'm');
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.a_instruction = gl.getAttribLocation(
|
||||
program, ol.DEBUG ? 'a_instruction' : 'e');
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.a_position = gl.getAttribLocation(
|
||||
program, ol.DEBUG ? 'a_position' : 'd');
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.a_radius = gl.getAttribLocation(
|
||||
program, ol.DEBUG ? 'a_radius' : 'f');
|
||||
};
|
||||
418
src/ol/render/webgl/circlereplay/index.js
Normal file
418
src/ol/render/webgl/circlereplay/index.js
Normal file
@@ -0,0 +1,418 @@
|
||||
goog.provide('ol.render.webgl.CircleReplay');
|
||||
|
||||
goog.require('ol');
|
||||
goog.require('ol.color');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.obj');
|
||||
goog.require('ol.geom.flat.transform');
|
||||
goog.require('ol.render.webgl.circlereplay.defaultshader');
|
||||
goog.require('ol.render.webgl.Replay');
|
||||
goog.require('ol.render.webgl');
|
||||
goog.require('ol.webgl');
|
||||
goog.require('ol.webgl.Buffer');
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.render.webgl.Replay}
|
||||
* @param {number} tolerance Tolerance.
|
||||
* @param {ol.Extent} maxExtent Max extent.
|
||||
* @struct
|
||||
*/
|
||||
ol.render.webgl.CircleReplay = function(tolerance, maxExtent) {
|
||||
ol.render.webgl.Replay.call(this, tolerance, maxExtent);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.render.webgl.circlereplay.defaultshader.Locations}
|
||||
*/
|
||||
this.defaultLocations_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<Array.<Array.<number>|number>>}
|
||||
*/
|
||||
this.styles_ = [];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this.styleIndices_ = [];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.radius_ = 0;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {{fillColor: (Array.<number>|null),
|
||||
* strokeColor: (Array.<number>|null),
|
||||
* lineDash: Array.<number>,
|
||||
* lineWidth: (number|undefined),
|
||||
* changed: boolean}|null}
|
||||
*/
|
||||
this.state_ = {
|
||||
fillColor: null,
|
||||
strokeColor: null,
|
||||
lineDash: null,
|
||||
lineWidth: undefined,
|
||||
changed: false
|
||||
};
|
||||
|
||||
};
|
||||
ol.inherits(ol.render.webgl.CircleReplay, ol.render.webgl.Replay);
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
*/
|
||||
ol.render.webgl.CircleReplay.prototype.drawCoordinates_ = function(
|
||||
flatCoordinates, offset, end, stride) {
|
||||
var numVertices = this.vertices.length;
|
||||
var numIndices = this.indices.length;
|
||||
var n = numVertices / 4;
|
||||
var i, ii;
|
||||
for (i = offset, ii = end; i < ii; i += stride) {
|
||||
this.vertices[numVertices++] = flatCoordinates[i];
|
||||
this.vertices[numVertices++] = flatCoordinates[i + 1];
|
||||
this.vertices[numVertices++] = 0;
|
||||
this.vertices[numVertices++] = this.radius_;
|
||||
|
||||
this.vertices[numVertices++] = flatCoordinates[i];
|
||||
this.vertices[numVertices++] = flatCoordinates[i + 1];
|
||||
this.vertices[numVertices++] = 1;
|
||||
this.vertices[numVertices++] = this.radius_;
|
||||
|
||||
this.vertices[numVertices++] = flatCoordinates[i];
|
||||
this.vertices[numVertices++] = flatCoordinates[i + 1];
|
||||
this.vertices[numVertices++] = 2;
|
||||
this.vertices[numVertices++] = this.radius_;
|
||||
|
||||
this.indices[numIndices++] = n++;
|
||||
this.indices[numIndices++] = n++;
|
||||
this.indices[numIndices++] = n++;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.webgl.CircleReplay.prototype.drawCircle = function(circleGeometry, feature) {
|
||||
var radius = circleGeometry.getRadius();
|
||||
var stride = circleGeometry.getStride();
|
||||
if (radius) {
|
||||
this.startIndices.push(this.indices.length);
|
||||
this.startIndicesFeature.push(feature);
|
||||
if (this.state_.changed) {
|
||||
this.styleIndices_.push(this.indices.length);
|
||||
this.state_.changed = false;
|
||||
}
|
||||
|
||||
this.radius_ = radius;
|
||||
var flatCoordinates = circleGeometry.getFlatCoordinates();
|
||||
flatCoordinates = ol.geom.flat.transform.translate(flatCoordinates, 0, 2,
|
||||
stride, -this.origin[0], -this.origin[1]);
|
||||
this.drawCoordinates_(flatCoordinates, 0, 2, stride);
|
||||
} else {
|
||||
if (this.state_.changed) {
|
||||
this.styles_.pop();
|
||||
if (this.styles_.length) {
|
||||
var lastState = this.styles_[this.styles_.length - 1];
|
||||
this.state_.fillColor = /** @type {Array.<number>} */ (lastState[0]);
|
||||
this.state_.strokeColor = /** @type {Array.<number>} */ (lastState[1]);
|
||||
this.state_.lineWidth = /** @type {number} */ (lastState[2]);
|
||||
this.state_.changed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
**/
|
||||
ol.render.webgl.CircleReplay.prototype.finish = function(context) {
|
||||
// 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);
|
||||
|
||||
this.startIndices.push(this.indices.length);
|
||||
|
||||
//Clean up, if there is nothing to draw
|
||||
if (this.styleIndices_.length === 0 && this.styles_.length > 0) {
|
||||
this.styles_ = [];
|
||||
}
|
||||
|
||||
this.vertices = null;
|
||||
this.indices = null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.webgl.CircleReplay.prototype.getDeleteResourcesFunction = function(context) {
|
||||
// We only delete our stuff here. The shaders and the program may
|
||||
// be used by other PolygonReplay instances (for other layers). And
|
||||
// they will be deleted when disposing of the ol.webgl.Context
|
||||
// object.
|
||||
ol.DEBUG && console.assert(this.verticesBuffer,
|
||||
'verticesBuffer must not be null');
|
||||
ol.DEBUG && console.assert(this.indicesBuffer,
|
||||
'indicesBuffer must not be null');
|
||||
var verticesBuffer = this.verticesBuffer;
|
||||
var indicesBuffer = this.indicesBuffer;
|
||||
return function() {
|
||||
context.deleteBuffer(verticesBuffer);
|
||||
context.deleteBuffer(indicesBuffer);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.webgl.CircleReplay.prototype.setUpProgram = function(gl, context, size, pixelRatio) {
|
||||
// get the program
|
||||
var fragmentShader, vertexShader;
|
||||
fragmentShader = ol.render.webgl.circlereplay.defaultshader.fragment;
|
||||
vertexShader = ol.render.webgl.circlereplay.defaultshader.vertex;
|
||||
var program = context.getProgram(fragmentShader, vertexShader);
|
||||
|
||||
// get the locations
|
||||
var locations;
|
||||
if (!this.defaultLocations_) {
|
||||
locations =
|
||||
new ol.render.webgl.circlereplay.defaultshader.Locations(gl, program);
|
||||
this.defaultLocations_ = locations;
|
||||
} else {
|
||||
locations = this.defaultLocations_;
|
||||
}
|
||||
|
||||
context.useProgram(program);
|
||||
|
||||
// enable the vertex attrib arrays
|
||||
gl.enableVertexAttribArray(locations.a_position);
|
||||
gl.vertexAttribPointer(locations.a_position, 2, ol.webgl.FLOAT,
|
||||
false, 16, 0);
|
||||
|
||||
gl.enableVertexAttribArray(locations.a_instruction);
|
||||
gl.vertexAttribPointer(locations.a_instruction, 1, ol.webgl.FLOAT,
|
||||
false, 16, 8);
|
||||
|
||||
gl.enableVertexAttribArray(locations.a_radius);
|
||||
gl.vertexAttribPointer(locations.a_radius, 1, ol.webgl.FLOAT,
|
||||
false, 16, 12);
|
||||
|
||||
// Enable renderer specific uniforms.
|
||||
gl.uniform2fv(locations.u_size, size);
|
||||
gl.uniform1f(locations.u_pixelRatio, pixelRatio);
|
||||
|
||||
return locations;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.webgl.CircleReplay.prototype.shutDownProgram = function(gl, locations) {
|
||||
gl.disableVertexAttribArray(locations.a_position);
|
||||
gl.disableVertexAttribArray(locations.a_instruction);
|
||||
gl.disableVertexAttribArray(locations.a_radius);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.webgl.CircleReplay.prototype.drawReplay = function(gl, context, skippedFeaturesHash, hitDetection) {
|
||||
if (!ol.obj.isEmpty(skippedFeaturesHash)) {
|
||||
this.drawReplaySkipping_(gl, context, skippedFeaturesHash);
|
||||
} else {
|
||||
ol.DEBUG && console.assert(this.styles_.length === this.styleIndices_.length,
|
||||
'number of styles and styleIndices match');
|
||||
|
||||
//Draw by style groups to minimize drawElements() calls.
|
||||
var i, start, end, nextStyle;
|
||||
end = this.startIndices[this.startIndices.length - 1];
|
||||
for (i = this.styleIndices_.length - 1; i >= 0; --i) {
|
||||
start = this.styleIndices_[i];
|
||||
nextStyle = this.styles_[i];
|
||||
this.setFillStyle_(gl, /** @type {Array.<number>} */ (nextStyle[0]));
|
||||
this.setStrokeStyle_(gl, /** @type {Array.<number>} */ (nextStyle[1]),
|
||||
/** @type {number} */ (nextStyle[2]));
|
||||
this.drawElements(gl, context, start, end);
|
||||
end = start;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.webgl.CircleReplay.prototype.drawHitDetectionReplayOneByOne = function(gl, context, skippedFeaturesHash,
|
||||
featureCallback, opt_hitExtent) {
|
||||
ol.DEBUG && console.assert(this.styles_.length === this.styleIndices_.length,
|
||||
'number of styles and styleIndices match');
|
||||
ol.DEBUG && console.assert(this.startIndices.length - 1 === this.startIndicesFeature.length,
|
||||
'number of startIndices and startIndicesFeature match');
|
||||
|
||||
var i, start, end, nextStyle, groupStart, feature, featureUid, featureIndex;
|
||||
featureIndex = this.startIndices.length - 2;
|
||||
end = this.startIndices[featureIndex + 1];
|
||||
for (i = this.styleIndices_.length - 1; i >= 0; --i) {
|
||||
nextStyle = this.styles_[i];
|
||||
this.setFillStyle_(gl, /** @type {Array.<number>} */ (nextStyle[0]));
|
||||
this.setStrokeStyle_(gl, /** @type {Array.<number>} */ (nextStyle[1]),
|
||||
/** @type {number} */ (nextStyle[2]));
|
||||
groupStart = this.styleIndices_[i];
|
||||
|
||||
while (featureIndex >= 0 &&
|
||||
this.startIndices[featureIndex] >= groupStart) {
|
||||
start = this.startIndices[featureIndex];
|
||||
feature = this.startIndicesFeature[featureIndex];
|
||||
featureUid = ol.getUid(feature).toString();
|
||||
|
||||
if (skippedFeaturesHash[featureUid] === undefined &&
|
||||
feature.getGeometry() &&
|
||||
(opt_hitExtent === undefined || ol.extent.intersects(
|
||||
/** @type {Array<number>} */ (opt_hitExtent),
|
||||
feature.getGeometry().getExtent()))) {
|
||||
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||||
this.drawElements(gl, context, start, end);
|
||||
|
||||
var result = featureCallback(feature);
|
||||
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
featureIndex--;
|
||||
end = start;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {WebGLRenderingContext} gl gl.
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @param {Object} skippedFeaturesHash Ids of features to skip.
|
||||
*/
|
||||
ol.render.webgl.CircleReplay.prototype.drawReplaySkipping_ = function(gl, context, skippedFeaturesHash) {
|
||||
ol.DEBUG && console.assert(this.startIndices.length - 1 === this.startIndicesFeature.length,
|
||||
'number of startIndices and startIndicesFeature match');
|
||||
|
||||
var i, start, end, nextStyle, groupStart, feature, featureUid, featureIndex, featureStart;
|
||||
featureIndex = this.startIndices.length - 2;
|
||||
end = start = this.startIndices[featureIndex + 1];
|
||||
for (i = this.styleIndices_.length - 1; i >= 0; --i) {
|
||||
nextStyle = this.styles_[i];
|
||||
this.setFillStyle_(gl, /** @type {Array.<number>} */ (nextStyle[0]));
|
||||
this.setStrokeStyle_(gl, /** @type {Array.<number>} */ (nextStyle[1]),
|
||||
/** @type {number} */ (nextStyle[2]));
|
||||
groupStart = this.styleIndices_[i];
|
||||
|
||||
while (featureIndex >= 0 &&
|
||||
this.startIndices[featureIndex] >= groupStart) {
|
||||
featureStart = this.startIndices[featureIndex];
|
||||
feature = this.startIndicesFeature[featureIndex];
|
||||
featureUid = ol.getUid(feature).toString();
|
||||
|
||||
if (skippedFeaturesHash[featureUid]) {
|
||||
if (start !== end) {
|
||||
this.drawElements(gl, context, start, end);
|
||||
}
|
||||
end = featureStart;
|
||||
}
|
||||
featureIndex--;
|
||||
start = featureStart;
|
||||
}
|
||||
if (start !== end) {
|
||||
this.drawElements(gl, context, start, end);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {WebGLRenderingContext} gl gl.
|
||||
* @param {Array.<number>} color Color.
|
||||
*/
|
||||
ol.render.webgl.CircleReplay.prototype.setFillStyle_ = function(gl, color) {
|
||||
gl.uniform4fv(this.defaultLocations_.u_fillColor, color);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {WebGLRenderingContext} gl gl.
|
||||
* @param {Array.<number>} color Color.
|
||||
* @param {number} lineWidth Line width.
|
||||
*/
|
||||
ol.render.webgl.CircleReplay.prototype.setStrokeStyle_ = function(gl, color, lineWidth) {
|
||||
gl.uniform4fv(this.defaultLocations_.u_strokeColor, color);
|
||||
gl.uniform1f(this.defaultLocations_.u_lineWidth, lineWidth);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.webgl.CircleReplay.prototype.setFillStrokeStyle = function(fillStyle, strokeStyle) {
|
||||
ol.DEBUG && console.assert(this.state_, 'this.state_ should not be null');
|
||||
var strokeStyleColor, strokeStyleWidth;
|
||||
if (strokeStyle) {
|
||||
var strokeStyleLineDash = strokeStyle.getLineDash();
|
||||
this.state_.lineDash = strokeStyleLineDash ?
|
||||
strokeStyleLineDash : ol.render.webgl.defaultLineDash;
|
||||
strokeStyleColor = strokeStyle.getColor();
|
||||
if (!(strokeStyleColor instanceof CanvasGradient) &&
|
||||
!(strokeStyleColor instanceof CanvasPattern)) {
|
||||
strokeStyleColor = ol.color.asArray(strokeStyleColor).map(function(c, i) {
|
||||
return i != 3 ? c / 255 : c;
|
||||
}) || ol.render.webgl.defaultStrokeStyle;
|
||||
} else {
|
||||
strokeStyleColor = ol.render.webgl.defaultStrokeStyle;
|
||||
}
|
||||
strokeStyleWidth = strokeStyle.getWidth();
|
||||
strokeStyleWidth = strokeStyleWidth !== undefined ?
|
||||
strokeStyleWidth : ol.render.webgl.defaultLineWidth;
|
||||
} else {
|
||||
strokeStyleColor = [0, 0, 0, 0];
|
||||
strokeStyleWidth = 0;
|
||||
}
|
||||
var fillStyleColor = fillStyle ? fillStyle.getColor() : [0, 0, 0, 0];
|
||||
if (!(fillStyleColor instanceof CanvasGradient) &&
|
||||
!(fillStyleColor instanceof CanvasPattern)) {
|
||||
fillStyleColor = ol.color.asArray(fillStyleColor).map(function(c, i) {
|
||||
return i != 3 ? c / 255 : c;
|
||||
}) || ol.render.webgl.defaultFillStyle;
|
||||
} else {
|
||||
fillStyleColor = ol.render.webgl.defaultFillStyle;
|
||||
}
|
||||
if (!this.state_.strokeColor || !ol.array.equals(this.state_.strokeColor, strokeStyleColor) ||
|
||||
!this.state_.fillColor || !ol.array.equals(this.state_.fillColor, fillStyleColor) ||
|
||||
this.state_.lineWidth !== strokeStyleWidth) {
|
||||
this.state_.changed = true;
|
||||
this.state_.fillColor = fillStyleColor;
|
||||
this.state_.strokeColor = strokeStyleColor;
|
||||
this.state_.lineWidth = strokeStyleWidth;
|
||||
this.styles_.push([fillStyleColor, strokeStyleColor, strokeStyleWidth]);
|
||||
}
|
||||
};
|
||||
@@ -132,7 +132,8 @@ ol.render.webgl.Replay.prototype.finish = function(context) {};
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @param {ol.Size} size Size.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @return {ol.render.webgl.imagereplay.defaultshader.Locations|
|
||||
* @return {ol.render.webgl.circlereplay.defaultshader.Locations|
|
||||
ol.render.webgl.imagereplay.defaultshader.Locations|
|
||||
ol.render.webgl.linestringreplay.defaultshader.Locations|
|
||||
ol.render.webgl.polygonreplay.defaultshader.Locations} Locations.
|
||||
*/
|
||||
@@ -143,7 +144,8 @@ ol.render.webgl.Replay.prototype.setUpProgram = function(gl, context, size, pixe
|
||||
* @abstract
|
||||
* @protected
|
||||
* @param {WebGLRenderingContext} gl gl.
|
||||
* @param {ol.render.webgl.imagereplay.defaultshader.Locations|
|
||||
* @param {ol.render.webgl.circlereplay.defaultshader.Locations|
|
||||
ol.render.webgl.imagereplay.defaultshader.Locations|
|
||||
ol.render.webgl.linestringreplay.defaultshader.Locations|
|
||||
ol.render.webgl.polygonreplay.defaultshader.Locations} locations Locations.
|
||||
*/
|
||||
|
||||
@@ -4,6 +4,7 @@ goog.require('ol');
|
||||
goog.require('ol.array');
|
||||
goog.require('ol.render.ReplayGroup');
|
||||
goog.require('ol.render.webgl');
|
||||
goog.require('ol.render.webgl.CircleReplay');
|
||||
goog.require('ol.render.webgl.ImageReplay');
|
||||
goog.require('ol.render.webgl.LineStringReplay');
|
||||
goog.require('ol.render.webgl.PolygonReplay');
|
||||
@@ -104,7 +105,7 @@ ol.render.webgl.ReplayGroup.prototype.getReplay = function(zIndex, replayType) {
|
||||
var Constructor = ol.render.webgl.ReplayGroup.BATCH_CONSTRUCTORS_[replayType];
|
||||
ol.DEBUG && console.assert(Constructor !== undefined,
|
||||
replayType +
|
||||
' constructor missing from ol.render.canvas.ReplayGroup.BATCH_CONSTRUCTORS_');
|
||||
' constructor missing from ol.render.webgl.ReplayGroup.BATCH_CONSTRUCTORS_');
|
||||
replay = new Constructor(this.tolerance_, this.maxExtent_);
|
||||
replays[replayType] = replay;
|
||||
}
|
||||
@@ -308,6 +309,7 @@ ol.render.webgl.ReplayGroup.HIT_DETECTION_SIZE_ = [1, 1];
|
||||
* ol.Extent)>}
|
||||
*/
|
||||
ol.render.webgl.ReplayGroup.BATCH_CONSTRUCTORS_ = {
|
||||
'Circle': ol.render.webgl.CircleReplay,
|
||||
'Image': ol.render.webgl.ImageReplay,
|
||||
'LineString': ol.render.webgl.LineStringReplay,
|
||||
'Polygon': ol.render.webgl.PolygonReplay
|
||||
|
||||
@@ -47,10 +47,10 @@ ol.renderer.vector.renderCircleGeometry_ = function(replayGroup, geometry, style
|
||||
var fillStyle = style.getFill();
|
||||
var strokeStyle = style.getStroke();
|
||||
if (fillStyle || strokeStyle) {
|
||||
var polygonReplay = replayGroup.getReplay(
|
||||
style.getZIndex(), ol.render.ReplayType.POLYGON);
|
||||
polygonReplay.setFillStrokeStyle(fillStyle, strokeStyle);
|
||||
polygonReplay.drawCircle(geometry, feature);
|
||||
var circleReplay = replayGroup.getReplay(
|
||||
style.getZIndex(), ol.render.ReplayType.CIRCLE);
|
||||
circleReplay.setFillStrokeStyle(fillStyle, strokeStyle);
|
||||
circleReplay.drawCircle(geometry, feature);
|
||||
}
|
||||
var textStyle = style.getText();
|
||||
if (textStyle) {
|
||||
|
||||
Reference in New Issue
Block a user