Properly triangulate linestrings
This commit is contained in:
@@ -104,6 +104,20 @@ ol.render.webgl.ImageReplay = function(tolerance, maxExtent) {
|
||||
*/
|
||||
this.indicesBuffer_ = null;
|
||||
|
||||
/**
|
||||
* Start index per feature (the index).
|
||||
* @type {Array.<number>}
|
||||
* @private
|
||||
*/
|
||||
this.startIndices_ = [];
|
||||
|
||||
/**
|
||||
* Start index per feature (the feature).
|
||||
* @type {Array.<ol.Feature|ol.render.Feature>}
|
||||
* @private
|
||||
*/
|
||||
this.startIndicesFeature_ = [];
|
||||
|
||||
/**
|
||||
* @type {Array.<number>}
|
||||
* @private
|
||||
@@ -119,6 +133,23 @@ ol.render.webgl.ImageReplay = function(tolerance, maxExtent) {
|
||||
};
|
||||
goog.inherits(ol.render.webgl.Replay, ol.render.VectorContext);
|
||||
|
||||
|
||||
/**
|
||||
* @enum {number}
|
||||
*/
|
||||
ol.render.webgl.LineStringInstruction = {
|
||||
BEGIN_LINE: 0,
|
||||
END_LINE: 1,
|
||||
SQUARE_CAP: 2,
|
||||
BEVEL_FIRST: 3,
|
||||
BEVEL_SECOND: 4,
|
||||
MITER_BOTTOM: 5,
|
||||
MITER_TOP: 6,
|
||||
ROUND_JOIN: 7,
|
||||
ROUND_CAP: 8,
|
||||
ROUND_BOTH: 9
|
||||
};
|
||||
|
||||
ol.render.webgl.Replay.prototype.getDeleteResourcesFunction = goog.abstractMethod;
|
||||
|
||||
ol.render.webgl.Replay.prototype.finish = goog.abstractMethod;
|
||||
@@ -162,7 +193,7 @@ ol.render.webgl.Replay.prototype.replay = function(context,
|
||||
'indicesBuffer must not be null');
|
||||
context.bindBuffer(goog.webgl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer_);
|
||||
|
||||
var locations = this.setUpProgram_(gl, context);
|
||||
var locations = this.setUpProgram_(gl, context, size);
|
||||
|
||||
// set the "uniform" values
|
||||
var projectionMatrix = ol.transform.reset(this.projectionMatrix_);
|
||||
@@ -207,6 +238,21 @@ ol.render.webgl.Replay.prototype.replay = function(context,
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {WebGLRenderingContext} gl gl.
|
||||
* @param {number} start Start index.
|
||||
* @param {number} end End index.
|
||||
* @param {number} elementType Element type.
|
||||
* @param {number} elementSize Element Size.
|
||||
*/
|
||||
ol.render.webgl.Replay.prototype.drawElements_ = function(
|
||||
gl, start, end, elementType, elementSize) {
|
||||
var numItems = end - start;
|
||||
var offsetInBytes = start * elementSize;
|
||||
gl.drawElements(goog.webgl.TRIANGLES, numItems, elementType, offsetInBytes);
|
||||
};
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.render.webgl.Replay}
|
||||
@@ -326,20 +372,6 @@ ol.render.webgl.ImageReplay = function(tolerance, maxExtent) {
|
||||
*/
|
||||
this.hitDetectionTextures_ = [];
|
||||
|
||||
/**
|
||||
* Start index per feature (the index).
|
||||
* @type {Array.<number>}
|
||||
* @private
|
||||
*/
|
||||
this.startIndices_ = [];
|
||||
|
||||
/**
|
||||
* Start index per feature (the feature).
|
||||
* @type {Array.<ol.Feature|ol.render.Feature>}
|
||||
* @private
|
||||
*/
|
||||
this.startIndicesFeature_ = [];
|
||||
|
||||
/**
|
||||
* @type {number|undefined}
|
||||
* @private
|
||||
@@ -620,9 +652,10 @@ ol.render.webgl.ImageReplay.prototype.createTextures_ = function(textures, image
|
||||
* @private
|
||||
* @param {WebGLRenderingContext} gl gl.
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @param {ol.Size} size Size.
|
||||
* @return {ol.render.webgl.imagereplay.shader.Default.Locations} Locations.
|
||||
*/
|
||||
ol.render.webgl.ImageReplay.prototype.setUpProgram_ = function(gl, context) {
|
||||
ol.render.webgl.ImageReplay.prototype.setUpProgram_ = function(gl, context, size) {
|
||||
// get the program
|
||||
var fragmentShader = ol.render.webgl.imagereplay.defaultshader.fragment;
|
||||
var vertexShader = ol.render.webgl.imagereplay.defaultshader.vertex;
|
||||
@@ -768,22 +801,6 @@ ol.render.webgl.ImageReplay.prototype.drawReplaySkipping_ = function(gl, skipped
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {WebGLRenderingContext} gl gl.
|
||||
* @param {number} start Start index.
|
||||
* @param {number} end End index.
|
||||
* @param {number} elementType Element type.
|
||||
* @param {number} elementSize Element Size.
|
||||
*/
|
||||
ol.render.webgl.ImageReplay.prototype.drawElements_ = function(
|
||||
gl, start, end, elementType, elementSize) {
|
||||
var numItems = end - start;
|
||||
var offsetInBytes = start * elementSize;
|
||||
gl.drawElements(ol.webgl.TRIANGLES, numItems, elementType, offsetInBytes);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {WebGLRenderingContext} gl gl.
|
||||
@@ -1020,29 +1037,182 @@ goog.inherits(ol.render.webgl.LineStringReplay, ol.render.webgl.Replay);
|
||||
* @private
|
||||
*/
|
||||
ol.render.webgl.LineStringReplay.prototype.drawCoordinates_ = function(flatCoordinates, offset, end, stride) {
|
||||
|
||||
var i, ii;
|
||||
var numVertices = this.vertices_.length;
|
||||
var numIndices = this.indices_.length;
|
||||
var n = this.indices_.length > 0 ? this.indices_[numIndices - 1] + 1 : 0;
|
||||
var lineJoin = this.state_.lineJoin;
|
||||
var verticesPerPoint = lineJoin === 'bevel' ? 3 : 4;
|
||||
//var lineCap = this.state_.lineCap;
|
||||
var closed = this.isClosed_(flatCoordinates, offset, end, stride);
|
||||
var lastIndex;
|
||||
var lastSign = 1;
|
||||
//We need the adjacent vertices to define normals in joins. p0 = last, p1 = current, p2 = next.
|
||||
//We rotate those points, thus every point is RTE corrected only once.
|
||||
var p0, p1, p2, tempP;
|
||||
|
||||
// Shift the indices to take into account previously handled lines
|
||||
for (i = offset, ii = end - stride; i < ii; i += stride) {
|
||||
for (i = offset, ii = end; i < ii; i += stride) {
|
||||
|
||||
if (i == offset) {
|
||||
this.vertices_[numVertices++] = flatCoordinates[i] - this.origin_[0];
|
||||
this.vertices_[numVertices++] = flatCoordinates[i + 1] - this.origin_[1];
|
||||
var n = numVertices / 8;
|
||||
|
||||
i += stride;
|
||||
tempP = tempP || p1;
|
||||
p1 = p2 || [flatCoordinates[i] - this.origin_[0], flatCoordinates[i + 1] - this.origin_[1]];
|
||||
//First vertex.
|
||||
if (i === offset) {
|
||||
p2 = [flatCoordinates[i + stride] - this.origin_[0], flatCoordinates[i + stride + 1] - this.origin_[1]];
|
||||
if (closed) {
|
||||
//A closed line! Complete the circle.
|
||||
tempP = [flatCoordinates[end - stride] - this.origin_[0], flatCoordinates[end - stride + 1] - this.origin_[1]];
|
||||
} else {
|
||||
//Add the first two vertices.
|
||||
p0 = undefined;
|
||||
this.vertices_[numVertices++] = 0;
|
||||
this.vertices_[numVertices++] = 0;
|
||||
this.vertices_[numVertices++] = p1[0];
|
||||
this.vertices_[numVertices++] = p1[1];
|
||||
this.vertices_[numVertices++] = p2[0];
|
||||
this.vertices_[numVertices++] = p2[1];
|
||||
this.vertices_[numVertices++] = 1;
|
||||
this.vertices_[numVertices++] = ol.render.webgl.LineStringInstruction.BEGIN_LINE;
|
||||
|
||||
this.vertices_[numVertices++] = 0;
|
||||
this.vertices_[numVertices++] = 0;
|
||||
this.vertices_[numVertices++] = p1[0];
|
||||
this.vertices_[numVertices++] = p1[1];
|
||||
this.vertices_[numVertices++] = p2[0];
|
||||
this.vertices_[numVertices++] = p2[1];
|
||||
this.vertices_[numVertices++] = -1;
|
||||
this.vertices_[numVertices++] = ol.render.webgl.LineStringInstruction.BEGIN_LINE;
|
||||
|
||||
lastIndex = n + 1;
|
||||
|
||||
continue;
|
||||
}
|
||||
} else if (i === end - stride) {
|
||||
//Last vertex.
|
||||
if (closed) {
|
||||
p2 = [flatCoordinates[offset] - this.origin_[0], flatCoordinates[offset + 1] - this.origin_[1]];
|
||||
} else {
|
||||
p2 = undefined;
|
||||
p0 = tempP || p0;
|
||||
|
||||
this.vertices_[numVertices++] = p0[0];
|
||||
this.vertices_[numVertices++] = p0[1];
|
||||
this.vertices_[numVertices++] = p1[0];
|
||||
this.vertices_[numVertices++] = p1[1];
|
||||
this.vertices_[numVertices++] = 0;
|
||||
this.vertices_[numVertices++] = 0;
|
||||
this.vertices_[numVertices++] = lastSign;
|
||||
this.vertices_[numVertices++] = ol.render.webgl.LineStringInstruction.END_LINE;
|
||||
|
||||
this.vertices_[numVertices++] = p0[0];
|
||||
this.vertices_[numVertices++] = p0[1];
|
||||
this.vertices_[numVertices++] = p1[0];
|
||||
this.vertices_[numVertices++] = p1[1];
|
||||
this.vertices_[numVertices++] = 0;
|
||||
this.vertices_[numVertices++] = 0;
|
||||
this.vertices_[numVertices++] = -lastSign;
|
||||
this.vertices_[numVertices++] = ol.render.webgl.LineStringInstruction.END_LINE;
|
||||
|
||||
this.indices_[numIndices++] = n;
|
||||
this.indices_[numIndices++] = lastIndex - 1;
|
||||
this.indices_[numIndices++] = lastIndex;
|
||||
|
||||
this.indices_[numIndices++] = lastIndex;
|
||||
this.indices_[numIndices++] = n + 1;
|
||||
this.indices_[numIndices++] = n;
|
||||
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
p2 = [flatCoordinates[i + stride] - this.origin_[0], flatCoordinates[i + stride + 1] - this.origin_[1]];
|
||||
}
|
||||
//Sort out duplicate points.
|
||||
if (ol.array.equals(p1, p2)) continue;
|
||||
p0 = tempP || p0;
|
||||
tempP = undefined;
|
||||
//The sign of the area determines the line segment's orientation.
|
||||
var sign = ol.geom.flat.orient.linearRingIsClockwise([p0[0], p0[1], p1[0], p1[1], p2[0], p2[1]], 0, 6, 2)
|
||||
? 1 : -1;
|
||||
|
||||
this.vertices_[numVertices++] = flatCoordinates[i] - this.origin_[0];
|
||||
this.vertices_[numVertices++] = flatCoordinates[i + 1] - this.origin_[1];
|
||||
this.vertices_[numVertices++] = p0[0];
|
||||
this.vertices_[numVertices++] = p0[1];
|
||||
this.vertices_[numVertices++] = p1[0];
|
||||
this.vertices_[numVertices++] = p1[1];
|
||||
this.vertices_[numVertices++] = p2[0];
|
||||
this.vertices_[numVertices++] = p2[1];
|
||||
this.vertices_[numVertices++] = sign;
|
||||
this.vertices_[numVertices++] = ol.render.webgl.LineStringInstruction.BEVEL_FIRST;
|
||||
|
||||
this.vertices_[numVertices++] = p0[0];
|
||||
this.vertices_[numVertices++] = p0[1];
|
||||
this.vertices_[numVertices++] = p1[0];
|
||||
this.vertices_[numVertices++] = p1[1];
|
||||
this.vertices_[numVertices++] = p2[0];
|
||||
this.vertices_[numVertices++] = p2[1];
|
||||
this.vertices_[numVertices++] = sign;
|
||||
this.vertices_[numVertices++] = ol.render.webgl.LineStringInstruction.BEVEL_SECOND;
|
||||
|
||||
this.vertices_[numVertices++] = p0[0];
|
||||
this.vertices_[numVertices++] = p0[1];
|
||||
this.vertices_[numVertices++] = p1[0];
|
||||
this.vertices_[numVertices++] = p1[1];
|
||||
this.vertices_[numVertices++] = p2[0];
|
||||
this.vertices_[numVertices++] = p2[1];
|
||||
this.vertices_[numVertices++] = -sign;
|
||||
this.vertices_[numVertices++] = ol.render.webgl.LineStringInstruction.MITER_BOTTOM;
|
||||
|
||||
this.indices_[numIndices++] = n++;
|
||||
this.indices_[numIndices++] = n;
|
||||
this.indices_[numIndices++] = lastIndex - 1;
|
||||
this.indices_[numIndices++] = lastIndex;
|
||||
|
||||
this.indices_[numIndices++] = n + 2;
|
||||
this.indices_[numIndices++] = n;
|
||||
this.indices_[numIndices++] = lastSign * sign > 0 ? lastIndex : lastIndex - 1;
|
||||
|
||||
this.indices_[numIndices++] = n;
|
||||
this.indices_[numIndices++] = n + 2;
|
||||
this.indices_[numIndices++] = n + 1;
|
||||
|
||||
lastIndex = n + 2;
|
||||
lastSign = sign;
|
||||
|
||||
//Add miter
|
||||
if (verticesPerPoint === 4) {
|
||||
this.vertices_[numVertices++] = p0[0];
|
||||
this.vertices_[numVertices++] = p0[1];
|
||||
this.vertices_[numVertices++] = p1[0];
|
||||
this.vertices_[numVertices++] = p1[1];
|
||||
this.vertices_[numVertices++] = p2[0];
|
||||
this.vertices_[numVertices++] = p2[1];
|
||||
this.vertices_[numVertices++] = sign;
|
||||
this.vertices_[numVertices++] = ol.render.webgl.LineStringInstruction.MITER_TOP;
|
||||
|
||||
this.indices_[numIndices++] = n + 1;
|
||||
this.indices_[numIndices++] = n + 3;
|
||||
this.indices_[numIndices++] = n;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if the linestring is a boundary.
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
* @return {boolean} The linestring is a boundary.
|
||||
* @private
|
||||
*/
|
||||
ol.render.webgl.LineStringReplay.prototype.isClosed_ = function(flatCoordinates, offset, end, stride) {
|
||||
var lastCoord = end - stride;
|
||||
if (flatCoordinates[offset] === flatCoordinates[lastCoord] &&
|
||||
flatCoordinates[offset + 1] === flatCoordinates[lastCoord + 1]) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
@@ -1050,8 +1220,12 @@ ol.render.webgl.LineStringReplay.prototype.drawCoordinates_ = function(flatCoord
|
||||
ol.render.webgl.LineStringReplay.prototype.drawLineString = function(lineStringGeometry, feature) {
|
||||
var flatCoordinates = lineStringGeometry.getFlatCoordinates();
|
||||
var stride = lineStringGeometry.getStride();
|
||||
this.drawCoordinates_(
|
||||
flatCoordinates, 0, flatCoordinates.length, stride);
|
||||
if (flatCoordinates.length > stride) {
|
||||
this.startIndices_.push(this.indices_.length);
|
||||
this.startIndicesFeature_.push(feature);
|
||||
this.drawCoordinates_(
|
||||
flatCoordinates, 0, flatCoordinates.length, stride);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1059,13 +1233,12 @@ ol.render.webgl.LineStringReplay.prototype.drawLineString = function(lineStringG
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.webgl.LineStringReplay.prototype.drawMultiLineString = function(multiLineStringGeometry, feature) {
|
||||
this.startIndices_.push(this.indices_.length);
|
||||
this.startIndicesFeature_.push(feature);
|
||||
var lineStringGeometries = multiLineStringGeometry.getLineStrings();
|
||||
var i, ii;
|
||||
for (i = 0, ii = lineStringGeometries.length; i < ii; ++i) {
|
||||
var flatCoordinates = lineStringGeometries[i].getFlatCoordinates();
|
||||
var stride = lineStringGeometries[i].getStride();
|
||||
this.drawCoordinates_(
|
||||
flatCoordinates, 0, flatCoordinates.length, stride);
|
||||
this.drawLineString(lineStringGeometries[i], feature);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1074,6 +1247,8 @@ ol.render.webgl.LineStringReplay.prototype.drawMultiLineString = function(multiL
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
**/
|
||||
ol.render.webgl.LineStringReplay.prototype.finish = function(context) {
|
||||
this.startIndices_.push(this.indices_.length);
|
||||
|
||||
// create, bind, and populate the vertices buffer
|
||||
this.verticesBuffer_ = new ol.webgl.Buffer(this.vertices_);
|
||||
context.bindBuffer(goog.webgl.ARRAY_BUFFER, this.verticesBuffer_);
|
||||
@@ -1081,6 +1256,9 @@ ol.render.webgl.LineStringReplay.prototype.finish = function(context) {
|
||||
// create, bind, and populate the indices buffer
|
||||
this.indicesBuffer_ = new ol.webgl.Buffer(this.indices_);
|
||||
context.bindBuffer(goog.webgl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer_);
|
||||
|
||||
this.vertices_ = null;
|
||||
this.indices_ = null;
|
||||
};
|
||||
|
||||
|
||||
@@ -1108,9 +1286,10 @@ ol.render.webgl.LineStringReplay.prototype.getDeleteResourcesFunction = function
|
||||
* @private
|
||||
* @param {WebGLRenderingContext} gl gl.
|
||||
* @param {ol.webgl.Context} context Context.
|
||||
* @param {ol.Size} size Size.
|
||||
* @return {ol.render.webgl.linestringreplay.shader.Default.Locations} Locations.
|
||||
*/
|
||||
ol.render.webgl.LineStringReplay.prototype.setUpProgram_ = function(gl, context) {
|
||||
ol.render.webgl.LineStringReplay.prototype.setUpProgram_ = function(gl, context, size) {
|
||||
// get the program
|
||||
var fragmentShader, vertexShader;
|
||||
fragmentShader =
|
||||
@@ -1132,12 +1311,37 @@ ol.render.webgl.LineStringReplay.prototype.setUpProgram_ = function(gl, context)
|
||||
context.useProgram(program);
|
||||
|
||||
// enable the vertex attrib arrays
|
||||
gl.enableVertexAttribArray(locations.a_lastPos);
|
||||
gl.vertexAttribPointer(locations.a_lastPos, 2, goog.webgl.FLOAT,
|
||||
false, 32, 0);
|
||||
|
||||
gl.enableVertexAttribArray(locations.a_position);
|
||||
gl.vertexAttribPointer(locations.a_position, 2, goog.webgl.FLOAT,
|
||||
false, 8, 0);
|
||||
false, 32, 8);
|
||||
|
||||
gl.enableVertexAttribArray(locations.a_nextPos);
|
||||
gl.vertexAttribPointer(locations.a_nextPos, 2, goog.webgl.FLOAT,
|
||||
false, 32, 16);
|
||||
|
||||
gl.enableVertexAttribArray(locations.a_direction);
|
||||
gl.vertexAttribPointer(locations.a_direction, 1, goog.webgl.FLOAT,
|
||||
false, 32, 24);
|
||||
|
||||
gl.enableVertexAttribArray(locations.a_instruction);
|
||||
gl.vertexAttribPointer(locations.a_instruction, 1, goog.webgl.FLOAT,
|
||||
false, 32, 28);
|
||||
|
||||
var round = this.state_.lineJoin === 'round' && this.state_.lineCap === 'round' ?
|
||||
ol.render.webgl.LineStringInstruction.ROUND_BOTH : this.state_.lineJoin === 'round' ?
|
||||
ol.render.webgl.LineStringInstruction.ROUND_JOIN : this.state_.lineCap === 'round' ?
|
||||
ol.render.webgl.LineStringInstruction.ROUND_CAP : 0;
|
||||
|
||||
// enable renderer specific uniforms
|
||||
gl.uniform4fv(locations.u_color, this.state_.strokeColor);
|
||||
gl.uniform1f(locations.u_lineWidth, this.state_.lineWidth);
|
||||
gl.uniform1f(locations.u_miterLimit, this.state_.miterLimit);
|
||||
gl.uniform2fv(locations.u_size, size);
|
||||
gl.uniform1f(locations.u_round, round);
|
||||
|
||||
return locations;
|
||||
};
|
||||
@@ -1150,16 +1354,19 @@ ol.render.webgl.LineStringReplay.prototype.setUpProgram_ = function(gl, context)
|
||||
* @param {Object} skippedFeaturesHash Ids of features to skip.
|
||||
*/
|
||||
ol.render.webgl.LineStringReplay.prototype.drawReplay_ = function(gl, context, skippedFeaturesHash) {
|
||||
var elementType = context.hasOESElementIndexUint ?
|
||||
goog.webgl.UNSIGNED_INT : goog.webgl.UNSIGNED_SHORT;
|
||||
var elementSize = context.hasOESElementIndexUint ? 4 : 2;
|
||||
|
||||
if (!goog.object.isEmpty(skippedFeaturesHash)) {
|
||||
// TODO: draw by blocks to skip features
|
||||
} else {
|
||||
var numItems = this.indices_.length;
|
||||
// FIXME: not compatible with batching, hardcoding some arbitrary value
|
||||
if (this.state_.lineWidth) {
|
||||
gl.lineWidth(this.state_.lineWidth);
|
||||
var i, ii;
|
||||
for (i = 0, ii = this.startIndices_.length - 1; i < ii; ++i) {
|
||||
var start = this.startIndices_[i];
|
||||
var end = this.startIndices_[i + 1];
|
||||
this.drawElements_(gl, start, end, elementType, elementSize);
|
||||
}
|
||||
gl.drawElements(goog.webgl.LINES, numItems, goog.webgl.UNSIGNED_SHORT, 0);
|
||||
gl.lineWidth(1);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1203,9 +1410,21 @@ ol.render.webgl.LineStringReplay.prototype.setFillStrokeStyle = function(fillSty
|
||||
ol.color.asArray(strokeStyleColor).map(function(c, i) {
|
||||
return i != 3 ? c / 255 : c;
|
||||
}) : ol.render.webgl.defaultStrokeStyle;
|
||||
var strokeStyleLineCap = strokeStyle.getLineCap();
|
||||
this.state_.lineCap = strokeStyleLineCap !== undefined ?
|
||||
strokeStyleLineCap : ol.render.webgl.defaultLineCap;
|
||||
var strokeStyleLineDash = strokeStyle.getLineDash();
|
||||
this.state_.lineDash = strokeStyleLineDash ?
|
||||
strokeStyleLineDash : ol.render.webgl.defaultLineDash;
|
||||
var strokeStyleLineJoin = strokeStyle.getLineJoin();
|
||||
this.state_.lineJoin = strokeStyleLineJoin !== undefined ?
|
||||
strokeStyleLineJoin : ol.render.webgl.defaultLineJoin;
|
||||
var strokeStyleWidth = strokeStyle.getWidth();
|
||||
this.state_.lineWidth = strokeStyleWidth !== undefined ?
|
||||
strokeStyleWidth : ol.render.webgl.defaultLineWidth;
|
||||
var strokeStyleMiterLimit = strokeStyle.getMiterLimit();
|
||||
this.state_.miterLimit = strokeStyleMiterLimit !== undefined ?
|
||||
strokeStyleMiterLimit : ol.render.webgl.defaultMiterLimit;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -3,19 +3,83 @@
|
||||
|
||||
|
||||
//! COMMON
|
||||
varying float v_round;
|
||||
varying vec4 v_roundVertex;
|
||||
varying float v_halfWidth;
|
||||
|
||||
|
||||
//! VERTEX
|
||||
attribute vec2 a_lastPos;
|
||||
attribute vec2 a_position;
|
||||
attribute vec2 a_nextPos;
|
||||
attribute float a_direction;
|
||||
attribute float a_instruction;
|
||||
|
||||
uniform mat4 u_projectionMatrix;
|
||||
uniform mat4 u_offsetScaleMatrix;
|
||||
uniform mat4 u_offsetRotateMatrix;
|
||||
uniform float u_lineWidth;
|
||||
uniform float u_miterLimit;
|
||||
uniform float u_round;
|
||||
|
||||
void main(void) {
|
||||
mat4 offsetMatrix = u_offsetScaleMatrix;
|
||||
vec4 offsets = offsetMatrix * vec4(0., 0., 0., 0.);
|
||||
gl_Position = u_projectionMatrix * vec4(a_position, 0., 1.) + offsets;
|
||||
v_halfWidth = u_lineWidth / 2.0;
|
||||
vec2 offset;
|
||||
v_round = 0.0;
|
||||
vec4 projPos = u_projectionMatrix * vec4(a_position, 0., 1.);
|
||||
if (a_instruction == 0. || a_instruction == 4.) {
|
||||
vec2 dirVect = a_nextPos - a_position;
|
||||
vec2 normal = normalize(vec2(-dirVect.y, dirVect.x));
|
||||
offset = v_halfWidth * normal * a_direction;
|
||||
if (a_instruction == 4. && (u_round == 7. || u_round == 9.)) {
|
||||
v_roundVertex = projPos + u_offsetScaleMatrix * vec4(0., 0., 0., 0.);
|
||||
}
|
||||
} else if (a_instruction == 1. || a_instruction == 3.) {
|
||||
vec2 dirVect = a_lastPos - a_position;
|
||||
vec2 normal = normalize(vec2(dirVect.y, -dirVect.x));
|
||||
offset = v_halfWidth * normal * a_direction;
|
||||
if (a_instruction == 3. && (u_round == 7. || u_round == 9.)) {
|
||||
v_roundVertex = projPos + u_offsetScaleMatrix * vec4(0., 0., 0., 0.);
|
||||
}
|
||||
} else if (a_instruction == 5. || a_instruction == 6.) {
|
||||
vec2 dirVect = a_nextPos - a_position;
|
||||
vec2 tmpNormal = normalize(vec2(-dirVect.y, dirVect.x));
|
||||
vec2 tangent = normalize(normalize(a_nextPos - a_position) + normalize(a_position - a_lastPos));
|
||||
vec2 normal = vec2(tangent.y, -tangent.x);
|
||||
float miterLength = v_halfWidth / dot(normal, tmpNormal);
|
||||
if (a_instruction == 6.) {
|
||||
if (u_round == 7. || u_round == 9.) {
|
||||
offset = normal * a_direction * miterLength;
|
||||
v_round = 1.0;
|
||||
v_roundVertex = projPos + u_offsetScaleMatrix * vec4(0., 0., 0., 0.);
|
||||
} else if (miterLength > u_miterLimit) {
|
||||
offset = tmpNormal * a_direction * v_halfWidth;
|
||||
} else {
|
||||
offset = normal * a_direction * miterLength;
|
||||
}
|
||||
} else if (a_instruction == 5.) {
|
||||
offset = normal * a_direction * miterLength;
|
||||
vec4 defaultOffset = u_offsetScaleMatrix * vec4(0., 0., 0., 0.);
|
||||
vec4 firstProjPos = u_projectionMatrix * vec4(a_lastPos, 0., 1.) + defaultOffset;
|
||||
vec4 secondProjPos = projPos + defaultOffset;
|
||||
vec4 thirdProjPos = u_projectionMatrix * vec4(a_nextPos, 0., 1.) + defaultOffset;
|
||||
float firstSegLength = distance(secondProjPos.xy, firstProjPos.xy);
|
||||
float secondSegLength = distance(thirdProjPos.xy, secondProjPos.xy);
|
||||
float miterSegLength = distance(secondProjPos.xy, vec4(projPos + u_offsetScaleMatrix * vec4(offset, 0., 0.)).xy);
|
||||
//TODO: Write a more accurate method for identifying sharp angles.
|
||||
if (miterSegLength > min(firstSegLength, secondSegLength)) {
|
||||
if (firstSegLength < secondSegLength) {
|
||||
dirVect = a_lastPos - a_position;
|
||||
tmpNormal = normalize(vec2(dirVect.y, -dirVect.x));
|
||||
projPos = firstProjPos - defaultOffset;
|
||||
} else {
|
||||
projPos = thirdProjPos - defaultOffset;
|
||||
}
|
||||
offset = tmpNormal * a_direction * v_halfWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
vec4 offsets = u_offsetScaleMatrix * vec4(offset, 0., 0.);
|
||||
gl_Position = projPos + offsets;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,8 +87,15 @@ void main(void) {
|
||||
|
||||
uniform float u_opacity;
|
||||
uniform vec4 u_color;
|
||||
uniform vec2 u_size;
|
||||
|
||||
void main(void) {
|
||||
if (v_round > 0.0) {
|
||||
vec2 windowCoords = vec2((v_roundVertex.x + 1.0) / 2.0 * u_size.x, (v_roundVertex.y + 1.0) / 2.0 * u_size.y);
|
||||
if (length(windowCoords - gl_FragCoord.xy) > v_halfWidth) {
|
||||
discard;
|
||||
}
|
||||
}
|
||||
gl_FragColor = u_color;
|
||||
float alpha = u_color.a * u_opacity;
|
||||
if (alpha == 0.0) {
|
||||
|
||||
@@ -23,14 +23,14 @@ goog.addSingletonGetter(ol.render.webgl.linestringreplay.shader.DefaultFragment)
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.render.webgl.linestringreplay.shader.DefaultFragment.DEBUG_SOURCE = 'precision mediump float;\n\n\n\nuniform float u_opacity;\nuniform vec4 u_color;\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';
|
||||
ol.render.webgl.linestringreplay.shader.DefaultFragment.DEBUG_SOURCE = 'precision mediump float;\nvarying float v_round;\nvarying vec4 v_roundVertex;\nvarying float v_halfWidth;\n\n\n\nuniform float u_opacity;\nuniform vec4 u_color;\nuniform vec2 u_size;\n\nvoid main(void) {\n if (v_round > 0.0) {\n vec2 windowCoords = vec2((v_roundVertex.x + 1.0) / 2.0 * u_size.x, (v_roundVertex.y + 1.0) / 2.0 * u_size.y);\n if (length(windowCoords - gl_FragCoord.xy) > v_halfWidth) {\n discard;\n }\n }\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.linestringreplay.shader.DefaultFragment.OPTIMIZED_SOURCE = 'precision mediump float;uniform float e;uniform vec4 f;void main(void){gl_FragColor=f;float alpha=f.a*e;if(alpha==0.0){discard;}gl_FragColor.a=alpha;}';
|
||||
ol.render.webgl.linestringreplay.shader.DefaultFragment.OPTIMIZED_SOURCE = 'precision mediump float;varying float a;varying vec4 b;varying float c;uniform float n;uniform vec4 o;uniform vec2 p;void main(void){if(a>0.0){vec2 windowCoords=vec2((b.x+1.0)/2.0*p.x,(b.y+1.0)/2.0*p.y);if(length(windowCoords-gl_FragCoord.xy)>c){discard;}} gl_FragColor=o;float alpha=o.a*n;if(alpha==0.0){discard;}gl_FragColor.a=alpha;}';
|
||||
|
||||
|
||||
/**
|
||||
@@ -58,14 +58,14 @@ goog.addSingletonGetter(ol.render.webgl.linestringreplay.shader.DefaultVertex);
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.render.webgl.linestringreplay.shader.DefaultVertex.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 mat4 offsetMatrix = u_offsetScaleMatrix;\n vec4 offsets = offsetMatrix * vec4(0., 0., 0., 0.);\n gl_Position = u_projectionMatrix * vec4(a_position, 0., 1.) + offsets;\n}\n\n\n';
|
||||
ol.render.webgl.linestringreplay.shader.DefaultVertex.DEBUG_SOURCE = 'varying float v_round;\nvarying vec4 v_roundVertex;\nvarying float v_halfWidth;\n\n\nattribute vec2 a_lastPos;\nattribute vec2 a_position;\nattribute vec2 a_nextPos;\nattribute float a_direction;\nattribute float a_instruction;\n\nuniform mat4 u_projectionMatrix;\nuniform mat4 u_offsetScaleMatrix;\nuniform float u_lineWidth;\nuniform float u_miterLimit;\nuniform float u_round;\n\nvoid main(void) {\n v_halfWidth = u_lineWidth / 2.0;\n vec2 offset;\n v_round = 0.0;\n vec4 projPos = u_projectionMatrix * vec4(a_position, 0., 1.);\n if (a_instruction == 0. || a_instruction == 4.) {\n vec2 dirVect = a_nextPos - a_position;\n vec2 normal = normalize(vec2(-dirVect.y, dirVect.x));\n offset = v_halfWidth * normal * a_direction;\n if (a_instruction == 4. && (u_round == 7. || u_round == 9.)) {\n v_roundVertex = projPos + u_offsetScaleMatrix * vec4(0., 0., 0., 0.);\n }\n } else if (a_instruction == 1. || a_instruction == 3.) {\n vec2 dirVect = a_lastPos - a_position;\n vec2 normal = normalize(vec2(dirVect.y, -dirVect.x));\n offset = v_halfWidth * normal * a_direction;\n if (a_instruction == 3. && (u_round == 7. || u_round == 9.)) {\n v_roundVertex = projPos + u_offsetScaleMatrix * vec4(0., 0., 0., 0.);\n }\n } else if (a_instruction == 5. || a_instruction == 6.) {\n vec2 dirVect = a_nextPos - a_position;\n vec2 tmpNormal = normalize(vec2(-dirVect.y, dirVect.x));\n vec2 tangent = normalize(normalize(a_nextPos - a_position) + normalize(a_position - a_lastPos));\n vec2 normal = vec2(tangent.y, -tangent.x);\n float miterLength = v_halfWidth / dot(normal, tmpNormal);\n if (a_instruction == 6.) {\n if (u_round == 7. || u_round == 9.) {\n offset = normal * a_direction * miterLength;\n v_round = 1.0;\n v_roundVertex = projPos + u_offsetScaleMatrix * vec4(0., 0., 0., 0.);\n } else if (miterLength > u_miterLimit) {\n offset = tmpNormal * a_direction * v_halfWidth;\n } else {\n offset = normal * a_direction * miterLength;\n }\n } else if (a_instruction == 5.) {\n offset = normal * a_direction * miterLength;\n vec4 defaultOffset = u_offsetScaleMatrix * vec4(0., 0., 0., 0.);\n vec4 firstProjPos = u_projectionMatrix * vec4(a_lastPos, 0., 1.) + defaultOffset;\n vec4 secondProjPos = projPos + defaultOffset;\n vec4 thirdProjPos = u_projectionMatrix * vec4(a_nextPos, 0., 1.) + defaultOffset;\n float firstSegLength = distance(secondProjPos.xy, firstProjPos.xy);\n float secondSegLength = distance(thirdProjPos.xy, secondProjPos.xy);\n float miterSegLength = distance(secondProjPos.xy, vec4(projPos + u_offsetScaleMatrix * vec4(offset, 0., 0.)).xy);\n //TODO: Write a more accurate method for identifying sharp angles.\n if (miterSegLength > min(firstSegLength, secondSegLength)) {\n if (firstSegLength < secondSegLength) {\n dirVect = a_lastPos - a_position;\n tmpNormal = normalize(vec2(dirVect.y, -dirVect.x));\n projPos = firstProjPos - defaultOffset;\n } else {\n projPos = thirdProjPos - defaultOffset;\n }\n offset = tmpNormal * a_direction * v_halfWidth;\n }\n }\n }\n vec4 offsets = u_offsetScaleMatrix * vec4(offset, 0., 0.);\n gl_Position = projPos + offsets;\n}\n\n\n';
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.render.webgl.linestringreplay.shader.DefaultVertex.OPTIMIZED_SOURCE = 'attribute vec2 a;uniform mat4 b;uniform mat4 c;uniform mat4 d;void main(void){mat4 offsetMatrix=c;vec4 offsets=offsetMatrix*vec4(0.,0.,0.,0.);gl_Position=b*vec4(a,0.,1.)+offsets;}';
|
||||
ol.render.webgl.linestringreplay.shader.DefaultVertex.OPTIMIZED_SOURCE = 'varying float a;varying vec4 b;varying float c;attribute vec2 d;attribute vec2 e;attribute vec2 f;attribute float g;attribute float h;uniform mat4 i;uniform mat4 j;uniform float k;uniform float l;uniform float m;void main(void){c=k/2.0;vec2 offset;a=0.0;vec4 projPos=i*vec4(e,0.,1.);if(h==0.||h==4.){vec2 dirVect=f-e;vec2 normal=normalize(vec2(-dirVect.y,dirVect.x));offset=c*normal*g;if(h==4.&&(m==7.||m==9.)){b=projPos+j*vec4(0.,0.,0.,0.);}} else if(h==1.||h==3.){vec2 dirVect=d-e;vec2 normal=normalize(vec2(dirVect.y,-dirVect.x));offset=c*normal*g;if(h==3.&&(m==7.||m==9.)){b=projPos+j*vec4(0.,0.,0.,0.);}} else if(h==5.||h==6.){vec2 dirVect=f-e;vec2 tmpNormal=normalize(vec2(-dirVect.y,dirVect.x));vec2 tangent=normalize(normalize(f-e)+normalize(e-d));vec2 normal=vec2(tangent.y,-tangent.x);float miterLength=c/dot(normal,tmpNormal);if(h==6.){if(m==7.||m==9.){offset=normal*g*miterLength;a=1.0;b=projPos+j*vec4(0.,0.,0.,0.);}else if(miterLength>l){offset=tmpNormal*g*c;}else{offset=normal*g*miterLength;}} else if(h==5.){offset=normal*g*miterLength;vec4 defaultOffset=j*vec4(0.,0.,0.,0.);vec4 firstProjPos=i*vec4(d,0.,1.)+defaultOffset;vec4 secondProjPos=projPos+defaultOffset;vec4 thirdProjPos=i*vec4(f,0.,1.)+defaultOffset;float firstSegLength=distance(secondProjPos.xy,firstProjPos.xy);float secondSegLength=distance(thirdProjPos.xy,secondProjPos.xy);float miterSegLength=distance(secondProjPos.xy,vec4(projPos+j*vec4(offset,0.,0.)).xy);if(miterSegLength>min(firstSegLength,secondSegLength)){if(firstSegLength<secondSegLength){dirVect=d-e;tmpNormal=normalize(vec2(dirVect.y,-dirVect.x));projPos=firstProjPos-defaultOffset;}else{projPos=thirdProjPos-defaultOffset;}offset=tmpNormal*g*c;}}}vec4 offsets=j*vec4(offset,0.,0.);gl_Position=projPos+offsets;}';
|
||||
|
||||
|
||||
/**
|
||||
@@ -89,35 +89,77 @@ ol.render.webgl.linestringreplay.shader.Default.Locations = function(gl, program
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_color = gl.getUniformLocation(
|
||||
program, goog.DEBUG ? 'u_color' : 'f');
|
||||
program, goog.DEBUG ? 'u_color' : 'o');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_offsetRotateMatrix = gl.getUniformLocation(
|
||||
program, goog.DEBUG ? 'u_offsetRotateMatrix' : 'd');
|
||||
this.u_lineWidth = gl.getUniformLocation(
|
||||
program, goog.DEBUG ? 'u_lineWidth' : 'k');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_miterLimit = gl.getUniformLocation(
|
||||
program, goog.DEBUG ? 'u_miterLimit' : 'l');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_offsetScaleMatrix = gl.getUniformLocation(
|
||||
program, goog.DEBUG ? 'u_offsetScaleMatrix' : 'c');
|
||||
program, goog.DEBUG ? 'u_offsetScaleMatrix' : 'j');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_opacity = gl.getUniformLocation(
|
||||
program, goog.DEBUG ? 'u_opacity' : 'e');
|
||||
program, goog.DEBUG ? 'u_opacity' : 'n');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_projectionMatrix = gl.getUniformLocation(
|
||||
program, goog.DEBUG ? 'u_projectionMatrix' : 'b');
|
||||
program, goog.DEBUG ? 'u_projectionMatrix' : 'i');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_round = gl.getUniformLocation(
|
||||
program, goog.DEBUG ? 'u_round' : 'm');
|
||||
|
||||
/**
|
||||
* @type {WebGLUniformLocation}
|
||||
*/
|
||||
this.u_size = gl.getUniformLocation(
|
||||
program, goog.DEBUG ? 'u_size' : 'p');
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.a_direction = gl.getAttribLocation(
|
||||
program, goog.DEBUG ? 'a_direction' : 'g');
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.a_instruction = gl.getAttribLocation(
|
||||
program, goog.DEBUG ? 'a_instruction' : 'h');
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.a_lastPos = gl.getAttribLocation(
|
||||
program, goog.DEBUG ? 'a_lastPos' : 'd');
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.a_nextPos = gl.getAttribLocation(
|
||||
program, goog.DEBUG ? 'a_nextPos' : 'f');
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.a_position = gl.getAttribLocation(
|
||||
program, goog.DEBUG ? 'a_position' : 'a');
|
||||
program, goog.DEBUG ? 'a_position' : 'e');
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user