tofu

Making something with OpenGL in Go
Log | Files | Refs

texture.go (2231B)


      1 package tofu
      2 
      3 import (
      4 	"fmt"
      5 	"image"
      6 	draw "image/draw"
      7 	_ "image/jpeg"
      8 	_ "image/png"
      9 	"os"
     10 
     11 	"github.com/go-gl/gl/v3.3-core/gl"
     12 )
     13 
     14 func loadImage(name string) (image.Image, error) {
     15 	f, err := os.Open(name)
     16 	if err != nil {
     17 		return nil, fmt.Errorf("open: %v", err)
     18 	}
     19 	defer f.Close()
     20 	img, _, err := image.Decode(f)
     21 	if err != nil {
     22 		return nil, fmt.Errorf("decode image %s: %v", name, err)
     23 	}
     24 	return img, nil
     25 }
     26 
     27 type Texture struct {
     28 	id   uint32
     29 	unit uint32
     30 }
     31 
     32 var nextUnit uint32 = gl.TEXTURE0
     33 
     34 func NewTexture(name string) (*Texture, error) {
     35 	return NewTextureFlip(name, false, false)
     36 }
     37 
     38 func NewTextureFlip(name string, v bool, h bool) (*Texture, error) {
     39 	var id uint32
     40 	gl.GenTextures(1, &id)
     41 	gl.BindTexture(gl.TEXTURE_2D, id)
     42 	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT)
     43 	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT)
     44 	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
     45 	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
     46 	img, err := loadImage(name)
     47 	if err != nil {
     48 		return nil, fmt.Errorf("load texture: %v", err)
     49 	}
     50 	rgba := image.NewRGBA(img.Bounds())
     51 	if v {
     52 		img = flipV(img)
     53 	}
     54 	if h {
     55 		img = flipH(img)
     56 	}
     57 	draw.Draw(rgba, rgba.Bounds(), img, image.ZP, draw.Src)
     58 	if rgba.Stride != rgba.Rect.Dx()*4 {
     59 		return nil, fmt.Errorf("data should be packed dense")
     60 	}
     61 	gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA,
     62 		int32(rgba.Rect.Dx()), int32(rgba.Rect.Dy()), 0,
     63 		gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(rgba.Pix))
     64 	gl.GenerateMipmap(gl.TEXTURE_2D)
     65 	unit := nextUnit
     66 	nextUnit++
     67 	return &Texture{id: id, unit: unit}, nil
     68 }
     69 
     70 func flipV(img image.Image) image.Image {
     71 	dst := image.NewRGBA(img.Bounds())
     72 	xmin, ymin := dst.Bounds().Min.X, dst.Bounds().Min.Y
     73 	xmax, ymax := dst.Bounds().Max.X, dst.Bounds().Max.Y
     74 	for y := ymin; y < ymax; y++ {
     75 		for x := xmin; x < xmax; x++ {
     76 			dst.Set(x, ymax+ymin-y, img.At(x, y))
     77 		}
     78 	}
     79 	return dst
     80 }
     81 
     82 func flipH(img image.Image) image.Image {
     83 	dst := image.NewRGBA(img.Bounds())
     84 	xmin, ymin := dst.Bounds().Min.X, dst.Bounds().Min.Y
     85 	xmax, ymax := dst.Bounds().Max.X, dst.Bounds().Max.Y
     86 	for y := ymin; y < ymax; y++ {
     87 		for x := xmin; x < xmax; x++ {
     88 			dst.Set(xmax+xmin-x, y, img.At(x, y))
     89 		}
     90 	}
     91 	return dst
     92 }