Beispiel #1
0
// Commit creates the actual texture from the atlas image data.
// This should be called after all regions have been defined and set,
// and before you start using the texture for display.
func (a *TextureAtlas) Commit(target gl.GLenum) {
	gl.PushAttrib(gl.CURRENT_BIT | gl.ENABLE_BIT)
	gl.Enable(target)

	a.texture.Bind(target)

	gl.TexParameteri(target, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
	gl.TexParameteri(target, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
	gl.TexParameteri(target, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
	gl.TexParameteri(target, gl.TEXTURE_MIN_FILTER, gl.LINEAR)

	switch a.depth {
	case 4:
		gl.TexImage2D(target, 0, gl.RGBA, a.width, a.height,
			0, gl.RGBA, gl.UNSIGNED_BYTE, a.data)

	case 3:
		gl.TexImage2D(target, 0, gl.RGB, a.width, a.height,
			0, gl.RGB, gl.UNSIGNED_BYTE, a.data)

	case 1:
		gl.TexImage2D(target, 0, gl.ALPHA, a.width, a.height,
			0, gl.ALPHA, gl.UNSIGNED_BYTE, a.data)
	}

	gl.PopAttrib()
}
Beispiel #2
0
func (t *Texture) FromImageRGBA(rgba *image.RGBA, level int) {
	With(t, func() {
		gl.TexImage2D(gl.TEXTURE_2D, level, gl.RGBA,
			rgba.Bounds().Dx(), rgba.Bounds().Dy(),
			0, gl.RGBA, gl.UNSIGNED_BYTE, rgba.Pix)
	})
}
Beispiel #3
0
func createTexture(r io.Reader) (gl.Texture, error) {
	img, err := png.Decode(r)
	if err != nil {
		return gl.Texture(0), err
	}

	rgbaImg, ok := img.(*image.NRGBA)
	if !ok {
		return gl.Texture(0), errors.New("texture must be an NRGBA image")
	}

	textureId := gl.GenTexture()
	textureId.Bind(gl.TEXTURE_2D)
	gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
	gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)

	// flip image: first pixel is lower left corner
	imgWidth, imgHeight := img.Bounds().Dx(), img.Bounds().Dy()
	data := make([]byte, imgWidth*imgHeight*4)
	lineLen := imgWidth * 4
	dest := len(data) - lineLen
	for src := 0; src < len(rgbaImg.Pix); src += rgbaImg.Stride {
		copy(data[dest:dest+lineLen], rgbaImg.Pix[src:src+rgbaImg.Stride])
		dest -= lineLen
	}
	gl.TexImage2D(gl.TEXTURE_2D, 0, 4, imgWidth, imgHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, data)

	return textureId, nil
}
Beispiel #4
0
// Creates a new Framebuffer.
func NewFramebuffer(w int, h int) (fb *Framebuffer, err error) {
	var (
		buffer  gl.Framebuffer
		texture gl.Texture
	)
	buffer = gl.GenFramebuffer()
	buffer.Bind()
	texture = gl.GenTexture()
	texture.Bind(gl.TEXTURE_2D)
	gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, w, h, 0, gl.RGBA, gl.UNSIGNED_BYTE, nil)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
	gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0)
	gl.DrawBuffer(gl.COLOR_ATTACHMENT0)
	if gl.CheckFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE {
		err = fmt.Errorf("Framebuffer could not be set up")
		return
	}
	fb = &Framebuffer{
		Buffer:  buffer,
		Texture: texture,
		Width:   w,
		Height:  h,
	}
	return
}
func (self *OpenGLRenderer) glTexImage2D(textureType gl.GLenum, texture *render.Texture) {
	gl.TexImage2D(textureType, 0, gl.RGB,
		texture.Image.Width(), texture.Image.Height(), 0,
		gl.BGR, gl.UNSIGNED_BYTE,
		texture.Image.Bytes(),
	)
}
Beispiel #6
0
// loadFont loads the given font data. This does not deal with font scaling.
// Scaling should be handled by the independent Bitmap/Truetype loaders.
// We therefore expect the supplied image and charset to already be adjusted
// to the correct font scale.
//
// The image should hold a sprite sheet, defining the graphical layout for
// every glyph. The config describes font metadata.
func loadFont(img *image.RGBA, config *FontConfig) (f *Font, err error) {
	f = new(Font)
	f.Config = config

	// Resize image to next power-of-two.
	img = glh.Pow2Image(img).(*image.RGBA)
	ib := img.Bounds()

	f.Width = ib.Dx()
	f.Height = ib.Dy()

	// Create the texture itself. It will contain all glyphs.
	// Individual glyph-quads display a subset of this texture.
	f.Texture = gl.GenTexture()
	f.Texture.Bind(gl.TEXTURE_2D)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
	gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, ib.Dx(), ib.Dy(), 0,
		gl.RGBA, gl.UNSIGNED_BYTE, img.Pix)

	// file, err := os.Create("font.png")
	// if err != nil {
	// 	log.Fatal(err)
	// }

	// err = png.Encode(file, img)
	// if err != nil {
	// 	log.Fatal(err)
	// }

	return
}
Beispiel #7
0
// Initialize texture storage. _REQUIRED_ before using it as a framebuffer target.
func (t *Texture) Init() {
	With(t, func() {
		// generate base level storage
		gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, t.W, t.H, 0, gl.RGBA, gl.UNSIGNED_BYTE, nil)
		// generate required number of mipmaps given texture dimensions
		gl.GenerateMipmap(gl.TEXTURE_2D)
	})
}
Beispiel #8
0
func (v *Video) Render() {
	for running {
		select {
		case dimensions := <-v.resize:
			v.ResizeEvent(dimensions[0], dimensions[1])
		case val := <-v.tick:
			slice := make([]uint8, len(val)*3)
			for i := 0; i < len(val); i = i + 1 {
				slice[i*3+0] = (uint8)((val[i] >> 16) & 0xff)
				slice[i*3+1] = (uint8)((val[i] >> 8) & 0xff)
				slice[i*3+2] = (uint8)((val[i]) & 0xff)
			}

			gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)

			v.tex.Bind(gl.TEXTURE_2D)

			if ppu.OverscanEnabled {
				gl.TexImage2D(gl.TEXTURE_2D, 0, 3, 240, 224, 0, gl.RGB, gl.UNSIGNED_BYTE, slice)
			} else {
				gl.TexImage2D(gl.TEXTURE_2D, 0, 3, 256, 240, 0, gl.RGB, gl.UNSIGNED_BYTE, slice)
			}

			gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
			gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)

			gl.Begin(gl.QUADS)
			gl.TexCoord2f(0.0, 1.0)
			gl.Vertex3f(-1.0, -1.0, 0.0)
			gl.TexCoord2f(1.0, 1.0)
			gl.Vertex3f(1.0, -1.0, 0.0)
			gl.TexCoord2f(1.0, 0.0)
			gl.Vertex3f(1.0, 1.0, 0.0)
			gl.TexCoord2f(0.0, 0.0)
			gl.Vertex3f(-1.0, 1.0, 0.0)
			gl.End()

			if v.screen != nil {
				sdl.GL_SwapBuffers()
			}

			v.frametick <- true
		}
	}
}
Beispiel #9
0
func imageAlpha(pix []byte, width, height int) (*Sampler2D, error) {
	s := &Sampler2D{
		tex: gl.GenTexture(),
	}
	s.bind()
	gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
	gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
	gl.TexImage2D(gl.TEXTURE_2D, 0, gl.R8, width, height, 0, gl.RED, gl.UNSIGNED_BYTE, pix)
	return s, nil
}
Beispiel #10
0
func initTexture2(filename string) gl.Texture {
	img, err := glfw.ReadImage(filename+".tga", glfw.NoRescaleBit)
	if err != nil {
		panic(err)
	}
	rt := gl.GenTexture()
	gl.Enable(gl.TEXTURE_2D)
	rt.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)
	gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, img.Width(), img.Height(), 0, gl.RGBA, gl.UNSIGNED_BYTE, img.Data())
	fmt.Println(filename, img.Width(), img.Height())
	return rt
}
Beispiel #11
0
func uploadTexture_RGBA32(w, h int, data []byte) gl.Texture {

	id := gl.GenTexture()
	id.Bind(gl.TEXTURE_2D)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE)
	gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, int(w), int(h), 0, gl.RGBA, gl.UNSIGNED_BYTE, data)

	if gl.GetError() != gl.NO_ERROR {
		id.Delete()
		panic("Failed to load a texture")
		return 0
	}
	return id
}
Beispiel #12
0
func CreateTexture(img image.Image) (*Texture, error) {
	imgW, imgH := img.Bounds().Dx(), img.Bounds().Dy()
	imgDim := Vector2{float32(imgW), float32(imgH)}

	rgbaImg, ok := img.(*image.NRGBA)
	if !ok {
		return nil, errors.New("texture must be an NRGBA image")
	}

	textureId := gl.GenTexture()
	textureId.Bind(gl.TEXTURE_2D)
	gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
	gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)

	gl.TexImage2D(gl.TEXTURE_2D, 0, 4, imgW, imgH, 0, gl.RGBA, gl.UNSIGNED_BYTE, rgbaImg.Pix)

	return &Texture{textureId, imgDim, false, false, false, nextTextureCacheId()}, nil
}
Beispiel #13
0
func NewTextureEmpty(width int, height int, model color.Model) *Texture {
	internalFormat, typ, format, target, e := ColorModelToGLTypes(model)
	if e != nil {
		return nil
	}
	a := gl.GenTexture()
	a.Bind(target)
	gl.TexImage2D(target, 0, internalFormat, width, height, 0, typ, format, nil)

	t := &Texture{a, false, nil, format, typ, internalFormat, target, width, height}

	t.SetWraping(WrapS, ClampToEdge)
	t.SetWraping(WrapT, ClampToEdge)
	t.SetFiltering(Nearest, Nearest)

	ResourceManager.Add(t)

	return t
}
Beispiel #14
0
func functionAdaptor(target gl.GLenum, iformat gl.GLint, format, tp gl.GLenum) texFunction {
	switch target {
	case gl.TEXTURE_1D:
		return func(level int, g *TextureGeometry, pixels interface{}) {
			gl.TexImage1D(gl.TEXTURE_1D, level, int(iformat), g.Width, 0, format, tp, pixels)
		}

	case gl.TEXTURE_2D:
		return func(level int, g *TextureGeometry, pixels interface{}) {
			gl.TexImage2D(gl.TEXTURE_2D, level, int(iformat), g.Width, g.Height, 0, format, tp, pixels)
		}

	case gl.TEXTURE_3D:
		return func(level int, g *TextureGeometry, pixels interface{}) {
			gl.TexImage3D(gl.TEXTURE_3D, level, int(iformat), g.Width, g.Height, g.Depth, 0, format, tp, pixels)
		}
		break
	}

	panic(0)
}
Beispiel #15
0
func initTexture(filename string, width, height int) gl.Texture {
	file, err := os.Open(filename + ".png")
	if err != nil {
		panic(err)
	}
	defer file.Close()
	img, _, err := image.Decode(file)
	if err != nil {
		panic(err)
	}
	t := reflect.ValueOf(img)
	fmt.Println(t.Elem().Type().Name())
	canvas := image.NewRGBA(image.Rect(0, 0, width, height))
	for y := 0; y < height; y++ {
		for x := 0; x < width; x++ {
			r, g, b, a := img.At(x, y).RGBA()
			if (filename == "hex4v" || filename == "hexstar2" || filename == "hexborder") && r == 0 && g == 0 && b == 0 {
				a = 0
			}
			// if filename == "hex5k" {
			// 	fmt.Println(r, g, b, a)
			// }
			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)
		}
	}
	rt := gl.GenTexture()
	gl.Enable(gl.TEXTURE_2D)
	rt.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)
	gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, canvas.Pix)
	return rt
}
Beispiel #16
0
func (v *Video) Render(frame []byte, frame_w int, frame_h int) {
	gl.Clear(gl.COLOR_BUFFER_BIT)
	v.Texture.Bind(gl.TEXTURE_2D)

	gl.TexImage2D(gl.TEXTURE_2D, 0, 3, frame_w, frame_h, 0, gl.RGB, gl.UNSIGNED_BYTE, frame)

	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)

	gl.Begin(gl.QUADS)
	gl.TexCoord2f(0.0, 1.0)
	gl.Vertex3f(-1.0, -1.0, 0.0)
	gl.TexCoord2f(1.0, 1.0)
	gl.Vertex3f(1.0, -1.0, 0.0)
	gl.TexCoord2f(1.0, 0.0)
	gl.Vertex3f(1.0, 1.0, 0.0)
	gl.TexCoord2f(0.0, 0.0)
	gl.Vertex3f(-1.0, 1.0, 0.0)
	gl.End()

	glfw.SwapBuffers()
}
Beispiel #17
0
// Packs image into a texture of size * size dimensions
func (i *ImagePacker) pack(size int) (SpriteSheet, error) {
	rootNode := newNode(size, size)

	for v, img := range i.images {
		err := rootNode.recInsert(img.w, img.h, v)
		if err != nil {
			return SpriteSheet{}, err
		}
	}

	nodeImage := image.NewRGBA(image.Rect(0, 0, size, size))

	traverseNodes(rootNode, func(nd node) {
		draw.Draw(nodeImage, image.Rect(nd.rc.left, nd.rc.top, nd.rc.right, nd.rc.bottom), i.images[nd.id].image, image.ZP, draw.Src)

		i.sprites[nd.id].left = float32(nd.rc.left) / float32(size)
		i.sprites[nd.id].top = float32(nd.rc.bottom) / float32(size)
		i.sprites[nd.id].right = float32(nd.rc.right) / float32(size)
		i.sprites[nd.id].bottom = float32(nd.rc.top) / float32(size)
		i.sprites[nd.id].W = float32(nd.rc.right - nd.rc.left)
		i.sprites[nd.id].H = float32(nd.rc.bottom - nd.rc.top)
	})

	texture := gl.GenTexture()
	texture.Bind(gl.TEXTURE_2D)

	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)

	gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, nodeImage.Pix)

	texture.Unbind(gl.TEXTURE_2D)

	spriteSheet := NewSpriteSheet(texture, size, size)

	return spriteSheet, nil
}
Beispiel #18
0
// bind the given atlas to the current GL context
//
// the current implementation is very stupid, since it will
// upload the texture every single call.
//
// later, improve this to upload only if there is a real need for it
func (a *Atlas) bind() error {
	// discard any possible error
	if err := checkGlError(); err != nil {
		return err
	}
	if gl.Object(a.gltex).IsTexture() {
		a.gltex = gl.GenTexture()
	}
	a.gltex.Bind(gl.TEXTURE_2D)
	gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, a.data.Bounds().Dx(), a.data.Bounds().Dy(), 0, gl.RGBA, gl.UNSIGNED_BYTE, a.data.Pix)
	if err := checkGlError(gl.OUT_OF_MEMORY, gl.INVALID_OPERATION); err != nil {
		return err
	}

	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR)
	gl.GenerateMipmap(gl.TEXTURE_2D)
	panicGlError()
	return nil
}
Beispiel #19
0
func LoadTexture(filename string) gl.Texture {
	r, err := os.Open(filename)
	if err != nil {
		fmt.Fprintf(os.Stderr, "[e] %v\n", err)
		return 0
	}
	defer r.Close()

	img, _, err := image.Decode(r)
	if err != nil {
		fmt.Fprintf(os.Stderr, "[e] %v\n", err)
		return 0
	}

	// lazy way to ensure we have the correct image format for opengl
	rgbaImg := image.NewNRGBA(img.Bounds())
	draw.Draw(rgbaImg, img.Bounds(), img, image.ZP, draw.Src)

	tex := gl.GenTexture()
	tex.Bind(gl.TEXTURE_2D)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)

	// flip image: first pixel is lower left corner
	w, h := img.Bounds().Dx(), img.Bounds().Dy()
	data := make([]byte, w*h*4)
	lineLen := w * 4
	dest := len(data) - lineLen
	for src := 0; src < len(rgbaImg.Pix); src += rgbaImg.Stride {
		copy(data[dest:dest+lineLen], rgbaImg.Pix[src:src+rgbaImg.Stride])
		dest -= lineLen
	}
	gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, w, h, 0, gl.RGBA, gl.UNSIGNED_BYTE, data)

	return tex
}
Beispiel #20
0
func NewTexture2(data interface{}, width int, height int, target gl.GLenum, internalFormat int, typ gl.GLenum, format gl.GLenum) *Texture {
	a := gl.GenTexture()
	a.Bind(target)
	gl.TexImage2D(target, 0, internalFormat, width, height, 0, typ, format, data)

	t := &Texture{a, false, data, format, typ, internalFormat, target, width, height}

	t.SetWraping(WrapS, ClampToEdge)
	t.SetWraping(WrapT, ClampToEdge)
	t.SetFiltering(Nearest, Nearest)

	//ansi := []float32{0}
	//gl.GetFloatv(gl.MAX_TEXTURE_MAX_ANISOTROPY_EXT, ansi)
	//gl.TexParameterf(target, gl.TEXTURE_MAX_ANISOTROPY_EXT, ansi[0])

	t.PreloadRender() //Forcing texture to go to VRAM and prevent shuttering
	t.data = nil
	data = nil

	ResourceManager.Add(t)

	return t
}
Beispiel #21
0
// Initialize texture storage. _REQUIRED_ before using it as a framebuffer target.
func (t *Texture) Init() {
	With(t, func() {
		gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, t.W, t.H, 0, gl.RGBA,
			gl.UNSIGNED_BYTE, nil)
	})
}
Beispiel #22
0
func (video *SDLVideo) Run() {
	running := true
	frame := make([]uint32, 0xf000)

	for running {
		select {
		case ev := <-sdl.Events:
			var event Event

			switch e := ev.(type) {
			case sdl.QuitEvent:
				running = false
				event = &QuitEvent{}
			case sdl.KeyboardEvent:
				switch e.Keysym.Sym {
				case sdl.K_BACKQUOTE:
					if e.Type == sdl.KEYDOWN {
						video.overscan = !video.overscan
					}
				case sdl.K_1:
					if e.Type == sdl.KEYDOWN {
						video.ResizeEvent(256, 240)
					}
				case sdl.K_2:
					if e.Type == sdl.KEYDOWN {
						video.ResizeEvent(512, 480)
					}
				case sdl.K_3:
					if e.Type == sdl.KEYDOWN {
						video.ResizeEvent(768, 720)
					}
				case sdl.K_4:
					if e.Type == sdl.KEYDOWN {
						video.ResizeEvent(1024, 960)
					}
				case sdl.K_5:
					if e.Type == sdl.KEYDOWN {
						video.ResizeEvent(2560, 1440)
					}
				case sdl.K_p:
					if e.Type == sdl.KEYDOWN {
						event = &PauseEvent{}
					}
				case sdl.K_n:
					if e.Type == sdl.KEYDOWN {
						event = &FrameStepEvent{}
					}
				case sdl.K_q:
					if e.Type == sdl.KEYDOWN {
						running = false
						event = &QuitEvent{}
					}
				case sdl.K_l:
					if e.Type == sdl.KEYDOWN {
						event = &SavePatternTablesEvent{}
					}
				case sdl.K_r:
					if e.Type == sdl.KEYDOWN {
						event = &ResetEvent{}
					}
				case sdl.K_s:
					if e.Type == sdl.KEYDOWN {
						event = &RecordEvent{}
					}
				case sdl.K_d:
					if e.Type == sdl.KEYDOWN {
						event = &StopEvent{}
					}
				case sdl.K_KP_PLUS:
					if e.Type == sdl.KEYDOWN {
						event = &AudioRecordEvent{}
					}
				case sdl.K_KP_MINUS:
					if e.Type == sdl.KEYDOWN {
						event = &AudioStopEvent{}
					}

				case sdl.K_o:
					if e.Type == sdl.KEYDOWN {
						event = &CPUDecodeEvent{}
					}
				case sdl.K_i:
					if e.Type == sdl.KEYDOWN {
						event = &PPUDecodeEvent{}
					}
				case sdl.K_9:
					if e.Type == sdl.KEYDOWN {
						event = &ShowBackgroundEvent{}
					}
				case sdl.K_0:
					if e.Type == sdl.KEYDOWN {
						event = &ShowSpritesEvent{}
					}
				case sdl.K_F1:
					if e.Type == sdl.KEYDOWN {
						event = &SaveStateEvent{}
					}
				case sdl.K_F5:
					if e.Type == sdl.KEYDOWN {
						event = &LoadStateEvent{}
					}
				case sdl.K_F8:
					if e.Type == sdl.KEYDOWN {
						event = &FPSEvent{2.}
					}
				case sdl.K_F9:
					if e.Type == sdl.KEYDOWN {
						event = &FPSEvent{1.}
					}
				case sdl.K_F10:
					if e.Type == sdl.KEYDOWN {
						event = &FPSEvent{.75}
					}
				case sdl.K_F11:
					if e.Type == sdl.KEYDOWN {
						event = &FPSEvent{.5}
					}
				case sdl.K_F12:
					if e.Type == sdl.KEYDOWN {
						event = &FPSEvent{.25}
					}
				case sdl.K_KP0:
					if e.Type == sdl.KEYDOWN {
						event = &MuteEvent{}
					}
				case sdl.K_KP1:
					if e.Type == sdl.KEYDOWN {
						event = &MutePulse1Event{}
					}
				case sdl.K_KP2:
					if e.Type == sdl.KEYDOWN {
						event = &MutePulse2Event{}
					}
				case sdl.K_KP3:
					if e.Type == sdl.KEYDOWN {
						event = &MuteTriangleEvent{}
					}
				case sdl.K_KP4:
					if e.Type == sdl.KEYDOWN {
						event = &MuteNoiseEvent{}
					}
				case sdl.K_KP5:
					if e.Type == sdl.KEYDOWN {
						event = &MuteDMCEvent{}
					}
				}

				if event == nil && running {
					event = &ControllerEvent{
						Button: button(e),
						Down:   e.Type == sdl.KEYDOWN,
					}
				}
			}

			if event != nil {
				go func() { video.events <- event }()
			}
		case colors := <-video.input:
			index := 0
			x, y := 0, 0

			for _, c := range colors {
				if pixelInFrame(x, y, video.overscan) {
					frame[index] = video.palette[c]
					index++
				}

				switch x {
				case 255:
					x = 0
					y++
				default:
					x++
				}
			}
			video.framePool.Put(colors)

			gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)

			video.prog.Use()

			gl.ActiveTexture(gl.TEXTURE0)
			video.texture.Bind(gl.TEXTURE_2D)

			gl.TexImage2D(gl.TEXTURE_2D, 0, 3, video.frameWidth(), video.frameHeight(), 0, gl.RGBA,
				gl.UNSIGNED_INT_8_8_8_8, frame)

			gl.DrawArrays(gl.TRIANGLES, 0, 6)

			if video.screen != nil {
				sdl.GL_SwapBuffers()
			}
		}
	}
}
Beispiel #23
0
func (v *Video) Render() {
	for running {
		select {
		case buf := <-v.videoTick:
			gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)

			v.prog.Use()

			gl.ActiveTexture(gl.TEXTURE0)
			v.texture.Bind(gl.TEXTURE_2D)

			gl.TexImage2D(gl.TEXTURE_2D, 0, 3, 240, 224, 0, gl.RGBA,
				gl.UNSIGNED_INT_8_8_8_8, buf)

			gl.DrawArrays(gl.TRIANGLES, 0, 6)

			if v.screen != nil {
				sdl.GL_SwapBuffers()
				v.fpsmanager.FramerateDelay()
			}
		case ev := <-sdl.Events:
			switch e := ev.(type) {
			case sdl.ResizeEvent:
				v.ResizeEvent(int(e.W), int(e.H))
			case sdl.QuitEvent:
				os.Exit(0)
			case sdl.KeyboardEvent:
				switch e.Keysym.Sym {
				case sdl.K_ESCAPE:
					running = false
				case sdl.K_r:
					// Trigger reset interrupt
					if e.Type == sdl.KEYDOWN {
						// cpu.RequestInterrupt(InterruptReset)
					}
				case sdl.K_l:
					if e.Type == sdl.KEYDOWN {
						nes.LoadGameState()
					}
				case sdl.K_s:
					if e.Type == sdl.KEYDOWN {
						nes.SaveGameState()
					}
				case sdl.K_i:
					if e.Type == sdl.KEYDOWN {
						nes.AudioEnabled = !nes.AudioEnabled
					}
				case sdl.K_1:
					if e.Type == sdl.KEYDOWN {
						v.ResizeEvent(256, 240)
					}
				case sdl.K_2:
					if e.Type == sdl.KEYDOWN {
						v.ResizeEvent(512, 480)
					}
				case sdl.K_3:
					if e.Type == sdl.KEYDOWN {
						v.ResizeEvent(768, 720)
					}
				case sdl.K_4:
					if e.Type == sdl.KEYDOWN {
						v.ResizeEvent(1024, 960)
					}
				}

				switch e.Type {
				case sdl.KEYDOWN:
					nes.Pads[0].KeyDown(e, 0)
				case sdl.KEYUP:
					nes.Pads[0].KeyUp(e, 0)
				}
			}
		}
	}
}
Beispiel #24
0
// Create a *Texture containing a rendering of `str` with `size`.
// TODO: allow for alternative fonts
func MakeText(str string, size float64) *Text {
	if str == "" {
		panic("Trying to build empty text")
	}

	defer OpenGLSentinel()()

	// TODO: Something if font doesn't exist
	fontBytes, err := ioutil.ReadFile(FontFile)
	if err != nil {
		log.Panic(err)
	}
	font, err := freetype.ParseFont(fontBytes)
	if err != nil {
		log.Panic(err)
	}

	fg, bg := image.White, image.Black

	c := freetype.NewContext()
	c.SetDPI(72)
	c.SetFont(font)
	c.SetFontSize(size)

	pt := freetype.Pt(0, int(c.PointToFix32(size)>>8))
	s, err := c.DrawString(str, pt)
	if err != nil {
		log.Panic("Error: ", err)
	}

	spacing, offset := 1.5, 3

	w := int(s.X >> 8)
	h := int(c.PointToFix32(size*spacing)>>8) - offset

	text := &Text{str: str, Texture: NewTexture(w, h)}

	if text.W > 4096 {
		text.W = 4096
	}

	rgba := image.NewRGBA(image.Rect(0, 0, text.W, text.H))
	draw.Draw(rgba, rgba.Bounds(), bg, image.ZP, draw.Src)
	c.SetClip(rgba.Bounds())
	c.SetDst(rgba)
	c.SetSrc(fg)

	_, err = c.DrawString(text.str, pt)
	if err != nil {
		log.Panic("Error: ", err)
	}

	With(text, func() {
		gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, text.W, text.H, 0, gl.RGBA,
			gl.UNSIGNED_BYTE, rgba.Pix)
	})

	if gl.GetError() != gl.NO_ERROR {
		log.Panic("Failed to load a texture, err = ", gl.GetError(),
			" str = ", str, " w = ", text.W, " h = ", text.H)
	}

	return text
}
Beispiel #25
0
func main() {
	b, _ := ioutil.ReadFile("./roboto/roboto-light.ttf")

	font, ferr := tt.Parse(b)

	if ferr != nil {
		fmt.Println("can't parse font %v , len %v", ferr.Error(), len(b))
	}

	fc := ft.NewContext()
	fc.SetFont(font)

	glfw.SetErrorCallback(errorCallback)

	if !glfw.Init() {
		panic("Can't init glfw!")
	}
	defer glfw.Terminate()

	window, err := glfw.CreateWindow(800, 600, "Testing", nil, nil)
	if err != nil {
		panic(err)
	}

	window.MakeContextCurrent()

	gl.Init()

	program := gl.CreateProgram()

	vertexShader := gl.CreateShader(gl.VERTEX_SHADER)
	vertexShader.Source(`
        attribute vec4 a_position;
        attribute vec2 a_coord;
        varying vec2 v_coord;
        void main() {
          gl_Position = a_position;
          v_coord = a_coord;
        }
    `)
	vertexShader.Compile()
	fmt.Printf("vertex: %v\n", vertexShader.GetInfoLog())

	fragmentShader := gl.CreateShader(gl.FRAGMENT_SHADER)
	fragmentShader.Source(`
        varying vec2 v_coord;
        uniform sampler2D s_picture;
        uniform vec4 color;
        uniform bool has_picture;
        void main() {
            if(has_picture) {
	            gl_FragColor = texture2D(s_picture, v_coord);
	        } else {
                gl_FragColor = color;
	        }
        } 
    `)

	fragmentShader.Compile()
	fmt.Printf("fragment %v \n", fragmentShader.GetInfoLog())

	program.AttachShader(vertexShader)
	program.AttachShader(fragmentShader)

	program.Link()

	// ini

	//gl.MatrixMode(gl.PROJECTION)
	//gl.Ortho(0, 640, 0, 480, 0, 1)

	gl.ClearColor(0.5, 0.5, 0.5, 0.0)

	root := widget.Widget{
		Name:       "Red",
		Rect:       image.Rect(0, 0, 800, 600),
		Background: color.RGBA{255, 128, 128, 126},
		OnClick:    widget.ClickInner,
		OnDrag:     widget.DragInner,
		OnHover:    widget.HoverInner,
		OnResize:   widget.ResizeItself,
	}

	blue := root.AddWidget(&widget.Widget{
		Name:       "Blue",
		Rect:       image.Rect(100, 100, 200, 200),
		Image:      LoadImage("./test.png"),
		Background: color.RGBA{128, 128, 255, 126},
		OnClick: func(w *widget.Widget, p image.Point) {
			root.SetTop(w)
			fmt.Println("Clicked blue box")
			widget.ClickInner(w, p)
		},
		OnDrag: func(w *widget.Widget, p image.Point, d image.Point) bool {
			widget.DragInner(w, p, d)
			widget.DragItself(w, p, d)
			return true
		},
		OnResize: widget.ResizeItself,
	})

	blue.AddWidget(&widget.Widget{
		Name:       "White",
		Rect:       image.Rect(90, 90, 100, 100),
		Background: color.RGBA{250, 250, 250, 250},
		OnDrag: func(w *widget.Widget, p image.Point, d image.Point) bool {
			widget.DragItself(w, p, d)
			blue.Resize(d)
			return true
		},
	})

	root.AddWidget(&widget.Widget{
		Name:       "Green",
		Rect:       image.Rect(100, 300, 200, 400),
		Background: color.RGBA{128, 255, 128, 126},
		OnClick: func(w *widget.Widget, p image.Point) {
			root.SetTop(w)
			w.Image = LoadImage("./test2.png")
		},
		OnDrag: widget.DragItself,
	})

	root.AddWidget(&widget.Widget{
		Name:       "Black",
		Rect:       image.Rect(100, 400, 150, 450),
		Background: color.RGBA{0, 0, 0, 126},
		OnHover: func(w *widget.Widget, p0 image.Point, p1 image.Point) {
			if p1.In(w.Rect) {
				w.Background = color.RGBA{255, 255, 255, 126}
			} else {
				w.Background = color.RGBA{0, 0, 0, 126}
			}
		},
	})

	white := root.AddWidget(&widget.Widget{
		Name:       "White",
		Text:       "Меня зовут Светлана, я из города Иваново. «Единая Россия» очень много сделала достижений: они подняли экономик… экономику, мы стали более лучшие… одеваться, и не было того что щас — это очень большие достижения! В сельском хозяйстве очень хорошо. (Гладин: Что именно в сельском хозяйстве они сделали?) Стало больше… земель за-а… много, ну… я не знаю даже как сказать… засеивать больше земель… а-а-а вот, овощи там, рожь — вот это всё. Что еще сказать… Так как у нас страна многонациональная, у нас в Москве очень много людей, которые очень помогают нам… с других городов… (вопрос Гладина: Вы считаете это достижение «Единой России»?) Да, это большое достижение! Очень хорошее даже! Видите ну… да… Видите ну у нас в Иванове очень хорошая стала медицина… а…что ещё… благоустройство в городах хорошее… с жильём… никаких проблем. Люди подмогают очень хорошо",
		Rect:       image.Rect(400, 200, 700, 500),
		Foreground: color.RGBA{0, 0, 0, 0},
		Background: color.RGBA{255, 255, 255, 126},
		OnDrag: func(w *widget.Widget, p image.Point, d image.Point) bool {
			root.SetTop(w)
			widget.DragInner(w, p, d)
			widget.DragItself(w, p, d)
			return true
		},
		OnResize: widget.ResizeItself,
		Padding:  image.Rect(20, 20, 20, 20),
	})

	white.AddWidget(&widget.Widget{
		Name:       "White",
		Rect:       image.Rect(290, 290, 300, 300),
		Background: color.RGBA{0, 0, 0, 250},
		OnDrag: func(w *widget.Widget, p image.Point, d image.Point) bool {
			widget.DragItself(w, p, d)
			white.Resize(d)
			return true
		},
	})

	x0 := 0.0
	y0 := 0.0

	window.SetMouseButtonCallback(func(w *glfw.Window, but glfw.MouseButton, act glfw.Action, key glfw.ModifierKey) {
		xpos, ypos := w.GetCursorPosition()

		if act == glfw.Press {
			root.Click(image.Point{X: int(xpos), Y: int(ypos)})

			x0, y0 = xpos, ypos
		}
	})

	window.SetCursorPositionCallback(func(w *glfw.Window, xpos float64, ypos float64) {
		root.Hover(image.Point{X: int(x0), Y: int(y0)}, image.Point{X: int(xpos), Y: int(ypos)})

		if w.GetMouseButton(glfw.MouseButtonLeft) == glfw.Press {
			root.Drag(image.Point{X: int(x0), Y: int(y0)}, image.Point{X: int(xpos - x0), Y: int(ypos - y0)})
			x0, y0 = xpos, ypos
		}

		x0, y0 = xpos, ypos
	})

	width0, height0 := window.GetSize()

	window.SetSizeCallback(func(w *glfw.Window, width int, height int) {
		gl.Viewport(0, 0, width, height)
		root.Rect.Max = image.Point{width, height}
		width0, height0 = width, height
	})

	/*switch(color_type){
	case PNG_COLOR_TYPE_GRAY:
		return GL_LUMINANCE;
	case PNG_COLOR_TYPE_GRAY_ALPHA:
		return GL_LUMINANCE_ALPHA;
	case PNG_COLOR_TYPE_RGB:
		return GL_RGB;
	case PNG_COLOR_TYPE_RGB_ALPHA:
		return GL_RGBA;
	*/

	/*
	   here init texture pool

	   texturePool := make([widget.Widget]texture)
	*/
	for !window.ShouldClose() {
		//Do OpenGL stuff
		program.Use()

		gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)

		root.DrawBy(image.Point{}, func(w *widget.Widget, corner image.Point) {
			var texture gl.Texture

			if w.Image != nil {
				texture = gl.GenTexture()
				texture.Bind(gl.TEXTURE_2D)
				gl.ActiveTexture(gl.TEXTURE0)

				gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA,
					w.Image.Rect.Dx(), w.Image.Rect.Dy(),
					0, gl.RGBA, gl.UNSIGNED_BYTE, w.Image.Pix)
			}

			leftX := 2.0*float32(corner.X+w.Rect.Min.X)/float32(root.Rect.Dx()) - 1.0
			leftY := 1.0 - 2.0*float32(corner.Y+w.Rect.Min.Y)/float32(root.Rect.Dy())

			rightX := 2.0*float32(corner.X+w.Rect.Min.X)/float32(root.Rect.Dx()) - 1.0
			rightY := 1.0 - 2.0*float32(corner.Y+w.Rect.Max.Y)/float32(root.Rect.Dy())

			bottomX := 2.0*float32(corner.X+w.Rect.Max.X)/float32(root.Rect.Dx()) - 1.0
			bottomY := 1.0 - 2.0*float32(corner.Y+w.Rect.Min.Y)/float32(root.Rect.Dy())

			topX := 2.0*float32(corner.X+w.Rect.Max.X)/float32(root.Rect.Dx()) - 1.0
			topY := 1.0 - 2.0*float32(corner.Y+w.Rect.Max.Y)/float32(root.Rect.Dy())

			vertices := []float32{
				leftX, leftY,
				rightX, rightY,
				bottomX, bottomY,
				topX, topY,
			}

			texturePoints := []float32{
				0.0, 0.0, 0.0, 1.0,
				1.0, 0.0, 1.0, 1.0,
			}

			s_picture := program.GetUniformLocation("s_picture")
			s_picture.Uniform1i(0)

			has_picture := program.GetUniformLocation("has_picture")

			if w.Image != nil {
				has_picture.Uniform1i(1)
			} else {
				has_picture.Uniform1i(0)
			}

			col := program.GetUniformLocation("color")
			r, g, b, a := w.Background.RGBA()
			col.Uniform4f(float32(r)/float32(0xFFFF), float32(g)/float32(0xFFFF), float32(b)/float32(0xFFFF), float32(a)/float32(0xFFFF))

			gl.PixelStorei(gl.UNPACK_ALIGNMENT, gl.UNSIGNED_BYTE)
			gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)

			a_position := program.GetAttribLocation("a_position")
			a_position.AttribPointer(2, gl.FLOAT, false, 0, vertices)
			a_position.EnableArray()

			a_coord := program.GetAttribLocation("a_coord")
			a_coord.AttribPointer(2, gl.FLOAT, false, 0, texturePoints)
			a_coord.EnableArray()

			gl.DrawArrays(gl.TRIANGLE_STRIP, 0, 4)
			gl.Flush()

			texture.Delete()

			if len(w.Text) > 0 {
				rct := w.Rect
				rct.Max = rct.Max.Sub(w.Rect.Min)
				rct.Min = rct.Min.Sub(w.Rect.Min)

				fg := image.NewRGBA(rct)
				fgu := image.NewUniform(color.RGBA{0, 16, 32, 255})
				draw.Draw(fg, fg.Bounds(), fgu, image.ZP, draw.Src)

				bg := image.NewRGBA(rct)
				bgu := image.NewUniform(color.RGBA{255, 255, 255, 255})
				draw.Draw(bg, bg.Bounds(), bgu, image.ZP, draw.Src)

				lineHeight := 20.0

				fc.SetDPI(100.0)
				fc.SetFont(font)
				fc.SetFontSize(12.0)
				fc.SetClip(bg.Bounds())
				fc.SetDst(bg)
				fc.SetSrc(fg)

				p0 := ft.Pt(w.Padding.Min.X, w.Padding.Min.Y)
				p := p0
				for _, s := range w.Text {
					p, _ = fc.DrawString(string(s), p)
					if int(p.X>>8) > rct.Max.X-w.Padding.Max.X-w.Padding.Min.X {
						p.X = p0.X
						p.Y += raster.Fix32(lineHeight * 256)
					}
				}

				var texture gl.Texture

				if bg != nil {
					texture = gl.GenTexture()
					texture.Bind(gl.TEXTURE_2D)
					gl.ActiveTexture(gl.TEXTURE0)

					gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA,
						bg.Rect.Dx(), bg.Rect.Dy(),
						0, gl.RGBA, gl.UNSIGNED_BYTE, bg.Pix)
				}

				leftX := 2.0*float32(corner.X+w.Rect.Min.X)/float32(root.Rect.Dx()) - 1.0
				leftY := 1.0 - 2.0*float32(corner.Y+w.Rect.Min.Y)/float32(root.Rect.Dy())

				rightX := 2.0*float32(corner.X+w.Rect.Min.X)/float32(root.Rect.Dx()) - 1.0
				rightY := 1.0 - 2.0*float32(corner.Y+w.Rect.Max.Y)/float32(root.Rect.Dy())

				bottomX := 2.0*float32(corner.X+w.Rect.Max.X)/float32(root.Rect.Dx()) - 1.0
				bottomY := 1.0 - 2.0*float32(corner.Y+w.Rect.Min.Y)/float32(root.Rect.Dy())

				topX := 2.0*float32(corner.X+w.Rect.Max.X)/float32(root.Rect.Dx()) - 1.0
				topY := 1.0 - 2.0*float32(corner.Y+w.Rect.Max.Y)/float32(root.Rect.Dy())

				vertices := []float32{
					leftX, leftY,
					rightX, rightY,
					bottomX, bottomY,
					topX, topY,
				}

				texturePoints := []float32{
					0.0, 0.0, 0.0, 1.0,
					1.0, 0.0, 1.0, 1.0,
				}

				s_picture := program.GetUniformLocation("s_picture")
				s_picture.Uniform1i(0)

				has_picture := program.GetUniformLocation("has_picture")

				if bg != nil {
					has_picture.Uniform1i(1)
				} else {
					has_picture.Uniform1i(0)
				}

				col := program.GetUniformLocation("color")
				r, g, b, a := w.Background.RGBA()
				col.Uniform4f(float32(r)/float32(0xFFFF), float32(g)/float32(0xFFFF), float32(b)/float32(0xFFFF), float32(a)/float32(0xFFFF))

				gl.PixelStorei(gl.UNPACK_ALIGNMENT, gl.UNSIGNED_BYTE)
				gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)

				a_position := program.GetAttribLocation("a_position")
				a_position.AttribPointer(2, gl.FLOAT, false, 0, vertices)
				a_position.EnableArray()

				a_coord := program.GetAttribLocation("a_coord")
				a_coord.AttribPointer(2, gl.FLOAT, false, 0, texturePoints)
				a_coord.EnableArray()

				gl.DrawArrays(gl.TRIANGLE_STRIP, 0, 4)
				gl.Flush()

				texture.Delete()
			}
		})

		window.SwapBuffers()
		glfw.PollEvents()
	}
}
Beispiel #26
0
// loadFont loads the given font data. This does not deal with font scaling.
// Scaling should be handled by the independent Bitmap/Truetype loaders.
// We therefore expect the supplied image and charset to already be adjusted
// to the correct font scale.
//
// The image should hold a sprite sheet, defining the graphical layout for
// every glyph. The config describes font metadata.
func loadFont(img *image.RGBA, config *FontConfig) (f *Font, err error) {
	f = new(Font)
	f.config = config

	// Resize image to next power-of-two.
	img = glh.Pow2Image(img).(*image.RGBA)
	ib := img.Bounds()

	// Create the texture itself. It will contain all glyphs.
	// Individual glyph-quads display a subset of this texture.
	f.texture = gl.GenTexture()
	f.texture.Bind(gl.TEXTURE_2D)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
	gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, ib.Dx(), ib.Dy(), 0,
		gl.RGBA, gl.UNSIGNED_BYTE, img.Pix)

	// Create display lists for each glyph.
	f.listbase = gl.GenLists(len(config.Glyphs))

	texWidth := float32(ib.Dx())
	texHeight := float32(ib.Dy())

	for index, glyph := range config.Glyphs {
		// Update max glyph bounds.
		if glyph.Width > f.maxGlyphWidth {
			f.maxGlyphWidth = glyph.Width
		}

		if glyph.Height > f.maxGlyphHeight {
			f.maxGlyphHeight = glyph.Height
		}

		// Quad width/height
		vw := float32(glyph.Width)
		vh := float32(glyph.Height)

		// Texture coordinate offsets.
		tx1 := float32(glyph.X) / texWidth
		ty1 := float32(glyph.Y) / texHeight
		tx2 := (float32(glyph.X) + vw) / texWidth
		ty2 := (float32(glyph.Y) + vh) / texHeight

		// Advance width (or height if we render top-to-bottom)
		adv := float32(glyph.Advance)

		gl.NewList(f.listbase+uint(index), gl.COMPILE)
		{
			gl.Begin(gl.QUADS)
			{
				gl.TexCoord2f(tx1, ty2)
				gl.Vertex2f(0, 0)
				gl.TexCoord2f(tx2, ty2)
				gl.Vertex2f(vw, 0)
				gl.TexCoord2f(tx2, ty1)
				gl.Vertex2f(vw, vh)
				gl.TexCoord2f(tx1, ty1)
				gl.Vertex2f(0, vh)
			}
			gl.End()

			switch config.Dir {
			case LeftToRight:
				gl.Translatef(adv, 0, 0)
			case RightToLeft:
				gl.Translatef(-adv, 0, 0)
			case TopToBottom:
				gl.Translatef(0, -adv, 0)
			}
		}
		gl.EndList()
	}

	err = glh.CheckGLError()
	return
}
Beispiel #27
0
func LoadTexture() {
	gl.ActiveTexture(gl.TEXTURE0)
	if err := CheckGlError(); err != nil {
		panic(err)
	}

	t := gl.GenTexture()
	if err := CheckGlError(); err != nil {
		panic(err)
	}

	const target = gl.TEXTURE_2D

	t.Bind(target)
	if err := CheckGlError(); err != nil {
		panic(err)
	}

	img, err := LoadImage("test.jpg")
	if err != nil {
		panic(err)
	}

	data := GlRgba(img, matrix23{1, 0, 0, 1, 0, 0})
	size := img.Bounds().Size()

	gl.TexImage2D(
		target,
		0,                // Mipmap level.
		gl.SRGB8_ALPHA8,  // Format inside OpenGL.
		size.X,           // Width.
		size.Y,           // Height.
		0,                // Border.  Doc says it must be 0.
		gl.RGBA,          // Format of the data that...
		gl.UNSIGNED_BYTE, // ... I give to OpenGL.
		data,             // And the data itself.
	)
	if err := CheckGlError(); err != nil {
		panic(err)
	}

	gl.GenerateMipmap(target)
	if err := CheckGlError(); err != nil {
		panic(err)
	}

	gl.TexParameteri(target, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR)
	if err := CheckGlError(); err != nil {
		panic(err)
	}
	gl.TexParameteri(target, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
	if err := CheckGlError(); err != nil {
		panic(err)
	}
	gl.TexParameteri(target, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE)
	if err := CheckGlError(); err != nil {
		panic(err)
	}
	gl.TexParameteri(target, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
	if err := CheckGlError(); err != nil {
		panic(err)
	}

	t.Unbind(target)

	globaltexture = t
}
Beispiel #28
0
func LoadSkybox() {
	gl.ActiveTexture(gl.TEXTURE0)
	if err := CheckGlError(); err != nil {
		panic(err)
	}

	t := gl.GenTexture()
	if err := CheckGlError(); err != nil {
		panic(err)
	}

	t.Bind(gl.TEXTURE_CUBE_MAP)
	if err := CheckGlError(); err != nil {
		panic(err)
	}

	const filename = "Skybox_tut13_384x256.png"
	img, err := LoadImage(filename)
	if err != nil {
		panic(err)
	}

	size := img.Bounds().Size()
	w := size.X
	h := size.Y
	if w/3 != h/2 {
		panic("incorrect aspect ratio")
	}
	s := h / 2 // Size of one face of the cube.

	targets := [...]gl.GLenum{
		gl.TEXTURE_CUBE_MAP_NEGATIVE_X,
		gl.TEXTURE_CUBE_MAP_POSITIVE_X,
		gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,
		gl.TEXTURE_CUBE_MAP_POSITIVE_Y,
		gl.TEXTURE_CUBE_MAP_NEGATIVE_Z,
		gl.TEXTURE_CUBE_MAP_POSITIVE_Z,
	}
	rs := []image.Rectangle{
		image.Rect(0*s, 0*s, 1*s, 1*s), // 0 side.
		image.Rect(1*s, 0*s, 2*s, 1*s), // 1 side.
		image.Rect(2*s, 0*s, 3*s, 1*s), // 2 side.
		image.Rect(0*s, 1*s, 1*s, 2*s), // 3 bottom.
		image.Rect(1*s, 1*s, 2*s, 2*s), // 4 top.
		image.Rect(2*s, 1*s, 3*s, 2*s), // 5 side.
	}
	// redirect must end with 3 and 4.  This places the floor at -z and the
	// sky at +z.
	// All the sides look properly oriented (grass down) on the +y side.
	// Considering that the sky is properly oriented the way it is, then
	// rectangle 5 contains the picture that matches it on the +y side.
	// Therefore, redirect must end with 5, 3, 4.
	// Problem now: all the other sides, and maybe the floor too, need to be
	// rotated in order to line up, that is having their sky on top.
	redirect := [...]int{0, 2, 1, 5, 3, 4}

	ID := matrix23{1, 0, 0, 1, 0, 0}
	ms := [...]matrix23{
		matrix23{0, -1, 1, 0, 0, s - 1},
		matrix23{0, 1, -1, 0, s - 1, 0},
		matrix23{-1, 0, 0, -1, s - 1, s - 1},
		ID,
		matrix23{-1, 0, 0, -1, s - 1, s - 1},
		ID,
	}

	rgba := forceRGBA(img)
	for i, target := range targets {
		subimage := rgba.SubImage(rs[redirect[i]])
		data := GlRgba(subimage, ms[i])
		gl.TexImage2D(
			target,
			0,                // Mipmap level.
			gl.SRGB8_ALPHA8,  // Format inside OpenGL.
			s,                // Width.
			s,                // Height.
			0,                // Border.  Doc says it must be 0.
			gl.RGBA,          // Format of the data that...
			gl.UNSIGNED_BYTE, // ... I give to OpenGL.
			data,             // And the data itself.
		)
		if err := CheckGlError(); err != nil {
			panic(err)
		}
	}

	const target = gl.TEXTURE_CUBE_MAP
	gl.GenerateMipmap(target)
	if err := CheckGlError(); err != nil {
		panic(err)
	}

	gl.TexParameteri(target, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR)
	if err := CheckGlError(); err != nil {
		panic(err)
	}
	gl.TexParameteri(target, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
	if err := CheckGlError(); err != nil {
		panic(err)
	}
	gl.TexParameteri(target, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE)
	if err := CheckGlError(); err != nil {
		panic(err)
	}
	gl.TexParameteri(target, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
	if err := CheckGlError(); err != nil {
		panic(err)
	}
	gl.TexParameteri(target, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
	if err := CheckGlError(); err != nil {
		panic(err)
	}

	t.Unbind(target)

	globaltexture = t
}