diff --git a/graphics.go b/graphics.go
index 2e81cd877f4f9a19843bbe5fb3c59716d73aecde..9b788982506bc33bb65b82c4a478ba5cc6154fb2 100644
--- a/graphics.go
+++ b/graphics.go
@@ -116,13 +116,12 @@ func (td *TrianglesData) Picture(i int) Vec {
 // the Sprite, use Target's SetTransform method.
 type Sprite struct {
 	data TrianglesData
-	td   TrianglesDrawer
-	pic  *GLPicture
+	d    Drawer
 }
 
 // NewSprite creates a Sprite with the supplied Picture. The dimensions of the returned Sprite match
 // the dimensions of the Picture.
-func NewSprite(pic *GLPicture) *Sprite {
+func NewSprite(pic Picture) *Sprite {
 	s := &Sprite{
 		data: TrianglesData{
 			{Position: V(0, 0), Color: NRGBA{1, 1, 1, 1}, Picture: V(0, 0)},
@@ -133,15 +132,15 @@ func NewSprite(pic *GLPicture) *Sprite {
 			{Position: V(0, 0), Color: NRGBA{1, 1, 1, 1}, Picture: V(0, 1)},
 		},
 	}
-	s.td = TrianglesDrawer{Triangles: &s.data}
+	s.d = Drawer{Triangles: &s.data}
 	s.SetPicture(pic)
 	return s
 }
 
 // SetPicture changes the Picture of the Sprite and resizes it accordingly.
-func (s *Sprite) SetPicture(pic *GLPicture) {
-	oldPic := s.pic
-	s.pic = pic
+func (s *Sprite) SetPicture(pic Picture) {
+	oldPic := s.d.Picture
+	s.d.Picture = pic
 	if oldPic != nil && oldPic.Bounds().Size == pic.Bounds().Size {
 		return
 	}
@@ -152,23 +151,23 @@ func (s *Sprite) SetPicture(pic *GLPicture) {
 	s.data[3].Position = V(0, 0)
 	s.data[4].Position = V(w, h)
 	s.data[5].Position = V(0, h)
-	s.td.Dirty()
+	s.d.Dirty()
 }
 
 // Picture returns the current Picture of the Sprite.
-func (s *Sprite) Picture() *GLPicture {
-	return s.pic
+func (s *Sprite) Picture() Picture {
+	return s.d.Picture
 }
 
 // Draw draws the Sprite onto the provided Target.
 func (s *Sprite) Draw(t Target) {
-	s.td.Draw(t)
+	s.d.Draw(t)
 }
 
 // Polygon is a convex polygon shape filled with a single color.
 type Polygon struct {
 	data TrianglesData
-	td   TrianglesDrawer
+	d    Drawer
 	col  NRGBA
 }
 
@@ -178,7 +177,7 @@ func NewPolygon(c color.Color, points ...Vec) *Polygon {
 	p := &Polygon{
 		data: TrianglesData{},
 	}
-	p.td = TrianglesDrawer{Triangles: &p.data}
+	p.d = Drawer{Triangles: &p.data}
 	p.SetColor(c)
 	p.SetPoints(points...)
 	return p
@@ -193,7 +192,7 @@ func (p *Polygon) SetColor(c color.Color) {
 	for i := range p.data {
 		p.data[i].Color = p.col
 	}
-	p.td.Dirty()
+	p.d.Dirty()
 }
 
 // Color returns the current color of the Polygon.
@@ -217,7 +216,7 @@ func (p *Polygon) SetPoints(points ...Vec) {
 	for i := range p.data {
 		p.data[i].Color = p.col
 	}
-	p.td.Dirty()
+	p.d.Dirty()
 }
 
 // Points returns a slice of points of the Polygon in the order they where supplied.
@@ -231,5 +230,5 @@ func (p *Polygon) Points() []Vec {
 
 // Draw draws the Polygon onto the Target.
 func (p *Polygon) Draw(t Target) {
-	p.td.Draw(t)
+	p.d.Draw(t)
 }
diff --git a/interface.go b/interface.go
index 059bc3ca4dff53454490b3eade31dbd03412d465..18dfe910ba94e10771d32f6470738c779cfc90c4 100644
--- a/interface.go
+++ b/interface.go
@@ -31,9 +31,9 @@ type BasicTarget interface {
 	// Triangles.
 	SetTransform(...Transform)
 
-	// SetMaskColor sets a color that will be multiplied with the TrianglesColor property of all
+	// SetMColorMask sets a color that will be multiplied with the TrianglesColor property of all
 	// Triangles.
-	SetMaskColor(color.Color)
+	SetColorMask(color.Color)
 }
 
 // Triangles represents a list of vertices, where each three vertices form a triangle. (First,
@@ -69,14 +69,8 @@ type Triangles interface {
 	Copy() Triangles
 }
 
-//TODO: doc
-type Picture interface {
-	Bounds() Rect
-	Slice(Rect) Picture
-}
-
 // TargetTriangles are Triangles generated by a Target with MakeTriangles method. They can be drawn
-// onto that Target.
+// onto that (no other) Target.
 type TargetTriangles interface {
 	Triangles
 
@@ -84,13 +78,6 @@ type TargetTriangles interface {
 	Draw()
 }
 
-//TODO: doc
-type TargetPicture interface {
-	Picture
-
-	Draw(TargetTriangles)
-}
-
 // TrianglesPosition specifies Triangles with Position property.
 type TrianglesPosition interface {
 	Triangles
@@ -110,3 +97,32 @@ type TrianglesPicture interface {
 	Triangles
 	Picture(i int) Vec
 }
+
+// Picture represents a rectangular area of raster data, such as a color. It has Bounds which
+// specify the rectangle where data is located.
+type Picture interface {
+	// Bounds returns the rectangle of the Picture. All data is located witih this rectangle.
+	// Querying properties outside the rectangle should return default value of that property.
+	Bounds() Rect
+
+	// Slice returns a sub-Picture with specified Bounds.
+	Slice(Rect) Picture
+}
+
+// TargetPicture is a Picture generated by a Target using MakePicture method. This Picture can be drawn onto
+// that (no other) Target together with a TargetTriangles generated by the same Target.
+//
+// The TargetTriangles specify where, shape and how the Picture should be drawn.
+type TargetPicture interface {
+	Picture
+
+	Draw(TargetTriangles)
+}
+
+// PictureColor specifies Picture with Color property, so that every position inside the Picture's
+// Bounds has a color.
+//
+// Positions outside the Picture's Bounds must return opaque white (NRGBA{R: 1, G: 1, B:1, A: 1}).
+type PictureColor interface {
+	Color(at Vec) NRGBA
+}
diff --git a/picture.go b/picture.go
deleted file mode 100644
index cc89f550ec4f62ab2ccd44ccfa927bab30f28348..0000000000000000000000000000000000000000
--- a/picture.go
+++ /dev/null
@@ -1,113 +0,0 @@
-package pixel
-
-import (
-	"image"
-	"image/draw"
-
-	"github.com/faiface/glhf"
-	"github.com/faiface/mainthread"
-)
-
-// GLPicture is a raster picture. It is usually used with sprites.
-//
-// A GLPicture is created from an image.Image, that can be either loaded from a file, or
-// generated. After the creation, Pictures can be sliced (slicing creates a "sub-GLPicture"
-// from a GLPicture) into smaller Pictures.
-type GLPicture struct {
-	tex    *glhf.Texture
-	bounds Rect
-}
-
-// NewPicture creates a new Picture from an image.Image.
-func NewPicture(img image.Image, smooth bool) *GLPicture {
-	// convert the image to NRGBA format
-	bounds := img.Bounds()
-	nrgba := image.NewNRGBA(image.Rect(0, 0, bounds.Dx(), bounds.Dy()))
-	draw.Draw(nrgba, nrgba.Bounds(), img, bounds.Min, draw.Src)
-
-	// flip the image vertically
-	tmp := make([]byte, nrgba.Stride)
-	for i, j := 0, bounds.Dy()-1; i < j; i, j = i+1, j-1 {
-		iSlice := nrgba.Pix[i*nrgba.Stride : (i+1)*nrgba.Stride]
-		jSlice := nrgba.Pix[j*nrgba.Stride : (j+1)*nrgba.Stride]
-		copy(tmp, iSlice)
-		copy(iSlice, jSlice)
-		copy(jSlice, tmp)
-	}
-
-	var tex *glhf.Texture
-	mainthread.Call(func() {
-		tex = glhf.NewTexture(
-			img.Bounds().Dx(),
-			img.Bounds().Dy(),
-			smooth,
-			nrgba.Pix,
-		)
-	})
-
-	return PictureFromTexture(tex)
-}
-
-// PictureFromTexture returns a new Picture that spans the whole supplied Texture.
-func PictureFromTexture(tex *glhf.Texture) *GLPicture {
-	return &GLPicture{
-		tex:    tex,
-		bounds: R(0, 0, float64(tex.Width()), float64(tex.Height())),
-	}
-}
-
-// Image returns the content of the Picture as an image.NRGBA.
-//
-// Note, that this operation can be rather expensive.
-func (p *GLPicture) Image() *image.NRGBA {
-	bounds := p.Bounds()
-	nrgba := image.NewNRGBA(image.Rect(0, 0, int(bounds.W()), int(bounds.H())))
-
-	mainthread.Call(func() {
-		p.tex.Begin()
-		nrgba.Pix = p.tex.Pixels(
-			int(bounds.X()),
-			int(bounds.Y()),
-			int(bounds.W()),
-			int(bounds.H()),
-		)
-		p.tex.End()
-	})
-
-	// flip the image vertically
-	tmp := make([]byte, nrgba.Stride)
-	for i, j := 0, nrgba.Bounds().Dy()-1; i < j; i, j = i+1, j-1 {
-		iSlice := nrgba.Pix[i*nrgba.Stride : (i+1)*nrgba.Stride]
-		jSlice := nrgba.Pix[j*nrgba.Stride : (j+1)*nrgba.Stride]
-		copy(tmp, iSlice)
-		copy(iSlice, jSlice)
-		copy(jSlice, tmp)
-	}
-
-	return nrgba
-}
-
-// Texture returns a pointer to the underlying OpenGL texture of the Picture.
-func (p *GLPicture) Texture() *glhf.Texture {
-	return p.tex
-}
-
-// Slice returns a Picture within the supplied rectangle of the original picture. The original
-// and the sliced Picture share the same texture.
-//
-// For example, suppose we have a 100x200 pixels Picture. If we slice it with rectangle (50,
-// 100, 50, 100), we get the upper-right quadrant of the original Picture.
-func (p *GLPicture) Slice(slice Rect) *GLPicture {
-	return &GLPicture{
-		tex:    p.tex,
-		bounds: Rect{p.bounds.Pos + slice.Pos, slice.Size},
-	}
-}
-
-// Bounds returns the bounding rectangle of this Picture relative to the most original picture.
-//
-// If the original Picture was sliced with the return value of this method, this Picture would
-// be obtained.
-func (p *GLPicture) Bounds() Rect {
-	return p.bounds
-}
diff --git a/util.go b/util.go
index 654ba4c3639a48904d7493f625977922324a90cc..45f5ba28cd8a408a6eec0df77a4be34468bf8381 100644
--- a/util.go
+++ b/util.go
@@ -31,8 +31,8 @@ func transformToMat(t ...Transform) mgl32.Mat3 {
 	return mat
 }
 
-func pictureBounds(p *GLPicture, v Vec) Vec {
-	w, h := float64(p.Texture().Width()), float64(p.Texture().Height())
+func pictureBounds(p Picture, v Vec) Vec {
+	w, h := p.Bounds().Size.XY()
 	a := p.Bounds().Pos
 	b := p.Bounds().Pos + p.Bounds().Size
 	u := lerp2d(v, a, b)