diff --git a/CHANGELOG b/CHANGELOG
index 19a39127ee..2973b6abdb 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -4,7 +4,8 @@ Version History
* Renderable : added support for rendering mask (in both Canvas and WebGL mode), allowing to use any polygon based Shape as a mask
* Renderer : `drawShape()` is deprecated and has been replaced by a `fill()` and `stroke() methods
* Renderer : cleaned and aligned drawing APIs between the Canvas and WebGL Renderer
-* WebGLRenderer : added fill operations for polygon based shapes
+* WebGLRenderer : added stroke and fill operations for all me.Shape objects
+* WebGLRenderer : optimized shape drawing operations by preventing temporary array allocation
6.2.0
* Audio : fixed a regression when passing an initial volume value to the play function (thanks @PLAYERKILLERS)
diff --git a/examples/alphablending/index.html b/examples/alphablending/index.html
index dc7df9a320..5918f9536c 100644
--- a/examples/alphablending/index.html
+++ b/examples/alphablending/index.html
@@ -1,7 +1,7 @@
- melonJS - alpha blending
+ melonJS - Graphics drawing
@@ -43,6 +43,7 @@
me.video.renderer.setColor(r);
mask.pos.set(60 + 50, 25);
me.video.renderer.fill(mask);
+ me.video.renderer.stroke(mask);
me.video.renderer.fillRect(60, 20, 100 ,100);
me.video.renderer.strokeRect(65, 25, 90 , 90);
@@ -56,8 +57,9 @@
me.video.renderer.setColor(b);
mask.pos.set(160 + 50, 125);
- me.video.renderer.fill(mask);
me.video.renderer.fillRect(160, 120, 100 ,100);
+ me.video.renderer.fillEllipse(160 + 50, 120 + 50, 35, 35);
+ me.video.renderer.strokeEllipse(160 + 50, 120 + 50, 30, 30);
me.video.renderer.strokeRect(165, 125, 90 , 90);
});
diff --git a/src/shapes/poly.js b/src/shapes/poly.js
index 0ed1577f1a..e315b66d84 100644
--- a/src/shapes/poly.js
+++ b/src/shapes/poly.js
@@ -260,7 +260,7 @@
/**
* returns a list of indices for all triangles defined in this polygon
- * @name toIndices
+ * @name getIndices
* @memberOf me.Polygon
* @function
* @param {Vector2d[]} a list of vector
diff --git a/src/video/canvas/canvas_renderer.js b/src/video/canvas/canvas_renderer.js
index 77b8603453..e42e2ef6cc 100644
--- a/src/video/canvas/canvas_renderer.js
+++ b/src/video/canvas/canvas_renderer.js
@@ -315,12 +315,12 @@
},
/**
- * Stroke an ellipse at the specified coordinates with given radius, start and end points
+ * Stroke an ellipse at the specified coordinates with given radius
* @name strokeEllipse
* @memberOf me.CanvasRenderer
* @function
- * @param {Number} x arc center point x-axis
- * @param {Number} y arc center point y-axis
+ * @param {Number} x ellipse center point x-axis
+ * @param {Number} y ellipse center point y-axis
* @param {Number} w horizontal radius of the ellipse
* @param {Number} h vertical radius of the ellipse
*/
@@ -356,12 +356,12 @@
},
/**
- * Fill an ellipse at the specified coordinates with given radius, start and end points
+ * Fill an ellipse at the specified coordinates with given radius
* @name fillEllipse
* @memberOf me.CanvasRenderer
* @function
- * @param {Number} x arc center point x-axis
- * @param {Number} y arc center point y-axis
+ * @param {Number} x ellipse center point x-axis
+ * @param {Number} y ellipse center point y-axis
* @param {Number} w horizontal radius of the ellipse
* @param {Number} h vertical radius of the ellipse
*/
diff --git a/src/video/renderer.js b/src/video/renderer.js
index 51d825ac72..79bc1d950f 100644
--- a/src/video/renderer.js
+++ b/src/video/renderer.js
@@ -309,28 +309,14 @@
} else if (shape instanceof me.Line || shape instanceof me.Polygon) {
this.strokePolygon(shape, fill);
} else if (shape instanceof me.Ellipse) {
- if (shape.radiusV.x === shape.radiusV.y) {
- // it's a circle
- this.strokeArc(
- shape.pos.x - shape.radius,
- shape.pos.y - shape.radius,
- shape.radius,
- 0,
- 2 * Math.PI,
- false,
- fill
- );
- } else {
- // it's an ellipse
- this.strokeEllipse(
- shape.pos.x,
- shape.pos.y,
- shape.radiusV.x,
- shape.radiusV.y,
- false,
- fill
- );
- }
+ this.strokeEllipse(
+ shape.pos.x,
+ shape.pos.y,
+ shape.radiusV.x,
+ shape.radiusV.y,
+ false,
+ fill
+ );
}
},
diff --git a/src/video/webgl/compositor.js b/src/video/webgl/compositor.js
index 225e78a1c1..d8fae0d49a 100644
--- a/src/video/webgl/compositor.js
+++ b/src/video/webgl/compositor.js
@@ -547,11 +547,14 @@
* @memberOf me.WebGLRenderer.Compositor
* @function
* @param {me.Vector2d[]} points Line vertices
+ * @param {Number} [len=points.length] amount of points defined in the points array
* @param {Boolean} [open=false] Whether the line is open (true) or closed (false)
*/
- drawLine : function (points, open) {
+ drawLine : function (points, len, open) {
var gl = this.gl;
+ len = len || points.length;
+
this.useShader(this.primitiveShader.handle);
// Put vertex data into the stream buffer
@@ -573,7 +576,7 @@
// Copy data into the stream buffer
gl.bufferData(
gl.ARRAY_BUFFER,
- this.stream.subarray(0, points.length * 2),
+ this.stream.subarray(0, len * 2),
gl.STREAM_DRAW
);
@@ -588,7 +591,7 @@
);
// Draw the stream buffer
- gl.drawArrays(open ? gl.LINE_STRIP : gl.LINE_LOOP, 0, points.length);
+ gl.drawArrays(open ? gl.LINE_STRIP : gl.LINE_LOOP, 0, len);
// FIXME: Configure vertex attrib pointers in `useShader`
gl.vertexAttribPointer(
diff --git a/src/video/webgl/webgl_renderer.js b/src/video/webgl/webgl_renderer.js
index 7dafc0a1e7..17a7859901 100644
--- a/src/video/webgl/webgl_renderer.js
+++ b/src/video/webgl/webgl_renderer.js
@@ -59,7 +59,7 @@
/**
* @ignore
*/
- this._linePoints = [
+ this._glPoints = [
new me.Vector2d(),
new me.Vector2d(),
new me.Vector2d(),
@@ -643,8 +643,12 @@
* @param {Number} end end angle in radians
* @param {Boolean} [antiClockwise=false] draw arc anti-clockwise
*/
- strokeArc : function (/*x, y, radius, start, end, antiClockwise*/) {
- console.warn("strokeArc() is not implemented");
+ strokeArc : function (x, y, radius, start, end, antiClockwise, fill) {
+ if (fill === true ) {
+ this.fillArc(x, y, radius, start, end, antiClockwise);
+ } else {
+ console.warn("strokeArc() is not implemented");
+ }
},
/**
@@ -660,35 +664,71 @@
* @param {Boolean} [antiClockwise=false] draw arc anti-clockwise
*/
fillArc : function (x, y, radius, start, end, antiClockwise) {
- this.strokeArc(x, y, radius, start, end, antiClockwise || false, true);
+ console.warn("fillArc() is not implemented");
},
/**
- * Stroke an ellipse at the specified coordinates with given radius, start and end points
+ * Stroke an ellipse at the specified coordinates with given radius
* @name strokeEllipse
* @memberOf me.WebGLRenderer
* @function
- * @param {Number} x arc center point x-axis
- * @param {Number} y arc center point y-axis
+ * @param {Number} x ellipse center point x-axis
+ * @param {Number} y ellipse center point y-axis
* @param {Number} w horizontal radius of the ellipse
* @param {Number} h vertical radius of the ellipse
*/
- strokeEllipse : function (/*x, y, w, h*/) {
- console.warn("strokeEllipse() is not implemented");
+ strokeEllipse : function (x, y, w, h, fill) {
+ if (fill === true ) {
+ this.fillEllipse(x, y, w, h);
+ } else {
+ // XXX to be optimzed using a specific shader
+ var len = Math.floor(24 * Math.sqrt(w)) ||
+ Math.floor(12 * Math.sqrt(w + h));
+ var segment = (Math.PI * 2) / len;
+ var points = this._glPoints,
+ i;
+
+ // Grow internal points buffer if necessary
+ for (i = points.length; i < len; i++) {
+ points.push(new me.Vector2d());
+ }
+
+ // calculate and draw all segments
+ for (i = 0; i < len; i++) {
+ points[i].x = x + (Math.sin(segment * -i) * w);
+ points[i].y = y + (Math.cos(segment * -i) * h);
+ }
+ this.compositor.drawLine(points, len);
+ }
+
},
/**
- * Fill an ellipse at the specified coordinates with given radius, start and end points
+ * Fill an ellipse at the specified coordinates with given radius
* @name fillEllipse
* @memberOf me.WebGLRenderer
* @function
- * @param {Number} x arc center point x-axis
- * @param {Number} y arc center point y-axis
+ * @param {Number} x ellipse center point x-axis
+ * @param {Number} y ellipse center point y-axis
* @param {Number} w horizontal radius of the ellipse
* @param {Number} h vertical radius of the ellipse
*/
fillEllipse : function (x, y, w, h) {
- this.strokeEllipse(x, y, w, h, true);
+ // XXX to be optimzed using a specific shader
+ var len = Math.floor(24 * Math.sqrt(w)) ||
+ Math.floor(12 * Math.sqrt(w + h));
+ var segment = (Math.PI * 2) / len;
+
+ // draw all vertices vertex coordinates
+ for (var i = 0; i < len; i++) {
+ this.compositor.drawTriangle(
+ x, y,
+ x + (Math.sin(segment * i) * w),
+ y + (Math.cos(segment * i) * h),
+ x + (Math.sin(segment * (i + 1)) * w),
+ y + (Math.cos(segment * (i + 1)) * h)
+ );
+ }
},
/**
@@ -702,12 +742,12 @@
* @param {Number} endY the end y coordinate
*/
strokeLine : function (startX, startY, endX, endY) {
- var points = this._linePoints.slice(0, 2);
+ var points = this._glPoints;
points[0].x = startX;
points[0].y = startY;
points[1].x = endX;
points[1].y = endY;
- this.compositor.drawLine(points, true);
+ this.compositor.drawLine(points, 2, true);
},
@@ -737,20 +777,20 @@
this.fillPolygon(poly);
} else {
var len = poly.points.length,
- points,
+ points = this._glPoints,
i;
// Grow internal points buffer if necessary
- for (i = this._linePoints.length; i < len; i++) {
- this._linePoints.push(new me.Vector2d());
+ for (i = points.length; i < len; i++) {
+ points.push(new me.Vector2d());
}
- points = this._linePoints.slice(0, len);
+ // calculate and draw all segments
for (i = 0; i < len; i++) {
points[i].x = poly.pos.x + poly.points[i].x;
points[i].y = poly.pos.y + poly.points[i].y;
}
- this.compositor.drawLine(points);
+ this.compositor.drawLine(points, len);
}
},
@@ -786,7 +826,7 @@
* @param {Number} height
*/
strokeRect : function (x, y, width, height) {
- var points = this._linePoints.slice(0, 4);
+ var points = this._glPoints;
points[0].x = x;
points[0].y = y;
points[1].x = x + width;
@@ -795,7 +835,7 @@
points[2].y = y + height;
points[3].x = x;
points[3].y = y + height;
- this.compositor.drawLine(points);
+ this.compositor.drawLine(points, 4);
},
/**