func (m *Manager) LoadSprite(path string) (*Sprite, error) { // We can't run this during an init() function because it will get queued to // run before the opengl context is created, so we just check here and run // it if we haven't run it before. gen_tex_once.Do(func() { render.Queue(func() { gl.Enable(gl.TEXTURE_2D) error_texture = gl.GenTexture() error_texture.Bind(gl.TEXTURE_2D) gl.TexEnvf(gl.TEXTURE_ENV, gl.TEXTURE_ENV_MODE, gl.MODULATE) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT) pink := []byte{255, 0, 255, 255} glu.Build2DMipmaps(gl.TEXTURE_2D, 4, 1, 1, gl.RGBA, pink) }) }) path = filepath.Clean(path) err := m.loadSharedSprite(path) if err != nil { return nil, err } var s Sprite m.mutex.Lock() s.shared = m.shared[path] m.mutex.Unlock() s.anim_node = s.shared.anim_start s.state_node = s.shared.state_start return &s, nil }
// Creates a LosTexture with the specified size, which must be a power of two. func MakeLosTexture() *LosTexture { var lt LosTexture lt.pix = make([]byte, LosTextureSizeSquared) lt.p2d = make([][]byte, LosTextureSize) lt.rec = make(chan gl.Texture, 1) for i := 0; i < LosTextureSize; i++ { lt.p2d[i] = lt.pix[i*LosTextureSize : (i+1)*LosTextureSize] } render.Queue(func() { gl.Enable(gl.TEXTURE_2D) tex := gl.GenTexture() tex.Bind(gl.TEXTURE_2D) gl.TexEnvf(gl.TEXTURE_ENV, gl.TEXTURE_ENV_MODE, gl.MODULATE) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT) gl.TexImage2D(gl.TEXTURE_2D, 0, gl.ALPHA, len(lt.p2d), len(lt.p2d), 0, gl.ALPHA, gl.BYTE, lt.pix) lt.rec <- tex runtime.SetFinalizer(<, losTextureFinalize) }) return < }
func makeErrorTexture() { gl.Enable(gl.TEXTURE_2D) error_texture = gl.GenTexture() error_texture.Bind(gl.TEXTURE_2D) gl.TexEnvf(gl.TEXTURE_ENV, gl.TEXTURE_ENV_MODE, gl.MODULATE) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT) transparent := []byte{0, 0, 0, 0} glu.Build2DMipmaps(gl.TEXTURE_2D, 4, 1, 1, gl.RGBA, transparent) }
func (s *sheet) makeTexture(pixer <-chan []byte) { gl.Enable(gl.TEXTURE_2D) s.texture = gl.GenTexture() s.texture.Bind(gl.TEXTURE_2D) gl.TexEnvf(gl.TEXTURE_ENV, gl.TEXTURE_ENV_MODE, gl.MODULATE) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT) data := <-pixer glu.Build2DMipmaps(gl.TEXTURE_2D, 4, s.dx, s.dy, gl.RGBA, data) memory.FreeBlock(data) }
func (w *ImageBox) SetImage(path string) { w.UnsetImage() data, err := os.Open(path) if err != nil { // TODO: Log error return } var img image.Image img, _, err = image.Decode(data) if err != nil { // TODO: Log error return } w.Request_dims.Dx = img.Bounds().Dx() w.Request_dims.Dy = img.Bounds().Dy() canvas := image.NewRGBA(image.Rect(0, 0, img.Bounds().Dx(), img.Bounds().Dy())) for y := 0; y < canvas.Bounds().Dy(); y++ { for x := 0; x < canvas.Bounds().Dx(); x++ { r, g, b, a := img.At(x, y).RGBA() base := 4*x + canvas.Stride*y canvas.Pix[base] = uint8(r) canvas.Pix[base+1] = uint8(g) canvas.Pix[base+2] = uint8(b) canvas.Pix[base+3] = uint8(a) } } w.texture = gl.GenTexture() gl.Enable(gl.TEXTURE_2D) w.texture.Bind(gl.TEXTURE_2D) gl.TexEnvf(gl.TEXTURE_ENV, gl.TEXTURE_ENV_MODE, gl.MODULATE) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT) glu.Build2DMipmaps(gl.TEXTURE_2D, 4, img.Bounds().Dx(), img.Bounds().Dy(), gl.RGBA, canvas.Pix) w.active = true }
func (w *TextLine) figureDims() { // Always draw the text as white on a transparent background so that we can change // the color easily through opengl w.rdims.Dx, w.rdims.Dy = drawText(w.font, w.context, color.RGBA{255, 255, 255, 255}, image.NewRGBA(image.Rect(0, 0, 1, 1)), w.text) texture_dims := Dims{ Dx: int(nextPowerOf2(uint32(w.rdims.Dx))), Dy: int(nextPowerOf2(uint32(w.rdims.Dy))), } w.rgba = image.NewRGBA(image.Rect(0, 0, texture_dims.Dx, texture_dims.Dy)) drawText(w.font, w.context, color.RGBA{255, 255, 255, 255}, w.rgba, w.text) gl.Enable(gl.TEXTURE_2D) w.texture.Bind(gl.TEXTURE_2D) gl.TexEnvf(gl.TEXTURE_ENV, gl.TEXTURE_ENV_MODE, gl.MODULATE) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT) glu.Build2DMipmaps(gl.TEXTURE_2D, 4, w.rgba.Bounds().Dx(), w.rgba.Bounds().Dy(), gl.RGBA, w.rgba.Pix) gl.Disable(gl.TEXTURE_2D) }
func handleLoadRequest(req loadRequest) { f, _ := os.Open(req.path) im, _, err := image.Decode(f) f.Close() if err != nil { return } gray := true dx := im.Bounds().Dx() dy := im.Bounds().Dy() for i := 0; i < dx; i++ { for j := 0; j < dy; j++ { r, g, b, _ := im.At(i, j).RGBA() if r != g || g != b { gray = false break } } if !gray { break } } var canvas draw.Image var pix []byte if gray { ga := NewGrayAlpha(im.Bounds()) pix = ga.Pix canvas = ga } else { pix = memory.GetBlock(4 * req.data.dx * req.data.dy) canvas = &image.RGBA{pix, 4 * req.data.dx, im.Bounds()} } draw.Draw(canvas, im.Bounds(), im, image.Point{}, draw.Src) load_mutex.Lock() load_count += len(pix) manual_unlock := false // This prevents us from trying to send too much to opengl in a single // frame. If we go over the threshold then we hold the lock until we're // done sending data to opengl, then other requests will be free to // queue up and they will run on the next frame. if load_count < load_threshold { load_mutex.Unlock() } else { manual_unlock = true } render.Queue(func() { { gl.Enable(gl.TEXTURE_2D) req.data.texture = gl.GenTexture() req.data.texture.Bind(gl.TEXTURE_2D) gl.TexEnvf(gl.TEXTURE_ENV, gl.TEXTURE_ENV_MODE, gl.MODULATE) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT) } if gray { glu.Build2DMipmaps(gl.TEXTURE_2D, gl.LUMINANCE_ALPHA, req.data.dx, req.data.dy, gl.LUMINANCE_ALPHA, pix) } else { glu.Build2DMipmaps(gl.TEXTURE_2D, gl.RGBA, req.data.dx, req.data.dy, gl.RGBA, pix) } memory.FreeBlock(pix) if manual_unlock { load_count = 0 load_mutex.Unlock() } }) }