直接画三条线段就可以实现
DrawWireframeTriangle(P0, P1, P2, color)
{
DrawLine(P0, P1, color);
DrawLine(P1, P2, color);
DrawLine(P2, P0, color); }
可以将三角形视为一组水平线段的集合,这些线段一起绘制时看起来像一个三角形,从而实现绘制填充三角形的目的。
效果图
源码样例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>光栅化 填充三角形</title>
</head>
<div class="centered">
<canvas id="canvas" width=600 height=600 style="border: 1px grey solid"></canvas>
</div>
<script>
"use strict";
let canvas = document.getElementById("canvas");
let canvas_context = canvas.getContext("2d");
let canvas_buffer = canvas_context.getImageData(0, 0, canvas.width, canvas.height);
// A color.
function Color(r, g, b) {
return { r, g, b };
}
// The PutPixel() function.
function PutPixel(x, y, color) {
= canvas.width / 2 + (x | 0);
x = canvas.height / 2 - (y | 0) - 1;
y
if (x < 0 || x >= canvas.width || y < 0 || y >= canvas.height) {
return;
}
let offset = 4 * (x + canvas_buffer.width * y);
.data[offset++] = color.r;
canvas_buffer.data[offset++] = color.g;
canvas_buffer.data[offset++] = color.b;
canvas_buffer.data[offset++] = 255; // Alpha = 255 (full opacity)
canvas_buffer
}
// Displays the contents of the offscreen buffer into the canvas.
function UpdateCanvas() {
.putImageData(canvas_buffer, 0, 0);
canvas_context
}
// A Point.
function Pt(x, y) {
return { x, y };
}
function Interpolate(i0, d0, i1, d1) {
if (i0 == i1) {
return [d0];
}
let values = [];
let a = (d1 - d0) / (i1 - i0);
let d = d0;
for (let i = i0; i <= i1; i++) {
.push(d);
values+= a;
d
}
return values;
}
function DrawLine(p0, p1, color) {
let dx = p1.x - p0.x, dy = p1.y - p0.y;
if (Math.abs(dx) > Math.abs(dy)) {
// The line is horizontal-ish. Make sure it's left to right.
if (dx < 0) { let swap = p0; p0 = p1; p1 = swap; }
// Compute the Y values and draw.
let ys = Interpolate(p0.x, p0.y, p1.x, p1.y);
for (let x = p0.x; x <= p1.x; x++) {
PutPixel(x, ys[(x - p0.x) | 0], color);
}else {
} // The line is verical-ish. Make sure it's bottom to top.
if (dy < 0) { let swap = p0; p0 = p1; p1 = swap; }
// Compute the X values and draw.
let xs = Interpolate(p0.y, p0.x, p1.y, p1.x);
for (let y = p0.y; y <= p1.y; y++) {
PutPixel(xs[(y - p0.y) | 0], y, color);
}
}
}
function DrawWireframeTriangle(p0, p1, p2, color) {
DrawLine(p0, p1, color);
DrawLine(p1, p2, color);
DrawLine(p0, p2, color);
}
function DrawFilledTriangle(p0, p1, p2, color) {
// Sort the points from bottom to top.
if (p1.y < p0.y) { let swap = p0; p0 = p1; p1 = swap; }
if (p2.y < p0.y) { let swap = p0; p0 = p2; p2 = swap; }
if (p2.y < p1.y) { let swap = p1; p1 = p2; p2 = swap; }
// 到此p0.y < p1.y < p2.y
// Compute X coordinates of the edges.
let x01 = Interpolate(p0.y, p0.x, p1.y, p1.x);
let x12 = Interpolate(p1.y, p1.x, p2.y, p2.x);
let x02 = Interpolate(p0.y, p0.x, p2.y, p2.x);
// Merge the two short sides.
.pop();
x01let x012 = x01.concat(x12);
// Determine which is left and which is right.
let x_left, x_right;
let m = (x02.length / 2) | 0;
if (x02[m] < x012[m]) {
= x02;
x_left = x012;
x_right else {
} = x012;
x_left = x02;
x_right
}
// Draw horizontal segments.
for (let y = p0.y; y <= p2.y; y++) {
for (let x = x_left[y - p0.y]; x <= x_right[y - p0.y]; x++) {
PutPixel(x, y, color);
}
}
}
// 三角形三个点
let p0 = new Pt(-200, -250);
let p1 = new Pt(200, 50);
let p2 = new Pt(20, 250);
// 画填充三角形
DrawFilledTriangle(p0, p1, p2, new Color(0, 255, 0));
// 画三角形轮廓
DrawWireframeTriangle(p0, p1, p2, new Color(0, 0, 0));
UpdateCanvas();
</script>
</html>