diff --git a/graphics.go b/graphics.go
index 6dc110886666f634d6d37b1add224b758029284b..8b58afb45d361775b8cc44f97ba6da2d0720d360 100644
--- a/graphics.go
+++ b/graphics.go
@@ -79,6 +79,13 @@ func (td *TrianglesData) Append(t Triangles) {
 	*td = append(*td, newTd...)
 }
 
+// Copy returns an exact independent copy of this TrianglesData.
+func (td *TrianglesData) Copy() Triangles {
+	copyTd := make(TrianglesData, td.Len())
+	copyTd.Update(td)
+	return &copyTd
+}
+
 // Position returns the position property of i-th vertex.
 func (td *TrianglesData) Position(i int) Vec {
 	return (*td)[i].Position
@@ -117,6 +124,11 @@ func (td *TrianglesColorData) Append(t Triangles) {
 	(*TrianglesData)(td).Append(t)
 }
 
+// Copy returns an exact independent copy of this TrianglesColorData.
+func (td *TrianglesColorData) Copy() Triangles {
+	return (*TrianglesColorData)((*TrianglesData)(td).Copy().(*TrianglesData))
+}
+
 // Position returns the position property of i-th vertex.
 func (td *TrianglesColorData) Position(i int) Vec {
 	return (*TrianglesData)(td).Position(i)
@@ -150,6 +162,11 @@ func (td *TrianglesTextureData) Append(t Triangles) {
 	(*TrianglesData)(td).Append(t)
 }
 
+// Copy returns an exact independent copy of this TrianglesTextureData.
+func (td *TrianglesTextureData) Copy() Triangles {
+	return (*TrianglesTextureData)((*TrianglesData)(td).Copy().(*TrianglesData))
+}
+
 // Position returns the position property of i-th vertex.
 func (td *TrianglesTextureData) Position(i int) Vec {
 	return (*TrianglesData)(td).Position(i)
@@ -198,13 +215,24 @@ func (td *TrianglesDrawer) Draw(target Target) {
 	tri.Draw()
 }
 
-// Update updates the wrapped Triangles with the supplied Triangles. Call only this method to
-// update the wrapped Triangles, otherwise the TrianglesDrawer will not work correctly.
+// Update updates the wrapped Triangles with the supplied Triangles.
+//
+// Call only this method to update the wrapped Triangles, otherwise the TrianglesDrawer will not
+// work correctly.
 func (td *TrianglesDrawer) Update(t Triangles) {
 	td.dirty = true
 	td.Triangles.Update(t)
 }
 
+// Append appends the supplied Triangles to the wrapped Triangles.
+//
+// Call only this method to append to the wrapped Triangles, otherwise the TrianglesDrawer will not
+// work correctly.
+func (td *TrianglesDrawer) Append(t Triangles) {
+	td.dirty = true
+	td.Triangles.Append(t)
+}
+
 // Sprite is a picture, positioned somewhere, with an optional mask color.
 type Sprite struct {
 	td        TrianglesDrawer
diff --git a/interface.go b/interface.go
index 9dc400ec530fea2ae3b9746ac2c52fe500bf6f2d..6130b8154b3dfb2ea7a4ebf92b2c5730e7cb14b3 100644
--- a/interface.go
+++ b/interface.go
@@ -49,6 +49,9 @@ type Triangles interface {
 	//
 	// Behavior regarding unsupported properties should be same as with Update.
 	Append(Triangles)
+
+	// Copy creates an exact independent copy of this Triangles (with the same underlying type).
+	Copy() Triangles
 }
 
 // Drawer is something that can be drawn onto any Target.
diff --git a/util.go b/util.go
index 24e61991f8b3811104c419be3fce74582f56b36e..ce46294408f766d7be735bfd8d5ceeee78eb0a4f 100644
--- a/util.go
+++ b/util.go
@@ -1,5 +1,7 @@
 package pixel
 
+import "github.com/go-gl/mathgl/mgl32"
+
 func clamp(x, low, high float64) float64 {
 	if x < low {
 		return low
@@ -9,3 +11,11 @@ func clamp(x, low, high float64) float64 {
 	}
 	return x
 }
+
+func transformToMat(t ...Transform) mgl32.Mat3 {
+	mat := mgl32.Ident3()
+	for i := range t {
+		mat = mat.Mul3(t[i].Mat())
+	}
+	return mat
+}
diff --git a/window.go b/window.go
index 177ea73550374758d186181458fe6bcc70597092..8eb9d29be775c831b31353ece213c94c8a95be37 100644
--- a/window.go
+++ b/window.go
@@ -470,6 +470,15 @@ func (wt *windowTriangles) Append(t Triangles) {
 	wt.submitData()
 }
 
+func (wt *windowTriangles) Copy() Triangles {
+	copyWt := &windowTriangles{
+		w:  wt.w,
+		vs: pixelgl.MakeVertexSlice(wt.w.shader, 0, 0),
+	}
+	copyWt.Update(wt)
+	return copyWt
+}
+
 func (wt *windowTriangles) Position(i int) Vec {
 	v := wt.data[i][positionVec2].(mgl32.Vec2)
 	return V(float64(v.X()), float64(v.Y()))
@@ -512,10 +521,7 @@ func (w *Window) SetPicture(p *Picture) {
 //
 // Transforms are applied right-to-left.
 func (w *Window) SetTransform(t ...Transform) {
-	w.mat = mgl32.Ident3()
-	for i := range t {
-		w.mat = w.mat.Mul3(t[i].Mat())
-	}
+	w.mat = transformToMat(t...)
 }
 
 // SetMaskColor sets a global mask color for the Window.