diff --git a/imdraw/imdraw.go b/imdraw/imdraw.go
index efa0c1ad0b9de6b5540d1153fd765e0a21259300..10a1e8d6e77175d981990d952a7969278c19f9fd 100644
--- a/imdraw/imdraw.go
+++ b/imdraw/imdraw.go
@@ -183,6 +183,20 @@ func (imd *IMDraw) Line(thickness float64) {
 	imd.polyline(thickness, false)
 }
 
+// Rectangle draws a rectangle between each two subsequent Pushed points. Drawing a rectangle
+// between two points means drawing a rectangle with sides parallel to the axes of the coordinate
+// system, where the two points specify it's two opposite corners.
+//
+// If the thickness is 0, rectangles will be filled, otherwise will be outlined with the given
+// thickness.
+func (imd *IMDraw) Rectangle(thickness float64) {
+	if thickness == 0 {
+		imd.fillRectangle()
+	} else {
+		imd.outlineRectangle(thickness)
+	}
+}
+
 // Polygon draws a polygon from the Pushed points. If the thickness is 0, the convex polygon will be
 // filled. Otherwise, an outline of the specified thickness will be drawn. The outline does not have
 // to be convex.
@@ -264,6 +278,64 @@ func (imd *IMDraw) applyMatrixAndMask(off int) {
 	}
 }
 
+func (imd *IMDraw) fillRectangle() {
+	points := imd.getAndClearPoints()
+
+	if len(points) < 2 {
+		return
+	}
+
+	off := imd.tri.Len()
+	imd.tri.SetLen(imd.tri.Len() + 6*(len(points)-1))
+
+	for i, j := 0, off; i+1 < len(points); i, j = i+1, j+6 {
+		a, b := points[i], points[i+1]
+		c := point{
+			pos: pixel.V(a.pos.X(), b.pos.Y()),
+			col: a.col.Add(b.col).Mul(pixel.Alpha(0.5)),
+			pic: pixel.V(a.pic.X(), b.pic.Y()),
+			in:  (a.in + b.in) / 2,
+		}
+		d := point{
+			pos: pixel.V(b.pos.X(), a.pos.Y()),
+			col: a.col.Add(b.col).Mul(pixel.Alpha(0.5)),
+			pic: pixel.V(b.pic.X(), a.pic.Y()),
+			in:  (a.in + b.in) / 2,
+		}
+
+		for k, p := range []point{a, b, c, a, b, d} {
+			(*imd.tri)[j+k].Position = p.pos
+			(*imd.tri)[j+k].Color = p.col
+			(*imd.tri)[j+k].Picture = p.pic
+			(*imd.tri)[j+k].Intensity = p.in
+		}
+	}
+
+	imd.applyMatrixAndMask(off)
+	imd.batch.Dirty()
+}
+
+func (imd *IMDraw) outlineRectangle(thickness float64) {
+	points := imd.getAndClearPoints()
+
+	if len(points) < 2 {
+		return
+	}
+
+	for i := 0; i+1 < len(points); i++ {
+		a, b := points[i], points[i+1]
+		mid := a
+		mid.col = a.col.Add(b.col).Mul(pixel.Alpha(0.5))
+		mid.in = (a.in + b.in) / 2
+
+		imd.pushPt(a.pos, a)
+		imd.pushPt(pixel.V(a.pos.X(), b.pos.Y()), mid)
+		imd.pushPt(b.pos, b)
+		imd.pushPt(pixel.V(b.pos.X(), a.pos.Y()), mid)
+		imd.polyline(thickness, true)
+	}
+}
+
 func (imd *IMDraw) fillPolygon() {
 	points := imd.getAndClearPoints()