Merge pull request #6314 from ahocevar/webgl-define
WebGL conditional compilation
This commit is contained in:
@@ -1,68 +1,72 @@
|
||||
goog.provide('ol.render.webgl');
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {ol.Color}
|
||||
*/
|
||||
ol.render.webgl.defaultFillStyle = [0.0, 0.0, 0.0, 1.0];
|
||||
if (ol.ENABLE_WEBGL) {
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.render.webgl.defaultLineCap = 'round';
|
||||
/**
|
||||
* @const
|
||||
* @type {ol.Color}
|
||||
*/
|
||||
ol.render.webgl.defaultFillStyle = [0.0, 0.0, 0.0, 1.0];
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.render.webgl.defaultLineCap = 'round';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
ol.render.webgl.defaultLineDash = [];
|
||||
/**
|
||||
* @const
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
ol.render.webgl.defaultLineDash = [];
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.render.webgl.defaultLineJoin = 'round';
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.render.webgl.defaultLineJoin = 'round';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.render.webgl.defaultMiterLimit = 10;
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.render.webgl.defaultMiterLimit = 10;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {ol.Color}
|
||||
*/
|
||||
ol.render.webgl.defaultStrokeStyle = [0.0, 0.0, 0.0, 1.0];
|
||||
/**
|
||||
* @const
|
||||
* @type {ol.Color}
|
||||
*/
|
||||
ol.render.webgl.defaultStrokeStyle = [0.0, 0.0, 0.0, 1.0];
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.render.webgl.defaultLineWidth = 1;
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.render.webgl.defaultLineWidth = 1;
|
||||
|
||||
/**
|
||||
* Calculates the orientation of a triangle based on the determinant method.
|
||||
* @param {number} x1 First X coordinate.
|
||||
* @param {number} y1 First Y coordinate.
|
||||
* @param {number} x2 Second X coordinate.
|
||||
* @param {number} y2 Second Y coordinate.
|
||||
* @param {number} x3 Third X coordinate.
|
||||
* @param {number} y3 Third Y coordinate.
|
||||
* @return {boolean|undefined} Triangle is clockwise.
|
||||
*/
|
||||
ol.render.webgl.triangleIsCounterClockwise = function(x1, y1, x2, y2, x3, y3) {
|
||||
var area = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1);
|
||||
return (area <= ol.render.webgl.EPSILON && area >= -ol.render.webgl.EPSILON) ?
|
||||
undefined : area > 0;
|
||||
};
|
||||
/**
|
||||
* Calculates the orientation of a triangle based on the determinant method.
|
||||
* @param {number} x1 First X coordinate.
|
||||
* @param {number} y1 First Y coordinate.
|
||||
* @param {number} x2 Second X coordinate.
|
||||
* @param {number} y2 Second Y coordinate.
|
||||
* @param {number} x3 Third X coordinate.
|
||||
* @param {number} y3 Third Y coordinate.
|
||||
* @return {boolean|undefined} Triangle is clockwise.
|
||||
*/
|
||||
ol.render.webgl.triangleIsCounterClockwise = function(x1, y1, x2, y2, x3, y3) {
|
||||
var area = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1);
|
||||
return (area <= ol.render.webgl.EPSILON && area >= -ol.render.webgl.EPSILON) ?
|
||||
undefined : area > 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.render.webgl.EPSILON = Number.EPSILON || 2.220446049250313e-16;
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.render.webgl.EPSILON = Number.EPSILON || 2.220446049250313e-16;
|
||||
|
||||
}
|
||||
|
||||
@@ -13,403 +13,407 @@ 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);
|
||||
if (ol.ENABLE_WEBGL) {
|
||||
|
||||
/**
|
||||
* @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
|
||||
* @type {ol.render.webgl.circlereplay.defaultshader.Locations}
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
*/
|
||||
this.defaultLocations_ = null;
|
||||
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_;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<Array.<Array.<number>|number>>}
|
||||
*/
|
||||
this.styles_ = [];
|
||||
this.vertices[numVertices++] = flatCoordinates[i];
|
||||
this.vertices[numVertices++] = flatCoordinates[i + 1];
|
||||
this.vertices[numVertices++] = 1;
|
||||
this.vertices[numVertices++] = this.radius_;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this.styleIndices_ = [];
|
||||
this.vertices[numVertices++] = flatCoordinates[i];
|
||||
this.vertices[numVertices++] = flatCoordinates[i + 1];
|
||||
this.vertices[numVertices++] = 2;
|
||||
this.vertices[numVertices++] = this.radius_;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.radius_ = 0;
|
||||
this.vertices[numVertices++] = flatCoordinates[i];
|
||||
this.vertices[numVertices++] = flatCoordinates[i + 1];
|
||||
this.vertices[numVertices++] = 3;
|
||||
this.vertices[numVertices++] = this.radius_;
|
||||
|
||||
/**
|
||||
* @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
|
||||
this.indices[numIndices++] = n;
|
||||
this.indices[numIndices++] = n + 1;
|
||||
this.indices[numIndices++] = n + 2;
|
||||
|
||||
this.indices[numIndices++] = n + 2;
|
||||
this.indices[numIndices++] = n + 3;
|
||||
this.indices[numIndices++] = n;
|
||||
|
||||
n += 4;
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
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.vertices[numVertices++] = flatCoordinates[i];
|
||||
this.vertices[numVertices++] = flatCoordinates[i + 1];
|
||||
this.vertices[numVertices++] = 3;
|
||||
this.vertices[numVertices++] = this.radius_;
|
||||
|
||||
this.indices[numIndices++] = n;
|
||||
this.indices[numIndices++] = n + 1;
|
||||
this.indices[numIndices++] = n + 2;
|
||||
|
||||
this.indices[numIndices++] = n + 2;
|
||||
this.indices[numIndices++] = n + 3;
|
||||
this.indices[numIndices++] = n;
|
||||
|
||||
n += 4;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @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]);
|
||||
/**
|
||||
* @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 CircleReplay instances (for other layers). And
|
||||
// they will be deleted when disposing of the ol.webgl.Context
|
||||
// object.
|
||||
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);
|
||||
/**
|
||||
* @inheritDoc
|
||||
**/
|
||||
ol.render.webgl.CircleReplay.prototype.finish = function(context) {
|
||||
// create, bind, and populate the vertices buffer
|
||||
this.verticesBuffer = new ol.webgl.Buffer(this.vertices);
|
||||
|
||||
// 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_;
|
||||
}
|
||||
// create, bind, and populate the indices buffer
|
||||
this.indicesBuffer = new ol.webgl.Buffer(this.indices);
|
||||
|
||||
context.useProgram(program);
|
||||
this.startIndices.push(this.indices.length);
|
||||
|
||||
// enable the vertex attrib arrays
|
||||
gl.enableVertexAttribArray(locations.a_position);
|
||||
gl.vertexAttribPointer(locations.a_position, 2, ol.webgl.FLOAT,
|
||||
false, 16, 0);
|
||||
//Clean up, if there is nothing to draw
|
||||
if (this.styleIndices_.length === 0 && this.styles_.length > 0) {
|
||||
this.styles_ = [];
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
this.vertices = null;
|
||||
this.indices = null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @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.getDeleteResourcesFunction = function(context) {
|
||||
// We only delete our stuff here. The shaders and the program may
|
||||
// be used by other CircleReplay instances (for other layers). And
|
||||
// they will be deleted when disposing of the ol.webgl.Context
|
||||
// object.
|
||||
var verticesBuffer = this.verticesBuffer;
|
||||
var indicesBuffer = this.indicesBuffer;
|
||||
return function() {
|
||||
context.deleteBuffer(verticesBuffer);
|
||||
context.deleteBuffer(indicesBuffer);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.webgl.CircleReplay.prototype.drawReplay = function(gl, context, skippedFeaturesHash, hitDetection) {
|
||||
if (!ol.obj.isEmpty(skippedFeaturesHash)) {
|
||||
this.drawReplaySkipping_(gl, context, skippedFeaturesHash);
|
||||
} else {
|
||||
//Draw by style groups to minimize drawElements() calls.
|
||||
var i, start, end, nextStyle;
|
||||
end = this.startIndices[this.startIndices.length - 1];
|
||||
/**
|
||||
* @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 {
|
||||
//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) {
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
};
|
||||
groupStart = this.styleIndices_[i];
|
||||
|
||||
while (featureIndex >= 0 &&
|
||||
this.startIndices[featureIndex] >= groupStart) {
|
||||
start = this.startIndices[featureIndex];
|
||||
feature = this.startIndicesFeature[featureIndex];
|
||||
featureUid = ol.getUid(feature).toString();
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.webgl.CircleReplay.prototype.drawHitDetectionReplayOneByOne = function(gl, context, skippedFeaturesHash,
|
||||
featureCallback, opt_hitExtent) {
|
||||
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) {
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
end = featureStart;
|
||||
featureIndex--;
|
||||
end = start;
|
||||
}
|
||||
featureIndex--;
|
||||
start = featureStart;
|
||||
}
|
||||
if (start !== end) {
|
||||
this.drawElements(gl, context, start, end);
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
start = end = groupStart;
|
||||
}
|
||||
start = end = groupStart;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
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);
|
||||
};
|
||||
/**
|
||||
* @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) {
|
||||
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;
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.webgl.CircleReplay.prototype.setFillStrokeStyle = function(fillStyle, strokeStyle) {
|
||||
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 = ol.render.webgl.defaultStrokeStyle;
|
||||
strokeStyleColor = [0, 0, 0, 0];
|
||||
strokeStyleWidth = 0;
|
||||
}
|
||||
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]);
|
||||
}
|
||||
};
|
||||
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]);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -6,141 +6,145 @@ 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;\nvarying float v_pixelRatio;\n\n\n\nuniform float u_opacity;\nuniform vec4 u_fillColor;\nuniform vec4 u_strokeColor;\nuniform vec2 u_size;\n\nvoid main(void) {\n vec2 windowCenter = vec2((v_center.x + 1.0) / 2.0 * u_size.x * v_pixelRatio,\n (v_center.y + 1.0) / 2.0 * u_size.y * v_pixelRatio);\n vec2 windowOffset = vec2((v_offset.x + 1.0) / 2.0 * u_size.x * v_pixelRatio,\n (v_offset.y + 1.0) / 2.0 * u_size.y * v_pixelRatio);\n float radius = length(windowCenter - windowOffset);\n float dist = length(windowCenter - gl_FragCoord.xy);\n if (dist > radius + v_halfWidth) {\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));\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) {\n gl_FragColor.a = gl_FragColor.a - (radius - v_halfWidth - dist);\n }\n } else {\n gl_FragColor = u_fillColor;\n float strokeDist = radius - v_halfWidth;\n float antialias = 2.0 * v_pixelRatio;\n if (dist > strokeDist) {\n gl_FragColor = u_strokeColor;\n } else if (dist >= strokeDist - antialias) {\n float step = smoothstep(strokeDist - antialias, 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;varying float d;uniform float m;uniform vec4 n;uniform vec4 o;uniform vec2 p;void main(void){vec2 windowCenter=vec2((a.x+1.0)/2.0*p.x*d,(a.y+1.0)/2.0*p.y*d);vec2 windowOffset=vec2((b.x+1.0)/2.0*p.x*d,(b.y+1.0)/2.0*p.y*d);float radius=length(windowCenter-windowOffset);float dist=length(windowCenter-gl_FragCoord.xy);if(dist>radius+c){if(o.a==0.0){gl_FragColor=n;}else{gl_FragColor=o;}gl_FragColor.a=gl_FragColor.a-(dist-(radius+c));}else if(n.a==0.0){gl_FragColor=o;if(dist<radius-c){gl_FragColor.a=gl_FragColor.a-(radius-c-dist);}} else{gl_FragColor=n;float strokeDist=radius-c;float antialias=2.0*d;if(dist>strokeDist){gl_FragColor=o;}else if(dist>=strokeDist-antialias){float step=smoothstep(strokeDist-antialias,strokeDist,dist);gl_FragColor=mix(n,o,step);}} gl_FragColor.a=gl_FragColor.a*m;if(gl_FragColor.a<=0.0){discard;}}';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.render.webgl.circlereplay.defaultshader.Fragment.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;\nvarying float v_pixelRatio;\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;\nuniform float u_pixelRatio;\n\nvoid main(void) {\n mat4 offsetMatrix = u_offsetScaleMatrix * u_offsetRotateMatrix;\n v_center = vec4(u_projectionMatrix * vec4(a_position, 0.0, 1.0)).xy;\n v_pixelRatio = u_pixelRatio;\n float lineWidth = u_lineWidth * u_pixelRatio;\n v_halfWidth = lineWidth / 2.0;\n if (lineWidth == 0.0) {\n lineWidth = 2.0 * u_pixelRatio;\n }\n vec2 offset;\n // Radius with anitaliasing (roughly).\n float radius = a_radius + 3.0 * u_pixelRatio;\n // Until we get gl_VertexID in WebGL, we store an instruction.\n if (a_instruction == 0.0) {\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(-1.0, 1.0);\n } else if (a_instruction == 1.0) {\n offset = vec2(-1.0, -1.0);\n } else if (a_instruction == 2.0) {\n offset = vec2(1.0, -1.0);\n } else {\n offset = vec2(1.0, 1.0);\n }\n\n gl_Position = u_projectionMatrix * vec4(a_position + offset * radius, 0.0, 1.0) +\n offsetMatrix * vec4(offset * lineWidth, 0.0, 0.0);\n v_offset = vec4(u_projectionMatrix * vec4(a_position.x + a_radius, a_position.y,\n 0.0, 1.0)).xy;\n\n if (distance(v_center, v_offset) > 20000.0) {\n gl_Position = vec4(v_center, 0.0, 1.0);\n }\n}\n\n\n';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.render.webgl.circlereplay.defaultshader.Vertex.OPTIMIZED_SOURCE = 'varying vec2 a;varying vec2 b;varying float c;varying float d;attribute vec2 e;attribute float f;attribute float g;uniform mat4 h;uniform mat4 i;uniform mat4 j;uniform float k;uniform float l;void main(void){mat4 offsetMatrix=i*j;a=vec4(h*vec4(e,0.0,1.0)).xy;d=l;float lineWidth=k*l;c=lineWidth/2.0;if(lineWidth==0.0){lineWidth=2.0*l;}vec2 offset;float radius=g+3.0*l;if(f==0.0){offset=vec2(-1.0,1.0);}else if(f==1.0){offset=vec2(-1.0,-1.0);}else if(f==2.0){offset=vec2(1.0,-1.0);}else{offset=vec2(1.0,1.0);}gl_Position=h*vec4(e+offset*radius,0.0,1.0)+offsetMatrix*vec4(offset*lineWidth,0.0,0.0);b=vec4(h*vec4(e.x+g,e.y,0.0,1.0)).xy;if(distance(a,b)>20000.0){gl_Position=vec4(a,0.0,1.0);}}';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.render.webgl.circlereplay.defaultshader.Vertex.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) {
|
||||
if (ol.ENABLE_WEBGL) {
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
* @constructor
|
||||
* @extends {ol.webgl.Fragment}
|
||||
* @struct
|
||||
*/
|
||||
this.u_fillColor = gl.getUniformLocation(program, 'n');
|
||||
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);
|
||||
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
this.u_lineWidth = gl.getUniformLocation(program, 'k');
|
||||
ol.render.webgl.circlereplay.defaultshader.Fragment.DEBUG_SOURCE = 'precision mediump float;\nvarying vec2 v_center;\nvarying vec2 v_offset;\nvarying float v_halfWidth;\nvarying float v_pixelRatio;\n\n\n\nuniform float u_opacity;\nuniform vec4 u_fillColor;\nuniform vec4 u_strokeColor;\nuniform vec2 u_size;\n\nvoid main(void) {\n vec2 windowCenter = vec2((v_center.x + 1.0) / 2.0 * u_size.x * v_pixelRatio,\n (v_center.y + 1.0) / 2.0 * u_size.y * v_pixelRatio);\n vec2 windowOffset = vec2((v_offset.x + 1.0) / 2.0 * u_size.x * v_pixelRatio,\n (v_offset.y + 1.0) / 2.0 * u_size.y * v_pixelRatio);\n float radius = length(windowCenter - windowOffset);\n float dist = length(windowCenter - gl_FragCoord.xy);\n if (dist > radius + v_halfWidth) {\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));\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) {\n gl_FragColor.a = gl_FragColor.a - (radius - v_halfWidth - dist);\n }\n } else {\n gl_FragColor = u_fillColor;\n float strokeDist = radius - v_halfWidth;\n float antialias = 2.0 * v_pixelRatio;\n if (dist > strokeDist) {\n gl_FragColor = u_strokeColor;\n } else if (dist >= strokeDist - antialias) {\n float step = smoothstep(strokeDist - antialias, 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';
|
||||
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
this.u_offsetRotateMatrix = gl.getUniformLocation(program, 'j');
|
||||
ol.render.webgl.circlereplay.defaultshader.Fragment.OPTIMIZED_SOURCE = 'precision mediump float;varying vec2 a;varying vec2 b;varying float c;varying float d;uniform float m;uniform vec4 n;uniform vec4 o;uniform vec2 p;void main(void){vec2 windowCenter=vec2((a.x+1.0)/2.0*p.x*d,(a.y+1.0)/2.0*p.y*d);vec2 windowOffset=vec2((b.x+1.0)/2.0*p.x*d,(b.y+1.0)/2.0*p.y*d);float radius=length(windowCenter-windowOffset);float dist=length(windowCenter-gl_FragCoord.xy);if(dist>radius+c){if(o.a==0.0){gl_FragColor=n;}else{gl_FragColor=o;}gl_FragColor.a=gl_FragColor.a-(dist-(radius+c));}else if(n.a==0.0){gl_FragColor=o;if(dist<radius-c){gl_FragColor.a=gl_FragColor.a-(radius-c-dist);}} else{gl_FragColor=n;float strokeDist=radius-c;float antialias=2.0*d;if(dist>strokeDist){gl_FragColor=o;}else if(dist>=strokeDist-antialias){float step=smoothstep(strokeDist-antialias,strokeDist,dist);gl_FragColor=mix(n,o,step);}} gl_FragColor.a=gl_FragColor.a*m;if(gl_FragColor.a<=0.0){discard;}}';
|
||||
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
this.u_offsetScaleMatrix = gl.getUniformLocation(program, 'i');
|
||||
ol.render.webgl.circlereplay.defaultshader.Fragment.SOURCE = ol.render.webgl.circlereplay.defaultshader.Fragment.OPTIMIZED_SOURCE;
|
||||
|
||||
|
||||
ol.render.webgl.circlereplay.defaultshader.fragment = new ol.render.webgl.circlereplay.defaultshader.Fragment();
|
||||
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
* @constructor
|
||||
* @extends {ol.webgl.Vertex}
|
||||
* @struct
|
||||
*/
|
||||
this.u_opacity = gl.getUniformLocation(program, 'm');
|
||||
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);
|
||||
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
this.u_pixelRatio = gl.getUniformLocation(program, 'l');
|
||||
ol.render.webgl.circlereplay.defaultshader.Vertex.DEBUG_SOURCE = 'varying vec2 v_center;\nvarying vec2 v_offset;\nvarying float v_halfWidth;\nvarying float v_pixelRatio;\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;\nuniform float u_pixelRatio;\n\nvoid main(void) {\n mat4 offsetMatrix = u_offsetScaleMatrix * u_offsetRotateMatrix;\n v_center = vec4(u_projectionMatrix * vec4(a_position, 0.0, 1.0)).xy;\n v_pixelRatio = u_pixelRatio;\n float lineWidth = u_lineWidth * u_pixelRatio;\n v_halfWidth = lineWidth / 2.0;\n if (lineWidth == 0.0) {\n lineWidth = 2.0 * u_pixelRatio;\n }\n vec2 offset;\n // Radius with anitaliasing (roughly).\n float radius = a_radius + 3.0 * u_pixelRatio;\n // Until we get gl_VertexID in WebGL, we store an instruction.\n if (a_instruction == 0.0) {\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(-1.0, 1.0);\n } else if (a_instruction == 1.0) {\n offset = vec2(-1.0, -1.0);\n } else if (a_instruction == 2.0) {\n offset = vec2(1.0, -1.0);\n } else {\n offset = vec2(1.0, 1.0);\n }\n\n gl_Position = u_projectionMatrix * vec4(a_position + offset * radius, 0.0, 1.0) +\n offsetMatrix * vec4(offset * lineWidth, 0.0, 0.0);\n v_offset = vec4(u_projectionMatrix * vec4(a_position.x + a_radius, a_position.y,\n 0.0, 1.0)).xy;\n\n if (distance(v_center, v_offset) > 20000.0) {\n gl_Position = vec4(v_center, 0.0, 1.0);\n }\n}\n\n\n';
|
||||
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
this.u_projectionMatrix = gl.getUniformLocation(program, 'h');
|
||||
ol.render.webgl.circlereplay.defaultshader.Vertex.OPTIMIZED_SOURCE = 'varying vec2 a;varying vec2 b;varying float c;varying float d;attribute vec2 e;attribute float f;attribute float g;uniform mat4 h;uniform mat4 i;uniform mat4 j;uniform float k;uniform float l;void main(void){mat4 offsetMatrix=i*j;a=vec4(h*vec4(e,0.0,1.0)).xy;d=l;float lineWidth=k*l;c=lineWidth/2.0;if(lineWidth==0.0){lineWidth=2.0*l;}vec2 offset;float radius=g+3.0*l;if(f==0.0){offset=vec2(-1.0,1.0);}else if(f==1.0){offset=vec2(-1.0,-1.0);}else if(f==2.0){offset=vec2(1.0,-1.0);}else{offset=vec2(1.0,1.0);}gl_Position=h*vec4(e+offset*radius,0.0,1.0)+offsetMatrix*vec4(offset*lineWidth,0.0,0.0);b=vec4(h*vec4(e.x+g,e.y,0.0,1.0)).xy;if(distance(a,b)>20000.0){gl_Position=vec4(a,0.0,1.0);}}';
|
||||
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
this.u_size = gl.getUniformLocation(program, 'p');
|
||||
ol.render.webgl.circlereplay.defaultshader.Vertex.SOURCE = ol.render.webgl.circlereplay.defaultshader.Vertex.OPTIMIZED_SOURCE;
|
||||
|
||||
|
||||
ol.render.webgl.circlereplay.defaultshader.vertex = new ol.render.webgl.circlereplay.defaultshader.Vertex();
|
||||
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
* @constructor
|
||||
* @param {WebGLRenderingContext} gl GL.
|
||||
* @param {WebGLProgram} program Program.
|
||||
* @struct
|
||||
*/
|
||||
this.u_strokeColor = gl.getUniformLocation(program, 'o');
|
||||
ol.render.webgl.circlereplay.defaultshader.Locations = function(gl, program) {
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.a_instruction = gl.getAttribLocation(program, 'f');
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_fillColor = gl.getUniformLocation(program, 'n');
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.a_position = gl.getAttribLocation(program, 'e');
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_lineWidth = gl.getUniformLocation(program, 'k');
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.a_radius = gl.getAttribLocation(program, 'g');
|
||||
};
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_offsetRotateMatrix = gl.getUniformLocation(program, 'j');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_offsetScaleMatrix = gl.getUniformLocation(program, 'i');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_opacity = gl.getUniformLocation(program, 'm');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_pixelRatio = gl.getUniformLocation(program, 'l');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_projectionMatrix = gl.getUniformLocation(program, 'h');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_size = gl.getUniformLocation(program, 'p');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_strokeColor = gl.getUniformLocation(program, 'o');
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.a_instruction = gl.getAttribLocation(program, 'f');
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.a_position = gl.getAttribLocation(program, 'e');
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.a_radius = gl.getAttribLocation(program, 'g');
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,131 +6,135 @@ goog.require('ol.webgl.Fragment');
|
||||
goog.require('ol.webgl.Vertex');
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.webgl.Fragment}
|
||||
* @struct
|
||||
*/
|
||||
ol.render.webgl.imagereplay.defaultshader.Fragment = function() {
|
||||
ol.webgl.Fragment.call(this, ol.render.webgl.imagereplay.defaultshader.Fragment.SOURCE);
|
||||
};
|
||||
ol.inherits(ol.render.webgl.imagereplay.defaultshader.Fragment, ol.webgl.Fragment);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.render.webgl.imagereplay.defaultshader.Fragment.DEBUG_SOURCE = 'precision mediump float;\nvarying vec2 v_texCoord;\nvarying float v_opacity;\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 * v_opacity * u_opacity;\n if (alpha == 0.0) {\n discard;\n }\n gl_FragColor.a = alpha;\n}\n';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.render.webgl.imagereplay.defaultshader.Fragment.OPTIMIZED_SOURCE = 'precision mediump float;varying vec2 a;varying float b;uniform float k;uniform sampler2D l;void main(void){vec4 texColor=texture2D(l,a);gl_FragColor.rgb=texColor.rgb;float alpha=texColor.a*b*k;if(alpha==0.0){discard;}gl_FragColor.a=alpha;}';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.render.webgl.imagereplay.defaultshader.Fragment.SOURCE = ol.render.webgl.imagereplay.defaultshader.Fragment.OPTIMIZED_SOURCE;
|
||||
|
||||
|
||||
ol.render.webgl.imagereplay.defaultshader.fragment = new ol.render.webgl.imagereplay.defaultshader.Fragment();
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.webgl.Vertex}
|
||||
* @struct
|
||||
*/
|
||||
ol.render.webgl.imagereplay.defaultshader.Vertex = function() {
|
||||
ol.webgl.Vertex.call(this, ol.render.webgl.imagereplay.defaultshader.Vertex.SOURCE);
|
||||
};
|
||||
ol.inherits(ol.render.webgl.imagereplay.defaultshader.Vertex, ol.webgl.Vertex);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.render.webgl.imagereplay.defaultshader.Vertex.DEBUG_SOURCE = 'varying vec2 v_texCoord;\nvarying float v_opacity;\n\nattribute vec2 a_position;\nattribute vec2 a_texCoord;\nattribute vec2 a_offsets;\nattribute float a_opacity;\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 v_opacity = a_opacity;\n}\n\n\n';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.render.webgl.imagereplay.defaultshader.Vertex.OPTIMIZED_SOURCE = 'varying vec2 a;varying float b;attribute vec2 c;attribute vec2 d;attribute vec2 e;attribute float f;attribute float g;uniform mat4 h;uniform mat4 i;uniform mat4 j;void main(void){mat4 offsetMatrix=i;if(g==1.0){offsetMatrix=i*j;}vec4 offsets=offsetMatrix*vec4(e,0.0,0.0);gl_Position=h*vec4(c,0.0,1.0)+offsets;a=d;b=f;}';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.render.webgl.imagereplay.defaultshader.Vertex.SOURCE = ol.render.webgl.imagereplay.defaultshader.Vertex.OPTIMIZED_SOURCE;
|
||||
|
||||
|
||||
ol.render.webgl.imagereplay.defaultshader.vertex = new ol.render.webgl.imagereplay.defaultshader.Vertex();
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {WebGLRenderingContext} gl GL.
|
||||
* @param {WebGLProgram} program Program.
|
||||
* @struct
|
||||
*/
|
||||
ol.render.webgl.imagereplay.defaultshader.Locations = function(gl, program) {
|
||||
if (ol.ENABLE_WEBGL) {
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
* @constructor
|
||||
* @extends {ol.webgl.Fragment}
|
||||
* @struct
|
||||
*/
|
||||
this.u_image = gl.getUniformLocation(program, 'l');
|
||||
ol.render.webgl.imagereplay.defaultshader.Fragment = function() {
|
||||
ol.webgl.Fragment.call(this, ol.render.webgl.imagereplay.defaultshader.Fragment.SOURCE);
|
||||
};
|
||||
ol.inherits(ol.render.webgl.imagereplay.defaultshader.Fragment, ol.webgl.Fragment);
|
||||
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
this.u_offsetRotateMatrix = gl.getUniformLocation(program, 'j');
|
||||
ol.render.webgl.imagereplay.defaultshader.Fragment.DEBUG_SOURCE = 'precision mediump float;\nvarying vec2 v_texCoord;\nvarying float v_opacity;\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 * v_opacity * u_opacity;\n if (alpha == 0.0) {\n discard;\n }\n gl_FragColor.a = alpha;\n}\n';
|
||||
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
this.u_offsetScaleMatrix = gl.getUniformLocation(program, 'i');
|
||||
ol.render.webgl.imagereplay.defaultshader.Fragment.OPTIMIZED_SOURCE = 'precision mediump float;varying vec2 a;varying float b;uniform float k;uniform sampler2D l;void main(void){vec4 texColor=texture2D(l,a);gl_FragColor.rgb=texColor.rgb;float alpha=texColor.a*b*k;if(alpha==0.0){discard;}gl_FragColor.a=alpha;}';
|
||||
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
this.u_opacity = gl.getUniformLocation(program, 'k');
|
||||
ol.render.webgl.imagereplay.defaultshader.Fragment.SOURCE = ol.render.webgl.imagereplay.defaultshader.Fragment.OPTIMIZED_SOURCE;
|
||||
|
||||
|
||||
ol.render.webgl.imagereplay.defaultshader.fragment = new ol.render.webgl.imagereplay.defaultshader.Fragment();
|
||||
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
* @constructor
|
||||
* @extends {ol.webgl.Vertex}
|
||||
* @struct
|
||||
*/
|
||||
this.u_projectionMatrix = gl.getUniformLocation(program, 'h');
|
||||
ol.render.webgl.imagereplay.defaultshader.Vertex = function() {
|
||||
ol.webgl.Vertex.call(this, ol.render.webgl.imagereplay.defaultshader.Vertex.SOURCE);
|
||||
};
|
||||
ol.inherits(ol.render.webgl.imagereplay.defaultshader.Vertex, ol.webgl.Vertex);
|
||||
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
this.a_offsets = gl.getAttribLocation(program, 'e');
|
||||
ol.render.webgl.imagereplay.defaultshader.Vertex.DEBUG_SOURCE = 'varying vec2 v_texCoord;\nvarying float v_opacity;\n\nattribute vec2 a_position;\nattribute vec2 a_texCoord;\nattribute vec2 a_offsets;\nattribute float a_opacity;\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 v_opacity = a_opacity;\n}\n\n\n';
|
||||
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
this.a_opacity = gl.getAttribLocation(program, 'f');
|
||||
ol.render.webgl.imagereplay.defaultshader.Vertex.OPTIMIZED_SOURCE = 'varying vec2 a;varying float b;attribute vec2 c;attribute vec2 d;attribute vec2 e;attribute float f;attribute float g;uniform mat4 h;uniform mat4 i;uniform mat4 j;void main(void){mat4 offsetMatrix=i;if(g==1.0){offsetMatrix=i*j;}vec4 offsets=offsetMatrix*vec4(e,0.0,0.0);gl_Position=h*vec4(c,0.0,1.0)+offsets;a=d;b=f;}';
|
||||
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
this.a_position = gl.getAttribLocation(program, 'c');
|
||||
ol.render.webgl.imagereplay.defaultshader.Vertex.SOURCE = ol.render.webgl.imagereplay.defaultshader.Vertex.OPTIMIZED_SOURCE;
|
||||
|
||||
|
||||
ol.render.webgl.imagereplay.defaultshader.vertex = new ol.render.webgl.imagereplay.defaultshader.Vertex();
|
||||
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @constructor
|
||||
* @param {WebGLRenderingContext} gl GL.
|
||||
* @param {WebGLProgram} program Program.
|
||||
* @struct
|
||||
*/
|
||||
this.a_rotateWithView = gl.getAttribLocation(program, 'g');
|
||||
ol.render.webgl.imagereplay.defaultshader.Locations = function(gl, program) {
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.a_texCoord = gl.getAttribLocation(program, 'd');
|
||||
};
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_image = gl.getUniformLocation(program, 'l');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_offsetRotateMatrix = gl.getUniformLocation(program, 'j');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_offsetScaleMatrix = gl.getUniformLocation(program, 'i');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_opacity = gl.getUniformLocation(program, 'k');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_projectionMatrix = gl.getUniformLocation(program, 'h');
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.a_offsets = gl.getAttribLocation(program, 'e');
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.a_opacity = gl.getAttribLocation(program, 'f');
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.a_position = gl.getAttribLocation(program, 'c');
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.a_rotateWithView = gl.getAttribLocation(program, 'g');
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.a_texCoord = gl.getAttribLocation(program, 'd');
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -9,325 +9,329 @@ goog.require('ol.render.webgl.ReplayGroup');
|
||||
goog.require('ol.render.webgl');
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.render.VectorContext}
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @param {ol.Coordinate} center Center.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {number} rotation Rotation.
|
||||
* @param {ol.Size} size Size.
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @struct
|
||||
*/
|
||||
ol.render.webgl.Immediate = function(context, center, resolution, rotation, size, extent, pixelRatio) {
|
||||
ol.render.VectorContext.call(this);
|
||||
if (ol.ENABLE_WEBGL) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @constructor
|
||||
* @extends {ol.render.VectorContext}
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @param {ol.Coordinate} center Center.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {number} rotation Rotation.
|
||||
* @param {ol.Size} size Size.
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @struct
|
||||
*/
|
||||
this.context_ = context;
|
||||
ol.render.webgl.Immediate = function(context, center, resolution, rotation, size, extent, pixelRatio) {
|
||||
ol.render.VectorContext.call(this);
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
this.context_ = context;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
this.center_ = center;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
this.extent_ = extent;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
this.pixelRatio_ = pixelRatio;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
this.size_ = size;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
this.rotation_ = rotation;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
this.resolution_ = resolution;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.style.Image}
|
||||
*/
|
||||
this.imageStyle_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.style.Fill}
|
||||
*/
|
||||
this.fillStyle_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.style.Stroke}
|
||||
*/
|
||||
this.strokeStyle_ = null;
|
||||
|
||||
};
|
||||
ol.inherits(ol.render.webgl.Immediate, ol.render.VectorContext);
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Set the rendering style. Note that since this is an immediate rendering API,
|
||||
* any `zIndex` on the provided style will be ignored.
|
||||
*
|
||||
* @param {ol.style.Style} style The rendering style.
|
||||
* @api
|
||||
*/
|
||||
this.center_ = center;
|
||||
ol.render.webgl.Immediate.prototype.setStyle = function(style) {
|
||||
this.setFillStrokeStyle(style.getFill(), style.getStroke());
|
||||
this.setImageStyle(style.getImage());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Render a geometry into the canvas. Call
|
||||
* {@link ol.render.webgl.Immediate#setStyle} first to set the rendering style.
|
||||
*
|
||||
* @param {ol.geom.Geometry|ol.render.Feature} geometry The geometry to render.
|
||||
* @api
|
||||
*/
|
||||
this.extent_ = extent;
|
||||
ol.render.webgl.Immediate.prototype.drawGeometry = function(geometry) {
|
||||
var type = geometry.getType();
|
||||
switch (type) {
|
||||
case ol.geom.GeometryType.POINT:
|
||||
this.drawPoint(/** @type {ol.geom.Point} */ (geometry), null);
|
||||
break;
|
||||
case ol.geom.GeometryType.LINE_STRING:
|
||||
this.drawLineString(/** @type {ol.geom.LineString} */ (geometry), null);
|
||||
break;
|
||||
case ol.geom.GeometryType.POLYGON:
|
||||
this.drawPolygon(/** @type {ol.geom.Polygon} */ (geometry), null);
|
||||
break;
|
||||
case ol.geom.GeometryType.MULTI_POINT:
|
||||
this.drawMultiPoint(/** @type {ol.geom.MultiPoint} */ (geometry), null);
|
||||
break;
|
||||
case ol.geom.GeometryType.MULTI_LINE_STRING:
|
||||
this.drawMultiLineString(/** @type {ol.geom.MultiLineString} */ (geometry), null);
|
||||
break;
|
||||
case ol.geom.GeometryType.MULTI_POLYGON:
|
||||
this.drawMultiPolygon(/** @type {ol.geom.MultiPolygon} */ (geometry), null);
|
||||
break;
|
||||
case ol.geom.GeometryType.GEOMETRY_COLLECTION:
|
||||
this.drawGeometryCollection(/** @type {ol.geom.GeometryCollection} */ (geometry), null);
|
||||
break;
|
||||
case ol.geom.GeometryType.CIRCLE:
|
||||
this.drawCircle(/** @type {ol.geom.Circle} */ (geometry), null);
|
||||
break;
|
||||
default:
|
||||
// pass
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @inheritDoc
|
||||
* @api
|
||||
*/
|
||||
this.pixelRatio_ = pixelRatio;
|
||||
ol.render.webgl.Immediate.prototype.drawFeature = function(feature, style) {
|
||||
var geometry = style.getGeometryFunction()(feature);
|
||||
if (!geometry ||
|
||||
!ol.extent.intersects(this.extent_, geometry.getExtent())) {
|
||||
return;
|
||||
}
|
||||
this.setStyle(style);
|
||||
this.drawGeometry(geometry);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @inheritDoc
|
||||
*/
|
||||
this.size_ = size;
|
||||
ol.render.webgl.Immediate.prototype.drawGeometryCollection = function(geometry, data) {
|
||||
var geometries = geometry.getGeometriesArray();
|
||||
var i, ii;
|
||||
for (i = 0, ii = geometries.length; i < ii; ++i) {
|
||||
this.drawGeometry(geometries[i]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @inheritDoc
|
||||
*/
|
||||
this.rotation_ = rotation;
|
||||
ol.render.webgl.Immediate.prototype.drawPoint = function(geometry, data) {
|
||||
var context = this.context_;
|
||||
var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
|
||||
var replay = /** @type {ol.render.webgl.ImageReplay} */ (
|
||||
replayGroup.getReplay(0, ol.render.ReplayType.IMAGE));
|
||||
replay.setImageStyle(this.imageStyle_);
|
||||
replay.drawPoint(geometry, data);
|
||||
replay.finish(context);
|
||||
// default colors
|
||||
var opacity = 1;
|
||||
var skippedFeatures = {};
|
||||
var featureCallback;
|
||||
var oneByOne = false;
|
||||
replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
|
||||
this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
|
||||
oneByOne);
|
||||
replay.getDeleteResourcesFunction(context)();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @inheritDoc
|
||||
*/
|
||||
this.resolution_ = resolution;
|
||||
ol.render.webgl.Immediate.prototype.drawMultiPoint = function(geometry, data) {
|
||||
var context = this.context_;
|
||||
var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
|
||||
var replay = /** @type {ol.render.webgl.ImageReplay} */ (
|
||||
replayGroup.getReplay(0, ol.render.ReplayType.IMAGE));
|
||||
replay.setImageStyle(this.imageStyle_);
|
||||
replay.drawMultiPoint(geometry, data);
|
||||
replay.finish(context);
|
||||
var opacity = 1;
|
||||
var skippedFeatures = {};
|
||||
var featureCallback;
|
||||
var oneByOne = false;
|
||||
replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
|
||||
this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
|
||||
oneByOne);
|
||||
replay.getDeleteResourcesFunction(context)();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.style.Image}
|
||||
* @inheritDoc
|
||||
*/
|
||||
this.imageStyle_ = null;
|
||||
ol.render.webgl.Immediate.prototype.drawLineString = function(geometry, data) {
|
||||
var context = this.context_;
|
||||
var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
|
||||
var replay = /** @type {ol.render.webgl.LineStringReplay} */ (
|
||||
replayGroup.getReplay(0, ol.render.ReplayType.LINE_STRING));
|
||||
replay.setFillStrokeStyle(null, this.strokeStyle_);
|
||||
replay.drawLineString(geometry, data);
|
||||
replay.finish(context);
|
||||
var opacity = 1;
|
||||
var skippedFeatures = {};
|
||||
var featureCallback;
|
||||
var oneByOne = false;
|
||||
replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
|
||||
this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
|
||||
oneByOne);
|
||||
replay.getDeleteResourcesFunction(context)();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.style.Fill}
|
||||
* @inheritDoc
|
||||
*/
|
||||
this.fillStyle_ = null;
|
||||
ol.render.webgl.Immediate.prototype.drawMultiLineString = function(geometry, data) {
|
||||
var context = this.context_;
|
||||
var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
|
||||
var replay = /** @type {ol.render.webgl.LineStringReplay} */ (
|
||||
replayGroup.getReplay(0, ol.render.ReplayType.LINE_STRING));
|
||||
replay.setFillStrokeStyle(null, this.strokeStyle_);
|
||||
replay.drawMultiLineString(geometry, data);
|
||||
replay.finish(context);
|
||||
var opacity = 1;
|
||||
var skippedFeatures = {};
|
||||
var featureCallback;
|
||||
var oneByOne = false;
|
||||
replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
|
||||
this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
|
||||
oneByOne);
|
||||
replay.getDeleteResourcesFunction(context)();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.style.Stroke}
|
||||
* @inheritDoc
|
||||
*/
|
||||
this.strokeStyle_ = null;
|
||||
|
||||
};
|
||||
ol.inherits(ol.render.webgl.Immediate, ol.render.VectorContext);
|
||||
ol.render.webgl.Immediate.prototype.drawPolygon = function(geometry, data) {
|
||||
var context = this.context_;
|
||||
var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
|
||||
var replay = /** @type {ol.render.webgl.PolygonReplay} */ (
|
||||
replayGroup.getReplay(0, ol.render.ReplayType.POLYGON));
|
||||
replay.setFillStrokeStyle(this.fillStyle_, this.strokeStyle_);
|
||||
replay.drawPolygon(geometry, data);
|
||||
replay.finish(context);
|
||||
var opacity = 1;
|
||||
var skippedFeatures = {};
|
||||
var featureCallback;
|
||||
var oneByOne = false;
|
||||
replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
|
||||
this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
|
||||
oneByOne);
|
||||
replay.getDeleteResourcesFunction(context)();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the rendering style. Note that since this is an immediate rendering API,
|
||||
* any `zIndex` on the provided style will be ignored.
|
||||
*
|
||||
* @param {ol.style.Style} style The rendering style.
|
||||
* @api
|
||||
*/
|
||||
ol.render.webgl.Immediate.prototype.setStyle = function(style) {
|
||||
this.setFillStrokeStyle(style.getFill(), style.getStroke());
|
||||
this.setImageStyle(style.getImage());
|
||||
};
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.webgl.Immediate.prototype.drawMultiPolygon = function(geometry, data) {
|
||||
var context = this.context_;
|
||||
var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
|
||||
var replay = /** @type {ol.render.webgl.PolygonReplay} */ (
|
||||
replayGroup.getReplay(0, ol.render.ReplayType.POLYGON));
|
||||
replay.setFillStrokeStyle(this.fillStyle_, this.strokeStyle_);
|
||||
replay.drawMultiPolygon(geometry, data);
|
||||
replay.finish(context);
|
||||
var opacity = 1;
|
||||
var skippedFeatures = {};
|
||||
var featureCallback;
|
||||
var oneByOne = false;
|
||||
replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
|
||||
this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
|
||||
oneByOne);
|
||||
replay.getDeleteResourcesFunction(context)();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Render a geometry into the canvas. Call
|
||||
* {@link ol.render.webgl.Immediate#setStyle} first to set the rendering style.
|
||||
*
|
||||
* @param {ol.geom.Geometry|ol.render.Feature} geometry The geometry to render.
|
||||
* @api
|
||||
*/
|
||||
ol.render.webgl.Immediate.prototype.drawGeometry = function(geometry) {
|
||||
var type = geometry.getType();
|
||||
switch (type) {
|
||||
case ol.geom.GeometryType.POINT:
|
||||
this.drawPoint(/** @type {ol.geom.Point} */ (geometry), null);
|
||||
break;
|
||||
case ol.geom.GeometryType.LINE_STRING:
|
||||
this.drawLineString(/** @type {ol.geom.LineString} */ (geometry), null);
|
||||
break;
|
||||
case ol.geom.GeometryType.POLYGON:
|
||||
this.drawPolygon(/** @type {ol.geom.Polygon} */ (geometry), null);
|
||||
break;
|
||||
case ol.geom.GeometryType.MULTI_POINT:
|
||||
this.drawMultiPoint(/** @type {ol.geom.MultiPoint} */ (geometry), null);
|
||||
break;
|
||||
case ol.geom.GeometryType.MULTI_LINE_STRING:
|
||||
this.drawMultiLineString(/** @type {ol.geom.MultiLineString} */ (geometry), null);
|
||||
break;
|
||||
case ol.geom.GeometryType.MULTI_POLYGON:
|
||||
this.drawMultiPolygon(/** @type {ol.geom.MultiPolygon} */ (geometry), null);
|
||||
break;
|
||||
case ol.geom.GeometryType.GEOMETRY_COLLECTION:
|
||||
this.drawGeometryCollection(/** @type {ol.geom.GeometryCollection} */ (geometry), null);
|
||||
break;
|
||||
case ol.geom.GeometryType.CIRCLE:
|
||||
this.drawCircle(/** @type {ol.geom.Circle} */ (geometry), null);
|
||||
break;
|
||||
default:
|
||||
// pass
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.webgl.Immediate.prototype.drawCircle = function(geometry, data) {
|
||||
var context = this.context_;
|
||||
var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
|
||||
var replay = /** @type {ol.render.webgl.CircleReplay} */ (
|
||||
replayGroup.getReplay(0, ol.render.ReplayType.CIRCLE));
|
||||
replay.setFillStrokeStyle(this.fillStyle_, this.strokeStyle_);
|
||||
replay.drawCircle(geometry, data);
|
||||
replay.finish(context);
|
||||
var opacity = 1;
|
||||
var skippedFeatures = {};
|
||||
var featureCallback;
|
||||
var oneByOne = false;
|
||||
replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
|
||||
this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
|
||||
oneByOne);
|
||||
replay.getDeleteResourcesFunction(context)();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api
|
||||
*/
|
||||
ol.render.webgl.Immediate.prototype.drawFeature = function(feature, style) {
|
||||
var geometry = style.getGeometryFunction()(feature);
|
||||
if (!geometry ||
|
||||
!ol.extent.intersects(this.extent_, geometry.getExtent())) {
|
||||
return;
|
||||
}
|
||||
this.setStyle(style);
|
||||
this.drawGeometry(geometry);
|
||||
};
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.webgl.Immediate.prototype.setImageStyle = function(imageStyle) {
|
||||
this.imageStyle_ = imageStyle;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.webgl.Immediate.prototype.drawGeometryCollection = function(geometry, data) {
|
||||
var geometries = geometry.getGeometriesArray();
|
||||
var i, ii;
|
||||
for (i = 0, ii = geometries.length; i < ii; ++i) {
|
||||
this.drawGeometry(geometries[i]);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.webgl.Immediate.prototype.setFillStrokeStyle = function(fillStyle, strokeStyle) {
|
||||
this.fillStyle_ = fillStyle;
|
||||
this.strokeStyle_ = strokeStyle;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.webgl.Immediate.prototype.drawPoint = function(geometry, data) {
|
||||
var context = this.context_;
|
||||
var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
|
||||
var replay = /** @type {ol.render.webgl.ImageReplay} */ (
|
||||
replayGroup.getReplay(0, ol.render.ReplayType.IMAGE));
|
||||
replay.setImageStyle(this.imageStyle_);
|
||||
replay.drawPoint(geometry, data);
|
||||
replay.finish(context);
|
||||
// default colors
|
||||
var opacity = 1;
|
||||
var skippedFeatures = {};
|
||||
var featureCallback;
|
||||
var oneByOne = false;
|
||||
replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
|
||||
this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
|
||||
oneByOne);
|
||||
replay.getDeleteResourcesFunction(context)();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.webgl.Immediate.prototype.drawMultiPoint = function(geometry, data) {
|
||||
var context = this.context_;
|
||||
var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
|
||||
var replay = /** @type {ol.render.webgl.ImageReplay} */ (
|
||||
replayGroup.getReplay(0, ol.render.ReplayType.IMAGE));
|
||||
replay.setImageStyle(this.imageStyle_);
|
||||
replay.drawMultiPoint(geometry, data);
|
||||
replay.finish(context);
|
||||
var opacity = 1;
|
||||
var skippedFeatures = {};
|
||||
var featureCallback;
|
||||
var oneByOne = false;
|
||||
replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
|
||||
this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
|
||||
oneByOne);
|
||||
replay.getDeleteResourcesFunction(context)();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.webgl.Immediate.prototype.drawLineString = function(geometry, data) {
|
||||
var context = this.context_;
|
||||
var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
|
||||
var replay = /** @type {ol.render.webgl.LineStringReplay} */ (
|
||||
replayGroup.getReplay(0, ol.render.ReplayType.LINE_STRING));
|
||||
replay.setFillStrokeStyle(null, this.strokeStyle_);
|
||||
replay.drawLineString(geometry, data);
|
||||
replay.finish(context);
|
||||
var opacity = 1;
|
||||
var skippedFeatures = {};
|
||||
var featureCallback;
|
||||
var oneByOne = false;
|
||||
replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
|
||||
this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
|
||||
oneByOne);
|
||||
replay.getDeleteResourcesFunction(context)();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.webgl.Immediate.prototype.drawMultiLineString = function(geometry, data) {
|
||||
var context = this.context_;
|
||||
var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
|
||||
var replay = /** @type {ol.render.webgl.LineStringReplay} */ (
|
||||
replayGroup.getReplay(0, ol.render.ReplayType.LINE_STRING));
|
||||
replay.setFillStrokeStyle(null, this.strokeStyle_);
|
||||
replay.drawMultiLineString(geometry, data);
|
||||
replay.finish(context);
|
||||
var opacity = 1;
|
||||
var skippedFeatures = {};
|
||||
var featureCallback;
|
||||
var oneByOne = false;
|
||||
replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
|
||||
this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
|
||||
oneByOne);
|
||||
replay.getDeleteResourcesFunction(context)();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.webgl.Immediate.prototype.drawPolygon = function(geometry, data) {
|
||||
var context = this.context_;
|
||||
var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
|
||||
var replay = /** @type {ol.render.webgl.PolygonReplay} */ (
|
||||
replayGroup.getReplay(0, ol.render.ReplayType.POLYGON));
|
||||
replay.setFillStrokeStyle(this.fillStyle_, this.strokeStyle_);
|
||||
replay.drawPolygon(geometry, data);
|
||||
replay.finish(context);
|
||||
var opacity = 1;
|
||||
var skippedFeatures = {};
|
||||
var featureCallback;
|
||||
var oneByOne = false;
|
||||
replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
|
||||
this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
|
||||
oneByOne);
|
||||
replay.getDeleteResourcesFunction(context)();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.webgl.Immediate.prototype.drawMultiPolygon = function(geometry, data) {
|
||||
var context = this.context_;
|
||||
var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
|
||||
var replay = /** @type {ol.render.webgl.PolygonReplay} */ (
|
||||
replayGroup.getReplay(0, ol.render.ReplayType.POLYGON));
|
||||
replay.setFillStrokeStyle(this.fillStyle_, this.strokeStyle_);
|
||||
replay.drawMultiPolygon(geometry, data);
|
||||
replay.finish(context);
|
||||
var opacity = 1;
|
||||
var skippedFeatures = {};
|
||||
var featureCallback;
|
||||
var oneByOne = false;
|
||||
replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
|
||||
this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
|
||||
oneByOne);
|
||||
replay.getDeleteResourcesFunction(context)();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.webgl.Immediate.prototype.drawCircle = function(geometry, data) {
|
||||
var context = this.context_;
|
||||
var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
|
||||
var replay = /** @type {ol.render.webgl.CircleReplay} */ (
|
||||
replayGroup.getReplay(0, ol.render.ReplayType.CIRCLE));
|
||||
replay.setFillStrokeStyle(this.fillStyle_, this.strokeStyle_);
|
||||
replay.drawCircle(geometry, data);
|
||||
replay.finish(context);
|
||||
var opacity = 1;
|
||||
var skippedFeatures = {};
|
||||
var featureCallback;
|
||||
var oneByOne = false;
|
||||
replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
|
||||
this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
|
||||
oneByOne);
|
||||
replay.getDeleteResourcesFunction(context)();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.webgl.Immediate.prototype.setImageStyle = function(imageStyle) {
|
||||
this.imageStyle_ = imageStyle;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.webgl.Immediate.prototype.setFillStrokeStyle = function(fillStyle, strokeStyle) {
|
||||
this.fillStyle_ = fillStyle;
|
||||
this.strokeStyle_ = strokeStyle;
|
||||
};
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@@ -6,111 +6,115 @@ goog.require('ol.webgl.Fragment');
|
||||
goog.require('ol.webgl.Vertex');
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.webgl.Fragment}
|
||||
* @struct
|
||||
*/
|
||||
ol.render.webgl.polygonreplay.defaultshader.Fragment = function() {
|
||||
ol.webgl.Fragment.call(this, ol.render.webgl.polygonreplay.defaultshader.Fragment.SOURCE);
|
||||
};
|
||||
ol.inherits(ol.render.webgl.polygonreplay.defaultshader.Fragment, ol.webgl.Fragment);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.render.webgl.polygonreplay.defaultshader.Fragment.DEBUG_SOURCE = 'precision mediump float;\n\n\n\nuniform vec4 u_color;\nuniform float u_opacity;\n\nvoid main(void) {\n gl_FragColor = u_color;\n float alpha = u_color.a * u_opacity;\n if (alpha == 0.0) {\n discard;\n }\n gl_FragColor.a = alpha;\n}\n';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.render.webgl.polygonreplay.defaultshader.Fragment.OPTIMIZED_SOURCE = 'precision mediump float;uniform vec4 e;uniform float f;void main(void){gl_FragColor=e;float alpha=e.a*f;if(alpha==0.0){discard;}gl_FragColor.a=alpha;}';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.render.webgl.polygonreplay.defaultshader.Fragment.SOURCE = ol.render.webgl.polygonreplay.defaultshader.Fragment.OPTIMIZED_SOURCE;
|
||||
|
||||
|
||||
ol.render.webgl.polygonreplay.defaultshader.fragment = new ol.render.webgl.polygonreplay.defaultshader.Fragment();
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.webgl.Vertex}
|
||||
* @struct
|
||||
*/
|
||||
ol.render.webgl.polygonreplay.defaultshader.Vertex = function() {
|
||||
ol.webgl.Vertex.call(this, ol.render.webgl.polygonreplay.defaultshader.Vertex.SOURCE);
|
||||
};
|
||||
ol.inherits(ol.render.webgl.polygonreplay.defaultshader.Vertex, ol.webgl.Vertex);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.render.webgl.polygonreplay.defaultshader.Vertex.DEBUG_SOURCE = '\n\nattribute vec2 a_position;\n\nuniform mat4 u_projectionMatrix;\nuniform mat4 u_offsetScaleMatrix;\nuniform mat4 u_offsetRotateMatrix;\n\nvoid main(void) {\n gl_Position = u_projectionMatrix * vec4(a_position, 0.0, 1.0);\n}\n\n\n';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.render.webgl.polygonreplay.defaultshader.Vertex.OPTIMIZED_SOURCE = 'attribute vec2 a;uniform mat4 b;uniform mat4 c;uniform mat4 d;void main(void){gl_Position=b*vec4(a,0.0,1.0);}';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.render.webgl.polygonreplay.defaultshader.Vertex.SOURCE = ol.render.webgl.polygonreplay.defaultshader.Vertex.OPTIMIZED_SOURCE;
|
||||
|
||||
|
||||
ol.render.webgl.polygonreplay.defaultshader.vertex = new ol.render.webgl.polygonreplay.defaultshader.Vertex();
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {WebGLRenderingContext} gl GL.
|
||||
* @param {WebGLProgram} program Program.
|
||||
* @struct
|
||||
*/
|
||||
ol.render.webgl.polygonreplay.defaultshader.Locations = function(gl, program) {
|
||||
if (ol.ENABLE_WEBGL) {
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
* @constructor
|
||||
* @extends {ol.webgl.Fragment}
|
||||
* @struct
|
||||
*/
|
||||
this.u_color = gl.getUniformLocation(program, 'e');
|
||||
ol.render.webgl.polygonreplay.defaultshader.Fragment = function() {
|
||||
ol.webgl.Fragment.call(this, ol.render.webgl.polygonreplay.defaultshader.Fragment.SOURCE);
|
||||
};
|
||||
ol.inherits(ol.render.webgl.polygonreplay.defaultshader.Fragment, ol.webgl.Fragment);
|
||||
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
this.u_offsetRotateMatrix = gl.getUniformLocation(program, 'd');
|
||||
ol.render.webgl.polygonreplay.defaultshader.Fragment.DEBUG_SOURCE = 'precision mediump float;\n\n\n\nuniform vec4 u_color;\nuniform float u_opacity;\n\nvoid main(void) {\n gl_FragColor = u_color;\n float alpha = u_color.a * u_opacity;\n if (alpha == 0.0) {\n discard;\n }\n gl_FragColor.a = alpha;\n}\n';
|
||||
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
this.u_offsetScaleMatrix = gl.getUniformLocation(program, 'c');
|
||||
ol.render.webgl.polygonreplay.defaultshader.Fragment.OPTIMIZED_SOURCE = 'precision mediump float;uniform vec4 e;uniform float f;void main(void){gl_FragColor=e;float alpha=e.a*f;if(alpha==0.0){discard;}gl_FragColor.a=alpha;}';
|
||||
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
this.u_opacity = gl.getUniformLocation(program, 'f');
|
||||
ol.render.webgl.polygonreplay.defaultshader.Fragment.SOURCE = ol.render.webgl.polygonreplay.defaultshader.Fragment.OPTIMIZED_SOURCE;
|
||||
|
||||
|
||||
ol.render.webgl.polygonreplay.defaultshader.fragment = new ol.render.webgl.polygonreplay.defaultshader.Fragment();
|
||||
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
* @constructor
|
||||
* @extends {ol.webgl.Vertex}
|
||||
* @struct
|
||||
*/
|
||||
this.u_projectionMatrix = gl.getUniformLocation(program, 'b');
|
||||
ol.render.webgl.polygonreplay.defaultshader.Vertex = function() {
|
||||
ol.webgl.Vertex.call(this, ol.render.webgl.polygonreplay.defaultshader.Vertex.SOURCE);
|
||||
};
|
||||
ol.inherits(ol.render.webgl.polygonreplay.defaultshader.Vertex, ol.webgl.Vertex);
|
||||
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
this.a_position = gl.getAttribLocation(program, 'a');
|
||||
};
|
||||
ol.render.webgl.polygonreplay.defaultshader.Vertex.DEBUG_SOURCE = '\n\nattribute vec2 a_position;\n\nuniform mat4 u_projectionMatrix;\nuniform mat4 u_offsetScaleMatrix;\nuniform mat4 u_offsetRotateMatrix;\n\nvoid main(void) {\n gl_Position = u_projectionMatrix * vec4(a_position, 0.0, 1.0);\n}\n\n\n';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.render.webgl.polygonreplay.defaultshader.Vertex.OPTIMIZED_SOURCE = 'attribute vec2 a;uniform mat4 b;uniform mat4 c;uniform mat4 d;void main(void){gl_Position=b*vec4(a,0.0,1.0);}';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.render.webgl.polygonreplay.defaultshader.Vertex.SOURCE = ol.render.webgl.polygonreplay.defaultshader.Vertex.OPTIMIZED_SOURCE;
|
||||
|
||||
|
||||
ol.render.webgl.polygonreplay.defaultshader.vertex = new ol.render.webgl.polygonreplay.defaultshader.Vertex();
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {WebGLRenderingContext} gl GL.
|
||||
* @param {WebGLProgram} program Program.
|
||||
* @struct
|
||||
*/
|
||||
ol.render.webgl.polygonreplay.defaultshader.Locations = function(gl, program) {
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_color = gl.getUniformLocation(program, 'e');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_offsetRotateMatrix = gl.getUniformLocation(program, 'd');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_offsetScaleMatrix = gl.getUniformLocation(program, 'c');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_opacity = gl.getUniformLocation(program, 'f');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_projectionMatrix = gl.getUniformLocation(program, 'b');
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.a_position = gl.getAttribLocation(program, 'a');
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -7,353 +7,358 @@ goog.require('ol.transform');
|
||||
goog.require('ol.vec.Mat4');
|
||||
goog.require('ol.webgl');
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.render.VectorContext}
|
||||
* @param {number} tolerance Tolerance.
|
||||
* @param {ol.Extent} maxExtent Max extent.
|
||||
* @struct
|
||||
*/
|
||||
ol.render.webgl.Replay = function(tolerance, maxExtent) {
|
||||
ol.render.VectorContext.call(this);
|
||||
|
||||
if (ol.ENABLE_WEBGL) {
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.render.VectorContext}
|
||||
* @param {number} tolerance Tolerance.
|
||||
* @param {ol.Extent} maxExtent Max extent.
|
||||
* @struct
|
||||
*/
|
||||
ol.render.webgl.Replay = function(tolerance, maxExtent) {
|
||||
ol.render.VectorContext.call(this);
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {number}
|
||||
*/
|
||||
this.tolerance = tolerance;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @const
|
||||
* @type {ol.Extent}
|
||||
*/
|
||||
this.maxExtent = maxExtent;
|
||||
|
||||
/**
|
||||
* The origin of the coordinate system for the point coordinates sent to
|
||||
* the GPU. To eliminate jitter caused by precision problems in the GPU
|
||||
* we use the "Rendering Relative to Eye" technique described in the "3D
|
||||
* Engine Design for Virtual Globes" book.
|
||||
* @protected
|
||||
* @type {ol.Coordinate}
|
||||
*/
|
||||
this.origin = ol.extent.getCenter(maxExtent);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Transform}
|
||||
*/
|
||||
this.projectionMatrix_ = ol.transform.create();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Transform}
|
||||
*/
|
||||
this.offsetRotateMatrix_ = ol.transform.create();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Transform}
|
||||
*/
|
||||
this.offsetScaleMatrix_ = ol.transform.create();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this.tmpMat4_ = ol.vec.Mat4.create();
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this.indices = [];
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {?ol.webgl.Buffer}
|
||||
*/
|
||||
this.indicesBuffer = null;
|
||||
|
||||
/**
|
||||
* Start index per feature (the index).
|
||||
* @protected
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this.startIndices = [];
|
||||
|
||||
/**
|
||||
* Start index per feature (the feature).
|
||||
* @protected
|
||||
* @type {Array.<ol.Feature|ol.render.Feature>}
|
||||
*/
|
||||
this.startIndicesFeature = [];
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this.vertices = [];
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {?ol.webgl.Buffer}
|
||||
*/
|
||||
this.verticesBuffer = null;
|
||||
|
||||
/**
|
||||
* Optional parameter for PolygonReplay instances.
|
||||
* @protected
|
||||
* @type {ol.render.webgl.LineStringReplay|undefined}
|
||||
*/
|
||||
this.lineStringReplay = undefined;
|
||||
|
||||
};
|
||||
ol.inherits(ol.render.webgl.Replay, ol.render.VectorContext);
|
||||
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {ol.webgl.Context} context WebGL context.
|
||||
* @return {function()} Delete resources function.
|
||||
*/
|
||||
ol.render.webgl.Replay.prototype.getDeleteResourcesFunction = function(context) {};
|
||||
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
*/
|
||||
ol.render.webgl.Replay.prototype.finish = function(context) {};
|
||||
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @protected
|
||||
* @param {WebGLRenderingContext} gl gl.
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @param {ol.Size} size Size.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @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.
|
||||
*/
|
||||
ol.render.webgl.Replay.prototype.setUpProgram = function(gl, context, size, pixelRatio) {};
|
||||
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @protected
|
||||
* @param {WebGLRenderingContext} gl gl.
|
||||
* @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.
|
||||
*/
|
||||
ol.render.webgl.Replay.prototype.shutDownProgram = function(gl, locations) {};
|
||||
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @protected
|
||||
* @param {WebGLRenderingContext} gl gl.
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
|
||||
* to skip.
|
||||
* @param {boolean} hitDetection Hit detection mode.
|
||||
*/
|
||||
ol.render.webgl.Replay.prototype.drawReplay = function(gl, context, skippedFeaturesHash, hitDetection) {};
|
||||
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @protected
|
||||
* @param {WebGLRenderingContext} gl gl.
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
|
||||
* to skip.
|
||||
* @param {function((ol.Feature|ol.render.Feature)): T|undefined} featureCallback Feature callback.
|
||||
* @param {ol.Extent=} opt_hitExtent Hit extent: Only features intersecting
|
||||
* this extent are checked.
|
||||
* @return {T|undefined} Callback result.
|
||||
* @template T
|
||||
*/
|
||||
ol.render.webgl.Replay.prototype.drawHitDetectionReplayOneByOne = function(gl, context, skippedFeaturesHash, featureCallback, opt_hitExtent) {};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {number}
|
||||
* @param {WebGLRenderingContext} gl gl.
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
|
||||
* to skip.
|
||||
* @param {function((ol.Feature|ol.render.Feature)): T|undefined} featureCallback Feature callback.
|
||||
* @param {boolean} oneByOne Draw features one-by-one for the hit-detecion.
|
||||
* @param {ol.Extent=} opt_hitExtent Hit extent: Only features intersecting
|
||||
* this extent are checked.
|
||||
* @return {T|undefined} Callback result.
|
||||
* @template T
|
||||
*/
|
||||
this.tolerance = tolerance;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @const
|
||||
* @type {ol.Extent}
|
||||
*/
|
||||
this.maxExtent = maxExtent;
|
||||
|
||||
/**
|
||||
* The origin of the coordinate system for the point coordinates sent to
|
||||
* the GPU. To eliminate jitter caused by precision problems in the GPU
|
||||
* we use the "Rendering Relative to Eye" technique described in the "3D
|
||||
* Engine Design for Virtual Globes" book.
|
||||
* @protected
|
||||
* @type {ol.Coordinate}
|
||||
*/
|
||||
this.origin = ol.extent.getCenter(maxExtent);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Transform}
|
||||
*/
|
||||
this.projectionMatrix_ = ol.transform.create();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Transform}
|
||||
*/
|
||||
this.offsetRotateMatrix_ = ol.transform.create();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Transform}
|
||||
*/
|
||||
this.offsetScaleMatrix_ = ol.transform.create();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this.tmpMat4_ = ol.vec.Mat4.create();
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this.indices = [];
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {?ol.webgl.Buffer}
|
||||
*/
|
||||
this.indicesBuffer = null;
|
||||
|
||||
/**
|
||||
* Start index per feature (the index).
|
||||
* @protected
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this.startIndices = [];
|
||||
|
||||
/**
|
||||
* Start index per feature (the feature).
|
||||
* @protected
|
||||
* @type {Array.<ol.Feature|ol.render.Feature>}
|
||||
*/
|
||||
this.startIndicesFeature = [];
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this.vertices = [];
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {?ol.webgl.Buffer}
|
||||
*/
|
||||
this.verticesBuffer = null;
|
||||
|
||||
/**
|
||||
* Optional parameter for PolygonReplay instances.
|
||||
* @protected
|
||||
* @type {ol.render.webgl.LineStringReplay|undefined}
|
||||
*/
|
||||
this.lineStringReplay = undefined;
|
||||
|
||||
};
|
||||
ol.inherits(ol.render.webgl.Replay, ol.render.VectorContext);
|
||||
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {ol.webgl.Context} context WebGL context.
|
||||
* @return {function()} Delete resources function.
|
||||
*/
|
||||
ol.render.webgl.Replay.prototype.getDeleteResourcesFunction = function(context) {};
|
||||
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
*/
|
||||
ol.render.webgl.Replay.prototype.finish = function(context) {};
|
||||
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @protected
|
||||
* @param {WebGLRenderingContext} gl gl.
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @param {ol.Size} size Size.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @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.
|
||||
*/
|
||||
ol.render.webgl.Replay.prototype.setUpProgram = function(gl, context, size, pixelRatio) {};
|
||||
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @protected
|
||||
* @param {WebGLRenderingContext} gl gl.
|
||||
* @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.
|
||||
*/
|
||||
ol.render.webgl.Replay.prototype.shutDownProgram = function(gl, locations) {};
|
||||
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @protected
|
||||
* @param {WebGLRenderingContext} gl gl.
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
|
||||
* to skip.
|
||||
* @param {boolean} hitDetection Hit detection mode.
|
||||
*/
|
||||
ol.render.webgl.Replay.prototype.drawReplay = function(gl, context, skippedFeaturesHash, hitDetection) {};
|
||||
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @protected
|
||||
* @param {WebGLRenderingContext} gl gl.
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
|
||||
* to skip.
|
||||
* @param {function((ol.Feature|ol.render.Feature)): T|undefined} featureCallback Feature callback.
|
||||
* @param {ol.Extent=} opt_hitExtent Hit extent: Only features intersecting
|
||||
* this extent are checked.
|
||||
* @return {T|undefined} Callback result.
|
||||
* @template T
|
||||
*/
|
||||
ol.render.webgl.Replay.prototype.drawHitDetectionReplayOneByOne = function(gl, context, skippedFeaturesHash, featureCallback, opt_hitExtent) {};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @param {WebGLRenderingContext} gl gl.
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
|
||||
* to skip.
|
||||
* @param {function((ol.Feature|ol.render.Feature)): T|undefined} featureCallback Feature callback.
|
||||
* @param {boolean} oneByOne Draw features one-by-one for the hit-detecion.
|
||||
* @param {ol.Extent=} opt_hitExtent Hit extent: Only features intersecting
|
||||
* this extent are checked.
|
||||
* @return {T|undefined} Callback result.
|
||||
* @template T
|
||||
*/
|
||||
ol.render.webgl.Replay.prototype.drawHitDetectionReplay = function(gl, context, skippedFeaturesHash,
|
||||
featureCallback, oneByOne, opt_hitExtent) {
|
||||
if (!oneByOne) {
|
||||
// draw all hit-detection features in "once" (by texture group)
|
||||
return this.drawHitDetectionReplayAll(gl, context,
|
||||
skippedFeaturesHash, featureCallback);
|
||||
} else {
|
||||
// draw hit-detection features one by one
|
||||
return this.drawHitDetectionReplayOneByOne(gl, context,
|
||||
skippedFeaturesHash, featureCallback, opt_hitExtent);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @param {WebGLRenderingContext} gl gl.
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
|
||||
* to skip.
|
||||
* @param {function((ol.Feature|ol.render.Feature)): T|undefined} featureCallback Feature callback.
|
||||
* @return {T|undefined} Callback result.
|
||||
* @template T
|
||||
*/
|
||||
ol.render.webgl.Replay.prototype.drawHitDetectionReplayAll = function(gl, context, skippedFeaturesHash,
|
||||
featureCallback) {
|
||||
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||||
this.drawReplay(gl, context, skippedFeaturesHash, true);
|
||||
|
||||
var result = featureCallback(null);
|
||||
if (result) {
|
||||
return result;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @param {ol.Coordinate} center Center.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {number} rotation Rotation.
|
||||
* @param {ol.Size} size Size.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {number} opacity Global opacity.
|
||||
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
|
||||
* to skip.
|
||||
* @param {function((ol.Feature|ol.render.Feature)): T|undefined} featureCallback Feature callback.
|
||||
* @param {boolean} oneByOne Draw features one-by-one for the hit-detecion.
|
||||
* @param {ol.Extent=} opt_hitExtent Hit extent: Only features intersecting
|
||||
* this extent are checked.
|
||||
* @return {T|undefined} Callback result.
|
||||
* @template T
|
||||
*/
|
||||
ol.render.webgl.Replay.prototype.replay = function(context,
|
||||
center, resolution, rotation, size, pixelRatio,
|
||||
opacity, skippedFeaturesHash,
|
||||
featureCallback, oneByOne, opt_hitExtent) {
|
||||
var gl = context.getGL();
|
||||
var tmpStencil, tmpStencilFunc, tmpStencilMaskVal, tmpStencilRef, tmpStencilMask,
|
||||
tmpStencilOpFail, tmpStencilOpPass, tmpStencilOpZFail;
|
||||
|
||||
if (this.lineStringReplay) {
|
||||
tmpStencil = gl.isEnabled(gl.STENCIL_TEST);
|
||||
tmpStencilFunc = gl.getParameter(gl.STENCIL_FUNC);
|
||||
tmpStencilMaskVal = gl.getParameter(gl.STENCIL_VALUE_MASK);
|
||||
tmpStencilRef = gl.getParameter(gl.STENCIL_REF);
|
||||
tmpStencilMask = gl.getParameter(gl.STENCIL_WRITEMASK);
|
||||
tmpStencilOpFail = gl.getParameter(gl.STENCIL_FAIL);
|
||||
tmpStencilOpPass = gl.getParameter(gl.STENCIL_PASS_DEPTH_PASS);
|
||||
tmpStencilOpZFail = gl.getParameter(gl.STENCIL_PASS_DEPTH_FAIL);
|
||||
|
||||
gl.enable(gl.STENCIL_TEST);
|
||||
gl.clear(gl.STENCIL_BUFFER_BIT);
|
||||
gl.stencilMask(255);
|
||||
gl.stencilFunc(gl.ALWAYS, 1, 255);
|
||||
gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
|
||||
|
||||
this.lineStringReplay.replay(context,
|
||||
center, resolution, rotation, size, pixelRatio,
|
||||
opacity, skippedFeaturesHash,
|
||||
featureCallback, oneByOne, opt_hitExtent);
|
||||
|
||||
gl.stencilMask(0);
|
||||
gl.stencilFunc(gl.NOTEQUAL, 1, 255);
|
||||
}
|
||||
|
||||
context.bindBuffer(ol.webgl.ARRAY_BUFFER, this.verticesBuffer);
|
||||
|
||||
context.bindBuffer(ol.webgl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer);
|
||||
|
||||
var locations = this.setUpProgram(gl, context, size, pixelRatio);
|
||||
|
||||
// set the "uniform" values
|
||||
var projectionMatrix = ol.transform.reset(this.projectionMatrix_);
|
||||
ol.transform.scale(projectionMatrix, 2 / (resolution * size[0]), 2 / (resolution * size[1]));
|
||||
ol.transform.rotate(projectionMatrix, -rotation);
|
||||
ol.transform.translate(projectionMatrix, -(center[0] - this.origin[0]), -(center[1] - this.origin[1]));
|
||||
|
||||
var offsetScaleMatrix = ol.transform.reset(this.offsetScaleMatrix_);
|
||||
ol.transform.scale(offsetScaleMatrix, 2 / size[0], 2 / size[1]);
|
||||
|
||||
var offsetRotateMatrix = ol.transform.reset(this.offsetRotateMatrix_);
|
||||
if (rotation !== 0) {
|
||||
ol.transform.rotate(offsetRotateMatrix, -rotation);
|
||||
}
|
||||
|
||||
gl.uniformMatrix4fv(locations.u_projectionMatrix, false,
|
||||
ol.vec.Mat4.fromTransform(this.tmpMat4_, projectionMatrix));
|
||||
gl.uniformMatrix4fv(locations.u_offsetScaleMatrix, false,
|
||||
ol.vec.Mat4.fromTransform(this.tmpMat4_, offsetScaleMatrix));
|
||||
gl.uniformMatrix4fv(locations.u_offsetRotateMatrix, false,
|
||||
ol.vec.Mat4.fromTransform(this.tmpMat4_, offsetRotateMatrix));
|
||||
gl.uniform1f(locations.u_opacity, opacity);
|
||||
|
||||
// draw!
|
||||
var result;
|
||||
if (featureCallback === undefined) {
|
||||
this.drawReplay(gl, context, skippedFeaturesHash, false);
|
||||
} else {
|
||||
// draw feature by feature for the hit-detection
|
||||
result = this.drawHitDetectionReplay(gl, context, skippedFeaturesHash,
|
||||
featureCallback, oneByOne, opt_hitExtent);
|
||||
}
|
||||
|
||||
// disable the vertex attrib arrays
|
||||
this.shutDownProgram(gl, locations);
|
||||
|
||||
if (this.lineStringReplay) {
|
||||
if (!tmpStencil) {
|
||||
gl.disable(gl.STENCIL_TEST);
|
||||
ol.render.webgl.Replay.prototype.drawHitDetectionReplay = function(gl, context, skippedFeaturesHash,
|
||||
featureCallback, oneByOne, opt_hitExtent) {
|
||||
if (!oneByOne) {
|
||||
// draw all hit-detection features in "once" (by texture group)
|
||||
return this.drawHitDetectionReplayAll(gl, context,
|
||||
skippedFeaturesHash, featureCallback);
|
||||
} else {
|
||||
// draw hit-detection features one by one
|
||||
return this.drawHitDetectionReplayOneByOne(gl, context,
|
||||
skippedFeaturesHash, featureCallback, opt_hitExtent);
|
||||
}
|
||||
gl.clear(gl.STENCIL_BUFFER_BIT);
|
||||
gl.stencilFunc(/** @type {number} */ (tmpStencilFunc),
|
||||
/** @type {number} */ (tmpStencilRef), /** @type {number} */ (tmpStencilMaskVal));
|
||||
gl.stencilMask(/** @type {number} */ (tmpStencilMask));
|
||||
gl.stencilOp(/** @type {number} */ (tmpStencilOpFail),
|
||||
/** @type {number} */ (tmpStencilOpZFail), /** @type {number} */ (tmpStencilOpPass));
|
||||
}
|
||||
};
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @param {WebGLRenderingContext} gl gl.
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @param {number} start Start index.
|
||||
* @param {number} end End index.
|
||||
*/
|
||||
ol.render.webgl.Replay.prototype.drawElements = function(
|
||||
gl, context, start, end) {
|
||||
var elementType = context.hasOESElementIndexUint ?
|
||||
ol.webgl.UNSIGNED_INT : ol.webgl.UNSIGNED_SHORT;
|
||||
var elementSize = context.hasOESElementIndexUint ? 4 : 2;
|
||||
/**
|
||||
* @protected
|
||||
* @param {WebGLRenderingContext} gl gl.
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
|
||||
* to skip.
|
||||
* @param {function((ol.Feature|ol.render.Feature)): T|undefined} featureCallback Feature callback.
|
||||
* @return {T|undefined} Callback result.
|
||||
* @template T
|
||||
*/
|
||||
ol.render.webgl.Replay.prototype.drawHitDetectionReplayAll = function(gl, context, skippedFeaturesHash,
|
||||
featureCallback) {
|
||||
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||||
this.drawReplay(gl, context, skippedFeaturesHash, true);
|
||||
|
||||
var numItems = end - start;
|
||||
var offsetInBytes = start * elementSize;
|
||||
gl.drawElements(ol.webgl.TRIANGLES, numItems, elementType, offsetInBytes);
|
||||
};
|
||||
var result = featureCallback(null);
|
||||
if (result) {
|
||||
return result;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @param {ol.Coordinate} center Center.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {number} rotation Rotation.
|
||||
* @param {ol.Size} size Size.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {number} opacity Global opacity.
|
||||
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
|
||||
* to skip.
|
||||
* @param {function((ol.Feature|ol.render.Feature)): T|undefined} featureCallback Feature callback.
|
||||
* @param {boolean} oneByOne Draw features one-by-one for the hit-detecion.
|
||||
* @param {ol.Extent=} opt_hitExtent Hit extent: Only features intersecting
|
||||
* this extent are checked.
|
||||
* @return {T|undefined} Callback result.
|
||||
* @template T
|
||||
*/
|
||||
ol.render.webgl.Replay.prototype.replay = function(context,
|
||||
center, resolution, rotation, size, pixelRatio,
|
||||
opacity, skippedFeaturesHash,
|
||||
featureCallback, oneByOne, opt_hitExtent) {
|
||||
var gl = context.getGL();
|
||||
var tmpStencil, tmpStencilFunc, tmpStencilMaskVal, tmpStencilRef, tmpStencilMask,
|
||||
tmpStencilOpFail, tmpStencilOpPass, tmpStencilOpZFail;
|
||||
|
||||
if (this.lineStringReplay) {
|
||||
tmpStencil = gl.isEnabled(gl.STENCIL_TEST);
|
||||
tmpStencilFunc = gl.getParameter(gl.STENCIL_FUNC);
|
||||
tmpStencilMaskVal = gl.getParameter(gl.STENCIL_VALUE_MASK);
|
||||
tmpStencilRef = gl.getParameter(gl.STENCIL_REF);
|
||||
tmpStencilMask = gl.getParameter(gl.STENCIL_WRITEMASK);
|
||||
tmpStencilOpFail = gl.getParameter(gl.STENCIL_FAIL);
|
||||
tmpStencilOpPass = gl.getParameter(gl.STENCIL_PASS_DEPTH_PASS);
|
||||
tmpStencilOpZFail = gl.getParameter(gl.STENCIL_PASS_DEPTH_FAIL);
|
||||
|
||||
gl.enable(gl.STENCIL_TEST);
|
||||
gl.clear(gl.STENCIL_BUFFER_BIT);
|
||||
gl.stencilMask(255);
|
||||
gl.stencilFunc(gl.ALWAYS, 1, 255);
|
||||
gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
|
||||
|
||||
this.lineStringReplay.replay(context,
|
||||
center, resolution, rotation, size, pixelRatio,
|
||||
opacity, skippedFeaturesHash,
|
||||
featureCallback, oneByOne, opt_hitExtent);
|
||||
|
||||
gl.stencilMask(0);
|
||||
gl.stencilFunc(gl.NOTEQUAL, 1, 255);
|
||||
}
|
||||
|
||||
context.bindBuffer(ol.webgl.ARRAY_BUFFER, this.verticesBuffer);
|
||||
|
||||
context.bindBuffer(ol.webgl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer);
|
||||
|
||||
var locations = this.setUpProgram(gl, context, size, pixelRatio);
|
||||
|
||||
// set the "uniform" values
|
||||
var projectionMatrix = ol.transform.reset(this.projectionMatrix_);
|
||||
ol.transform.scale(projectionMatrix, 2 / (resolution * size[0]), 2 / (resolution * size[1]));
|
||||
ol.transform.rotate(projectionMatrix, -rotation);
|
||||
ol.transform.translate(projectionMatrix, -(center[0] - this.origin[0]), -(center[1] - this.origin[1]));
|
||||
|
||||
var offsetScaleMatrix = ol.transform.reset(this.offsetScaleMatrix_);
|
||||
ol.transform.scale(offsetScaleMatrix, 2 / size[0], 2 / size[1]);
|
||||
|
||||
var offsetRotateMatrix = ol.transform.reset(this.offsetRotateMatrix_);
|
||||
if (rotation !== 0) {
|
||||
ol.transform.rotate(offsetRotateMatrix, -rotation);
|
||||
}
|
||||
|
||||
gl.uniformMatrix4fv(locations.u_projectionMatrix, false,
|
||||
ol.vec.Mat4.fromTransform(this.tmpMat4_, projectionMatrix));
|
||||
gl.uniformMatrix4fv(locations.u_offsetScaleMatrix, false,
|
||||
ol.vec.Mat4.fromTransform(this.tmpMat4_, offsetScaleMatrix));
|
||||
gl.uniformMatrix4fv(locations.u_offsetRotateMatrix, false,
|
||||
ol.vec.Mat4.fromTransform(this.tmpMat4_, offsetRotateMatrix));
|
||||
gl.uniform1f(locations.u_opacity, opacity);
|
||||
|
||||
// draw!
|
||||
var result;
|
||||
if (featureCallback === undefined) {
|
||||
this.drawReplay(gl, context, skippedFeaturesHash, false);
|
||||
} else {
|
||||
// draw feature by feature for the hit-detection
|
||||
result = this.drawHitDetectionReplay(gl, context, skippedFeaturesHash,
|
||||
featureCallback, oneByOne, opt_hitExtent);
|
||||
}
|
||||
|
||||
// disable the vertex attrib arrays
|
||||
this.shutDownProgram(gl, locations);
|
||||
|
||||
if (this.lineStringReplay) {
|
||||
if (!tmpStencil) {
|
||||
gl.disable(gl.STENCIL_TEST);
|
||||
}
|
||||
gl.clear(gl.STENCIL_BUFFER_BIT);
|
||||
gl.stencilFunc(/** @type {number} */ (tmpStencilFunc),
|
||||
/** @type {number} */ (tmpStencilRef), /** @type {number} */ (tmpStencilMaskVal));
|
||||
gl.stencilMask(/** @type {number} */ (tmpStencilMask));
|
||||
gl.stencilOp(/** @type {number} */ (tmpStencilOpFail),
|
||||
/** @type {number} */ (tmpStencilOpZFail), /** @type {number} */ (tmpStencilOpPass));
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @param {WebGLRenderingContext} gl gl.
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @param {number} start Start index.
|
||||
* @param {number} end End index.
|
||||
*/
|
||||
ol.render.webgl.Replay.prototype.drawElements = function(
|
||||
gl, context, start, end) {
|
||||
var elementType = context.hasOESElementIndexUint ?
|
||||
ol.webgl.UNSIGNED_INT : ol.webgl.UNSIGNED_SHORT;
|
||||
var elementSize = context.hasOESElementIndexUint ? 4 : 2;
|
||||
|
||||
var numItems = end - start;
|
||||
var offsetInBytes = start * elementSize;
|
||||
gl.drawElements(ol.webgl.TRIANGLES, numItems, elementType, offsetInBytes);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -13,306 +13,311 @@ goog.require('ol.render.webgl.LineStringReplay');
|
||||
goog.require('ol.render.webgl.PolygonReplay');
|
||||
goog.require('ol.render.webgl.TextReplay');
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.render.ReplayGroup}
|
||||
* @param {number} tolerance Tolerance.
|
||||
* @param {ol.Extent} maxExtent Max extent.
|
||||
* @param {number=} opt_renderBuffer Render buffer.
|
||||
* @struct
|
||||
*/
|
||||
ol.render.webgl.ReplayGroup = function(tolerance, maxExtent, opt_renderBuffer) {
|
||||
ol.render.ReplayGroup.call(this);
|
||||
|
||||
if (ol.ENABLE_WEBGL) {
|
||||
|
||||
/**
|
||||
* @type {ol.Extent}
|
||||
* @private
|
||||
* @constructor
|
||||
* @extends {ol.render.ReplayGroup}
|
||||
* @param {number} tolerance Tolerance.
|
||||
* @param {ol.Extent} maxExtent Max extent.
|
||||
* @param {number=} opt_renderBuffer Render buffer.
|
||||
* @struct
|
||||
*/
|
||||
this.maxExtent_ = maxExtent;
|
||||
ol.render.webgl.ReplayGroup = function(tolerance, maxExtent, opt_renderBuffer) {
|
||||
ol.render.ReplayGroup.call(this);
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.tolerance_ = tolerance;
|
||||
/**
|
||||
* @type {ol.Extent}
|
||||
* @private
|
||||
*/
|
||||
this.maxExtent_ = maxExtent;
|
||||
|
||||
/**
|
||||
* @type {number|undefined}
|
||||
* @private
|
||||
*/
|
||||
this.renderBuffer_ = opt_renderBuffer;
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.tolerance_ = tolerance;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!Object.<string,
|
||||
* Object.<ol.render.ReplayType, ol.render.webgl.Replay>>}
|
||||
*/
|
||||
this.replaysByZIndex_ = {};
|
||||
/**
|
||||
* @type {number|undefined}
|
||||
* @private
|
||||
*/
|
||||
this.renderBuffer_ = opt_renderBuffer;
|
||||
|
||||
};
|
||||
ol.inherits(ol.render.webgl.ReplayGroup, ol.render.ReplayGroup);
|
||||
/**
|
||||
* @private
|
||||
* @type {!Object.<string,
|
||||
* Object.<ol.render.ReplayType, ol.render.webgl.Replay>>}
|
||||
*/
|
||||
this.replaysByZIndex_ = {};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.webgl.Context} context WebGL context.
|
||||
* @return {function()} Delete resources function.
|
||||
*/
|
||||
ol.render.webgl.ReplayGroup.prototype.getDeleteResourcesFunction = function(context) {
|
||||
var functions = [];
|
||||
var zKey;
|
||||
for (zKey in this.replaysByZIndex_) {
|
||||
var replays = this.replaysByZIndex_[zKey];
|
||||
var replayKey;
|
||||
for (replayKey in replays) {
|
||||
functions.push(
|
||||
replays[replayKey].getDeleteResourcesFunction(context));
|
||||
}
|
||||
}
|
||||
return function() {
|
||||
var length = functions.length;
|
||||
var result;
|
||||
for (var i = 0; i < length; i++) {
|
||||
result = functions[i].apply(this, arguments);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
};
|
||||
ol.inherits(ol.render.webgl.ReplayGroup, ol.render.ReplayGroup);
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
*/
|
||||
ol.render.webgl.ReplayGroup.prototype.finish = function(context) {
|
||||
var zKey;
|
||||
for (zKey in this.replaysByZIndex_) {
|
||||
var replays = this.replaysByZIndex_[zKey];
|
||||
var replayKey;
|
||||
for (replayKey in replays) {
|
||||
replays[replayKey].finish(context);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.webgl.ReplayGroup.prototype.getReplay = function(zIndex, replayType) {
|
||||
var zIndexKey = zIndex !== undefined ? zIndex.toString() : '0';
|
||||
var replays = this.replaysByZIndex_[zIndexKey];
|
||||
if (replays === undefined) {
|
||||
replays = {};
|
||||
this.replaysByZIndex_[zIndexKey] = replays;
|
||||
}
|
||||
var replay = replays[replayType];
|
||||
if (replay === undefined) {
|
||||
var Constructor = ol.render.webgl.ReplayGroup.BATCH_CONSTRUCTORS_[replayType];
|
||||
replay = new Constructor(this.tolerance_, this.maxExtent_);
|
||||
replays[replayType] = replay;
|
||||
}
|
||||
return replay;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.webgl.ReplayGroup.prototype.isEmpty = function() {
|
||||
return ol.obj.isEmpty(this.replaysByZIndex_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @param {ol.Coordinate} center Center.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {number} rotation Rotation.
|
||||
* @param {ol.Size} size Size.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {number} opacity Global opacity.
|
||||
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
|
||||
* to skip.
|
||||
*/
|
||||
ol.render.webgl.ReplayGroup.prototype.replay = function(context,
|
||||
center, resolution, rotation, size, pixelRatio,
|
||||
opacity, skippedFeaturesHash) {
|
||||
/** @type {Array.<number>} */
|
||||
var zs = Object.keys(this.replaysByZIndex_).map(Number);
|
||||
zs.sort(ol.array.numberSafeCompareFunction);
|
||||
|
||||
var i, ii, j, jj, replays, replay;
|
||||
for (i = 0, ii = zs.length; i < ii; ++i) {
|
||||
replays = this.replaysByZIndex_[zs[i].toString()];
|
||||
for (j = 0, jj = ol.render.replay.ORDER.length; j < jj; ++j) {
|
||||
replay = replays[ol.render.replay.ORDER[j]];
|
||||
if (replay !== undefined) {
|
||||
replay.replay(context,
|
||||
center, resolution, rotation, size, pixelRatio,
|
||||
opacity, skippedFeaturesHash,
|
||||
undefined, false);
|
||||
/**
|
||||
* @param {ol.webgl.Context} context WebGL context.
|
||||
* @return {function()} Delete resources function.
|
||||
*/
|
||||
ol.render.webgl.ReplayGroup.prototype.getDeleteResourcesFunction = function(context) {
|
||||
var functions = [];
|
||||
var zKey;
|
||||
for (zKey in this.replaysByZIndex_) {
|
||||
var replays = this.replaysByZIndex_[zKey];
|
||||
var replayKey;
|
||||
for (replayKey in replays) {
|
||||
functions.push(
|
||||
replays[replayKey].getDeleteResourcesFunction(context));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
return function() {
|
||||
var length = functions.length;
|
||||
var result;
|
||||
for (var i = 0; i < length; i++) {
|
||||
result = functions[i].apply(this, arguments);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @param {ol.Coordinate} center Center.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {number} rotation Rotation.
|
||||
* @param {ol.Size} size Size.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {number} opacity Global opacity.
|
||||
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
|
||||
* to skip.
|
||||
* @param {function((ol.Feature|ol.render.Feature)): T|undefined} featureCallback Feature callback.
|
||||
* @param {boolean} oneByOne Draw features one-by-one for the hit-detecion.
|
||||
* @param {ol.Extent=} opt_hitExtent Hit extent: Only features intersecting
|
||||
* this extent are checked.
|
||||
* @return {T|undefined} Callback result.
|
||||
* @template T
|
||||
*/
|
||||
ol.render.webgl.ReplayGroup.prototype.replayHitDetection_ = function(context,
|
||||
center, resolution, rotation, size, pixelRatio, opacity,
|
||||
skippedFeaturesHash, featureCallback, oneByOne, opt_hitExtent) {
|
||||
/** @type {Array.<number>} */
|
||||
var zs = Object.keys(this.replaysByZIndex_).map(Number);
|
||||
zs.sort(function(a, b) {
|
||||
return b - a;
|
||||
});
|
||||
/**
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
*/
|
||||
ol.render.webgl.ReplayGroup.prototype.finish = function(context) {
|
||||
var zKey;
|
||||
for (zKey in this.replaysByZIndex_) {
|
||||
var replays = this.replaysByZIndex_[zKey];
|
||||
var replayKey;
|
||||
for (replayKey in replays) {
|
||||
replays[replayKey].finish(context);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var i, ii, j, replays, replay, result;
|
||||
for (i = 0, ii = zs.length; i < ii; ++i) {
|
||||
replays = this.replaysByZIndex_[zs[i].toString()];
|
||||
for (j = ol.render.replay.ORDER.length - 1; j >= 0; --j) {
|
||||
replay = replays[ol.render.replay.ORDER[j]];
|
||||
if (replay !== undefined) {
|
||||
result = replay.replay(context,
|
||||
center, resolution, rotation, size, pixelRatio, opacity,
|
||||
skippedFeaturesHash, featureCallback, oneByOne, opt_hitExtent);
|
||||
if (result) {
|
||||
return result;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.webgl.ReplayGroup.prototype.getReplay = function(zIndex, replayType) {
|
||||
var zIndexKey = zIndex !== undefined ? zIndex.toString() : '0';
|
||||
var replays = this.replaysByZIndex_[zIndexKey];
|
||||
if (replays === undefined) {
|
||||
replays = {};
|
||||
this.replaysByZIndex_[zIndexKey] = replays;
|
||||
}
|
||||
var replay = replays[replayType];
|
||||
if (replay === undefined) {
|
||||
var Constructor = ol.render.webgl.ReplayGroup.BATCH_CONSTRUCTORS_[replayType];
|
||||
replay = new Constructor(this.tolerance_, this.maxExtent_);
|
||||
replays[replayType] = replay;
|
||||
}
|
||||
return replay;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.webgl.ReplayGroup.prototype.isEmpty = function() {
|
||||
return ol.obj.isEmpty(this.replaysByZIndex_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @param {ol.Coordinate} center Center.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {number} rotation Rotation.
|
||||
* @param {ol.Size} size Size.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {number} opacity Global opacity.
|
||||
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
|
||||
* to skip.
|
||||
*/
|
||||
ol.render.webgl.ReplayGroup.prototype.replay = function(context,
|
||||
center, resolution, rotation, size, pixelRatio,
|
||||
opacity, skippedFeaturesHash) {
|
||||
/** @type {Array.<number>} */
|
||||
var zs = Object.keys(this.replaysByZIndex_).map(Number);
|
||||
zs.sort(ol.array.numberSafeCompareFunction);
|
||||
|
||||
var i, ii, j, jj, replays, replay;
|
||||
for (i = 0, ii = zs.length; i < ii; ++i) {
|
||||
replays = this.replaysByZIndex_[zs[i].toString()];
|
||||
for (j = 0, jj = ol.render.replay.ORDER.length; j < jj; ++j) {
|
||||
replay = replays[ol.render.replay.ORDER[j]];
|
||||
if (replay !== undefined) {
|
||||
replay.replay(context,
|
||||
center, resolution, rotation, size, pixelRatio,
|
||||
opacity, skippedFeaturesHash,
|
||||
undefined, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @param {ol.Coordinate} center Center.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {number} rotation Rotation.
|
||||
* @param {ol.Size} size Size.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {number} opacity Global opacity.
|
||||
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
|
||||
* to skip.
|
||||
* @param {function((ol.Feature|ol.render.Feature)): T|undefined} callback Feature callback.
|
||||
* @return {T|undefined} Callback result.
|
||||
* @template T
|
||||
*/
|
||||
ol.render.webgl.ReplayGroup.prototype.forEachFeatureAtCoordinate = function(
|
||||
coordinate, context, center, resolution, rotation, size, pixelRatio,
|
||||
opacity, skippedFeaturesHash,
|
||||
callback) {
|
||||
var gl = context.getGL();
|
||||
gl.bindFramebuffer(
|
||||
gl.FRAMEBUFFER, context.getHitDetectionFramebuffer());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @type {ol.Extent}
|
||||
* @private
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @param {ol.Coordinate} center Center.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {number} rotation Rotation.
|
||||
* @param {ol.Size} size Size.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {number} opacity Global opacity.
|
||||
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
|
||||
* to skip.
|
||||
* @param {function((ol.Feature|ol.render.Feature)): T|undefined} featureCallback Feature callback.
|
||||
* @param {boolean} oneByOne Draw features one-by-one for the hit-detecion.
|
||||
* @param {ol.Extent=} opt_hitExtent Hit extent: Only features intersecting
|
||||
* this extent are checked.
|
||||
* @return {T|undefined} Callback result.
|
||||
* @template T
|
||||
*/
|
||||
var hitExtent;
|
||||
if (this.renderBuffer_ !== undefined) {
|
||||
// build an extent around the coordinate, so that only features that
|
||||
// intersect this extent are checked
|
||||
hitExtent = ol.extent.buffer(
|
||||
ol.extent.createOrUpdateFromCoordinate(coordinate),
|
||||
resolution * this.renderBuffer_);
|
||||
}
|
||||
ol.render.webgl.ReplayGroup.prototype.replayHitDetection_ = function(context,
|
||||
center, resolution, rotation, size, pixelRatio, opacity,
|
||||
skippedFeaturesHash, featureCallback, oneByOne, opt_hitExtent) {
|
||||
/** @type {Array.<number>} */
|
||||
var zs = Object.keys(this.replaysByZIndex_).map(Number);
|
||||
zs.sort(function(a, b) {
|
||||
return b - a;
|
||||
});
|
||||
|
||||
return this.replayHitDetection_(context,
|
||||
coordinate, resolution, rotation, ol.render.webgl.ReplayGroup.HIT_DETECTION_SIZE_,
|
||||
pixelRatio, opacity, skippedFeaturesHash,
|
||||
/**
|
||||
* @param {ol.Feature|ol.render.Feature} feature Feature.
|
||||
* @return {?} Callback result.
|
||||
*/
|
||||
function(feature) {
|
||||
var imageData = new Uint8Array(4);
|
||||
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, imageData);
|
||||
|
||||
if (imageData[3] > 0) {
|
||||
var result = callback(feature);
|
||||
var i, ii, j, replays, replay, result;
|
||||
for (i = 0, ii = zs.length; i < ii; ++i) {
|
||||
replays = this.replaysByZIndex_[zs[i].toString()];
|
||||
for (j = ol.render.replay.ORDER.length - 1; j >= 0; --j) {
|
||||
replay = replays[ol.render.replay.ORDER[j]];
|
||||
if (replay !== undefined) {
|
||||
result = replay.replay(context,
|
||||
center, resolution, rotation, size, pixelRatio, opacity,
|
||||
skippedFeaturesHash, featureCallback, oneByOne, opt_hitExtent);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}, true, hitExtent);
|
||||
};
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @param {ol.Coordinate} center Center.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {number} rotation Rotation.
|
||||
* @param {ol.Size} size Size.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {number} opacity Global opacity.
|
||||
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
|
||||
* to skip.
|
||||
* @return {boolean} Is there a feature at the given coordinate?
|
||||
*/
|
||||
ol.render.webgl.ReplayGroup.prototype.hasFeatureAtCoordinate = function(
|
||||
coordinate, context, center, resolution, rotation, size, pixelRatio,
|
||||
opacity, skippedFeaturesHash) {
|
||||
var gl = context.getGL();
|
||||
gl.bindFramebuffer(
|
||||
gl.FRAMEBUFFER, context.getHitDetectionFramebuffer());
|
||||
/**
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @param {ol.Coordinate} center Center.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {number} rotation Rotation.
|
||||
* @param {ol.Size} size Size.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {number} opacity Global opacity.
|
||||
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
|
||||
* to skip.
|
||||
* @param {function((ol.Feature|ol.render.Feature)): T|undefined} callback Feature callback.
|
||||
* @return {T|undefined} Callback result.
|
||||
* @template T
|
||||
*/
|
||||
ol.render.webgl.ReplayGroup.prototype.forEachFeatureAtCoordinate = function(
|
||||
coordinate, context, center, resolution, rotation, size, pixelRatio,
|
||||
opacity, skippedFeaturesHash,
|
||||
callback) {
|
||||
var gl = context.getGL();
|
||||
gl.bindFramebuffer(
|
||||
gl.FRAMEBUFFER, context.getHitDetectionFramebuffer());
|
||||
|
||||
var hasFeature = this.replayHitDetection_(context,
|
||||
coordinate, resolution, rotation, ol.render.webgl.ReplayGroup.HIT_DETECTION_SIZE_,
|
||||
pixelRatio, opacity, skippedFeaturesHash,
|
||||
/**
|
||||
* @param {ol.Feature|ol.render.Feature} feature Feature.
|
||||
* @return {boolean} Is there a feature?
|
||||
*/
|
||||
function(feature) {
|
||||
var imageData = new Uint8Array(4);
|
||||
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, imageData);
|
||||
return imageData[3] > 0;
|
||||
}, false);
|
||||
|
||||
return hasFeature !== undefined;
|
||||
};
|
||||
/**
|
||||
* @type {ol.Extent}
|
||||
*/
|
||||
var hitExtent;
|
||||
if (this.renderBuffer_ !== undefined) {
|
||||
// build an extent around the coordinate, so that only features that
|
||||
// intersect this extent are checked
|
||||
hitExtent = ol.extent.buffer(
|
||||
ol.extent.createOrUpdateFromCoordinate(coordinate),
|
||||
resolution * this.renderBuffer_);
|
||||
}
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @private
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
ol.render.webgl.ReplayGroup.HIT_DETECTION_SIZE_ = [1, 1];
|
||||
return this.replayHitDetection_(context,
|
||||
coordinate, resolution, rotation, ol.render.webgl.ReplayGroup.HIT_DETECTION_SIZE_,
|
||||
pixelRatio, opacity, skippedFeaturesHash,
|
||||
/**
|
||||
* @param {ol.Feature|ol.render.Feature} feature Feature.
|
||||
* @return {?} Callback result.
|
||||
*/
|
||||
function(feature) {
|
||||
var imageData = new Uint8Array(4);
|
||||
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, imageData);
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @private
|
||||
* @type {Object.<ol.render.ReplayType,
|
||||
* function(new: ol.render.webgl.Replay, number,
|
||||
* 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,
|
||||
'Text': ol.render.webgl.TextReplay
|
||||
};
|
||||
if (imageData[3] > 0) {
|
||||
var result = callback(feature);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}, true, hitExtent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @param {ol.Coordinate} center Center.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {number} rotation Rotation.
|
||||
* @param {ol.Size} size Size.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {number} opacity Global opacity.
|
||||
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
|
||||
* to skip.
|
||||
* @return {boolean} Is there a feature at the given coordinate?
|
||||
*/
|
||||
ol.render.webgl.ReplayGroup.prototype.hasFeatureAtCoordinate = function(
|
||||
coordinate, context, center, resolution, rotation, size, pixelRatio,
|
||||
opacity, skippedFeaturesHash) {
|
||||
var gl = context.getGL();
|
||||
gl.bindFramebuffer(
|
||||
gl.FRAMEBUFFER, context.getHitDetectionFramebuffer());
|
||||
|
||||
var hasFeature = this.replayHitDetection_(context,
|
||||
coordinate, resolution, rotation, ol.render.webgl.ReplayGroup.HIT_DETECTION_SIZE_,
|
||||
pixelRatio, opacity, skippedFeaturesHash,
|
||||
/**
|
||||
* @param {ol.Feature|ol.render.Feature} feature Feature.
|
||||
* @return {boolean} Is there a feature?
|
||||
*/
|
||||
function(feature) {
|
||||
var imageData = new Uint8Array(4);
|
||||
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, imageData);
|
||||
return imageData[3] > 0;
|
||||
}, false);
|
||||
|
||||
return hasFeature !== undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @private
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
ol.render.webgl.ReplayGroup.HIT_DETECTION_SIZE_ = [1, 1];
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @private
|
||||
* @type {Object.<ol.render.ReplayType,
|
||||
* function(new: ol.render.webgl.Replay, number,
|
||||
* 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,
|
||||
'Text': ol.render.webgl.TextReplay
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -2,64 +2,69 @@ goog.provide('ol.render.webgl.TextReplay');
|
||||
|
||||
goog.require('ol');
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {number} tolerance Tolerance.
|
||||
* @param {ol.Extent} maxExtent Max extent.
|
||||
* @struct
|
||||
*/
|
||||
ol.render.webgl.TextReplay = function(tolerance, maxExtent) {};
|
||||
|
||||
/**
|
||||
* @param {ol.style.Text} textStyle Text style.
|
||||
*/
|
||||
ol.render.webgl.TextReplay.prototype.setTextStyle = function(textStyle) {};
|
||||
if (ol.ENABLE_WEBGL) {
|
||||
|
||||
/**
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @param {ol.Coordinate} center Center.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {number} rotation Rotation.
|
||||
* @param {ol.Size} size Size.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {number} opacity Global opacity.
|
||||
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
|
||||
* to skip.
|
||||
* @param {function((ol.Feature|ol.render.Feature)): T|undefined} featureCallback Feature callback.
|
||||
* @param {boolean} oneByOne Draw features one-by-one for the hit-detecion.
|
||||
* @param {ol.Extent=} opt_hitExtent Hit extent: Only features intersecting
|
||||
* this extent are checked.
|
||||
* @return {T|undefined} Callback result.
|
||||
* @template T
|
||||
*/
|
||||
ol.render.webgl.TextReplay.prototype.replay = function(context,
|
||||
center, resolution, rotation, size, pixelRatio,
|
||||
opacity, skippedFeaturesHash,
|
||||
featureCallback, oneByOne, opt_hitExtent) {
|
||||
return undefined;
|
||||
};
|
||||
/**
|
||||
* @constructor
|
||||
* @param {number} tolerance Tolerance.
|
||||
* @param {ol.Extent} maxExtent Max extent.
|
||||
* @struct
|
||||
*/
|
||||
ol.render.webgl.TextReplay = function(tolerance, maxExtent) {};
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @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,
|
||||
end, stride, geometry, feature) {};
|
||||
/**
|
||||
* @param {ol.style.Text} textStyle Text style.
|
||||
*/
|
||||
ol.render.webgl.TextReplay.prototype.setTextStyle = function(textStyle) {};
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
*/
|
||||
ol.render.webgl.TextReplay.prototype.finish = function(context) {};
|
||||
/**
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @param {ol.Coordinate} center Center.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {number} rotation Rotation.
|
||||
* @param {ol.Size} size Size.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {number} opacity Global opacity.
|
||||
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
|
||||
* to skip.
|
||||
* @param {function((ol.Feature|ol.render.Feature)): T|undefined} featureCallback Feature callback.
|
||||
* @param {boolean} oneByOne Draw features one-by-one for the hit-detecion.
|
||||
* @param {ol.Extent=} opt_hitExtent Hit extent: Only features intersecting
|
||||
* this extent are checked.
|
||||
* @return {T|undefined} Callback result.
|
||||
* @template T
|
||||
*/
|
||||
ol.render.webgl.TextReplay.prototype.replay = function(context,
|
||||
center, resolution, rotation, size, pixelRatio,
|
||||
opacity, skippedFeaturesHash,
|
||||
featureCallback, oneByOne, opt_hitExtent) {
|
||||
return undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {ol.webgl.Context} context WebGL context.
|
||||
* @return {function()} Delete resources function.
|
||||
*/
|
||||
ol.render.webgl.TextReplay.prototype.getDeleteResourcesFunction = function(context) {
|
||||
return ol.nullFunction;
|
||||
};
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @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,
|
||||
end, stride, geometry, feature) {};
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
*/
|
||||
ol.render.webgl.TextReplay.prototype.finish = function(context) {};
|
||||
|
||||
/**
|
||||
* @param {ol.webgl.Context} context WebGL context.
|
||||
* @return {function()} Delete resources function.
|
||||
*/
|
||||
ol.render.webgl.TextReplay.prototype.getDeleteResourcesFunction = function(context) {
|
||||
return ol.nullFunction;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -6,111 +6,115 @@ goog.require('ol.webgl.Fragment');
|
||||
goog.require('ol.webgl.Vertex');
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.webgl.Fragment}
|
||||
* @struct
|
||||
*/
|
||||
ol.renderer.webgl.defaultmapshader.Fragment = function() {
|
||||
ol.webgl.Fragment.call(this, ol.renderer.webgl.defaultmapshader.Fragment.SOURCE);
|
||||
};
|
||||
ol.inherits(ol.renderer.webgl.defaultmapshader.Fragment, ol.webgl.Fragment);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.renderer.webgl.defaultmapshader.Fragment.DEBUG_SOURCE = 'precision mediump float;\nvarying vec2 v_texCoord;\n\n\nuniform float u_opacity;\nuniform sampler2D u_texture;\n\nvoid main(void) {\n vec4 texColor = texture2D(u_texture, v_texCoord);\n gl_FragColor.rgb = texColor.rgb;\n gl_FragColor.a = texColor.a * u_opacity;\n}\n';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.renderer.webgl.defaultmapshader.Fragment.OPTIMIZED_SOURCE = 'precision mediump float;varying vec2 a;uniform float f;uniform sampler2D g;void main(void){vec4 texColor=texture2D(g,a);gl_FragColor.rgb=texColor.rgb;gl_FragColor.a=texColor.a*f;}';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.renderer.webgl.defaultmapshader.Fragment.SOURCE = ol.renderer.webgl.defaultmapshader.Fragment.OPTIMIZED_SOURCE;
|
||||
|
||||
|
||||
ol.renderer.webgl.defaultmapshader.fragment = new ol.renderer.webgl.defaultmapshader.Fragment();
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.webgl.Vertex}
|
||||
* @struct
|
||||
*/
|
||||
ol.renderer.webgl.defaultmapshader.Vertex = function() {
|
||||
ol.webgl.Vertex.call(this, ol.renderer.webgl.defaultmapshader.Vertex.SOURCE);
|
||||
};
|
||||
ol.inherits(ol.renderer.webgl.defaultmapshader.Vertex, ol.webgl.Vertex);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.renderer.webgl.defaultmapshader.Vertex.DEBUG_SOURCE = 'varying vec2 v_texCoord;\n\n\nattribute vec2 a_position;\nattribute vec2 a_texCoord;\n\nuniform mat4 u_texCoordMatrix;\nuniform mat4 u_projectionMatrix;\n\nvoid main(void) {\n gl_Position = u_projectionMatrix * vec4(a_position, 0., 1.);\n v_texCoord = (u_texCoordMatrix * vec4(a_texCoord, 0., 1.)).st;\n}\n\n\n';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.renderer.webgl.defaultmapshader.Vertex.OPTIMIZED_SOURCE = 'varying vec2 a;attribute vec2 b;attribute vec2 c;uniform mat4 d;uniform mat4 e;void main(void){gl_Position=e*vec4(b,0.,1.);a=(d*vec4(c,0.,1.)).st;}';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.renderer.webgl.defaultmapshader.Vertex.SOURCE = ol.renderer.webgl.defaultmapshader.Vertex.OPTIMIZED_SOURCE;
|
||||
|
||||
|
||||
ol.renderer.webgl.defaultmapshader.vertex = new ol.renderer.webgl.defaultmapshader.Vertex();
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {WebGLRenderingContext} gl GL.
|
||||
* @param {WebGLProgram} program Program.
|
||||
* @struct
|
||||
*/
|
||||
ol.renderer.webgl.defaultmapshader.Locations = function(gl, program) {
|
||||
if (ol.ENABLE_WEBGL) {
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
* @constructor
|
||||
* @extends {ol.webgl.Fragment}
|
||||
* @struct
|
||||
*/
|
||||
this.u_opacity = gl.getUniformLocation(program, 'f');
|
||||
ol.renderer.webgl.defaultmapshader.Fragment = function() {
|
||||
ol.webgl.Fragment.call(this, ol.renderer.webgl.defaultmapshader.Fragment.SOURCE);
|
||||
};
|
||||
ol.inherits(ol.renderer.webgl.defaultmapshader.Fragment, ol.webgl.Fragment);
|
||||
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
this.u_projectionMatrix = gl.getUniformLocation(program, 'e');
|
||||
ol.renderer.webgl.defaultmapshader.Fragment.DEBUG_SOURCE = 'precision mediump float;\nvarying vec2 v_texCoord;\n\n\nuniform float u_opacity;\nuniform sampler2D u_texture;\n\nvoid main(void) {\n vec4 texColor = texture2D(u_texture, v_texCoord);\n gl_FragColor.rgb = texColor.rgb;\n gl_FragColor.a = texColor.a * u_opacity;\n}\n';
|
||||
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
this.u_texCoordMatrix = gl.getUniformLocation(program, 'd');
|
||||
ol.renderer.webgl.defaultmapshader.Fragment.OPTIMIZED_SOURCE = 'precision mediump float;varying vec2 a;uniform float f;uniform sampler2D g;void main(void){vec4 texColor=texture2D(g,a);gl_FragColor.rgb=texColor.rgb;gl_FragColor.a=texColor.a*f;}';
|
||||
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
this.u_texture = gl.getUniformLocation(program, 'g');
|
||||
ol.renderer.webgl.defaultmapshader.Fragment.SOURCE = ol.renderer.webgl.defaultmapshader.Fragment.OPTIMIZED_SOURCE;
|
||||
|
||||
|
||||
ol.renderer.webgl.defaultmapshader.fragment = new ol.renderer.webgl.defaultmapshader.Fragment();
|
||||
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @constructor
|
||||
* @extends {ol.webgl.Vertex}
|
||||
* @struct
|
||||
*/
|
||||
this.a_position = gl.getAttribLocation(program, 'b');
|
||||
ol.renderer.webgl.defaultmapshader.Vertex = function() {
|
||||
ol.webgl.Vertex.call(this, ol.renderer.webgl.defaultmapshader.Vertex.SOURCE);
|
||||
};
|
||||
ol.inherits(ol.renderer.webgl.defaultmapshader.Vertex, ol.webgl.Vertex);
|
||||
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
this.a_texCoord = gl.getAttribLocation(program, 'c');
|
||||
};
|
||||
ol.renderer.webgl.defaultmapshader.Vertex.DEBUG_SOURCE = 'varying vec2 v_texCoord;\n\n\nattribute vec2 a_position;\nattribute vec2 a_texCoord;\n\nuniform mat4 u_texCoordMatrix;\nuniform mat4 u_projectionMatrix;\n\nvoid main(void) {\n gl_Position = u_projectionMatrix * vec4(a_position, 0., 1.);\n v_texCoord = (u_texCoordMatrix * vec4(a_texCoord, 0., 1.)).st;\n}\n\n\n';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.renderer.webgl.defaultmapshader.Vertex.OPTIMIZED_SOURCE = 'varying vec2 a;attribute vec2 b;attribute vec2 c;uniform mat4 d;uniform mat4 e;void main(void){gl_Position=e*vec4(b,0.,1.);a=(d*vec4(c,0.,1.)).st;}';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.renderer.webgl.defaultmapshader.Vertex.SOURCE = ol.renderer.webgl.defaultmapshader.Vertex.OPTIMIZED_SOURCE;
|
||||
|
||||
|
||||
ol.renderer.webgl.defaultmapshader.vertex = new ol.renderer.webgl.defaultmapshader.Vertex();
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {WebGLRenderingContext} gl GL.
|
||||
* @param {WebGLProgram} program Program.
|
||||
* @struct
|
||||
*/
|
||||
ol.renderer.webgl.defaultmapshader.Locations = function(gl, program) {
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_opacity = gl.getUniformLocation(program, 'f');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_projectionMatrix = gl.getUniformLocation(program, 'e');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_texCoordMatrix = gl.getUniformLocation(program, 'd');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_texture = gl.getUniformLocation(program, 'g');
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.a_position = gl.getAttribLocation(program, 'b');
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.a_texCoord = gl.getAttribLocation(program, 'c');
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -12,294 +12,298 @@ goog.require('ol.webgl');
|
||||
goog.require('ol.webgl.Context');
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.renderer.webgl.Layer}
|
||||
* @param {ol.renderer.webgl.Map} mapRenderer Map renderer.
|
||||
* @param {ol.layer.Image} imageLayer Tile layer.
|
||||
*/
|
||||
ol.renderer.webgl.ImageLayer = function(mapRenderer, imageLayer) {
|
||||
|
||||
ol.renderer.webgl.Layer.call(this, mapRenderer, imageLayer);
|
||||
if (ol.ENABLE_WEBGL) {
|
||||
|
||||
/**
|
||||
* The last rendered image.
|
||||
* @private
|
||||
* @type {?ol.ImageBase}
|
||||
* @constructor
|
||||
* @extends {ol.renderer.webgl.Layer}
|
||||
* @param {ol.renderer.webgl.Map} mapRenderer Map renderer.
|
||||
* @param {ol.layer.Image} imageLayer Tile layer.
|
||||
*/
|
||||
this.image_ = null;
|
||||
ol.renderer.webgl.ImageLayer = function(mapRenderer, imageLayer) {
|
||||
|
||||
ol.renderer.webgl.Layer.call(this, mapRenderer, imageLayer);
|
||||
|
||||
/**
|
||||
* The last rendered image.
|
||||
* @private
|
||||
* @type {?ol.ImageBase}
|
||||
*/
|
||||
this.image_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {CanvasRenderingContext2D}
|
||||
*/
|
||||
this.hitCanvasContext_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?ol.Transform}
|
||||
*/
|
||||
this.hitTransformationMatrix_ = null;
|
||||
|
||||
};
|
||||
ol.inherits(ol.renderer.webgl.ImageLayer, ol.renderer.webgl.Layer);
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.ImageBase} image Image.
|
||||
* @private
|
||||
* @type {CanvasRenderingContext2D}
|
||||
* @return {WebGLTexture} Texture.
|
||||
*/
|
||||
this.hitCanvasContext_ = null;
|
||||
ol.renderer.webgl.ImageLayer.prototype.createTexture_ = function(image) {
|
||||
|
||||
// We meet the conditions to work with non-power of two textures.
|
||||
// http://www.khronos.org/webgl/wiki/WebGL_and_OpenGL_Differences#Non-Power_of_Two_Texture_Support
|
||||
// http://learningwebgl.com/blog/?p=2101
|
||||
|
||||
var imageElement = image.getImage();
|
||||
var gl = this.mapRenderer.getGL();
|
||||
|
||||
return ol.webgl.Context.createTexture(
|
||||
gl, imageElement, ol.webgl.CLAMP_TO_EDGE, ol.webgl.CLAMP_TO_EDGE);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?ol.Transform}
|
||||
* @inheritDoc
|
||||
*/
|
||||
this.hitTransformationMatrix_ = null;
|
||||
ol.renderer.webgl.ImageLayer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, hitTolerance, callback, thisArg) {
|
||||
var layer = this.getLayer();
|
||||
var source = layer.getSource();
|
||||
var resolution = frameState.viewState.resolution;
|
||||
var rotation = frameState.viewState.rotation;
|
||||
var skippedFeatureUids = frameState.skippedFeatureUids;
|
||||
return source.forEachFeatureAtCoordinate(
|
||||
coordinate, resolution, rotation, hitTolerance, skippedFeatureUids,
|
||||
|
||||
};
|
||||
ol.inherits(ol.renderer.webgl.ImageLayer, ol.renderer.webgl.Layer);
|
||||
/**
|
||||
* @param {ol.Feature|ol.render.Feature} feature Feature.
|
||||
* @return {?} Callback result.
|
||||
*/
|
||||
function(feature) {
|
||||
return callback.call(thisArg, feature, layer);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.ImageBase} image Image.
|
||||
* @private
|
||||
* @return {WebGLTexture} Texture.
|
||||
*/
|
||||
ol.renderer.webgl.ImageLayer.prototype.createTexture_ = function(image) {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.ImageLayer.prototype.prepareFrame = function(frameState, layerState, context) {
|
||||
|
||||
// We meet the conditions to work with non-power of two textures.
|
||||
// http://www.khronos.org/webgl/wiki/WebGL_and_OpenGL_Differences#Non-Power_of_Two_Texture_Support
|
||||
// http://learningwebgl.com/blog/?p=2101
|
||||
var gl = this.mapRenderer.getGL();
|
||||
|
||||
var imageElement = image.getImage();
|
||||
var gl = this.mapRenderer.getGL();
|
||||
var pixelRatio = frameState.pixelRatio;
|
||||
var viewState = frameState.viewState;
|
||||
var viewCenter = viewState.center;
|
||||
var viewResolution = viewState.resolution;
|
||||
var viewRotation = viewState.rotation;
|
||||
|
||||
return ol.webgl.Context.createTexture(
|
||||
gl, imageElement, ol.webgl.CLAMP_TO_EDGE, ol.webgl.CLAMP_TO_EDGE);
|
||||
};
|
||||
var image = this.image_;
|
||||
var texture = this.texture;
|
||||
var imageLayer = /** @type {ol.layer.Image} */ (this.getLayer());
|
||||
var imageSource = imageLayer.getSource();
|
||||
|
||||
var hints = frameState.viewHints;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.ImageLayer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, hitTolerance, callback, thisArg) {
|
||||
var layer = this.getLayer();
|
||||
var source = layer.getSource();
|
||||
var resolution = frameState.viewState.resolution;
|
||||
var rotation = frameState.viewState.rotation;
|
||||
var skippedFeatureUids = frameState.skippedFeatureUids;
|
||||
return source.forEachFeatureAtCoordinate(
|
||||
coordinate, resolution, rotation, hitTolerance, skippedFeatureUids,
|
||||
|
||||
/**
|
||||
* @param {ol.Feature|ol.render.Feature} feature Feature.
|
||||
* @return {?} Callback result.
|
||||
*/
|
||||
function(feature) {
|
||||
return callback.call(thisArg, feature, layer);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.ImageLayer.prototype.prepareFrame = function(frameState, layerState, context) {
|
||||
|
||||
var gl = this.mapRenderer.getGL();
|
||||
|
||||
var pixelRatio = frameState.pixelRatio;
|
||||
var viewState = frameState.viewState;
|
||||
var viewCenter = viewState.center;
|
||||
var viewResolution = viewState.resolution;
|
||||
var viewRotation = viewState.rotation;
|
||||
|
||||
var image = this.image_;
|
||||
var texture = this.texture;
|
||||
var imageLayer = /** @type {ol.layer.Image} */ (this.getLayer());
|
||||
var imageSource = imageLayer.getSource();
|
||||
|
||||
var hints = frameState.viewHints;
|
||||
|
||||
var renderedExtent = frameState.extent;
|
||||
if (layerState.extent !== undefined) {
|
||||
renderedExtent = ol.extent.getIntersection(
|
||||
renderedExtent, layerState.extent);
|
||||
}
|
||||
if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.INTERACTING] &&
|
||||
!ol.extent.isEmpty(renderedExtent)) {
|
||||
var projection = viewState.projection;
|
||||
if (!ol.ENABLE_RASTER_REPROJECTION) {
|
||||
var sourceProjection = imageSource.getProjection();
|
||||
if (sourceProjection) {
|
||||
projection = sourceProjection;
|
||||
}
|
||||
var renderedExtent = frameState.extent;
|
||||
if (layerState.extent !== undefined) {
|
||||
renderedExtent = ol.extent.getIntersection(
|
||||
renderedExtent, layerState.extent);
|
||||
}
|
||||
var image_ = imageSource.getImage(renderedExtent, viewResolution,
|
||||
pixelRatio, projection);
|
||||
if (image_) {
|
||||
var loaded = this.loadImage(image_);
|
||||
if (loaded) {
|
||||
image = image_;
|
||||
texture = this.createTexture_(image_);
|
||||
if (this.texture) {
|
||||
/**
|
||||
* @param {WebGLRenderingContext} gl GL.
|
||||
* @param {WebGLTexture} texture Texture.
|
||||
*/
|
||||
var postRenderFunction = function(gl, texture) {
|
||||
if (!gl.isContextLost()) {
|
||||
gl.deleteTexture(texture);
|
||||
}
|
||||
}.bind(null, gl, this.texture);
|
||||
frameState.postRenderFunctions.push(
|
||||
/** @type {ol.PostRenderFunction} */ (postRenderFunction)
|
||||
);
|
||||
if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.INTERACTING] &&
|
||||
!ol.extent.isEmpty(renderedExtent)) {
|
||||
var projection = viewState.projection;
|
||||
if (!ol.ENABLE_RASTER_REPROJECTION) {
|
||||
var sourceProjection = imageSource.getProjection();
|
||||
if (sourceProjection) {
|
||||
projection = sourceProjection;
|
||||
}
|
||||
}
|
||||
var image_ = imageSource.getImage(renderedExtent, viewResolution,
|
||||
pixelRatio, projection);
|
||||
if (image_) {
|
||||
var loaded = this.loadImage(image_);
|
||||
if (loaded) {
|
||||
image = image_;
|
||||
texture = this.createTexture_(image_);
|
||||
if (this.texture) {
|
||||
/**
|
||||
* @param {WebGLRenderingContext} gl GL.
|
||||
* @param {WebGLTexture} texture Texture.
|
||||
*/
|
||||
var postRenderFunction = function(gl, texture) {
|
||||
if (!gl.isContextLost()) {
|
||||
gl.deleteTexture(texture);
|
||||
}
|
||||
}.bind(null, gl, this.texture);
|
||||
frameState.postRenderFunctions.push(
|
||||
/** @type {ol.PostRenderFunction} */ (postRenderFunction)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (image) {
|
||||
var canvas = this.mapRenderer.getContext().getCanvas();
|
||||
if (image) {
|
||||
var canvas = this.mapRenderer.getContext().getCanvas();
|
||||
|
||||
this.updateProjectionMatrix_(canvas.width, canvas.height,
|
||||
pixelRatio, viewCenter, viewResolution, viewRotation,
|
||||
image.getExtent());
|
||||
this.hitTransformationMatrix_ = null;
|
||||
this.updateProjectionMatrix_(canvas.width, canvas.height,
|
||||
pixelRatio, viewCenter, viewResolution, viewRotation,
|
||||
image.getExtent());
|
||||
this.hitTransformationMatrix_ = null;
|
||||
|
||||
// Translate and scale to flip the Y coord.
|
||||
var texCoordMatrix = this.texCoordMatrix;
|
||||
ol.transform.reset(texCoordMatrix);
|
||||
ol.transform.scale(texCoordMatrix, 1, -1);
|
||||
ol.transform.translate(texCoordMatrix, 0, -1);
|
||||
// Translate and scale to flip the Y coord.
|
||||
var texCoordMatrix = this.texCoordMatrix;
|
||||
ol.transform.reset(texCoordMatrix);
|
||||
ol.transform.scale(texCoordMatrix, 1, -1);
|
||||
ol.transform.translate(texCoordMatrix, 0, -1);
|
||||
|
||||
this.image_ = image;
|
||||
this.texture = texture;
|
||||
this.image_ = image;
|
||||
this.texture = texture;
|
||||
|
||||
this.updateAttributions(frameState.attributions, image.getAttributions());
|
||||
this.updateLogos(frameState, imageSource);
|
||||
}
|
||||
this.updateAttributions(frameState.attributions, image.getAttributions());
|
||||
this.updateLogos(frameState, imageSource);
|
||||
}
|
||||
|
||||
return !!image;
|
||||
};
|
||||
return !!image;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} canvasWidth Canvas width.
|
||||
* @param {number} canvasHeight Canvas height.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {ol.Coordinate} viewCenter View center.
|
||||
* @param {number} viewResolution View resolution.
|
||||
* @param {number} viewRotation View rotation.
|
||||
* @param {ol.Extent} imageExtent Image extent.
|
||||
* @private
|
||||
*/
|
||||
ol.renderer.webgl.ImageLayer.prototype.updateProjectionMatrix_ = function(canvasWidth, canvasHeight, pixelRatio,
|
||||
viewCenter, viewResolution, viewRotation, imageExtent) {
|
||||
/**
|
||||
* @param {number} canvasWidth Canvas width.
|
||||
* @param {number} canvasHeight Canvas height.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {ol.Coordinate} viewCenter View center.
|
||||
* @param {number} viewResolution View resolution.
|
||||
* @param {number} viewRotation View rotation.
|
||||
* @param {ol.Extent} imageExtent Image extent.
|
||||
* @private
|
||||
*/
|
||||
ol.renderer.webgl.ImageLayer.prototype.updateProjectionMatrix_ = function(canvasWidth, canvasHeight, pixelRatio,
|
||||
viewCenter, viewResolution, viewRotation, imageExtent) {
|
||||
|
||||
var canvasExtentWidth = canvasWidth * viewResolution;
|
||||
var canvasExtentHeight = canvasHeight * viewResolution;
|
||||
var canvasExtentWidth = canvasWidth * viewResolution;
|
||||
var canvasExtentHeight = canvasHeight * viewResolution;
|
||||
|
||||
var projectionMatrix = this.projectionMatrix;
|
||||
ol.transform.reset(projectionMatrix);
|
||||
ol.transform.scale(projectionMatrix,
|
||||
pixelRatio * 2 / canvasExtentWidth,
|
||||
pixelRatio * 2 / canvasExtentHeight);
|
||||
ol.transform.rotate(projectionMatrix, -viewRotation);
|
||||
ol.transform.translate(projectionMatrix,
|
||||
imageExtent[0] - viewCenter[0],
|
||||
imageExtent[1] - viewCenter[1]);
|
||||
ol.transform.scale(projectionMatrix,
|
||||
(imageExtent[2] - imageExtent[0]) / 2,
|
||||
(imageExtent[3] - imageExtent[1]) / 2);
|
||||
ol.transform.translate(projectionMatrix, 1, 1);
|
||||
var projectionMatrix = this.projectionMatrix;
|
||||
ol.transform.reset(projectionMatrix);
|
||||
ol.transform.scale(projectionMatrix,
|
||||
pixelRatio * 2 / canvasExtentWidth,
|
||||
pixelRatio * 2 / canvasExtentHeight);
|
||||
ol.transform.rotate(projectionMatrix, -viewRotation);
|
||||
ol.transform.translate(projectionMatrix,
|
||||
imageExtent[0] - viewCenter[0],
|
||||
imageExtent[1] - viewCenter[1]);
|
||||
ol.transform.scale(projectionMatrix,
|
||||
(imageExtent[2] - imageExtent[0]) / 2,
|
||||
(imageExtent[3] - imageExtent[1]) / 2);
|
||||
ol.transform.translate(projectionMatrix, 1, 1);
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.ImageLayer.prototype.hasFeatureAtCoordinate = function(coordinate, frameState) {
|
||||
var hasFeature = this.forEachFeatureAtCoordinate(
|
||||
coordinate, frameState, 0, ol.functions.TRUE, this);
|
||||
return hasFeature !== undefined;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.ImageLayer.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg) {
|
||||
if (!this.image_ || !this.image_.getImage()) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (this.getLayer().getSource() instanceof ol.source.ImageVector) {
|
||||
// for ImageVector sources use the original hit-detection logic,
|
||||
// so that for example also transparent polygons are detected
|
||||
var coordinate = ol.transform.apply(
|
||||
frameState.pixelToCoordinateTransform, pixel.slice());
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.ImageLayer.prototype.hasFeatureAtCoordinate = function(coordinate, frameState) {
|
||||
var hasFeature = this.forEachFeatureAtCoordinate(
|
||||
coordinate, frameState, 0, ol.functions.TRUE, this);
|
||||
return hasFeature !== undefined;
|
||||
};
|
||||
|
||||
if (hasFeature) {
|
||||
return callback.call(thisArg, this.getLayer(), null);
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.ImageLayer.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg) {
|
||||
if (!this.image_ || !this.image_.getImage()) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (this.getLayer().getSource() instanceof ol.source.ImageVector) {
|
||||
// for ImageVector sources use the original hit-detection logic,
|
||||
// so that for example also transparent polygons are detected
|
||||
var coordinate = ol.transform.apply(
|
||||
frameState.pixelToCoordinateTransform, pixel.slice());
|
||||
var hasFeature = this.forEachFeatureAtCoordinate(
|
||||
coordinate, frameState, 0, ol.functions.TRUE, this);
|
||||
|
||||
if (hasFeature) {
|
||||
return callback.call(thisArg, this.getLayer(), null);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
} else {
|
||||
return undefined;
|
||||
var imageSize =
|
||||
[this.image_.getImage().width, this.image_.getImage().height];
|
||||
|
||||
if (!this.hitTransformationMatrix_) {
|
||||
this.hitTransformationMatrix_ = this.getHitTransformationMatrix_(
|
||||
frameState.size, imageSize);
|
||||
}
|
||||
|
||||
var pixelOnFrameBuffer = ol.transform.apply(
|
||||
this.hitTransformationMatrix_, pixel.slice());
|
||||
|
||||
if (pixelOnFrameBuffer[0] < 0 || pixelOnFrameBuffer[0] > imageSize[0] ||
|
||||
pixelOnFrameBuffer[1] < 0 || pixelOnFrameBuffer[1] > imageSize[1]) {
|
||||
// outside the image, no need to check
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (!this.hitCanvasContext_) {
|
||||
this.hitCanvasContext_ = ol.dom.createCanvasContext2D(1, 1);
|
||||
}
|
||||
|
||||
this.hitCanvasContext_.clearRect(0, 0, 1, 1);
|
||||
this.hitCanvasContext_.drawImage(this.image_.getImage(),
|
||||
pixelOnFrameBuffer[0], pixelOnFrameBuffer[1], 1, 1, 0, 0, 1, 1);
|
||||
|
||||
var imageData = this.hitCanvasContext_.getImageData(0, 0, 1, 1).data;
|
||||
if (imageData[3] > 0) {
|
||||
return callback.call(thisArg, this.getLayer(), imageData);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var imageSize =
|
||||
[this.image_.getImage().width, this.image_.getImage().height];
|
||||
|
||||
if (!this.hitTransformationMatrix_) {
|
||||
this.hitTransformationMatrix_ = this.getHitTransformationMatrix_(
|
||||
frameState.size, imageSize);
|
||||
}
|
||||
|
||||
var pixelOnFrameBuffer = ol.transform.apply(
|
||||
this.hitTransformationMatrix_, pixel.slice());
|
||||
|
||||
if (pixelOnFrameBuffer[0] < 0 || pixelOnFrameBuffer[0] > imageSize[0] ||
|
||||
pixelOnFrameBuffer[1] < 0 || pixelOnFrameBuffer[1] > imageSize[1]) {
|
||||
// outside the image, no need to check
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (!this.hitCanvasContext_) {
|
||||
this.hitCanvasContext_ = ol.dom.createCanvasContext2D(1, 1);
|
||||
}
|
||||
|
||||
this.hitCanvasContext_.clearRect(0, 0, 1, 1);
|
||||
this.hitCanvasContext_.drawImage(this.image_.getImage(),
|
||||
pixelOnFrameBuffer[0], pixelOnFrameBuffer[1], 1, 1, 0, 0, 1, 1);
|
||||
|
||||
var imageData = this.hitCanvasContext_.getImageData(0, 0, 1, 1).data;
|
||||
if (imageData[3] > 0) {
|
||||
return callback.call(thisArg, this.getLayer(), imageData);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The transformation matrix to get the pixel on the image for a
|
||||
* pixel on the map.
|
||||
* @param {ol.Size} mapSize The map size.
|
||||
* @param {ol.Size} imageSize The image size.
|
||||
* @return {ol.Transform} The transformation matrix.
|
||||
* @private
|
||||
*/
|
||||
ol.renderer.webgl.ImageLayer.prototype.getHitTransformationMatrix_ = function(mapSize, imageSize) {
|
||||
// the first matrix takes a map pixel, flips the y-axis and scales to
|
||||
// a range between -1 ... 1
|
||||
var mapCoordTransform = ol.transform.create();
|
||||
ol.transform.translate(mapCoordTransform, -1, -1);
|
||||
ol.transform.scale(mapCoordTransform, 2 / mapSize[0], 2 / mapSize[1]);
|
||||
ol.transform.translate(mapCoordTransform, 0, mapSize[1]);
|
||||
ol.transform.scale(mapCoordTransform, 1, -1);
|
||||
/**
|
||||
* The transformation matrix to get the pixel on the image for a
|
||||
* pixel on the map.
|
||||
* @param {ol.Size} mapSize The map size.
|
||||
* @param {ol.Size} imageSize The image size.
|
||||
* @return {ol.Transform} The transformation matrix.
|
||||
* @private
|
||||
*/
|
||||
ol.renderer.webgl.ImageLayer.prototype.getHitTransformationMatrix_ = function(mapSize, imageSize) {
|
||||
// the first matrix takes a map pixel, flips the y-axis and scales to
|
||||
// a range between -1 ... 1
|
||||
var mapCoordTransform = ol.transform.create();
|
||||
ol.transform.translate(mapCoordTransform, -1, -1);
|
||||
ol.transform.scale(mapCoordTransform, 2 / mapSize[0], 2 / mapSize[1]);
|
||||
ol.transform.translate(mapCoordTransform, 0, mapSize[1]);
|
||||
ol.transform.scale(mapCoordTransform, 1, -1);
|
||||
|
||||
// the second matrix is the inverse of the projection matrix used in the
|
||||
// shader for drawing
|
||||
var projectionMatrixInv = ol.transform.invert(this.projectionMatrix.slice());
|
||||
// the second matrix is the inverse of the projection matrix used in the
|
||||
// shader for drawing
|
||||
var projectionMatrixInv = ol.transform.invert(this.projectionMatrix.slice());
|
||||
|
||||
// the third matrix scales to the image dimensions and flips the y-axis again
|
||||
var transform = ol.transform.create();
|
||||
ol.transform.translate(transform, 0, imageSize[1]);
|
||||
ol.transform.scale(transform, 1, -1);
|
||||
ol.transform.scale(transform, imageSize[0] / 2, imageSize[1] / 2);
|
||||
ol.transform.translate(transform, 1, 1);
|
||||
// the third matrix scales to the image dimensions and flips the y-axis again
|
||||
var transform = ol.transform.create();
|
||||
ol.transform.translate(transform, 0, imageSize[1]);
|
||||
ol.transform.scale(transform, 1, -1);
|
||||
ol.transform.scale(transform, imageSize[0] / 2, imageSize[1] / 2);
|
||||
ol.transform.translate(transform, 1, 1);
|
||||
|
||||
ol.transform.multiply(transform, projectionMatrixInv);
|
||||
ol.transform.multiply(transform, mapCoordTransform);
|
||||
ol.transform.multiply(transform, projectionMatrixInv);
|
||||
ol.transform.multiply(transform, mapCoordTransform);
|
||||
|
||||
return transform;
|
||||
};
|
||||
return transform;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -13,255 +13,259 @@ goog.require('ol.webgl.Buffer');
|
||||
goog.require('ol.webgl.Context');
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.renderer.Layer}
|
||||
* @param {ol.renderer.webgl.Map} mapRenderer Map renderer.
|
||||
* @param {ol.layer.Layer} layer Layer.
|
||||
*/
|
||||
ol.renderer.webgl.Layer = function(mapRenderer, layer) {
|
||||
|
||||
ol.renderer.Layer.call(this, layer);
|
||||
if (ol.ENABLE_WEBGL) {
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {ol.renderer.webgl.Map}
|
||||
* @constructor
|
||||
* @extends {ol.renderer.Layer}
|
||||
* @param {ol.renderer.webgl.Map} mapRenderer Map renderer.
|
||||
* @param {ol.layer.Layer} layer Layer.
|
||||
*/
|
||||
this.mapRenderer = mapRenderer;
|
||||
ol.renderer.webgl.Layer = function(mapRenderer, layer) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.webgl.Buffer}
|
||||
*/
|
||||
this.arrayBuffer_ = new ol.webgl.Buffer([
|
||||
-1, -1, 0, 0,
|
||||
1, -1, 1, 0,
|
||||
-1, 1, 0, 1,
|
||||
1, 1, 1, 1
|
||||
]);
|
||||
ol.renderer.Layer.call(this, layer);
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {WebGLTexture}
|
||||
*/
|
||||
this.texture = null;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {WebGLFramebuffer}
|
||||
*/
|
||||
this.framebuffer = null;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.framebufferDimension = undefined;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {ol.Transform}
|
||||
*/
|
||||
this.texCoordMatrix = ol.transform.create();
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {ol.Transform}
|
||||
*/
|
||||
this.projectionMatrix = ol.transform.create();
|
||||
|
||||
/**
|
||||
* @type {Array.<number>}
|
||||
* @private
|
||||
*/
|
||||
this.tmpMat4_ = ol.vec.Mat4.create();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.renderer.webgl.defaultmapshader.Locations}
|
||||
*/
|
||||
this.defaultLocations_ = null;
|
||||
|
||||
};
|
||||
ol.inherits(ol.renderer.webgl.Layer, ol.renderer.Layer);
|
||||
|
||||
|
||||
/**
|
||||
* @param {olx.FrameState} frameState Frame state.
|
||||
* @param {number} framebufferDimension Framebuffer dimension.
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.bindFramebuffer = function(frameState, framebufferDimension) {
|
||||
|
||||
var gl = this.mapRenderer.getGL();
|
||||
|
||||
if (this.framebufferDimension === undefined ||
|
||||
this.framebufferDimension != framebufferDimension) {
|
||||
/**
|
||||
* @param {WebGLRenderingContext} gl GL.
|
||||
* @param {WebGLFramebuffer} framebuffer Framebuffer.
|
||||
* @param {WebGLTexture} texture Texture.
|
||||
* @protected
|
||||
* @type {ol.renderer.webgl.Map}
|
||||
*/
|
||||
var postRenderFunction = function(gl, framebuffer, texture) {
|
||||
if (!gl.isContextLost()) {
|
||||
gl.deleteFramebuffer(framebuffer);
|
||||
gl.deleteTexture(texture);
|
||||
}
|
||||
}.bind(null, gl, this.framebuffer, this.texture);
|
||||
this.mapRenderer = mapRenderer;
|
||||
|
||||
frameState.postRenderFunctions.push(
|
||||
/** @type {ol.PostRenderFunction} */ (postRenderFunction)
|
||||
);
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.webgl.Buffer}
|
||||
*/
|
||||
this.arrayBuffer_ = new ol.webgl.Buffer([
|
||||
-1, -1, 0, 0,
|
||||
1, -1, 1, 0,
|
||||
-1, 1, 0, 1,
|
||||
1, 1, 1, 1
|
||||
]);
|
||||
|
||||
var texture = ol.webgl.Context.createEmptyTexture(
|
||||
gl, framebufferDimension, framebufferDimension);
|
||||
/**
|
||||
* @protected
|
||||
* @type {WebGLTexture}
|
||||
*/
|
||||
this.texture = null;
|
||||
|
||||
var framebuffer = gl.createFramebuffer();
|
||||
gl.bindFramebuffer(ol.webgl.FRAMEBUFFER, framebuffer);
|
||||
gl.framebufferTexture2D(ol.webgl.FRAMEBUFFER,
|
||||
ol.webgl.COLOR_ATTACHMENT0, ol.webgl.TEXTURE_2D, texture, 0);
|
||||
/**
|
||||
* @protected
|
||||
* @type {WebGLFramebuffer}
|
||||
*/
|
||||
this.framebuffer = null;
|
||||
|
||||
this.texture = texture;
|
||||
this.framebuffer = framebuffer;
|
||||
this.framebufferDimension = framebufferDimension;
|
||||
/**
|
||||
* @protected
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.framebufferDimension = undefined;
|
||||
|
||||
} else {
|
||||
gl.bindFramebuffer(ol.webgl.FRAMEBUFFER, this.framebuffer);
|
||||
}
|
||||
/**
|
||||
* @protected
|
||||
* @type {ol.Transform}
|
||||
*/
|
||||
this.texCoordMatrix = ol.transform.create();
|
||||
|
||||
};
|
||||
/**
|
||||
* @protected
|
||||
* @type {ol.Transform}
|
||||
*/
|
||||
this.projectionMatrix = ol.transform.create();
|
||||
|
||||
/**
|
||||
* @type {Array.<number>}
|
||||
* @private
|
||||
*/
|
||||
this.tmpMat4_ = ol.vec.Mat4.create();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.renderer.webgl.defaultmapshader.Locations}
|
||||
*/
|
||||
this.defaultLocations_ = null;
|
||||
|
||||
};
|
||||
ol.inherits(ol.renderer.webgl.Layer, ol.renderer.Layer);
|
||||
|
||||
|
||||
/**
|
||||
* @param {olx.FrameState} frameState Frame state.
|
||||
* @param {ol.LayerState} layerState Layer state.
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.composeFrame = function(frameState, layerState, context) {
|
||||
/**
|
||||
* @param {olx.FrameState} frameState Frame state.
|
||||
* @param {number} framebufferDimension Framebuffer dimension.
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.bindFramebuffer = function(frameState, framebufferDimension) {
|
||||
|
||||
this.dispatchComposeEvent_(
|
||||
ol.render.EventType.PRECOMPOSE, context, frameState);
|
||||
var gl = this.mapRenderer.getGL();
|
||||
|
||||
context.bindBuffer(ol.webgl.ARRAY_BUFFER, this.arrayBuffer_);
|
||||
if (this.framebufferDimension === undefined ||
|
||||
this.framebufferDimension != framebufferDimension) {
|
||||
/**
|
||||
* @param {WebGLRenderingContext} gl GL.
|
||||
* @param {WebGLFramebuffer} framebuffer Framebuffer.
|
||||
* @param {WebGLTexture} texture Texture.
|
||||
*/
|
||||
var postRenderFunction = function(gl, framebuffer, texture) {
|
||||
if (!gl.isContextLost()) {
|
||||
gl.deleteFramebuffer(framebuffer);
|
||||
gl.deleteTexture(texture);
|
||||
}
|
||||
}.bind(null, gl, this.framebuffer, this.texture);
|
||||
|
||||
var gl = context.getGL();
|
||||
frameState.postRenderFunctions.push(
|
||||
/** @type {ol.PostRenderFunction} */ (postRenderFunction)
|
||||
);
|
||||
|
||||
var fragmentShader = ol.renderer.webgl.defaultmapshader.fragment;
|
||||
var vertexShader = ol.renderer.webgl.defaultmapshader.vertex;
|
||||
var texture = ol.webgl.Context.createEmptyTexture(
|
||||
gl, framebufferDimension, framebufferDimension);
|
||||
|
||||
var program = context.getProgram(fragmentShader, vertexShader);
|
||||
var framebuffer = gl.createFramebuffer();
|
||||
gl.bindFramebuffer(ol.webgl.FRAMEBUFFER, framebuffer);
|
||||
gl.framebufferTexture2D(ol.webgl.FRAMEBUFFER,
|
||||
ol.webgl.COLOR_ATTACHMENT0, ol.webgl.TEXTURE_2D, texture, 0);
|
||||
|
||||
var locations;
|
||||
if (!this.defaultLocations_) {
|
||||
locations =
|
||||
new ol.renderer.webgl.defaultmapshader.Locations(gl, program);
|
||||
this.defaultLocations_ = locations;
|
||||
} else {
|
||||
locations = this.defaultLocations_;
|
||||
}
|
||||
this.texture = texture;
|
||||
this.framebuffer = framebuffer;
|
||||
this.framebufferDimension = framebufferDimension;
|
||||
|
||||
if (context.useProgram(program)) {
|
||||
gl.enableVertexAttribArray(locations.a_position);
|
||||
gl.vertexAttribPointer(
|
||||
locations.a_position, 2, ol.webgl.FLOAT, false, 16, 0);
|
||||
gl.enableVertexAttribArray(locations.a_texCoord);
|
||||
gl.vertexAttribPointer(
|
||||
locations.a_texCoord, 2, ol.webgl.FLOAT, false, 16, 8);
|
||||
gl.uniform1i(locations.u_texture, 0);
|
||||
}
|
||||
} else {
|
||||
gl.bindFramebuffer(ol.webgl.FRAMEBUFFER, this.framebuffer);
|
||||
}
|
||||
|
||||
gl.uniformMatrix4fv(locations.u_texCoordMatrix, false,
|
||||
ol.vec.Mat4.fromTransform(this.tmpMat4_, this.getTexCoordMatrix()));
|
||||
gl.uniformMatrix4fv(locations.u_projectionMatrix, false,
|
||||
ol.vec.Mat4.fromTransform(this.tmpMat4_, this.getProjectionMatrix()));
|
||||
gl.uniform1f(locations.u_opacity, layerState.opacity);
|
||||
gl.bindTexture(ol.webgl.TEXTURE_2D, this.getTexture());
|
||||
gl.drawArrays(ol.webgl.TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
this.dispatchComposeEvent_(
|
||||
ol.render.EventType.POSTCOMPOSE, context, frameState);
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.render.EventType} type Event type.
|
||||
* @param {ol.webgl.Context} context WebGL context.
|
||||
* @param {olx.FrameState} frameState Frame state.
|
||||
* @private
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.dispatchComposeEvent_ = function(type, context, frameState) {
|
||||
var layer = this.getLayer();
|
||||
if (layer.hasListener(type)) {
|
||||
var viewState = frameState.viewState;
|
||||
var resolution = viewState.resolution;
|
||||
var pixelRatio = frameState.pixelRatio;
|
||||
var extent = frameState.extent;
|
||||
var center = viewState.center;
|
||||
var rotation = viewState.rotation;
|
||||
var size = frameState.size;
|
||||
/**
|
||||
* @param {olx.FrameState} frameState Frame state.
|
||||
* @param {ol.LayerState} layerState Layer state.
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.composeFrame = function(frameState, layerState, context) {
|
||||
|
||||
var render = new ol.render.webgl.Immediate(
|
||||
context, center, resolution, rotation, size, extent, pixelRatio);
|
||||
var composeEvent = new ol.render.Event(
|
||||
type, render, frameState, null, context);
|
||||
layer.dispatchEvent(composeEvent);
|
||||
}
|
||||
};
|
||||
this.dispatchComposeEvent_(
|
||||
ol.render.EventType.PRECOMPOSE, context, frameState);
|
||||
|
||||
context.bindBuffer(ol.webgl.ARRAY_BUFFER, this.arrayBuffer_);
|
||||
|
||||
var gl = context.getGL();
|
||||
|
||||
var fragmentShader = ol.renderer.webgl.defaultmapshader.fragment;
|
||||
var vertexShader = ol.renderer.webgl.defaultmapshader.vertex;
|
||||
|
||||
var program = context.getProgram(fragmentShader, vertexShader);
|
||||
|
||||
var locations;
|
||||
if (!this.defaultLocations_) {
|
||||
locations =
|
||||
new ol.renderer.webgl.defaultmapshader.Locations(gl, program);
|
||||
this.defaultLocations_ = locations;
|
||||
} else {
|
||||
locations = this.defaultLocations_;
|
||||
}
|
||||
|
||||
if (context.useProgram(program)) {
|
||||
gl.enableVertexAttribArray(locations.a_position);
|
||||
gl.vertexAttribPointer(
|
||||
locations.a_position, 2, ol.webgl.FLOAT, false, 16, 0);
|
||||
gl.enableVertexAttribArray(locations.a_texCoord);
|
||||
gl.vertexAttribPointer(
|
||||
locations.a_texCoord, 2, ol.webgl.FLOAT, false, 16, 8);
|
||||
gl.uniform1i(locations.u_texture, 0);
|
||||
}
|
||||
|
||||
gl.uniformMatrix4fv(locations.u_texCoordMatrix, false,
|
||||
ol.vec.Mat4.fromTransform(this.tmpMat4_, this.getTexCoordMatrix()));
|
||||
gl.uniformMatrix4fv(locations.u_projectionMatrix, false,
|
||||
ol.vec.Mat4.fromTransform(this.tmpMat4_, this.getProjectionMatrix()));
|
||||
gl.uniform1f(locations.u_opacity, layerState.opacity);
|
||||
gl.bindTexture(ol.webgl.TEXTURE_2D, this.getTexture());
|
||||
gl.drawArrays(ol.webgl.TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
this.dispatchComposeEvent_(
|
||||
ol.render.EventType.POSTCOMPOSE, context, frameState);
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!ol.Transform} Matrix.
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.getTexCoordMatrix = function() {
|
||||
return this.texCoordMatrix;
|
||||
};
|
||||
/**
|
||||
* @param {ol.render.EventType} type Event type.
|
||||
* @param {ol.webgl.Context} context WebGL context.
|
||||
* @param {olx.FrameState} frameState Frame state.
|
||||
* @private
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.dispatchComposeEvent_ = function(type, context, frameState) {
|
||||
var layer = this.getLayer();
|
||||
if (layer.hasListener(type)) {
|
||||
var viewState = frameState.viewState;
|
||||
var resolution = viewState.resolution;
|
||||
var pixelRatio = frameState.pixelRatio;
|
||||
var extent = frameState.extent;
|
||||
var center = viewState.center;
|
||||
var rotation = viewState.rotation;
|
||||
var size = frameState.size;
|
||||
|
||||
var render = new ol.render.webgl.Immediate(
|
||||
context, center, resolution, rotation, size, extent, pixelRatio);
|
||||
var composeEvent = new ol.render.Event(
|
||||
type, render, frameState, null, context);
|
||||
layer.dispatchEvent(composeEvent);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {WebGLTexture} Texture.
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.getTexture = function() {
|
||||
return this.texture;
|
||||
};
|
||||
/**
|
||||
* @return {!ol.Transform} Matrix.
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.getTexCoordMatrix = function() {
|
||||
return this.texCoordMatrix;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!ol.Transform} Matrix.
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.getProjectionMatrix = function() {
|
||||
return this.projectionMatrix;
|
||||
};
|
||||
/**
|
||||
* @return {WebGLTexture} Texture.
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.getTexture = function() {
|
||||
return this.texture;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handle webglcontextlost.
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.handleWebGLContextLost = function() {
|
||||
this.texture = null;
|
||||
this.framebuffer = null;
|
||||
this.framebufferDimension = undefined;
|
||||
};
|
||||
/**
|
||||
* @return {!ol.Transform} Matrix.
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.getProjectionMatrix = function() {
|
||||
return this.projectionMatrix;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {olx.FrameState} frameState Frame state.
|
||||
* @param {ol.LayerState} layerState Layer state.
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @return {boolean} whether composeFrame should be called.
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.prepareFrame = function(frameState, layerState, context) {};
|
||||
/**
|
||||
* Handle webglcontextlost.
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.handleWebGLContextLost = function() {
|
||||
this.texture = null;
|
||||
this.framebuffer = null;
|
||||
this.framebufferDimension = undefined;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {ol.Pixel} pixel Pixel.
|
||||
* @param {olx.FrameState} frameState FrameState.
|
||||
* @param {function(this: S, ol.layer.Layer, (Uint8ClampedArray|Uint8Array)): T} callback Layer
|
||||
* callback.
|
||||
* @param {S} thisArg Value to use as `this` when executing `callback`.
|
||||
* @return {T|undefined} Callback result.
|
||||
* @template S,T,U
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg) {};
|
||||
/**
|
||||
* @abstract
|
||||
* @param {olx.FrameState} frameState Frame state.
|
||||
* @param {ol.LayerState} layerState Layer state.
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @return {boolean} whether composeFrame should be called.
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.prepareFrame = function(frameState, layerState, context) {};
|
||||
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {ol.Pixel} pixel Pixel.
|
||||
* @param {olx.FrameState} frameState FrameState.
|
||||
* @param {function(this: S, ol.layer.Layer, (Uint8ClampedArray|Uint8Array)): T} callback Layer
|
||||
* callback.
|
||||
* @param {S} thisArg Value to use as `this` when executing `callback`.
|
||||
* @return {T|undefined} Callback result.
|
||||
* @template S,T,U
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg) {};
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -17,373 +17,377 @@ goog.require('ol.webgl');
|
||||
goog.require('ol.webgl.Buffer');
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.renderer.webgl.Layer}
|
||||
* @param {ol.renderer.webgl.Map} mapRenderer Map renderer.
|
||||
* @param {ol.layer.Tile} tileLayer Tile layer.
|
||||
*/
|
||||
ol.renderer.webgl.TileLayer = function(mapRenderer, tileLayer) {
|
||||
|
||||
ol.renderer.webgl.Layer.call(this, mapRenderer, tileLayer);
|
||||
if (ol.ENABLE_WEBGL) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.webgl.Fragment}
|
||||
* @constructor
|
||||
* @extends {ol.renderer.webgl.Layer}
|
||||
* @param {ol.renderer.webgl.Map} mapRenderer Map renderer.
|
||||
* @param {ol.layer.Tile} tileLayer Tile layer.
|
||||
*/
|
||||
this.fragmentShader_ = ol.renderer.webgl.tilelayershader.fragment;
|
||||
ol.renderer.webgl.TileLayer = function(mapRenderer, tileLayer) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.webgl.Vertex}
|
||||
*/
|
||||
this.vertexShader_ = ol.renderer.webgl.tilelayershader.vertex;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.renderer.webgl.tilelayershader.Locations}
|
||||
*/
|
||||
this.locations_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.webgl.Buffer}
|
||||
*/
|
||||
this.renderArrayBuffer_ = new ol.webgl.Buffer([
|
||||
0, 0, 0, 1,
|
||||
1, 0, 1, 1,
|
||||
0, 1, 0, 0,
|
||||
1, 1, 1, 0
|
||||
]);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.TileRange}
|
||||
*/
|
||||
this.renderedTileRange_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Extent}
|
||||
*/
|
||||
this.renderedFramebufferExtent_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.renderedRevision_ = -1;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Size}
|
||||
*/
|
||||
this.tmpSize_ = [0, 0];
|
||||
|
||||
};
|
||||
ol.inherits(ol.renderer.webgl.TileLayer, ol.renderer.webgl.Layer);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.TileLayer.prototype.disposeInternal = function() {
|
||||
var context = this.mapRenderer.getContext();
|
||||
context.deleteBuffer(this.renderArrayBuffer_);
|
||||
ol.renderer.webgl.Layer.prototype.disposeInternal.call(this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a function that adds loaded tiles to the tile lookup.
|
||||
* @param {ol.source.Tile} source Tile source.
|
||||
* @param {ol.proj.Projection} projection Projection of the tiles.
|
||||
* @param {Object.<number, Object.<string, ol.Tile>>} tiles Lookup of loaded
|
||||
* tiles by zoom level.
|
||||
* @return {function(number, ol.TileRange):boolean} A function that can be
|
||||
* called with a zoom level and a tile range to add loaded tiles to the
|
||||
* lookup.
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.webgl.TileLayer.prototype.createLoadedTileFinder = function(source, projection, tiles) {
|
||||
var mapRenderer = this.mapRenderer;
|
||||
|
||||
return (
|
||||
/**
|
||||
* @param {number} zoom Zoom level.
|
||||
* @param {ol.TileRange} tileRange Tile range.
|
||||
* @return {boolean} The tile range is fully loaded.
|
||||
*/
|
||||
function(zoom, tileRange) {
|
||||
function callback(tile) {
|
||||
var loaded = mapRenderer.isTileTextureLoaded(tile);
|
||||
if (loaded) {
|
||||
if (!tiles[zoom]) {
|
||||
tiles[zoom] = {};
|
||||
}
|
||||
tiles[zoom][tile.tileCoord.toString()] = tile;
|
||||
}
|
||||
return loaded;
|
||||
}
|
||||
return source.forEachLoadedTile(projection, zoom, tileRange, callback);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.TileLayer.prototype.handleWebGLContextLost = function() {
|
||||
ol.renderer.webgl.Layer.prototype.handleWebGLContextLost.call(this);
|
||||
this.locations_ = null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.TileLayer.prototype.prepareFrame = function(frameState, layerState, context) {
|
||||
|
||||
var mapRenderer = this.mapRenderer;
|
||||
var gl = context.getGL();
|
||||
|
||||
var viewState = frameState.viewState;
|
||||
var projection = viewState.projection;
|
||||
|
||||
var tileLayer = /** @type {ol.layer.Tile} */ (this.getLayer());
|
||||
var tileSource = tileLayer.getSource();
|
||||
var tileGrid = tileSource.getTileGridForProjection(projection);
|
||||
var z = tileGrid.getZForResolution(viewState.resolution);
|
||||
var tileResolution = tileGrid.getResolution(z);
|
||||
|
||||
var tilePixelSize =
|
||||
tileSource.getTilePixelSize(z, frameState.pixelRatio, projection);
|
||||
var pixelRatio = tilePixelSize[0] /
|
||||
ol.size.toSize(tileGrid.getTileSize(z), this.tmpSize_)[0];
|
||||
var tilePixelResolution = tileResolution / pixelRatio;
|
||||
var tileGutter = tileSource.getTilePixelRatio(pixelRatio) * tileSource.getGutter(projection);
|
||||
|
||||
var center = viewState.center;
|
||||
var extent = frameState.extent;
|
||||
var tileRange = tileGrid.getTileRangeForExtentAndResolution(
|
||||
extent, tileResolution);
|
||||
|
||||
var framebufferExtent;
|
||||
if (this.renderedTileRange_ &&
|
||||
this.renderedTileRange_.equals(tileRange) &&
|
||||
this.renderedRevision_ == tileSource.getRevision()) {
|
||||
framebufferExtent = this.renderedFramebufferExtent_;
|
||||
} else {
|
||||
|
||||
var tileRangeSize = tileRange.getSize();
|
||||
|
||||
var maxDimension = Math.max(
|
||||
tileRangeSize[0] * tilePixelSize[0],
|
||||
tileRangeSize[1] * tilePixelSize[1]);
|
||||
var framebufferDimension = ol.math.roundUpToPowerOfTwo(maxDimension);
|
||||
var framebufferExtentDimension = tilePixelResolution * framebufferDimension;
|
||||
var origin = tileGrid.getOrigin(z);
|
||||
var minX = origin[0] +
|
||||
tileRange.minX * tilePixelSize[0] * tilePixelResolution;
|
||||
var minY = origin[1] +
|
||||
tileRange.minY * tilePixelSize[1] * tilePixelResolution;
|
||||
framebufferExtent = [
|
||||
minX, minY,
|
||||
minX + framebufferExtentDimension, minY + framebufferExtentDimension
|
||||
];
|
||||
|
||||
this.bindFramebuffer(frameState, framebufferDimension);
|
||||
gl.viewport(0, 0, framebufferDimension, framebufferDimension);
|
||||
|
||||
gl.clearColor(0, 0, 0, 0);
|
||||
gl.clear(ol.webgl.COLOR_BUFFER_BIT);
|
||||
gl.disable(ol.webgl.BLEND);
|
||||
|
||||
var program = context.getProgram(this.fragmentShader_, this.vertexShader_);
|
||||
context.useProgram(program);
|
||||
if (!this.locations_) {
|
||||
this.locations_ =
|
||||
new ol.renderer.webgl.tilelayershader.Locations(gl, program);
|
||||
}
|
||||
|
||||
context.bindBuffer(ol.webgl.ARRAY_BUFFER, this.renderArrayBuffer_);
|
||||
gl.enableVertexAttribArray(this.locations_.a_position);
|
||||
gl.vertexAttribPointer(
|
||||
this.locations_.a_position, 2, ol.webgl.FLOAT, false, 16, 0);
|
||||
gl.enableVertexAttribArray(this.locations_.a_texCoord);
|
||||
gl.vertexAttribPointer(
|
||||
this.locations_.a_texCoord, 2, ol.webgl.FLOAT, false, 16, 8);
|
||||
gl.uniform1i(this.locations_.u_texture, 0);
|
||||
ol.renderer.webgl.Layer.call(this, mapRenderer, tileLayer);
|
||||
|
||||
/**
|
||||
* @type {Object.<number, Object.<string, ol.Tile>>}
|
||||
* @private
|
||||
* @type {ol.webgl.Fragment}
|
||||
*/
|
||||
var tilesToDrawByZ = {};
|
||||
tilesToDrawByZ[z] = {};
|
||||
this.fragmentShader_ = ol.renderer.webgl.tilelayershader.fragment;
|
||||
|
||||
var findLoadedTiles = this.createLoadedTileFinder(
|
||||
tileSource, projection, tilesToDrawByZ);
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.webgl.Vertex}
|
||||
*/
|
||||
this.vertexShader_ = ol.renderer.webgl.tilelayershader.vertex;
|
||||
|
||||
var useInterimTilesOnError = tileLayer.getUseInterimTilesOnError();
|
||||
var allTilesLoaded = true;
|
||||
var tmpExtent = ol.extent.createEmpty();
|
||||
var tmpTileRange = new ol.TileRange(0, 0, 0, 0);
|
||||
var childTileRange, drawable, fullyLoaded, tile, tileState;
|
||||
var x, y, tileExtent;
|
||||
for (x = tileRange.minX; x <= tileRange.maxX; ++x) {
|
||||
for (y = tileRange.minY; y <= tileRange.maxY; ++y) {
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.renderer.webgl.tilelayershader.Locations}
|
||||
*/
|
||||
this.locations_ = null;
|
||||
|
||||
tile = tileSource.getTile(z, x, y, pixelRatio, projection);
|
||||
if (layerState.extent !== undefined) {
|
||||
// ignore tiles outside layer extent
|
||||
tileExtent = tileGrid.getTileCoordExtent(tile.tileCoord, tmpExtent);
|
||||
if (!ol.extent.intersects(tileExtent, layerState.extent)) {
|
||||
continue;
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.webgl.Buffer}
|
||||
*/
|
||||
this.renderArrayBuffer_ = new ol.webgl.Buffer([
|
||||
0, 0, 0, 1,
|
||||
1, 0, 1, 1,
|
||||
0, 1, 0, 0,
|
||||
1, 1, 1, 0
|
||||
]);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.TileRange}
|
||||
*/
|
||||
this.renderedTileRange_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Extent}
|
||||
*/
|
||||
this.renderedFramebufferExtent_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.renderedRevision_ = -1;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Size}
|
||||
*/
|
||||
this.tmpSize_ = [0, 0];
|
||||
|
||||
};
|
||||
ol.inherits(ol.renderer.webgl.TileLayer, ol.renderer.webgl.Layer);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.TileLayer.prototype.disposeInternal = function() {
|
||||
var context = this.mapRenderer.getContext();
|
||||
context.deleteBuffer(this.renderArrayBuffer_);
|
||||
ol.renderer.webgl.Layer.prototype.disposeInternal.call(this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a function that adds loaded tiles to the tile lookup.
|
||||
* @param {ol.source.Tile} source Tile source.
|
||||
* @param {ol.proj.Projection} projection Projection of the tiles.
|
||||
* @param {Object.<number, Object.<string, ol.Tile>>} tiles Lookup of loaded
|
||||
* tiles by zoom level.
|
||||
* @return {function(number, ol.TileRange):boolean} A function that can be
|
||||
* called with a zoom level and a tile range to add loaded tiles to the
|
||||
* lookup.
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.webgl.TileLayer.prototype.createLoadedTileFinder = function(source, projection, tiles) {
|
||||
var mapRenderer = this.mapRenderer;
|
||||
|
||||
return (
|
||||
/**
|
||||
* @param {number} zoom Zoom level.
|
||||
* @param {ol.TileRange} tileRange Tile range.
|
||||
* @return {boolean} The tile range is fully loaded.
|
||||
*/
|
||||
function(zoom, tileRange) {
|
||||
function callback(tile) {
|
||||
var loaded = mapRenderer.isTileTextureLoaded(tile);
|
||||
if (loaded) {
|
||||
if (!tiles[zoom]) {
|
||||
tiles[zoom] = {};
|
||||
}
|
||||
tiles[zoom][tile.tileCoord.toString()] = tile;
|
||||
}
|
||||
return loaded;
|
||||
}
|
||||
}
|
||||
tileState = tile.getState();
|
||||
drawable = tileState == ol.TileState.LOADED ||
|
||||
tileState == ol.TileState.EMPTY ||
|
||||
tileState == ol.TileState.ERROR && !useInterimTilesOnError;
|
||||
if (!drawable) {
|
||||
tile = tile.getInterimTile();
|
||||
}
|
||||
tileState = tile.getState();
|
||||
if (tileState == ol.TileState.LOADED) {
|
||||
if (mapRenderer.isTileTextureLoaded(tile)) {
|
||||
tilesToDrawByZ[z][tile.tileCoord.toString()] = tile;
|
||||
continue;
|
||||
}
|
||||
} else if (tileState == ol.TileState.EMPTY ||
|
||||
(tileState == ol.TileState.ERROR &&
|
||||
!useInterimTilesOnError)) {
|
||||
continue;
|
||||
}
|
||||
return source.forEachLoadedTile(projection, zoom, tileRange, callback);
|
||||
});
|
||||
};
|
||||
|
||||
allTilesLoaded = false;
|
||||
fullyLoaded = tileGrid.forEachTileCoordParentTileRange(
|
||||
tile.tileCoord, findLoadedTiles, null, tmpTileRange, tmpExtent);
|
||||
if (!fullyLoaded) {
|
||||
childTileRange = tileGrid.getTileCoordChildTileRange(
|
||||
tile.tileCoord, tmpTileRange, tmpExtent);
|
||||
if (childTileRange) {
|
||||
findLoadedTiles(z + 1, childTileRange);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.TileLayer.prototype.handleWebGLContextLost = function() {
|
||||
ol.renderer.webgl.Layer.prototype.handleWebGLContextLost.call(this);
|
||||
this.locations_ = null;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/** @type {Array.<number>} */
|
||||
var zs = Object.keys(tilesToDrawByZ).map(Number);
|
||||
zs.sort(ol.array.numberSafeCompareFunction);
|
||||
var u_tileOffset = new Float32Array(4);
|
||||
var i, ii, tileKey, tilesToDraw;
|
||||
for (i = 0, ii = zs.length; i < ii; ++i) {
|
||||
tilesToDraw = tilesToDrawByZ[zs[i]];
|
||||
for (tileKey in tilesToDraw) {
|
||||
tile = tilesToDraw[tileKey];
|
||||
tileExtent = tileGrid.getTileCoordExtent(tile.tileCoord, tmpExtent);
|
||||
u_tileOffset[0] = 2 * (tileExtent[2] - tileExtent[0]) /
|
||||
framebufferExtentDimension;
|
||||
u_tileOffset[1] = 2 * (tileExtent[3] - tileExtent[1]) /
|
||||
framebufferExtentDimension;
|
||||
u_tileOffset[2] = 2 * (tileExtent[0] - framebufferExtent[0]) /
|
||||
framebufferExtentDimension - 1;
|
||||
u_tileOffset[3] = 2 * (tileExtent[1] - framebufferExtent[1]) /
|
||||
framebufferExtentDimension - 1;
|
||||
gl.uniform4fv(this.locations_.u_tileOffset, u_tileOffset);
|
||||
mapRenderer.bindTileTexture(tile, tilePixelSize,
|
||||
tileGutter * pixelRatio, ol.webgl.LINEAR, ol.webgl.LINEAR);
|
||||
gl.drawArrays(ol.webgl.TRIANGLE_STRIP, 0, 4);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.TileLayer.prototype.prepareFrame = function(frameState, layerState, context) {
|
||||
|
||||
if (allTilesLoaded) {
|
||||
this.renderedTileRange_ = tileRange;
|
||||
this.renderedFramebufferExtent_ = framebufferExtent;
|
||||
this.renderedRevision_ = tileSource.getRevision();
|
||||
var mapRenderer = this.mapRenderer;
|
||||
var gl = context.getGL();
|
||||
|
||||
var viewState = frameState.viewState;
|
||||
var projection = viewState.projection;
|
||||
|
||||
var tileLayer = /** @type {ol.layer.Tile} */ (this.getLayer());
|
||||
var tileSource = tileLayer.getSource();
|
||||
var tileGrid = tileSource.getTileGridForProjection(projection);
|
||||
var z = tileGrid.getZForResolution(viewState.resolution);
|
||||
var tileResolution = tileGrid.getResolution(z);
|
||||
|
||||
var tilePixelSize =
|
||||
tileSource.getTilePixelSize(z, frameState.pixelRatio, projection);
|
||||
var pixelRatio = tilePixelSize[0] /
|
||||
ol.size.toSize(tileGrid.getTileSize(z), this.tmpSize_)[0];
|
||||
var tilePixelResolution = tileResolution / pixelRatio;
|
||||
var tileGutter = tileSource.getTilePixelRatio(pixelRatio) * tileSource.getGutter(projection);
|
||||
|
||||
var center = viewState.center;
|
||||
var extent = frameState.extent;
|
||||
var tileRange = tileGrid.getTileRangeForExtentAndResolution(
|
||||
extent, tileResolution);
|
||||
|
||||
var framebufferExtent;
|
||||
if (this.renderedTileRange_ &&
|
||||
this.renderedTileRange_.equals(tileRange) &&
|
||||
this.renderedRevision_ == tileSource.getRevision()) {
|
||||
framebufferExtent = this.renderedFramebufferExtent_;
|
||||
} else {
|
||||
this.renderedTileRange_ = null;
|
||||
this.renderedFramebufferExtent_ = null;
|
||||
this.renderedRevision_ = -1;
|
||||
frameState.animate = true;
|
||||
|
||||
var tileRangeSize = tileRange.getSize();
|
||||
|
||||
var maxDimension = Math.max(
|
||||
tileRangeSize[0] * tilePixelSize[0],
|
||||
tileRangeSize[1] * tilePixelSize[1]);
|
||||
var framebufferDimension = ol.math.roundUpToPowerOfTwo(maxDimension);
|
||||
var framebufferExtentDimension = tilePixelResolution * framebufferDimension;
|
||||
var origin = tileGrid.getOrigin(z);
|
||||
var minX = origin[0] +
|
||||
tileRange.minX * tilePixelSize[0] * tilePixelResolution;
|
||||
var minY = origin[1] +
|
||||
tileRange.minY * tilePixelSize[1] * tilePixelResolution;
|
||||
framebufferExtent = [
|
||||
minX, minY,
|
||||
minX + framebufferExtentDimension, minY + framebufferExtentDimension
|
||||
];
|
||||
|
||||
this.bindFramebuffer(frameState, framebufferDimension);
|
||||
gl.viewport(0, 0, framebufferDimension, framebufferDimension);
|
||||
|
||||
gl.clearColor(0, 0, 0, 0);
|
||||
gl.clear(ol.webgl.COLOR_BUFFER_BIT);
|
||||
gl.disable(ol.webgl.BLEND);
|
||||
|
||||
var program = context.getProgram(this.fragmentShader_, this.vertexShader_);
|
||||
context.useProgram(program);
|
||||
if (!this.locations_) {
|
||||
this.locations_ =
|
||||
new ol.renderer.webgl.tilelayershader.Locations(gl, program);
|
||||
}
|
||||
|
||||
context.bindBuffer(ol.webgl.ARRAY_BUFFER, this.renderArrayBuffer_);
|
||||
gl.enableVertexAttribArray(this.locations_.a_position);
|
||||
gl.vertexAttribPointer(
|
||||
this.locations_.a_position, 2, ol.webgl.FLOAT, false, 16, 0);
|
||||
gl.enableVertexAttribArray(this.locations_.a_texCoord);
|
||||
gl.vertexAttribPointer(
|
||||
this.locations_.a_texCoord, 2, ol.webgl.FLOAT, false, 16, 8);
|
||||
gl.uniform1i(this.locations_.u_texture, 0);
|
||||
|
||||
/**
|
||||
* @type {Object.<number, Object.<string, ol.Tile>>}
|
||||
*/
|
||||
var tilesToDrawByZ = {};
|
||||
tilesToDrawByZ[z] = {};
|
||||
|
||||
var findLoadedTiles = this.createLoadedTileFinder(
|
||||
tileSource, projection, tilesToDrawByZ);
|
||||
|
||||
var useInterimTilesOnError = tileLayer.getUseInterimTilesOnError();
|
||||
var allTilesLoaded = true;
|
||||
var tmpExtent = ol.extent.createEmpty();
|
||||
var tmpTileRange = new ol.TileRange(0, 0, 0, 0);
|
||||
var childTileRange, drawable, fullyLoaded, tile, tileState;
|
||||
var x, y, tileExtent;
|
||||
for (x = tileRange.minX; x <= tileRange.maxX; ++x) {
|
||||
for (y = tileRange.minY; y <= tileRange.maxY; ++y) {
|
||||
|
||||
tile = tileSource.getTile(z, x, y, pixelRatio, projection);
|
||||
if (layerState.extent !== undefined) {
|
||||
// ignore tiles outside layer extent
|
||||
tileExtent = tileGrid.getTileCoordExtent(tile.tileCoord, tmpExtent);
|
||||
if (!ol.extent.intersects(tileExtent, layerState.extent)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
tileState = tile.getState();
|
||||
drawable = tileState == ol.TileState.LOADED ||
|
||||
tileState == ol.TileState.EMPTY ||
|
||||
tileState == ol.TileState.ERROR && !useInterimTilesOnError;
|
||||
if (!drawable) {
|
||||
tile = tile.getInterimTile();
|
||||
}
|
||||
tileState = tile.getState();
|
||||
if (tileState == ol.TileState.LOADED) {
|
||||
if (mapRenderer.isTileTextureLoaded(tile)) {
|
||||
tilesToDrawByZ[z][tile.tileCoord.toString()] = tile;
|
||||
continue;
|
||||
}
|
||||
} else if (tileState == ol.TileState.EMPTY ||
|
||||
(tileState == ol.TileState.ERROR &&
|
||||
!useInterimTilesOnError)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
allTilesLoaded = false;
|
||||
fullyLoaded = tileGrid.forEachTileCoordParentTileRange(
|
||||
tile.tileCoord, findLoadedTiles, null, tmpTileRange, tmpExtent);
|
||||
if (!fullyLoaded) {
|
||||
childTileRange = tileGrid.getTileCoordChildTileRange(
|
||||
tile.tileCoord, tmpTileRange, tmpExtent);
|
||||
if (childTileRange) {
|
||||
findLoadedTiles(z + 1, childTileRange);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** @type {Array.<number>} */
|
||||
var zs = Object.keys(tilesToDrawByZ).map(Number);
|
||||
zs.sort(ol.array.numberSafeCompareFunction);
|
||||
var u_tileOffset = new Float32Array(4);
|
||||
var i, ii, tileKey, tilesToDraw;
|
||||
for (i = 0, ii = zs.length; i < ii; ++i) {
|
||||
tilesToDraw = tilesToDrawByZ[zs[i]];
|
||||
for (tileKey in tilesToDraw) {
|
||||
tile = tilesToDraw[tileKey];
|
||||
tileExtent = tileGrid.getTileCoordExtent(tile.tileCoord, tmpExtent);
|
||||
u_tileOffset[0] = 2 * (tileExtent[2] - tileExtent[0]) /
|
||||
framebufferExtentDimension;
|
||||
u_tileOffset[1] = 2 * (tileExtent[3] - tileExtent[1]) /
|
||||
framebufferExtentDimension;
|
||||
u_tileOffset[2] = 2 * (tileExtent[0] - framebufferExtent[0]) /
|
||||
framebufferExtentDimension - 1;
|
||||
u_tileOffset[3] = 2 * (tileExtent[1] - framebufferExtent[1]) /
|
||||
framebufferExtentDimension - 1;
|
||||
gl.uniform4fv(this.locations_.u_tileOffset, u_tileOffset);
|
||||
mapRenderer.bindTileTexture(tile, tilePixelSize,
|
||||
tileGutter * pixelRatio, ol.webgl.LINEAR, ol.webgl.LINEAR);
|
||||
gl.drawArrays(ol.webgl.TRIANGLE_STRIP, 0, 4);
|
||||
}
|
||||
}
|
||||
|
||||
if (allTilesLoaded) {
|
||||
this.renderedTileRange_ = tileRange;
|
||||
this.renderedFramebufferExtent_ = framebufferExtent;
|
||||
this.renderedRevision_ = tileSource.getRevision();
|
||||
} else {
|
||||
this.renderedTileRange_ = null;
|
||||
this.renderedFramebufferExtent_ = null;
|
||||
this.renderedRevision_ = -1;
|
||||
frameState.animate = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange);
|
||||
var tileTextureQueue = mapRenderer.getTileTextureQueue();
|
||||
this.manageTilePyramid(
|
||||
frameState, tileSource, tileGrid, pixelRatio, projection, extent, z,
|
||||
tileLayer.getPreload(),
|
||||
/**
|
||||
* @param {ol.Tile} tile Tile.
|
||||
*/
|
||||
function(tile) {
|
||||
if (tile.getState() == ol.TileState.LOADED &&
|
||||
!mapRenderer.isTileTextureLoaded(tile) &&
|
||||
!tileTextureQueue.isKeyQueued(tile.getKey())) {
|
||||
tileTextureQueue.enqueue([
|
||||
tile,
|
||||
tileGrid.getTileCoordCenter(tile.tileCoord),
|
||||
tileGrid.getResolution(tile.tileCoord[0]),
|
||||
tilePixelSize, tileGutter * pixelRatio
|
||||
]);
|
||||
}
|
||||
}, this);
|
||||
this.scheduleExpireCache(frameState, tileSource);
|
||||
this.updateLogos(frameState, tileSource);
|
||||
|
||||
this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange);
|
||||
var tileTextureQueue = mapRenderer.getTileTextureQueue();
|
||||
this.manageTilePyramid(
|
||||
frameState, tileSource, tileGrid, pixelRatio, projection, extent, z,
|
||||
tileLayer.getPreload(),
|
||||
/**
|
||||
* @param {ol.Tile} tile Tile.
|
||||
*/
|
||||
function(tile) {
|
||||
if (tile.getState() == ol.TileState.LOADED &&
|
||||
!mapRenderer.isTileTextureLoaded(tile) &&
|
||||
!tileTextureQueue.isKeyQueued(tile.getKey())) {
|
||||
tileTextureQueue.enqueue([
|
||||
tile,
|
||||
tileGrid.getTileCoordCenter(tile.tileCoord),
|
||||
tileGrid.getResolution(tile.tileCoord[0]),
|
||||
tilePixelSize, tileGutter * pixelRatio
|
||||
]);
|
||||
}
|
||||
}, this);
|
||||
this.scheduleExpireCache(frameState, tileSource);
|
||||
this.updateLogos(frameState, tileSource);
|
||||
var texCoordMatrix = this.texCoordMatrix;
|
||||
ol.transform.reset(texCoordMatrix);
|
||||
ol.transform.translate(texCoordMatrix,
|
||||
(Math.round(center[0] / tileResolution) * tileResolution - framebufferExtent[0]) /
|
||||
(framebufferExtent[2] - framebufferExtent[0]),
|
||||
(Math.round(center[1] / tileResolution) * tileResolution - framebufferExtent[1]) /
|
||||
(framebufferExtent[3] - framebufferExtent[1]));
|
||||
if (viewState.rotation !== 0) {
|
||||
ol.transform.rotate(texCoordMatrix, viewState.rotation);
|
||||
}
|
||||
ol.transform.scale(texCoordMatrix,
|
||||
frameState.size[0] * viewState.resolution /
|
||||
(framebufferExtent[2] - framebufferExtent[0]),
|
||||
frameState.size[1] * viewState.resolution /
|
||||
(framebufferExtent[3] - framebufferExtent[1]));
|
||||
ol.transform.translate(texCoordMatrix, -0.5, -0.5);
|
||||
|
||||
var texCoordMatrix = this.texCoordMatrix;
|
||||
ol.transform.reset(texCoordMatrix);
|
||||
ol.transform.translate(texCoordMatrix,
|
||||
(Math.round(center[0] / tileResolution) * tileResolution - framebufferExtent[0]) /
|
||||
(framebufferExtent[2] - framebufferExtent[0]),
|
||||
(Math.round(center[1] / tileResolution) * tileResolution - framebufferExtent[1]) /
|
||||
(framebufferExtent[3] - framebufferExtent[1]));
|
||||
if (viewState.rotation !== 0) {
|
||||
ol.transform.rotate(texCoordMatrix, viewState.rotation);
|
||||
}
|
||||
ol.transform.scale(texCoordMatrix,
|
||||
frameState.size[0] * viewState.resolution /
|
||||
(framebufferExtent[2] - framebufferExtent[0]),
|
||||
frameState.size[1] * viewState.resolution /
|
||||
(framebufferExtent[3] - framebufferExtent[1]));
|
||||
ol.transform.translate(texCoordMatrix, -0.5, -0.5);
|
||||
|
||||
return true;
|
||||
};
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.TileLayer.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg) {
|
||||
if (!this.framebuffer) {
|
||||
return undefined;
|
||||
}
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.TileLayer.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg) {
|
||||
if (!this.framebuffer) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var pixelOnMapScaled = [
|
||||
pixel[0] / frameState.size[0],
|
||||
(frameState.size[1] - pixel[1]) / frameState.size[1]];
|
||||
var pixelOnMapScaled = [
|
||||
pixel[0] / frameState.size[0],
|
||||
(frameState.size[1] - pixel[1]) / frameState.size[1]];
|
||||
|
||||
var pixelOnFrameBufferScaled = ol.transform.apply(
|
||||
this.texCoordMatrix, pixelOnMapScaled.slice());
|
||||
var pixelOnFrameBuffer = [
|
||||
pixelOnFrameBufferScaled[0] * this.framebufferDimension,
|
||||
pixelOnFrameBufferScaled[1] * this.framebufferDimension];
|
||||
var pixelOnFrameBufferScaled = ol.transform.apply(
|
||||
this.texCoordMatrix, pixelOnMapScaled.slice());
|
||||
var pixelOnFrameBuffer = [
|
||||
pixelOnFrameBufferScaled[0] * this.framebufferDimension,
|
||||
pixelOnFrameBufferScaled[1] * this.framebufferDimension];
|
||||
|
||||
var gl = this.mapRenderer.getContext().getGL();
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
|
||||
var imageData = new Uint8Array(4);
|
||||
gl.readPixels(pixelOnFrameBuffer[0], pixelOnFrameBuffer[1], 1, 1,
|
||||
gl.RGBA, gl.UNSIGNED_BYTE, imageData);
|
||||
var gl = this.mapRenderer.getContext().getGL();
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
|
||||
var imageData = new Uint8Array(4);
|
||||
gl.readPixels(pixelOnFrameBuffer[0], pixelOnFrameBuffer[1], 1, 1,
|
||||
gl.RGBA, gl.UNSIGNED_BYTE, imageData);
|
||||
|
||||
if (imageData[3] > 0) {
|
||||
return callback.call(thisArg, this.getLayer(), imageData);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
if (imageData[3] > 0) {
|
||||
return callback.call(thisArg, this.getLayer(), imageData);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -6,101 +6,105 @@ goog.require('ol.webgl.Fragment');
|
||||
goog.require('ol.webgl.Vertex');
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.webgl.Fragment}
|
||||
* @struct
|
||||
*/
|
||||
ol.renderer.webgl.tilelayershader.Fragment = function() {
|
||||
ol.webgl.Fragment.call(this, ol.renderer.webgl.tilelayershader.Fragment.SOURCE);
|
||||
};
|
||||
ol.inherits(ol.renderer.webgl.tilelayershader.Fragment, ol.webgl.Fragment);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.renderer.webgl.tilelayershader.Fragment.DEBUG_SOURCE = 'precision mediump float;\nvarying vec2 v_texCoord;\n\n\nuniform sampler2D u_texture;\n\nvoid main(void) {\n gl_FragColor = texture2D(u_texture, v_texCoord);\n}\n';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.renderer.webgl.tilelayershader.Fragment.OPTIMIZED_SOURCE = 'precision mediump float;varying vec2 a;uniform sampler2D e;void main(void){gl_FragColor=texture2D(e,a);}';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.renderer.webgl.tilelayershader.Fragment.SOURCE = ol.renderer.webgl.tilelayershader.Fragment.OPTIMIZED_SOURCE;
|
||||
|
||||
|
||||
ol.renderer.webgl.tilelayershader.fragment = new ol.renderer.webgl.tilelayershader.Fragment();
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.webgl.Vertex}
|
||||
* @struct
|
||||
*/
|
||||
ol.renderer.webgl.tilelayershader.Vertex = function() {
|
||||
ol.webgl.Vertex.call(this, ol.renderer.webgl.tilelayershader.Vertex.SOURCE);
|
||||
};
|
||||
ol.inherits(ol.renderer.webgl.tilelayershader.Vertex, ol.webgl.Vertex);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.renderer.webgl.tilelayershader.Vertex.DEBUG_SOURCE = 'varying vec2 v_texCoord;\n\n\nattribute vec2 a_position;\nattribute vec2 a_texCoord;\nuniform vec4 u_tileOffset;\n\nvoid main(void) {\n gl_Position = vec4(a_position * u_tileOffset.xy + u_tileOffset.zw, 0., 1.);\n v_texCoord = a_texCoord;\n}\n\n\n';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.renderer.webgl.tilelayershader.Vertex.OPTIMIZED_SOURCE = 'varying vec2 a;attribute vec2 b;attribute vec2 c;uniform vec4 d;void main(void){gl_Position=vec4(b*d.xy+d.zw,0.,1.);a=c;}';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.renderer.webgl.tilelayershader.Vertex.SOURCE = ol.renderer.webgl.tilelayershader.Vertex.OPTIMIZED_SOURCE;
|
||||
|
||||
|
||||
ol.renderer.webgl.tilelayershader.vertex = new ol.renderer.webgl.tilelayershader.Vertex();
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {WebGLRenderingContext} gl GL.
|
||||
* @param {WebGLProgram} program Program.
|
||||
* @struct
|
||||
*/
|
||||
ol.renderer.webgl.tilelayershader.Locations = function(gl, program) {
|
||||
if (ol.ENABLE_WEBGL) {
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
* @constructor
|
||||
* @extends {ol.webgl.Fragment}
|
||||
* @struct
|
||||
*/
|
||||
this.u_texture = gl.getUniformLocation(program, 'e');
|
||||
ol.renderer.webgl.tilelayershader.Fragment = function() {
|
||||
ol.webgl.Fragment.call(this, ol.renderer.webgl.tilelayershader.Fragment.SOURCE);
|
||||
};
|
||||
ol.inherits(ol.renderer.webgl.tilelayershader.Fragment, ol.webgl.Fragment);
|
||||
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
this.u_tileOffset = gl.getUniformLocation(program, 'd');
|
||||
ol.renderer.webgl.tilelayershader.Fragment.DEBUG_SOURCE = 'precision mediump float;\nvarying vec2 v_texCoord;\n\n\nuniform sampler2D u_texture;\n\nvoid main(void) {\n gl_FragColor = texture2D(u_texture, v_texCoord);\n}\n';
|
||||
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
this.a_position = gl.getAttribLocation(program, 'b');
|
||||
ol.renderer.webgl.tilelayershader.Fragment.OPTIMIZED_SOURCE = 'precision mediump float;varying vec2 a;uniform sampler2D e;void main(void){gl_FragColor=texture2D(e,a);}';
|
||||
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
this.a_texCoord = gl.getAttribLocation(program, 'c');
|
||||
};
|
||||
ol.renderer.webgl.tilelayershader.Fragment.SOURCE = ol.renderer.webgl.tilelayershader.Fragment.OPTIMIZED_SOURCE;
|
||||
|
||||
|
||||
ol.renderer.webgl.tilelayershader.fragment = new ol.renderer.webgl.tilelayershader.Fragment();
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.webgl.Vertex}
|
||||
* @struct
|
||||
*/
|
||||
ol.renderer.webgl.tilelayershader.Vertex = function() {
|
||||
ol.webgl.Vertex.call(this, ol.renderer.webgl.tilelayershader.Vertex.SOURCE);
|
||||
};
|
||||
ol.inherits(ol.renderer.webgl.tilelayershader.Vertex, ol.webgl.Vertex);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.renderer.webgl.tilelayershader.Vertex.DEBUG_SOURCE = 'varying vec2 v_texCoord;\n\n\nattribute vec2 a_position;\nattribute vec2 a_texCoord;\nuniform vec4 u_tileOffset;\n\nvoid main(void) {\n gl_Position = vec4(a_position * u_tileOffset.xy + u_tileOffset.zw, 0., 1.);\n v_texCoord = a_texCoord;\n}\n\n\n';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.renderer.webgl.tilelayershader.Vertex.OPTIMIZED_SOURCE = 'varying vec2 a;attribute vec2 b;attribute vec2 c;uniform vec4 d;void main(void){gl_Position=vec4(b*d.xy+d.zw,0.,1.);a=c;}';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.renderer.webgl.tilelayershader.Vertex.SOURCE = ol.renderer.webgl.tilelayershader.Vertex.OPTIMIZED_SOURCE;
|
||||
|
||||
|
||||
ol.renderer.webgl.tilelayershader.vertex = new ol.renderer.webgl.tilelayershader.Vertex();
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {WebGLRenderingContext} gl GL.
|
||||
* @param {WebGLProgram} program Program.
|
||||
* @struct
|
||||
*/
|
||||
ol.renderer.webgl.tilelayershader.Locations = function(gl, program) {
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_texture = gl.getUniformLocation(program, 'e');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_tileOffset = gl.getUniformLocation(program, 'd');
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.a_position = gl.getAttribLocation(program, 'b');
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.a_texCoord = gl.getAttribLocation(program, 'c');
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -9,307 +9,311 @@ goog.require('ol.renderer.webgl.Layer');
|
||||
goog.require('ol.transform');
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.renderer.webgl.Layer}
|
||||
* @param {ol.renderer.webgl.Map} mapRenderer Map renderer.
|
||||
* @param {ol.layer.Vector} vectorLayer Vector layer.
|
||||
*/
|
||||
ol.renderer.webgl.VectorLayer = function(mapRenderer, vectorLayer) {
|
||||
|
||||
ol.renderer.webgl.Layer.call(this, mapRenderer, vectorLayer);
|
||||
if (ol.ENABLE_WEBGL) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
* @constructor
|
||||
* @extends {ol.renderer.webgl.Layer}
|
||||
* @param {ol.renderer.webgl.Map} mapRenderer Map renderer.
|
||||
* @param {ol.layer.Vector} vectorLayer Vector layer.
|
||||
*/
|
||||
this.dirty_ = false;
|
||||
ol.renderer.webgl.VectorLayer = function(mapRenderer, vectorLayer) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.renderedRevision_ = -1;
|
||||
ol.renderer.webgl.Layer.call(this, mapRenderer, vectorLayer);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.renderedResolution_ = NaN;
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.dirty_ = false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Extent}
|
||||
*/
|
||||
this.renderedExtent_ = ol.extent.createEmpty();
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.renderedRevision_ = -1;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {function(ol.Feature, ol.Feature): number|null}
|
||||
*/
|
||||
this.renderedRenderOrder_ = null;
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.renderedResolution_ = NaN;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.render.webgl.ReplayGroup}
|
||||
*/
|
||||
this.replayGroup_ = null;
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Extent}
|
||||
*/
|
||||
this.renderedExtent_ = ol.extent.createEmpty();
|
||||
|
||||
/**
|
||||
* The last layer state.
|
||||
* @private
|
||||
* @type {?ol.LayerState}
|
||||
*/
|
||||
this.layerState_ = null;
|
||||
/**
|
||||
* @private
|
||||
* @type {function(ol.Feature, ol.Feature): number|null}
|
||||
*/
|
||||
this.renderedRenderOrder_ = null;
|
||||
|
||||
};
|
||||
ol.inherits(ol.renderer.webgl.VectorLayer, ol.renderer.webgl.Layer);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.VectorLayer.prototype.composeFrame = function(frameState, layerState, context) {
|
||||
this.layerState_ = layerState;
|
||||
var viewState = frameState.viewState;
|
||||
var replayGroup = this.replayGroup_;
|
||||
var size = frameState.size;
|
||||
var pixelRatio = frameState.pixelRatio;
|
||||
var gl = this.mapRenderer.getGL();
|
||||
if (replayGroup && !replayGroup.isEmpty()) {
|
||||
gl.enable(gl.SCISSOR_TEST);
|
||||
gl.scissor(0, 0, size[0] * pixelRatio, size[1] * pixelRatio);
|
||||
replayGroup.replay(context,
|
||||
viewState.center, viewState.resolution, viewState.rotation,
|
||||
size, pixelRatio, layerState.opacity,
|
||||
layerState.managed ? frameState.skippedFeatureUids : {});
|
||||
gl.disable(gl.SCISSOR_TEST);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.VectorLayer.prototype.disposeInternal = function() {
|
||||
var replayGroup = this.replayGroup_;
|
||||
if (replayGroup) {
|
||||
var context = this.mapRenderer.getContext();
|
||||
replayGroup.getDeleteResourcesFunction(context)();
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.render.webgl.ReplayGroup}
|
||||
*/
|
||||
this.replayGroup_ = null;
|
||||
}
|
||||
ol.renderer.webgl.Layer.prototype.disposeInternal.call(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* The last layer state.
|
||||
* @private
|
||||
* @type {?ol.LayerState}
|
||||
*/
|
||||
this.layerState_ = null;
|
||||
|
||||
};
|
||||
ol.inherits(ol.renderer.webgl.VectorLayer, ol.renderer.webgl.Layer);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.VectorLayer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, hitTolerance, callback, thisArg) {
|
||||
if (!this.replayGroup_ || !this.layerState_) {
|
||||
return undefined;
|
||||
} else {
|
||||
var context = this.mapRenderer.getContext();
|
||||
var viewState = frameState.viewState;
|
||||
var layer = this.getLayer();
|
||||
var layerState = this.layerState_;
|
||||
/** @type {Object.<string, boolean>} */
|
||||
var features = {};
|
||||
return this.replayGroup_.forEachFeatureAtCoordinate(coordinate,
|
||||
context, viewState.center, viewState.resolution, viewState.rotation,
|
||||
frameState.size, frameState.pixelRatio, layerState.opacity,
|
||||
{},
|
||||
/**
|
||||
* @param {ol.Feature|ol.render.Feature} feature Feature.
|
||||
* @return {?} Callback result.
|
||||
*/
|
||||
function(feature) {
|
||||
var key = ol.getUid(feature).toString();
|
||||
if (!(key in features)) {
|
||||
features[key] = true;
|
||||
return callback.call(thisArg, feature, layer);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.VectorLayer.prototype.hasFeatureAtCoordinate = function(coordinate, frameState) {
|
||||
if (!this.replayGroup_ || !this.layerState_) {
|
||||
return false;
|
||||
} else {
|
||||
var context = this.mapRenderer.getContext();
|
||||
var viewState = frameState.viewState;
|
||||
var layerState = this.layerState_;
|
||||
return this.replayGroup_.hasFeatureAtCoordinate(coordinate,
|
||||
context, viewState.center, viewState.resolution, viewState.rotation,
|
||||
frameState.size, frameState.pixelRatio, layerState.opacity,
|
||||
frameState.skippedFeatureUids);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.VectorLayer.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg) {
|
||||
var coordinate = ol.transform.apply(
|
||||
frameState.pixelToCoordinateTransform, pixel.slice());
|
||||
var hasFeature = this.hasFeatureAtCoordinate(coordinate, frameState);
|
||||
|
||||
if (hasFeature) {
|
||||
return callback.call(thisArg, this.getLayer(), null);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handle changes in image style state.
|
||||
* @param {ol.events.Event} event Image style change event.
|
||||
* @private
|
||||
*/
|
||||
ol.renderer.webgl.VectorLayer.prototype.handleStyleImageChange_ = function(event) {
|
||||
this.renderIfReadyAndVisible();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.VectorLayer.prototype.prepareFrame = function(frameState, layerState, context) {
|
||||
|
||||
var vectorLayer = /** @type {ol.layer.Vector} */ (this.getLayer());
|
||||
var vectorSource = vectorLayer.getSource();
|
||||
|
||||
this.updateAttributions(
|
||||
frameState.attributions, vectorSource.getAttributions());
|
||||
this.updateLogos(frameState, vectorSource);
|
||||
|
||||
var animating = frameState.viewHints[ol.ViewHint.ANIMATING];
|
||||
var interacting = frameState.viewHints[ol.ViewHint.INTERACTING];
|
||||
var updateWhileAnimating = vectorLayer.getUpdateWhileAnimating();
|
||||
var updateWhileInteracting = vectorLayer.getUpdateWhileInteracting();
|
||||
|
||||
if (!this.dirty_ && (!updateWhileAnimating && animating) ||
|
||||
(!updateWhileInteracting && interacting)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var frameStateExtent = frameState.extent;
|
||||
var viewState = frameState.viewState;
|
||||
var projection = viewState.projection;
|
||||
var resolution = viewState.resolution;
|
||||
var pixelRatio = frameState.pixelRatio;
|
||||
var vectorLayerRevision = vectorLayer.getRevision();
|
||||
var vectorLayerRenderBuffer = vectorLayer.getRenderBuffer();
|
||||
var vectorLayerRenderOrder = vectorLayer.getRenderOrder();
|
||||
|
||||
if (vectorLayerRenderOrder === undefined) {
|
||||
vectorLayerRenderOrder = ol.renderer.vector.defaultOrder;
|
||||
}
|
||||
|
||||
var extent = ol.extent.buffer(frameStateExtent,
|
||||
vectorLayerRenderBuffer * resolution);
|
||||
|
||||
if (!this.dirty_ &&
|
||||
this.renderedResolution_ == resolution &&
|
||||
this.renderedRevision_ == vectorLayerRevision &&
|
||||
this.renderedRenderOrder_ == vectorLayerRenderOrder &&
|
||||
ol.extent.containsExtent(this.renderedExtent_, extent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.replayGroup_) {
|
||||
frameState.postRenderFunctions.push(
|
||||
this.replayGroup_.getDeleteResourcesFunction(context));
|
||||
}
|
||||
|
||||
this.dirty_ = false;
|
||||
|
||||
var replayGroup = new ol.render.webgl.ReplayGroup(
|
||||
ol.renderer.vector.getTolerance(resolution, pixelRatio),
|
||||
extent, vectorLayer.getRenderBuffer());
|
||||
vectorSource.loadFeatures(extent, resolution, projection);
|
||||
/**
|
||||
* @param {ol.Feature} feature Feature.
|
||||
* @this {ol.renderer.webgl.VectorLayer}
|
||||
* @inheritDoc
|
||||
*/
|
||||
var renderFeature = function(feature) {
|
||||
var styles;
|
||||
var styleFunction = feature.getStyleFunction();
|
||||
if (styleFunction) {
|
||||
styles = styleFunction.call(feature, resolution);
|
||||
} else {
|
||||
styleFunction = vectorLayer.getStyleFunction();
|
||||
if (styleFunction) {
|
||||
styles = styleFunction(feature, resolution);
|
||||
}
|
||||
ol.renderer.webgl.VectorLayer.prototype.composeFrame = function(frameState, layerState, context) {
|
||||
this.layerState_ = layerState;
|
||||
var viewState = frameState.viewState;
|
||||
var replayGroup = this.replayGroup_;
|
||||
var size = frameState.size;
|
||||
var pixelRatio = frameState.pixelRatio;
|
||||
var gl = this.mapRenderer.getGL();
|
||||
if (replayGroup && !replayGroup.isEmpty()) {
|
||||
gl.enable(gl.SCISSOR_TEST);
|
||||
gl.scissor(0, 0, size[0] * pixelRatio, size[1] * pixelRatio);
|
||||
replayGroup.replay(context,
|
||||
viewState.center, viewState.resolution, viewState.rotation,
|
||||
size, pixelRatio, layerState.opacity,
|
||||
layerState.managed ? frameState.skippedFeatureUids : {});
|
||||
gl.disable(gl.SCISSOR_TEST);
|
||||
}
|
||||
if (styles) {
|
||||
var dirty = this.renderFeature(
|
||||
feature, resolution, pixelRatio, styles, replayGroup);
|
||||
this.dirty_ = this.dirty_ || dirty;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.VectorLayer.prototype.disposeInternal = function() {
|
||||
var replayGroup = this.replayGroup_;
|
||||
if (replayGroup) {
|
||||
var context = this.mapRenderer.getContext();
|
||||
replayGroup.getDeleteResourcesFunction(context)();
|
||||
this.replayGroup_ = null;
|
||||
}
|
||||
ol.renderer.webgl.Layer.prototype.disposeInternal.call(this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.VectorLayer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, hitTolerance, callback, thisArg) {
|
||||
if (!this.replayGroup_ || !this.layerState_) {
|
||||
return undefined;
|
||||
} else {
|
||||
var context = this.mapRenderer.getContext();
|
||||
var viewState = frameState.viewState;
|
||||
var layer = this.getLayer();
|
||||
var layerState = this.layerState_;
|
||||
/** @type {Object.<string, boolean>} */
|
||||
var features = {};
|
||||
return this.replayGroup_.forEachFeatureAtCoordinate(coordinate,
|
||||
context, viewState.center, viewState.resolution, viewState.rotation,
|
||||
frameState.size, frameState.pixelRatio, layerState.opacity,
|
||||
{},
|
||||
/**
|
||||
* @param {ol.Feature|ol.render.Feature} feature Feature.
|
||||
* @return {?} Callback result.
|
||||
*/
|
||||
function(feature) {
|
||||
var key = ol.getUid(feature).toString();
|
||||
if (!(key in features)) {
|
||||
features[key] = true;
|
||||
return callback.call(thisArg, feature, layer);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
if (vectorLayerRenderOrder) {
|
||||
/** @type {Array.<ol.Feature>} */
|
||||
var features = [];
|
||||
vectorSource.forEachFeatureInExtent(extent,
|
||||
/**
|
||||
* @param {ol.Feature} feature Feature.
|
||||
*/
|
||||
function(feature) {
|
||||
features.push(feature);
|
||||
}, this);
|
||||
features.sort(vectorLayerRenderOrder);
|
||||
features.forEach(renderFeature, this);
|
||||
} else {
|
||||
vectorSource.forEachFeatureInExtent(extent, renderFeature, this);
|
||||
}
|
||||
replayGroup.finish(context);
|
||||
|
||||
this.renderedResolution_ = resolution;
|
||||
this.renderedRevision_ = vectorLayerRevision;
|
||||
this.renderedRenderOrder_ = vectorLayerRenderOrder;
|
||||
this.renderedExtent_ = extent;
|
||||
this.replayGroup_ = replayGroup;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Feature} feature Feature.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {(ol.style.Style|Array.<ol.style.Style>)} styles The style or array of
|
||||
* styles.
|
||||
* @param {ol.render.webgl.ReplayGroup} replayGroup Replay group.
|
||||
* @return {boolean} `true` if an image is loading.
|
||||
*/
|
||||
ol.renderer.webgl.VectorLayer.prototype.renderFeature = function(feature, resolution, pixelRatio, styles, replayGroup) {
|
||||
if (!styles) {
|
||||
return false;
|
||||
}
|
||||
var loading = false;
|
||||
if (Array.isArray(styles)) {
|
||||
for (var i = styles.length - 1, ii = 0; i >= ii; --i) {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.VectorLayer.prototype.hasFeatureAtCoordinate = function(coordinate, frameState) {
|
||||
if (!this.replayGroup_ || !this.layerState_) {
|
||||
return false;
|
||||
} else {
|
||||
var context = this.mapRenderer.getContext();
|
||||
var viewState = frameState.viewState;
|
||||
var layerState = this.layerState_;
|
||||
return this.replayGroup_.hasFeatureAtCoordinate(coordinate,
|
||||
context, viewState.center, viewState.resolution, viewState.rotation,
|
||||
frameState.size, frameState.pixelRatio, layerState.opacity,
|
||||
frameState.skippedFeatureUids);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.VectorLayer.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg) {
|
||||
var coordinate = ol.transform.apply(
|
||||
frameState.pixelToCoordinateTransform, pixel.slice());
|
||||
var hasFeature = this.hasFeatureAtCoordinate(coordinate, frameState);
|
||||
|
||||
if (hasFeature) {
|
||||
return callback.call(thisArg, this.getLayer(), null);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handle changes in image style state.
|
||||
* @param {ol.events.Event} event Image style change event.
|
||||
* @private
|
||||
*/
|
||||
ol.renderer.webgl.VectorLayer.prototype.handleStyleImageChange_ = function(event) {
|
||||
this.renderIfReadyAndVisible();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.VectorLayer.prototype.prepareFrame = function(frameState, layerState, context) {
|
||||
|
||||
var vectorLayer = /** @type {ol.layer.Vector} */ (this.getLayer());
|
||||
var vectorSource = vectorLayer.getSource();
|
||||
|
||||
this.updateAttributions(
|
||||
frameState.attributions, vectorSource.getAttributions());
|
||||
this.updateLogos(frameState, vectorSource);
|
||||
|
||||
var animating = frameState.viewHints[ol.ViewHint.ANIMATING];
|
||||
var interacting = frameState.viewHints[ol.ViewHint.INTERACTING];
|
||||
var updateWhileAnimating = vectorLayer.getUpdateWhileAnimating();
|
||||
var updateWhileInteracting = vectorLayer.getUpdateWhileInteracting();
|
||||
|
||||
if (!this.dirty_ && (!updateWhileAnimating && animating) ||
|
||||
(!updateWhileInteracting && interacting)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var frameStateExtent = frameState.extent;
|
||||
var viewState = frameState.viewState;
|
||||
var projection = viewState.projection;
|
||||
var resolution = viewState.resolution;
|
||||
var pixelRatio = frameState.pixelRatio;
|
||||
var vectorLayerRevision = vectorLayer.getRevision();
|
||||
var vectorLayerRenderBuffer = vectorLayer.getRenderBuffer();
|
||||
var vectorLayerRenderOrder = vectorLayer.getRenderOrder();
|
||||
|
||||
if (vectorLayerRenderOrder === undefined) {
|
||||
vectorLayerRenderOrder = ol.renderer.vector.defaultOrder;
|
||||
}
|
||||
|
||||
var extent = ol.extent.buffer(frameStateExtent,
|
||||
vectorLayerRenderBuffer * resolution);
|
||||
|
||||
if (!this.dirty_ &&
|
||||
this.renderedResolution_ == resolution &&
|
||||
this.renderedRevision_ == vectorLayerRevision &&
|
||||
this.renderedRenderOrder_ == vectorLayerRenderOrder &&
|
||||
ol.extent.containsExtent(this.renderedExtent_, extent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.replayGroup_) {
|
||||
frameState.postRenderFunctions.push(
|
||||
this.replayGroup_.getDeleteResourcesFunction(context));
|
||||
}
|
||||
|
||||
this.dirty_ = false;
|
||||
|
||||
var replayGroup = new ol.render.webgl.ReplayGroup(
|
||||
ol.renderer.vector.getTolerance(resolution, pixelRatio),
|
||||
extent, vectorLayer.getRenderBuffer());
|
||||
vectorSource.loadFeatures(extent, resolution, projection);
|
||||
/**
|
||||
* @param {ol.Feature} feature Feature.
|
||||
* @this {ol.renderer.webgl.VectorLayer}
|
||||
*/
|
||||
var renderFeature = function(feature) {
|
||||
var styles;
|
||||
var styleFunction = feature.getStyleFunction();
|
||||
if (styleFunction) {
|
||||
styles = styleFunction.call(feature, resolution);
|
||||
} else {
|
||||
styleFunction = vectorLayer.getStyleFunction();
|
||||
if (styleFunction) {
|
||||
styles = styleFunction(feature, resolution);
|
||||
}
|
||||
}
|
||||
if (styles) {
|
||||
var dirty = this.renderFeature(
|
||||
feature, resolution, pixelRatio, styles, replayGroup);
|
||||
this.dirty_ = this.dirty_ || dirty;
|
||||
}
|
||||
};
|
||||
if (vectorLayerRenderOrder) {
|
||||
/** @type {Array.<ol.Feature>} */
|
||||
var features = [];
|
||||
vectorSource.forEachFeatureInExtent(extent,
|
||||
/**
|
||||
* @param {ol.Feature} feature Feature.
|
||||
*/
|
||||
function(feature) {
|
||||
features.push(feature);
|
||||
}, this);
|
||||
features.sort(vectorLayerRenderOrder);
|
||||
features.forEach(renderFeature, this);
|
||||
} else {
|
||||
vectorSource.forEachFeatureInExtent(extent, renderFeature, this);
|
||||
}
|
||||
replayGroup.finish(context);
|
||||
|
||||
this.renderedResolution_ = resolution;
|
||||
this.renderedRevision_ = vectorLayerRevision;
|
||||
this.renderedRenderOrder_ = vectorLayerRenderOrder;
|
||||
this.renderedExtent_ = extent;
|
||||
this.replayGroup_ = replayGroup;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Feature} feature Feature.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {(ol.style.Style|Array.<ol.style.Style>)} styles The style or array of
|
||||
* styles.
|
||||
* @param {ol.render.webgl.ReplayGroup} replayGroup Replay group.
|
||||
* @return {boolean} `true` if an image is loading.
|
||||
*/
|
||||
ol.renderer.webgl.VectorLayer.prototype.renderFeature = function(feature, resolution, pixelRatio, styles, replayGroup) {
|
||||
if (!styles) {
|
||||
return false;
|
||||
}
|
||||
var loading = false;
|
||||
if (Array.isArray(styles)) {
|
||||
for (var i = styles.length - 1, ii = 0; i >= ii; --i) {
|
||||
loading = ol.renderer.vector.renderFeature(
|
||||
replayGroup, feature, styles[i],
|
||||
ol.renderer.vector.getSquaredTolerance(resolution, pixelRatio),
|
||||
this.handleStyleImageChange_, this) || loading;
|
||||
}
|
||||
} else {
|
||||
loading = ol.renderer.vector.renderFeature(
|
||||
replayGroup, feature, styles[i],
|
||||
replayGroup, feature, styles,
|
||||
ol.renderer.vector.getSquaredTolerance(resolution, pixelRatio),
|
||||
this.handleStyleImageChange_, this) || loading;
|
||||
}
|
||||
} else {
|
||||
loading = ol.renderer.vector.renderFeature(
|
||||
replayGroup, feature, styles,
|
||||
ol.renderer.vector.getSquaredTolerance(resolution, pixelRatio),
|
||||
this.handleStyleImageChange_, this) || loading;
|
||||
}
|
||||
return loading;
|
||||
};
|
||||
return loading;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
418
src/ol/webgl.js
418
src/ol/webgl.js
@@ -1,288 +1,292 @@
|
||||
goog.provide('ol.webgl');
|
||||
|
||||
|
||||
/** Constants taken from goog.webgl
|
||||
*/
|
||||
if (ol.ENABLE_WEBGL) {
|
||||
|
||||
/** Constants taken from goog.webgl
|
||||
*/
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.ONE = 1;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.ONE = 1;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.SRC_ALPHA = 0x0302;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.SRC_ALPHA = 0x0302;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.COLOR_ATTACHMENT0 = 0x8CE0;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.COLOR_ATTACHMENT0 = 0x8CE0;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.COLOR_BUFFER_BIT = 0x00004000;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.COLOR_BUFFER_BIT = 0x00004000;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.TRIANGLES = 0x0004;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.TRIANGLES = 0x0004;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.TRIANGLE_STRIP = 0x0005;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.TRIANGLE_STRIP = 0x0005;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.ONE_MINUS_SRC_ALPHA = 0x0303;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.ONE_MINUS_SRC_ALPHA = 0x0303;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.ARRAY_BUFFER = 0x8892;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.ARRAY_BUFFER = 0x8892;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.ELEMENT_ARRAY_BUFFER = 0x8893;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.ELEMENT_ARRAY_BUFFER = 0x8893;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.STREAM_DRAW = 0x88E0;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.STREAM_DRAW = 0x88E0;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.STATIC_DRAW = 0x88E4;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.STATIC_DRAW = 0x88E4;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.DYNAMIC_DRAW = 0x88E8;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.DYNAMIC_DRAW = 0x88E8;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.CULL_FACE = 0x0B44;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.CULL_FACE = 0x0B44;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.BLEND = 0x0BE2;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.BLEND = 0x0BE2;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.STENCIL_TEST = 0x0B90;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.STENCIL_TEST = 0x0B90;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.DEPTH_TEST = 0x0B71;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.DEPTH_TEST = 0x0B71;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.SCISSOR_TEST = 0x0C11;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.SCISSOR_TEST = 0x0C11;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.UNSIGNED_BYTE = 0x1401;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.UNSIGNED_BYTE = 0x1401;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.UNSIGNED_SHORT = 0x1403;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.UNSIGNED_SHORT = 0x1403;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.UNSIGNED_INT = 0x1405;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.UNSIGNED_INT = 0x1405;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.FLOAT = 0x1406;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.FLOAT = 0x1406;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.RGBA = 0x1908;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.RGBA = 0x1908;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.FRAGMENT_SHADER = 0x8B30;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.FRAGMENT_SHADER = 0x8B30;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.VERTEX_SHADER = 0x8B31;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.VERTEX_SHADER = 0x8B31;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.LINK_STATUS = 0x8B82;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.LINK_STATUS = 0x8B82;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.LINEAR = 0x2601;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.LINEAR = 0x2601;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.TEXTURE_MAG_FILTER = 0x2800;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.TEXTURE_MAG_FILTER = 0x2800;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.TEXTURE_MIN_FILTER = 0x2801;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.TEXTURE_MIN_FILTER = 0x2801;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.TEXTURE_WRAP_S = 0x2802;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.TEXTURE_WRAP_S = 0x2802;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.TEXTURE_WRAP_T = 0x2803;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.TEXTURE_WRAP_T = 0x2803;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.TEXTURE_2D = 0x0DE1;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.TEXTURE_2D = 0x0DE1;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.TEXTURE0 = 0x84C0;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.TEXTURE0 = 0x84C0;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.CLAMP_TO_EDGE = 0x812F;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.CLAMP_TO_EDGE = 0x812F;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.COMPILE_STATUS = 0x8B81;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.COMPILE_STATUS = 0x8B81;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.FRAMEBUFFER = 0x8D40;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.webgl.FRAMEBUFFER = 0x8D40;
|
||||
|
||||
/** end of goog.webgl constants
|
||||
*/
|
||||
|
||||
/** end of goog.webgl constants
|
||||
*/
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @private
|
||||
* @type {Array.<string>}
|
||||
*/
|
||||
ol.webgl.CONTEXT_IDS_ = [
|
||||
'experimental-webgl',
|
||||
'webgl',
|
||||
'webkit-3d',
|
||||
'moz-webgl'
|
||||
];
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @private
|
||||
* @type {Array.<string>}
|
||||
*/
|
||||
ol.webgl.CONTEXT_IDS_ = [
|
||||
'experimental-webgl',
|
||||
'webgl',
|
||||
'webkit-3d',
|
||||
'moz-webgl'
|
||||
];
|
||||
|
||||
/**
|
||||
* @param {HTMLCanvasElement} canvas Canvas.
|
||||
* @param {Object=} opt_attributes Attributes.
|
||||
* @return {WebGLRenderingContext} WebGL rendering context.
|
||||
*/
|
||||
ol.webgl.getContext = function(canvas, opt_attributes) {
|
||||
var context, i, ii = ol.webgl.CONTEXT_IDS_.length;
|
||||
for (i = 0; i < ii; ++i) {
|
||||
try {
|
||||
context = canvas.getContext(ol.webgl.CONTEXT_IDS_[i], opt_attributes);
|
||||
if (context) {
|
||||
return /** @type {!WebGLRenderingContext} */ (context);
|
||||
|
||||
/**
|
||||
* @param {HTMLCanvasElement} canvas Canvas.
|
||||
* @param {Object=} opt_attributes Attributes.
|
||||
* @return {WebGLRenderingContext} WebGL rendering context.
|
||||
*/
|
||||
ol.webgl.getContext = function(canvas, opt_attributes) {
|
||||
var context, i, ii = ol.webgl.CONTEXT_IDS_.length;
|
||||
for (i = 0; i < ii; ++i) {
|
||||
try {
|
||||
context = canvas.getContext(ol.webgl.CONTEXT_IDS_[i], opt_attributes);
|
||||
if (context) {
|
||||
return /** @type {!WebGLRenderingContext} */ (context);
|
||||
}
|
||||
} catch (e) {
|
||||
// pass
|
||||
}
|
||||
} catch (e) {
|
||||
// pass
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
return null;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -4,52 +4,56 @@ goog.require('ol');
|
||||
goog.require('ol.webgl');
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {Array.<number>=} opt_arr Array.
|
||||
* @param {number=} opt_usage Usage.
|
||||
* @struct
|
||||
*/
|
||||
ol.webgl.Buffer = function(opt_arr, opt_usage) {
|
||||
if (ol.ENABLE_WEBGL) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<number>}
|
||||
* @constructor
|
||||
* @param {Array.<number>=} opt_arr Array.
|
||||
* @param {number=} opt_usage Usage.
|
||||
* @struct
|
||||
*/
|
||||
this.arr_ = opt_arr !== undefined ? opt_arr : [];
|
||||
ol.webgl.Buffer = function(opt_arr, opt_usage) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this.arr_ = opt_arr !== undefined ? opt_arr : [];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.usage_ = opt_usage !== undefined ?
|
||||
opt_usage : ol.webgl.Buffer.Usage_.STATIC_DRAW;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
* @return {Array.<number>} Array.
|
||||
*/
|
||||
this.usage_ = opt_usage !== undefined ?
|
||||
opt_usage : ol.webgl.Buffer.Usage_.STATIC_DRAW;
|
||||
|
||||
};
|
||||
ol.webgl.Buffer.prototype.getArray = function() {
|
||||
return this.arr_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<number>} Array.
|
||||
*/
|
||||
ol.webgl.Buffer.prototype.getArray = function() {
|
||||
return this.arr_;
|
||||
};
|
||||
/**
|
||||
* @return {number} Usage.
|
||||
*/
|
||||
ol.webgl.Buffer.prototype.getUsage = function() {
|
||||
return this.usage_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} Usage.
|
||||
*/
|
||||
ol.webgl.Buffer.prototype.getUsage = function() {
|
||||
return this.usage_;
|
||||
};
|
||||
/**
|
||||
* @enum {number}
|
||||
* @private
|
||||
*/
|
||||
ol.webgl.Buffer.Usage_ = {
|
||||
STATIC_DRAW: ol.webgl.STATIC_DRAW,
|
||||
STREAM_DRAW: ol.webgl.STREAM_DRAW,
|
||||
DYNAMIC_DRAW: ol.webgl.DYNAMIC_DRAW
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @enum {number}
|
||||
* @private
|
||||
*/
|
||||
ol.webgl.Buffer.Usage_ = {
|
||||
STATIC_DRAW: ol.webgl.STATIC_DRAW,
|
||||
STREAM_DRAW: ol.webgl.STREAM_DRAW,
|
||||
DYNAMIC_DRAW: ol.webgl.DYNAMIC_DRAW
|
||||
};
|
||||
}
|
||||
|
||||
@@ -9,363 +9,367 @@ goog.require('ol.webgl');
|
||||
goog.require('ol.webgl.ContextEventType');
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* A WebGL context for accessing low-level WebGL capabilities.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.Disposable}
|
||||
* @param {HTMLCanvasElement} canvas Canvas.
|
||||
* @param {WebGLRenderingContext} gl GL.
|
||||
*/
|
||||
ol.webgl.Context = function(canvas, gl) {
|
||||
if (ol.ENABLE_WEBGL) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLCanvasElement}
|
||||
* @classdesc
|
||||
* A WebGL context for accessing low-level WebGL capabilities.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.Disposable}
|
||||
* @param {HTMLCanvasElement} canvas Canvas.
|
||||
* @param {WebGLRenderingContext} gl GL.
|
||||
*/
|
||||
this.canvas_ = canvas;
|
||||
ol.webgl.Context = function(canvas, gl) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLCanvasElement}
|
||||
*/
|
||||
this.canvas_ = canvas;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {WebGLRenderingContext}
|
||||
*/
|
||||
this.gl_ = gl;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<string, ol.WebglBufferCacheEntry>}
|
||||
*/
|
||||
this.bufferCache_ = {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<string, WebGLShader>}
|
||||
*/
|
||||
this.shaderCache_ = {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<string, WebGLProgram>}
|
||||
*/
|
||||
this.programCache_ = {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {WebGLProgram}
|
||||
*/
|
||||
this.currentProgram_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {WebGLFramebuffer}
|
||||
*/
|
||||
this.hitDetectionFramebuffer_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {WebGLTexture}
|
||||
*/
|
||||
this.hitDetectionTexture_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {WebGLRenderbuffer}
|
||||
*/
|
||||
this.hitDetectionRenderbuffer_ = null;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.hasOESElementIndexUint = ol.array.includes(
|
||||
ol.WEBGL_EXTENSIONS, 'OES_element_index_uint');
|
||||
|
||||
// use the OES_element_index_uint extension if available
|
||||
if (this.hasOESElementIndexUint) {
|
||||
gl.getExtension('OES_element_index_uint');
|
||||
}
|
||||
|
||||
ol.events.listen(this.canvas_, ol.webgl.ContextEventType.LOST,
|
||||
this.handleWebGLContextLost, this);
|
||||
ol.events.listen(this.canvas_, ol.webgl.ContextEventType.RESTORED,
|
||||
this.handleWebGLContextRestored, this);
|
||||
|
||||
};
|
||||
ol.inherits(ol.webgl.Context, ol.Disposable);
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {WebGLRenderingContext}
|
||||
* Just bind the buffer if it's in the cache. Otherwise create
|
||||
* the WebGL buffer, bind it, populate it, and add an entry to
|
||||
* the cache.
|
||||
* @param {number} target Target.
|
||||
* @param {ol.webgl.Buffer} buf Buffer.
|
||||
*/
|
||||
this.gl_ = gl;
|
||||
ol.webgl.Context.prototype.bindBuffer = function(target, buf) {
|
||||
var gl = this.getGL();
|
||||
var arr = buf.getArray();
|
||||
var bufferKey = String(ol.getUid(buf));
|
||||
if (bufferKey in this.bufferCache_) {
|
||||
var bufferCacheEntry = this.bufferCache_[bufferKey];
|
||||
gl.bindBuffer(target, bufferCacheEntry.buffer);
|
||||
} else {
|
||||
var buffer = gl.createBuffer();
|
||||
gl.bindBuffer(target, buffer);
|
||||
var /** @type {ArrayBufferView} */ arrayBuffer;
|
||||
if (target == ol.webgl.ARRAY_BUFFER) {
|
||||
arrayBuffer = new Float32Array(arr);
|
||||
} else if (target == ol.webgl.ELEMENT_ARRAY_BUFFER) {
|
||||
arrayBuffer = this.hasOESElementIndexUint ?
|
||||
new Uint32Array(arr) : new Uint16Array(arr);
|
||||
}
|
||||
gl.bufferData(target, arrayBuffer, buf.getUsage());
|
||||
this.bufferCache_[bufferKey] = {
|
||||
buf: buf,
|
||||
buffer: buffer
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<string, ol.WebglBufferCacheEntry>}
|
||||
* @param {ol.webgl.Buffer} buf Buffer.
|
||||
*/
|
||||
this.bufferCache_ = {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<string, WebGLShader>}
|
||||
*/
|
||||
this.shaderCache_ = {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<string, WebGLProgram>}
|
||||
*/
|
||||
this.programCache_ = {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {WebGLProgram}
|
||||
*/
|
||||
this.currentProgram_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {WebGLFramebuffer}
|
||||
*/
|
||||
this.hitDetectionFramebuffer_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {WebGLTexture}
|
||||
*/
|
||||
this.hitDetectionTexture_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {WebGLRenderbuffer}
|
||||
*/
|
||||
this.hitDetectionRenderbuffer_ = null;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.hasOESElementIndexUint = ol.array.includes(
|
||||
ol.WEBGL_EXTENSIONS, 'OES_element_index_uint');
|
||||
|
||||
// use the OES_element_index_uint extension if available
|
||||
if (this.hasOESElementIndexUint) {
|
||||
gl.getExtension('OES_element_index_uint');
|
||||
}
|
||||
|
||||
ol.events.listen(this.canvas_, ol.webgl.ContextEventType.LOST,
|
||||
this.handleWebGLContextLost, this);
|
||||
ol.events.listen(this.canvas_, ol.webgl.ContextEventType.RESTORED,
|
||||
this.handleWebGLContextRestored, this);
|
||||
|
||||
};
|
||||
ol.inherits(ol.webgl.Context, ol.Disposable);
|
||||
|
||||
|
||||
/**
|
||||
* Just bind the buffer if it's in the cache. Otherwise create
|
||||
* the WebGL buffer, bind it, populate it, and add an entry to
|
||||
* the cache.
|
||||
* @param {number} target Target.
|
||||
* @param {ol.webgl.Buffer} buf Buffer.
|
||||
*/
|
||||
ol.webgl.Context.prototype.bindBuffer = function(target, buf) {
|
||||
var gl = this.getGL();
|
||||
var arr = buf.getArray();
|
||||
var bufferKey = String(ol.getUid(buf));
|
||||
if (bufferKey in this.bufferCache_) {
|
||||
ol.webgl.Context.prototype.deleteBuffer = function(buf) {
|
||||
var gl = this.getGL();
|
||||
var bufferKey = String(ol.getUid(buf));
|
||||
var bufferCacheEntry = this.bufferCache_[bufferKey];
|
||||
gl.bindBuffer(target, bufferCacheEntry.buffer);
|
||||
} else {
|
||||
var buffer = gl.createBuffer();
|
||||
gl.bindBuffer(target, buffer);
|
||||
var /** @type {ArrayBufferView} */ arrayBuffer;
|
||||
if (target == ol.webgl.ARRAY_BUFFER) {
|
||||
arrayBuffer = new Float32Array(arr);
|
||||
} else if (target == ol.webgl.ELEMENT_ARRAY_BUFFER) {
|
||||
arrayBuffer = this.hasOESElementIndexUint ?
|
||||
new Uint32Array(arr) : new Uint16Array(arr);
|
||||
if (!gl.isContextLost()) {
|
||||
gl.deleteBuffer(bufferCacheEntry.buffer);
|
||||
}
|
||||
gl.bufferData(target, arrayBuffer, buf.getUsage());
|
||||
this.bufferCache_[bufferKey] = {
|
||||
buf: buf,
|
||||
buffer: buffer
|
||||
};
|
||||
}
|
||||
};
|
||||
delete this.bufferCache_[bufferKey];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.webgl.Buffer} buf Buffer.
|
||||
*/
|
||||
ol.webgl.Context.prototype.deleteBuffer = function(buf) {
|
||||
var gl = this.getGL();
|
||||
var bufferKey = String(ol.getUid(buf));
|
||||
var bufferCacheEntry = this.bufferCache_[bufferKey];
|
||||
if (!gl.isContextLost()) {
|
||||
gl.deleteBuffer(bufferCacheEntry.buffer);
|
||||
}
|
||||
delete this.bufferCache_[bufferKey];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.webgl.Context.prototype.disposeInternal = function() {
|
||||
ol.events.unlistenAll(this.canvas_);
|
||||
var gl = this.getGL();
|
||||
if (!gl.isContextLost()) {
|
||||
var key;
|
||||
for (key in this.bufferCache_) {
|
||||
gl.deleteBuffer(this.bufferCache_[key].buffer);
|
||||
}
|
||||
for (key in this.programCache_) {
|
||||
gl.deleteProgram(this.programCache_[key]);
|
||||
}
|
||||
for (key in this.shaderCache_) {
|
||||
gl.deleteShader(this.shaderCache_[key]);
|
||||
}
|
||||
// delete objects for hit-detection
|
||||
gl.deleteFramebuffer(this.hitDetectionFramebuffer_);
|
||||
gl.deleteRenderbuffer(this.hitDetectionRenderbuffer_);
|
||||
gl.deleteTexture(this.hitDetectionTexture_);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {HTMLCanvasElement} Canvas.
|
||||
*/
|
||||
ol.webgl.Context.prototype.getCanvas = function() {
|
||||
return this.canvas_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the WebGL rendering context
|
||||
* @return {WebGLRenderingContext} The rendering context.
|
||||
* @api
|
||||
*/
|
||||
ol.webgl.Context.prototype.getGL = function() {
|
||||
return this.gl_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the frame buffer for hit detection.
|
||||
* @return {WebGLFramebuffer} The hit detection frame buffer.
|
||||
*/
|
||||
ol.webgl.Context.prototype.getHitDetectionFramebuffer = function() {
|
||||
if (!this.hitDetectionFramebuffer_) {
|
||||
this.initHitDetectionFramebuffer_();
|
||||
}
|
||||
return this.hitDetectionFramebuffer_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get shader from the cache if it's in the cache. Otherwise, create
|
||||
* the WebGL shader, compile it, and add entry to cache.
|
||||
* @param {ol.webgl.Shader} shaderObject Shader object.
|
||||
* @return {WebGLShader} Shader.
|
||||
*/
|
||||
ol.webgl.Context.prototype.getShader = function(shaderObject) {
|
||||
var shaderKey = String(ol.getUid(shaderObject));
|
||||
if (shaderKey in this.shaderCache_) {
|
||||
return this.shaderCache_[shaderKey];
|
||||
} else {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.webgl.Context.prototype.disposeInternal = function() {
|
||||
ol.events.unlistenAll(this.canvas_);
|
||||
var gl = this.getGL();
|
||||
var shader = gl.createShader(shaderObject.getType());
|
||||
gl.shaderSource(shader, shaderObject.getSource());
|
||||
gl.compileShader(shader);
|
||||
this.shaderCache_[shaderKey] = shader;
|
||||
return shader;
|
||||
}
|
||||
};
|
||||
if (!gl.isContextLost()) {
|
||||
var key;
|
||||
for (key in this.bufferCache_) {
|
||||
gl.deleteBuffer(this.bufferCache_[key].buffer);
|
||||
}
|
||||
for (key in this.programCache_) {
|
||||
gl.deleteProgram(this.programCache_[key]);
|
||||
}
|
||||
for (key in this.shaderCache_) {
|
||||
gl.deleteShader(this.shaderCache_[key]);
|
||||
}
|
||||
// delete objects for hit-detection
|
||||
gl.deleteFramebuffer(this.hitDetectionFramebuffer_);
|
||||
gl.deleteRenderbuffer(this.hitDetectionRenderbuffer_);
|
||||
gl.deleteTexture(this.hitDetectionTexture_);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the program from the cache if it's in the cache. Otherwise create
|
||||
* the WebGL program, attach the shaders to it, and add an entry to the
|
||||
* cache.
|
||||
* @param {ol.webgl.Fragment} fragmentShaderObject Fragment shader.
|
||||
* @param {ol.webgl.Vertex} vertexShaderObject Vertex shader.
|
||||
* @return {WebGLProgram} Program.
|
||||
*/
|
||||
ol.webgl.Context.prototype.getProgram = function(
|
||||
fragmentShaderObject, vertexShaderObject) {
|
||||
var programKey =
|
||||
ol.getUid(fragmentShaderObject) + '/' + ol.getUid(vertexShaderObject);
|
||||
if (programKey in this.programCache_) {
|
||||
return this.programCache_[programKey];
|
||||
} else {
|
||||
var gl = this.getGL();
|
||||
var program = gl.createProgram();
|
||||
gl.attachShader(program, this.getShader(fragmentShaderObject));
|
||||
gl.attachShader(program, this.getShader(vertexShaderObject));
|
||||
gl.linkProgram(program);
|
||||
this.programCache_[programKey] = program;
|
||||
return program;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @return {HTMLCanvasElement} Canvas.
|
||||
*/
|
||||
ol.webgl.Context.prototype.getCanvas = function() {
|
||||
return this.canvas_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* FIXME empy description for jsdoc
|
||||
*/
|
||||
ol.webgl.Context.prototype.handleWebGLContextLost = function() {
|
||||
ol.obj.clear(this.bufferCache_);
|
||||
ol.obj.clear(this.shaderCache_);
|
||||
ol.obj.clear(this.programCache_);
|
||||
this.currentProgram_ = null;
|
||||
this.hitDetectionFramebuffer_ = null;
|
||||
this.hitDetectionTexture_ = null;
|
||||
this.hitDetectionRenderbuffer_ = null;
|
||||
};
|
||||
/**
|
||||
* Get the WebGL rendering context
|
||||
* @return {WebGLRenderingContext} The rendering context.
|
||||
* @api
|
||||
*/
|
||||
ol.webgl.Context.prototype.getGL = function() {
|
||||
return this.gl_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* FIXME empy description for jsdoc
|
||||
*/
|
||||
ol.webgl.Context.prototype.handleWebGLContextRestored = function() {
|
||||
};
|
||||
/**
|
||||
* Get the frame buffer for hit detection.
|
||||
* @return {WebGLFramebuffer} The hit detection frame buffer.
|
||||
*/
|
||||
ol.webgl.Context.prototype.getHitDetectionFramebuffer = function() {
|
||||
if (!this.hitDetectionFramebuffer_) {
|
||||
this.initHitDetectionFramebuffer_();
|
||||
}
|
||||
return this.hitDetectionFramebuffer_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a 1x1 pixel framebuffer for the hit-detection.
|
||||
* @private
|
||||
*/
|
||||
ol.webgl.Context.prototype.initHitDetectionFramebuffer_ = function() {
|
||||
var gl = this.gl_;
|
||||
var framebuffer = gl.createFramebuffer();
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
|
||||
|
||||
var texture = ol.webgl.Context.createEmptyTexture(gl, 1, 1);
|
||||
var renderbuffer = gl.createRenderbuffer();
|
||||
gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
|
||||
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, 1, 1);
|
||||
gl.framebufferTexture2D(
|
||||
gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
|
||||
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT,
|
||||
gl.RENDERBUFFER, renderbuffer);
|
||||
|
||||
gl.bindTexture(gl.TEXTURE_2D, null);
|
||||
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
|
||||
this.hitDetectionFramebuffer_ = framebuffer;
|
||||
this.hitDetectionTexture_ = texture;
|
||||
this.hitDetectionRenderbuffer_ = renderbuffer;
|
||||
};
|
||||
/**
|
||||
* Get shader from the cache if it's in the cache. Otherwise, create
|
||||
* the WebGL shader, compile it, and add entry to cache.
|
||||
* @param {ol.webgl.Shader} shaderObject Shader object.
|
||||
* @return {WebGLShader} Shader.
|
||||
*/
|
||||
ol.webgl.Context.prototype.getShader = function(shaderObject) {
|
||||
var shaderKey = String(ol.getUid(shaderObject));
|
||||
if (shaderKey in this.shaderCache_) {
|
||||
return this.shaderCache_[shaderKey];
|
||||
} else {
|
||||
var gl = this.getGL();
|
||||
var shader = gl.createShader(shaderObject.getType());
|
||||
gl.shaderSource(shader, shaderObject.getSource());
|
||||
gl.compileShader(shader);
|
||||
this.shaderCache_[shaderKey] = shader;
|
||||
return shader;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Use a program. If the program is already in use, this will return `false`.
|
||||
* @param {WebGLProgram} program Program.
|
||||
* @return {boolean} Changed.
|
||||
* @api
|
||||
*/
|
||||
ol.webgl.Context.prototype.useProgram = function(program) {
|
||||
if (program == this.currentProgram_) {
|
||||
return false;
|
||||
} else {
|
||||
var gl = this.getGL();
|
||||
gl.useProgram(program);
|
||||
this.currentProgram_ = program;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Get the program from the cache if it's in the cache. Otherwise create
|
||||
* the WebGL program, attach the shaders to it, and add an entry to the
|
||||
* cache.
|
||||
* @param {ol.webgl.Fragment} fragmentShaderObject Fragment shader.
|
||||
* @param {ol.webgl.Vertex} vertexShaderObject Vertex shader.
|
||||
* @return {WebGLProgram} Program.
|
||||
*/
|
||||
ol.webgl.Context.prototype.getProgram = function(
|
||||
fragmentShaderObject, vertexShaderObject) {
|
||||
var programKey =
|
||||
ol.getUid(fragmentShaderObject) + '/' + ol.getUid(vertexShaderObject);
|
||||
if (programKey in this.programCache_) {
|
||||
return this.programCache_[programKey];
|
||||
} else {
|
||||
var gl = this.getGL();
|
||||
var program = gl.createProgram();
|
||||
gl.attachShader(program, this.getShader(fragmentShaderObject));
|
||||
gl.attachShader(program, this.getShader(vertexShaderObject));
|
||||
gl.linkProgram(program);
|
||||
this.programCache_[programKey] = program;
|
||||
return program;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {WebGLRenderingContext} gl WebGL rendering context.
|
||||
* @param {number=} opt_wrapS wrapS.
|
||||
* @param {number=} opt_wrapT wrapT.
|
||||
* @return {WebGLTexture} The texture.
|
||||
* @private
|
||||
*/
|
||||
ol.webgl.Context.createTexture_ = function(gl, opt_wrapS, opt_wrapT) {
|
||||
var texture = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
||||
|
||||
if (opt_wrapS !== undefined) {
|
||||
gl.texParameteri(
|
||||
ol.webgl.TEXTURE_2D, ol.webgl.TEXTURE_WRAP_S, opt_wrapS);
|
||||
}
|
||||
if (opt_wrapT !== undefined) {
|
||||
gl.texParameteri(
|
||||
ol.webgl.TEXTURE_2D, ol.webgl.TEXTURE_WRAP_T, opt_wrapT);
|
||||
}
|
||||
|
||||
return texture;
|
||||
};
|
||||
/**
|
||||
* FIXME empy description for jsdoc
|
||||
*/
|
||||
ol.webgl.Context.prototype.handleWebGLContextLost = function() {
|
||||
ol.obj.clear(this.bufferCache_);
|
||||
ol.obj.clear(this.shaderCache_);
|
||||
ol.obj.clear(this.programCache_);
|
||||
this.currentProgram_ = null;
|
||||
this.hitDetectionFramebuffer_ = null;
|
||||
this.hitDetectionTexture_ = null;
|
||||
this.hitDetectionRenderbuffer_ = null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {WebGLRenderingContext} gl WebGL rendering context.
|
||||
* @param {number} width Width.
|
||||
* @param {number} height Height.
|
||||
* @param {number=} opt_wrapS wrapS.
|
||||
* @param {number=} opt_wrapT wrapT.
|
||||
* @return {WebGLTexture} The texture.
|
||||
*/
|
||||
ol.webgl.Context.createEmptyTexture = function(
|
||||
gl, width, height, opt_wrapS, opt_wrapT) {
|
||||
var texture = ol.webgl.Context.createTexture_(gl, opt_wrapS, opt_wrapT);
|
||||
gl.texImage2D(
|
||||
gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE,
|
||||
null);
|
||||
|
||||
return texture;
|
||||
};
|
||||
/**
|
||||
* FIXME empy description for jsdoc
|
||||
*/
|
||||
ol.webgl.Context.prototype.handleWebGLContextRestored = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {WebGLRenderingContext} gl WebGL rendering context.
|
||||
* @param {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} image Image.
|
||||
* @param {number=} opt_wrapS wrapS.
|
||||
* @param {number=} opt_wrapT wrapT.
|
||||
* @return {WebGLTexture} The texture.
|
||||
*/
|
||||
ol.webgl.Context.createTexture = function(gl, image, opt_wrapS, opt_wrapT) {
|
||||
var texture = ol.webgl.Context.createTexture_(gl, opt_wrapS, opt_wrapT);
|
||||
gl.texImage2D(
|
||||
gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
|
||||
/**
|
||||
* Creates a 1x1 pixel framebuffer for the hit-detection.
|
||||
* @private
|
||||
*/
|
||||
ol.webgl.Context.prototype.initHitDetectionFramebuffer_ = function() {
|
||||
var gl = this.gl_;
|
||||
var framebuffer = gl.createFramebuffer();
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
|
||||
|
||||
return texture;
|
||||
};
|
||||
var texture = ol.webgl.Context.createEmptyTexture(gl, 1, 1);
|
||||
var renderbuffer = gl.createRenderbuffer();
|
||||
gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
|
||||
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, 1, 1);
|
||||
gl.framebufferTexture2D(
|
||||
gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
|
||||
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT,
|
||||
gl.RENDERBUFFER, renderbuffer);
|
||||
|
||||
gl.bindTexture(gl.TEXTURE_2D, null);
|
||||
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
|
||||
this.hitDetectionFramebuffer_ = framebuffer;
|
||||
this.hitDetectionTexture_ = texture;
|
||||
this.hitDetectionRenderbuffer_ = renderbuffer;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Use a program. If the program is already in use, this will return `false`.
|
||||
* @param {WebGLProgram} program Program.
|
||||
* @return {boolean} Changed.
|
||||
* @api
|
||||
*/
|
||||
ol.webgl.Context.prototype.useProgram = function(program) {
|
||||
if (program == this.currentProgram_) {
|
||||
return false;
|
||||
} else {
|
||||
var gl = this.getGL();
|
||||
gl.useProgram(program);
|
||||
this.currentProgram_ = program;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {WebGLRenderingContext} gl WebGL rendering context.
|
||||
* @param {number=} opt_wrapS wrapS.
|
||||
* @param {number=} opt_wrapT wrapT.
|
||||
* @return {WebGLTexture} The texture.
|
||||
* @private
|
||||
*/
|
||||
ol.webgl.Context.createTexture_ = function(gl, opt_wrapS, opt_wrapT) {
|
||||
var texture = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
||||
|
||||
if (opt_wrapS !== undefined) {
|
||||
gl.texParameteri(
|
||||
ol.webgl.TEXTURE_2D, ol.webgl.TEXTURE_WRAP_S, opt_wrapS);
|
||||
}
|
||||
if (opt_wrapT !== undefined) {
|
||||
gl.texParameteri(
|
||||
ol.webgl.TEXTURE_2D, ol.webgl.TEXTURE_WRAP_T, opt_wrapT);
|
||||
}
|
||||
|
||||
return texture;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {WebGLRenderingContext} gl WebGL rendering context.
|
||||
* @param {number} width Width.
|
||||
* @param {number} height Height.
|
||||
* @param {number=} opt_wrapS wrapS.
|
||||
* @param {number=} opt_wrapT wrapT.
|
||||
* @return {WebGLTexture} The texture.
|
||||
*/
|
||||
ol.webgl.Context.createEmptyTexture = function(
|
||||
gl, width, height, opt_wrapS, opt_wrapT) {
|
||||
var texture = ol.webgl.Context.createTexture_(gl, opt_wrapS, opt_wrapT);
|
||||
gl.texImage2D(
|
||||
gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE,
|
||||
null);
|
||||
|
||||
return texture;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {WebGLRenderingContext} gl WebGL rendering context.
|
||||
* @param {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} image Image.
|
||||
* @param {number=} opt_wrapS wrapS.
|
||||
* @param {number=} opt_wrapT wrapT.
|
||||
* @return {WebGLTexture} The texture.
|
||||
*/
|
||||
ol.webgl.Context.createTexture = function(gl, image, opt_wrapS, opt_wrapT) {
|
||||
var texture = ol.webgl.Context.createTexture_(gl, opt_wrapS, opt_wrapT);
|
||||
gl.texImage2D(
|
||||
gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
|
||||
|
||||
return texture;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -5,21 +5,25 @@ goog.require('ol.webgl');
|
||||
goog.require('ol.webgl.Shader');
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.webgl.Shader}
|
||||
* @param {string} source Source.
|
||||
* @struct
|
||||
*/
|
||||
ol.webgl.Fragment = function(source) {
|
||||
ol.webgl.Shader.call(this, source);
|
||||
};
|
||||
ol.inherits(ol.webgl.Fragment, ol.webgl.Shader);
|
||||
if (ol.ENABLE_WEBGL) {
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.webgl.Shader}
|
||||
* @param {string} source Source.
|
||||
* @struct
|
||||
*/
|
||||
ol.webgl.Fragment = function(source) {
|
||||
ol.webgl.Shader.call(this, source);
|
||||
};
|
||||
ol.inherits(ol.webgl.Fragment, ol.webgl.Shader);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.webgl.Fragment.prototype.getType = function() {
|
||||
return ol.webgl.FRAGMENT_SHADER;
|
||||
};
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.webgl.Fragment.prototype.getType = function() {
|
||||
return ol.webgl.FRAGMENT_SHADER;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -4,38 +4,42 @@ goog.require('ol.functions');
|
||||
goog.require('ol.webgl');
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {string} source Source.
|
||||
* @struct
|
||||
*/
|
||||
ol.webgl.Shader = function(source) {
|
||||
if (ol.ENABLE_WEBGL) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
* @constructor
|
||||
* @param {string} source Source.
|
||||
* @struct
|
||||
*/
|
||||
this.source_ = source;
|
||||
ol.webgl.Shader = function(source) {
|
||||
|
||||
};
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.source_ = source;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @return {number} Type.
|
||||
*/
|
||||
ol.webgl.Shader.prototype.getType = function() {};
|
||||
/**
|
||||
* @abstract
|
||||
* @return {number} Type.
|
||||
*/
|
||||
ol.webgl.Shader.prototype.getType = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @return {string} Source.
|
||||
*/
|
||||
ol.webgl.Shader.prototype.getSource = function() {
|
||||
return this.source_;
|
||||
};
|
||||
/**
|
||||
* @return {string} Source.
|
||||
*/
|
||||
ol.webgl.Shader.prototype.getSource = function() {
|
||||
return this.source_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Is animated?
|
||||
*/
|
||||
ol.webgl.Shader.prototype.isAnimated = ol.functions.FALSE;
|
||||
/**
|
||||
* @return {boolean} Is animated?
|
||||
*/
|
||||
ol.webgl.Shader.prototype.isAnimated = ol.functions.FALSE;
|
||||
|
||||
}
|
||||
|
||||
@@ -6,95 +6,99 @@ goog.require('ol.webgl.Fragment');
|
||||
goog.require('ol.webgl.Vertex');
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.webgl.Fragment}
|
||||
* @struct
|
||||
*/
|
||||
{{className}}.Fragment = function() {
|
||||
ol.webgl.Fragment.call(this, {{className}}.Fragment.SOURCE);
|
||||
};
|
||||
ol.inherits({{className}}.Fragment, ol.webgl.Fragment);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
{{className}}.Fragment.DEBUG_SOURCE = 'precision mediump float;\n{{{getOriginalFragmentSource}}}';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
{{className}}.Fragment.OPTIMIZED_SOURCE = 'precision mediump float;{{{getFragmentSource}}}';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
{{className}}.Fragment.SOURCE = {{className}}.Fragment.OPTIMIZED_SOURCE;
|
||||
|
||||
|
||||
{{className}}.fragment = new {{className}}.Fragment();
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.webgl.Vertex}
|
||||
* @struct
|
||||
*/
|
||||
{{className}}.Vertex = function() {
|
||||
ol.webgl.Vertex.call(this, {{className}}.Vertex.SOURCE);
|
||||
};
|
||||
ol.inherits({{className}}.Vertex, ol.webgl.Vertex);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
{{className}}.Vertex.DEBUG_SOURCE = '{{{getOriginalVertexSource}}}';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
{{className}}.Vertex.OPTIMIZED_SOURCE = '{{{getVertexSource}}}';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
{{className}}.Vertex.SOURCE = {{className}}.Vertex.OPTIMIZED_SOURCE;
|
||||
|
||||
|
||||
{{className}}.vertex = new {{className}}.Vertex();
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {WebGLRenderingContext} gl GL.
|
||||
* @param {WebGLProgram} program Program.
|
||||
* @struct
|
||||
*/
|
||||
{{namespace}}.Locations = function(gl, program) {
|
||||
{{#getUniforms}}
|
||||
if (ol.ENABLE_WEBGL) {
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
* @constructor
|
||||
* @extends {ol.webgl.Fragment}
|
||||
* @struct
|
||||
*/
|
||||
this.{{originalName}} = gl.getUniformLocation(program, '{{shortName}}');
|
||||
{{/getUniforms}}
|
||||
{{#getAttributes}}
|
||||
{{className}}.Fragment = function() {
|
||||
ol.webgl.Fragment.call(this, {{className}}.Fragment.SOURCE);
|
||||
};
|
||||
ol.inherits({{className}}.Fragment, ol.webgl.Fragment);
|
||||
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
this.{{originalName}} = gl.getAttribLocation(program, '{{shortName}}');
|
||||
{{/getAttributes}}
|
||||
};
|
||||
{{className}}.Fragment.DEBUG_SOURCE = 'precision mediump float;\n{{{getOriginalFragmentSource}}}';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
{{className}}.Fragment.OPTIMIZED_SOURCE = 'precision mediump float;{{{getFragmentSource}}}';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
{{className}}.Fragment.SOURCE = {{className}}.Fragment.OPTIMIZED_SOURCE;
|
||||
|
||||
|
||||
{{className}}.fragment = new {{className}}.Fragment();
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.webgl.Vertex}
|
||||
* @struct
|
||||
*/
|
||||
{{className}}.Vertex = function() {
|
||||
ol.webgl.Vertex.call(this, {{className}}.Vertex.SOURCE);
|
||||
};
|
||||
ol.inherits({{className}}.Vertex, ol.webgl.Vertex);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
{{className}}.Vertex.DEBUG_SOURCE = '{{{getOriginalVertexSource}}}';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
{{className}}.Vertex.OPTIMIZED_SOURCE = '{{{getVertexSource}}}';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
{{className}}.Vertex.SOURCE = {{className}}.Vertex.OPTIMIZED_SOURCE;
|
||||
|
||||
|
||||
{{className}}.vertex = new {{className}}.Vertex();
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {WebGLRenderingContext} gl GL.
|
||||
* @param {WebGLProgram} program Program.
|
||||
* @struct
|
||||
*/
|
||||
{{namespace}}.Locations = function(gl, program) {
|
||||
{{#getUniforms}}
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.{{originalName}} = gl.getUniformLocation(program, '{{shortName}}');
|
||||
{{/getUniforms}}
|
||||
{{#getAttributes}}
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.{{originalName}} = gl.getAttribLocation(program, '{{shortName}}');
|
||||
{{/getAttributes}}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -5,21 +5,25 @@ goog.require('ol.webgl');
|
||||
goog.require('ol.webgl.Shader');
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.webgl.Shader}
|
||||
* @param {string} source Source.
|
||||
* @struct
|
||||
*/
|
||||
ol.webgl.Vertex = function(source) {
|
||||
ol.webgl.Shader.call(this, source);
|
||||
};
|
||||
ol.inherits(ol.webgl.Vertex, ol.webgl.Shader);
|
||||
if (ol.ENABLE_WEBGL) {
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.webgl.Shader}
|
||||
* @param {string} source Source.
|
||||
* @struct
|
||||
*/
|
||||
ol.webgl.Vertex = function(source) {
|
||||
ol.webgl.Shader.call(this, source);
|
||||
};
|
||||
ol.inherits(ol.webgl.Vertex, ol.webgl.Shader);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.webgl.Vertex.prototype.getType = function() {
|
||||
return ol.webgl.VERTEX_SHADER;
|
||||
};
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.webgl.Vertex.prototype.getType = function() {
|
||||
return ol.webgl.VERTEX_SHADER;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user