Before accidentally see Ovilia with Threejs did a low POLY, that is, the effect of the image plane triangulation, feel very stunning, and then took a little time to try.
I did not use the Threejs, so I use the Canvas 2d drawing API directly, because it seems that the effect is not threejs.
Directly on the demo: http://whxaxes.github.io/canvas-test/src/Funny-demo/lowpoly/index.html (also can be seen on the mobile side, but because of the large amount of calculation, Mobile devices can take more time to calculate than PCs. )
The main need to do this effect is to triangulation the image, as well as the image of the edge detection. These two, the first Delaunay triangulation algorithm used, the second Sobel edge detection algorithm. Sounds like a big steal. Two algorithms have the corresponding open source components can be used directly: Ironwallaby Delaunay components and Miguel Mota Sobel components.
These two algorithms Sobel good point, Delaunay is a bit complicated, you can study later. But for now, you can use these components only to make an effect.
Two of the most important components are available, and the rest is simple:
First draw the picture to the canvas:
Canvas.width = (Img.width > 800)? 800:img.width;
Canvas.height = Img.height * canvas.width/img.width;
It then gets to the imgdata of the canvas and returns the new Imgdata by Sobel calculation.
var imgdata = ctx.getimagedata (0, 0, canvas.width, canvas.height);
var newimgdata = Sobel (Imgdata);
If we put the newimgdata on the canvas, we'll find that the color picture becomes the grayscale picture:
Since the Sobel component described above is not very suitable for its own use, and the code also has an improper place, so I do the appropriate modification and optimization, optimize the loop method, speed up the operation, while adding a callback function. See the Sobel.js file in the project GitHub
When the imgdata.data is traversed in the Sobel method, a callback function is invoked to record the coordinates of the color value greater than 40 (i.e. grayscale to RGB (40,40,40)) in the callback. Then randomly get a part of the edge points, and then add some random coordinates and four corners of the coordinate values. So we can get the coordinates we need.
var imgdata = ctx.getimagedata (0, 0, canvas.width, canvas.height);
Collect color value greater than 40 edge pixel dot
var collectors = [];
Sobel (Imgdata, function (value, x, y) {
if (value >) {collectors.push ([x, Y]);}
});
Add some random points
for (var i=0;i<300;i++) {Particles.push ([Math.random () *canvas.width, Math.random () *canvas.height] );}
Add random edge points, number of edge points in addition to the number of
var length = ~ ~ (collectors.length/50), random;
for (Var l=0;l<length;l++) {
random = (Math.random () *collectors.length) <<0;
Particles.push (Collectors[random]);
Collectors.splice (random, 1);
}
Add four vertex coordinates
particles.push ([0,0], [0,canvas.height], [canvas.width,0], [canvas.width,canvas.height]);
When you get to a coordinate point, you can do this by using the Delaunay component calculation to get the array of triangular coordinates in order, and to connect the dots in those arrays:
Of course, we want the effect is not wired, but to all the triangles color fill, that is, to get the triangle three coordinates, and then calculate the center point coordinates, and then according to the center point coordinates in the imgdata to obtain the corresponding RGB color values, and then fill the Triangle area can be:
Using Delaunay triangulation to obtain the triangular coordinate
var triangles = delaunay.triangulate (particles);
var x1,x2,x3,y1,y2,y3,cx,cy;
for (Var i=0;i < triangles.length; i+=3) {
x1 = particles[triangles[i]][0];
x2 = particles[triangles[i+1]][0];
x3 = particles[triangles[i+2]][0];
y1 = particles[triangles[i]][1];
y2 = particles[triangles[i+1]][1];
Y3 = particles[triangles[i+2]][1];
Gets the triangle center point coordinates
CX = ~ ~ ((x1 + x2 + x3)/3);
cy = ~ ~ ((y1 + y2 + y3)/3);
Gets the color value of the center point coordinate
index = (cy*imgdata.width + cx) *4;
var color_r = Imgdata.data[index];
var color_g = imgdata.data[index+1];
var color_b = imgdata.data[index+2];
Draw triangular
ctx.save ();
Ctx.beginpath ();
Ctx.moveto (x1, y1);
Ctx.lineto (x2, y2);
Ctx.lineto (x3, y3);
Ctx.closepath ();
Ctx.fillstyle = "Rgba" ("+color_r+", "+color_g+", "+color_b+", 1) ";
Ctx.fill ();
Ctx.restore ();
}
There is a point to note that the central point of access to the coordinates must be rounded to get the correct color parameters, if you want to do not take the whole, but in the acquisition of RGB index and then take the whole, get the color value is wrong. Because that pixel is not the center pixel we're going to get.
The color is also obtained after the simple line, and then fill the operation, the final effect is:
The above content for you to introduce the use of canvas to achieve a picture of the triangle (low POLY) effect, I hope to help you!