tofu

Making something with OpenGL in Go
Log | Files | Refs

texture.go (2139B)


      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 }
     30 
     31 func NewTexture(name string) (*Texture, error) {
     32 	return NewTextureFlip(name, false, false)
     33 }
     34 
     35 func NewTextureFlip(name string, v bool, h bool) (*Texture, error) {
     36 	var id uint32
     37 	gl.GenTextures(1, &id)
     38 	gl.BindTexture(gl.TEXTURE_2D, id)
     39 	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT)
     40 	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT)
     41 	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
     42 	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
     43 	img, err := loadImage(name)
     44 	if err != nil {
     45 		return nil, fmt.Errorf("load texture: %v", err)
     46 	}
     47 	rgba := image.NewRGBA(img.Bounds())
     48 	if v {
     49 		img = flipV(img)
     50 	}
     51 	if h {
     52 		img = flipH(img)
     53 	}
     54 	draw.Draw(rgba, rgba.Bounds(), img, image.ZP, draw.Src)
     55 	if rgba.Stride != rgba.Rect.Dx()*4 {
     56 		return nil, fmt.Errorf("data should be packed dense")
     57 	}
     58 	gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA,
     59 		int32(rgba.Rect.Dx()), int32(rgba.Rect.Dy()), 0,
     60 		gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(rgba.Pix))
     61 	gl.GenerateMipmap(gl.TEXTURE_2D)
     62 	return &Texture{id: id}, nil
     63 }
     64 
     65 func flipV(img image.Image) image.Image {
     66 	dst := image.NewRGBA(img.Bounds())
     67 	xmin, ymin := dst.Bounds().Min.X, dst.Bounds().Min.Y
     68 	xmax, ymax := dst.Bounds().Max.X, dst.Bounds().Max.Y
     69 	for y := ymin; y < ymax; y++ {
     70 		for x := xmin; x < xmax; x++ {
     71 			dst.Set(x, ymax+ymin-y, img.At(x, y))
     72 		}
     73 	}
     74 	return dst
     75 }
     76 
     77 func flipH(img image.Image) image.Image {
     78 	dst := image.NewRGBA(img.Bounds())
     79 	xmin, ymin := dst.Bounds().Min.X, dst.Bounds().Min.Y
     80 	xmax, ymax := dst.Bounds().Max.X, dst.Bounds().Max.Y
     81 	for y := ymin; y < ymax; y++ {
     82 		for x := xmin; x < xmax; x++ {
     83 			dst.Set(xmax+xmin-x, y, img.At(x, y))
     84 		}
     85 	}
     86 	return dst
     87 }