Example #1
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
}
Example #2
0
File: atlas.go Project: andrebq/exp
// NewAtlas will create a new atlas with enough space to
// at least nRows X nColumns chunks of widthXheight size. The total
// number of chunks are determinated by the power of two rule below.
//
// The actual memory used might be larger since all atlas MUST BE
// a power of 2 rect (16, 32, 64, 128...). But the rectangle used
// by the chunk is limited to width/height.
func NewAtlas(width, height, nRows, nColumns int) *Atlas {
	_, max := minMaxOf(powerOfTwo(nRows*height), powerOfTwo(nColumns*width))
	return &Atlas{
		cw:    width,
		ch:    height,
		data:  image.NewRGBA(image.Rect(0, 0, max, max)),
		gltex: gl.Texture(gl.FALSE),
	}
}
Example #3
0
File: atlas.go Project: andrebq/exp
func (a *Atlas) unbind(release bool) error {
	if !gl.Object(a.gltex).IsTexture() {
		return nil
	}
	a.gltex.Unbind(gl.TEXTURE_2D)
	if release {
		a.gltex.Delete()
	}
	a.gltex = gl.Texture(gl.FALSE)
	return checkGlError()
}
Example #4
0
// Bind binds the texture
func (t *Texture) Bind(coordType CoordType) {
	// ensureGlContext()

	if t != nil && t.t != 0 {
		// Bind the texture
		t.t.Bind(gl.TEXTURE_2D)

		// Check if we need to define a special texture matrix
		if coordType == CoordPixels || t.pixelsFlipped {
			matrix := [16]float32{1, 0, 0, 0,
				0, 1, 0, 0,
				0, 0, 1, 0,
				0, 0, 0, 1}

			// If non-normalized coordinates (= pixels) are requested, we need to
			// setup scale factors that convert the range [0 .. size] to [0 .. 1]
			if coordType == CoordPixels {
				matrix[0] = 1.0 / t.size.X
				matrix[5] = 1.0 / t.size.Y
			}

			// If pixels are flipped we must invert the Y axis
			if t.pixelsFlipped {
				matrix[5] = -matrix[5]
				matrix[13] = 1.0
			}

			// Load the matrix
			gl.MatrixMode(gl.TEXTURE)
			gl.LoadMatrixf(&matrix)

			// Go back to model-view mode (sf::RenderTarget relies on it)
			gl.MatrixMode(gl.MODELVIEW)
		}
	} else {
		// Bind no texture
		gl.Texture(0).Unbind(gl.TEXTURE_2D)

		// Reset the texture matrix
		gl.MatrixMode(gl.TEXTURE)
		gl.LoadIdentity()

		// Go back to model-view mode (sf::RenderTarget relies on it)
		gl.MatrixMode(gl.MODELVIEW)
	}
}
Example #5
0
func TextureFromDDS(fname string) (gl.Texture, error) {
	file, err := os.Open(fname)
	if err != nil {
		return gl.Texture(0), fmt.Errorf("Cannot open DDS file: %v", err)
	}
	defer file.Close()

	var filecode [4]byte
	binary.Read(file, binary.LittleEndian, &filecode) // DDS is always Little Endian encoded
	if string(filecode[:]) != "DDS " {
		return gl.Texture(0), fmt.Errorf("File code is not DDS, instead got %v.", string(filecode[:]))
	}

	header := ddsHeader{}
	err = binary.Read(file, binary.LittleEndian, &header)
	if err != nil {
		return gl.Texture(0), fmt.Errorf("Couldn't read DDS header: %v", err)
	}

	stat, err := file.Stat()
	if err != nil {
		return gl.Texture(0), fmt.Errorf("Couldn't get size of file: %v", err)
	}

	// All of the file after the header and file identifier "DDS "
	// is images. 4 byte identifier + 124 byte header = 128 bytes
	// to take off the file size.
	bufSize := stat.Size() - 128

	buffer := make([]byte, bufSize)
	err = binary.Read(file, binary.LittleEndian, buffer)
	if err != nil {
		return gl.Texture(0), fmt.Errorf("Couldn't read all mipmaps into buffer: %v", err)
	}

	//var components uint32
	var blockSize uint32
	var format gl.GLenum
	switch header.PixelFormat.FourCC {
	case fourCC_DXT1:
		format = gl.COMPRESSED_RGBA_S3TC_DXT1_EXT
		//components = 3
		blockSize = 8
	case fourCC_DXT3:
		format = gl.COMPRESSED_RGBA_S3TC_DXT3_EXT
		//components = 4
		blockSize = 16
	case fourCC_DXT5:
		format = gl.COMPRESSED_RGBA_S3TC_DXT5_EXT
		//components = 4
		blockSize = 16
	default:
		return gl.Texture(0), fmt.Errorf("Invalid four CC in DDS header. Got: %x; Expected %x; %x; or %x", header.PixelFormat.FourCC, fourCC_DXT1, fourCC_DXT3, fourCC_DXT5)
	}

	offset := 0

	tex := gl.GenTexture()
	tex.Bind(gl.TEXTURE_2D)
	gl.PixelStorei(gl.UNPACK_ALIGNMENT, 1)

	for level, width, height := 0, header.Width, header.Height; level < int(header.MipMapCount) && (width > 0 || height > 0); level, width, height = level+1, width/2, height/2 {
		size := int(((width + 3) / 4) * ((height + 3) / 4) * blockSize)
		gl.CompressedTexImage2D(gl.TEXTURE_2D, level, format, int(width), int(height), 0, size, &buffer[offset])

		offset += size
	}

	return tex, nil
}