Implementation of a picture triangulation (low POLY) effect with canvas

Source: Internet
Author: User
Tags add

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;

Ctx.drawimage (IMG, 0, 0, canvas.width, canvas.height);

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:

After the image is processed, the imgdata is traversed to record the coordinates of the color value greater than 40 (that is, the grayscale is RGB (40,40,40)). Because we want to randomly select some at the edge of the coordinate point, so the collected coordinates are disrupted, and then add some random coordinates and four corners of the coordinate values. So we can get the coordinates we need.

var collectors = [];
var index;
Collect edge points with color values greater than 40
for (Var x=0;xfor (Var y=0;yindex = ~ ~ (y*imgdata.width + x) *4;

if (Newimgdata.data[index] > 40) {
Collectors.push ([x, y]);
}
}
}

Randomly arrange the points that are collected
Collectors.sort (function () {return math.random ()-math.random ()});

Add some random points
for (Var i=0;i<500;i++) {Particles.push ([Math.random () *canvas.width, Math.random () *canvas.height]);

Add Edge Point
particles = Particles.concat (Collectors.slice (0,~~ (COLLECTORS.LENGTH/50)));

Add four vertex coordinates
particles = Particles.concat ([[[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 get triangular coordinates
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];

Get 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 triangles
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:

  

  

Although no designer manually painted the good-looking, but also a lot of convenience, do to play is very interesting.



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.