Exemple #1
0
func (this *Window) initGL() {
	gl.ShadeModel(gl.SMOOTH) //SMOOTH or FLAT
	gl.CullFace(gl.BACK)
	gl.FrontFace(gl.CCW)
	gl.Enable(gl.CULL_FACE)
	gl.Enable(gl.DEPTH_TEST)
	gl.Enable(gl.LIGHTING)
	gl.Enable(gl.BLEND)
	gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
	/*gl.Enable(gl.FOG)
	gl.Fogi(gl.FOG_MODE, gl.EXP)
	gl.Fogfv(gl.FOG_COLOR, []float32{0.5,0.5,0.5,1.0})
	gl.Fogf(gl.FOG_DENSITY, 0.0035)
	gl.Hint(gl.FOG_HINT, gl.DONT_CARE)
	gl.Fogf(gl.FOG_START, 1.0)
	gl.Fogf(gl.FOG_END  , 5000.0)//*/
	gl.Enable(gl.TEXTURE_2D)
	gl.TexEnvf(gl.TEXTURE_ENV, gl.TEXTURE_ENV_MODE, gl.MODULATE) //before: decal, std: modulate
	//gl.TexParameteri(gl.TEXTURE_2D, gl.GENERATE_MIPMAP, true) //mipmaps (dont use it!, its bad!)
	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_LINEAR or GL_NEAREST, no mipmap here
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR) //*/
	gl.ClearColor(.1, .1, .1, 1)
	//gl.Enable(gl.PRIMITIVE_RESTART)
	//gl.PrimitiveRestartIndex()
	this.setGLViewport()
}
Exemple #2
0
func loadTexture(path string) (*gl.Texture, error) {
	file, err := os.Open(path)
	if err != nil {

	}
	defer file.Close()

	srcimg, _, err := image.Decode(file)
	if err != nil {
		return nil, err
	}
	// convert to RGBA if not already
	b := srcimg.Bounds()
	var dstimg *image.RGBA
	if srcimg.ColorModel() != color.RGBAModel {
		dstimg = image.NewRGBA(b)
		draw.Draw(dstimg, b, srcimg, b.Min, draw.Src)
	} else {
		dstimg = srcimg.(*image.RGBA)
	}

	tex := gl.GenTexture()
	tex.Bind(gl.TEXTURE_2D)
	gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, b.Dx(), b.Dy(), 0, gl.RGBA, gl.UNSIGNED_BYTE, dstimg.Pix)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)

	return &tex, nil
}
Exemple #3
0
func (this *Window) initGL() {

	runtime.LockOSThread()

	if gl.Init() != 0 {
		panic("gl init error")
	}

	gl.ShadeModel(gl.SMOOTH)
	gl.CullFace(gl.BACK)
	gl.FrontFace(gl.CCW)
	gl.Enable(gl.CULL_FACE)
	gl.Enable(gl.DEPTH_TEST)
	gl.Enable(gl.LIGHTING)
	gl.Enable(gl.BLEND)
	gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
	gl.Enable(gl.TEXTURE_2D)
	gl.TexEnvf(gl.TEXTURE_ENV, gl.TEXTURE_ENV_MODE, gl.MODULATE)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT)
	var magFilter, minFilter = gl.LINEAR, gl.LINEAR
	if globals.CreateMipmaps {
		minFilter = gl.LINEAR_MIPMAP_LINEAR
	}
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFilter)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter)
	gl.Enable(gl.NORMALIZE)
	gl.ClearColor(.1, .1, .1, 1)
	this.setGLViewport()
}
Exemple #4
0
func uploadTexture_NRGBA32(img *image.NRGBA) gl.Texture {
	b := img.Bounds()
	data := make([]uint8, b.Max.X*b.Max.Y*4)
	for y := 0; y < b.Max.Y; y++ {
		for x := 0; x < b.Max.X; x++ {
			p := img.At(x, y)
			offset := y*b.Max.X*4 + x*4
			r, g, b, a := p.RGBA()
			data[offset+0] = uint8(r)
			data[offset+1] = uint8(g)
			data[offset+2] = uint8(b)
			data[offset+3] = uint8(a)
		}
	}

	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, b.Max.X, b.Max.Y, 0, gl.RGBA, gl.UNSIGNED_BYTE, data)

	if gl.GetError() != gl.NO_ERROR {
		id.Delete()
		panic(errors.New("Failed to load a texture"))
		return 0
	}
	return id
}
// Load bitmap from path as GL texture
func LoadGLTexture(path string) {
	image := sdl.Load(path)
	if image == nil {
		panic(sdl.GetError())
	}

	// Check that the image's width is a power of 2
	if image.W&(image.W-1) != 0 {
		fmt.Println("warning:", path, "has a width that is not a power of 2")
	}

	// Also check if the height is a power of 2
	if image.H&(image.H-1) != 0 {
		fmt.Println("warning:", path, "has an height that is not a power of 2")
	}

	// get the number of channels in the SDL surface
	nOfColors := image.Format.BytesPerPixel
	var textureFormat gl.GLenum

	if nOfColors == 4 { // contains alpha channel
		if image.Format.Rmask == 0x000000ff {
			textureFormat = gl.RGBA
		} else {
			textureFormat = gl.BGRA
		}
	} else if nOfColors == 3 { // no alpha channel
		if image.Format.Rmask == 0x000000ff {
			textureFormat = gl.RGB
		} else {
			textureFormat = gl.BGR
		}
	} else {
		fmt.Println("warning:", path, "is not truecolor, this will probably break")
	}

	texture = gl.GenTexture()

	// Typical texture generation using data from the bitmap
	gl.BindTexture(gl.TEXTURE_2D, uint(texture))

	// Generate the texture
	gl.TexImage2D(gl.TEXTURE_2D, 0, int(image.Format.BytesPerPixel),
		int(image.W), int(image.H),
		0, textureFormat, gl.UNSIGNED_BYTE, image.Pixels,
	)

	// linear filtering
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)

	// free up memory we have used.
	image.Free()
}
Exemple #6
0
func uploadTexture(img *image.RGBA) gl.Texture {
	gl.Enable(gl.TEXTURE_2D)
	tex := gl.GenTexture()
	tex.Bind(gl.TEXTURE_2D)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
	gl.TexImage2D(gl.TEXTURE_2D, 0, 4, img.Bounds().Max.X, img.Bounds().Max.Y,
		0, gl.RGBA, gl.UNSIGNED_BYTE, img.Pix)
	gl.Disable(gl.TEXTURE_2D)
	return tex
}
Exemple #7
0
func (t *TextureData) LoadIntoGL() {
	t.id.Bind(gl.TEXTURE_2D)
	for i, v := range t.Mips {
		gl.TexImage2D(gl.TEXTURE_2D, i, gl.RGBA, v.w, v.h, 0, gl.RGBA, gl.UNSIGNED_BYTE, v.Pix)
		if !globals.CreateMipmaps {
			gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
			gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
			break //just one level if no mipmaps are wanted
		}
	}
	t.Unbind()
}
Exemple #8
0
func (t *Skybox) RenderScaled(center, scale *Vec3) {
	v := []*Vec3{
		V3(-1, -1, 1),
		V3(1, -1, 1),
		V3(1, 1, 1),
		V3(-1, 1, 1),
		V3(-1, -1, -1),
		V3(1, -1, -1),
		V3(1, 1, -1),
		V3(-1, 1, -1)}
	for i := 0; i < 8; i++ {
		v[i].Muli(scale).Addi(center)
	}

	if globals.UseShader {
		program.Unuse()
	}

	//*//save attributes and change them
	gl.PushAttrib(gl.ENABLE_BIT | gl.TEXTURE_BIT)
	defer gl.PopAttrib() //reset to old attributes
	gl.Enable(gl.TEXTURE_2D)
	gl.Disable(gl.DEPTH_TEST)
	gl.Disable(gl.LIGHTING)
	gl.Disable(gl.BLEND) //*/
	oneSide := func(tex *texture.Texture, a, b, c, d int, n *Vec3) {
		tex.BindForSkybox(color.White)
		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.Begin(gl.TRIANGLES)
		gl.Normal3dv(n.Slc())
		gl.TexCoord2i(0, 0)
		gl.Vertex3dv(v[a].Slc())
		gl.TexCoord2i(1, 0)
		gl.Vertex3dv(v[b].Slc())
		gl.TexCoord2i(1, 1)
		gl.Vertex3dv(v[c].Slc())
		gl.TexCoord2i(0, 0)
		gl.Vertex3dv(v[a].Slc())
		gl.TexCoord2i(1, 1)
		gl.Vertex3dv(v[c].Slc())
		gl.TexCoord2i(0, 1)
		gl.Vertex3dv(v[d].Slc())
		gl.End()
	}
	oneSide(t.up, 2, 3, 7, 6, V3(0, -1, 0))
	oneSide(t.dn, 5, 4, 0, 1, V3(0, 1, 0))
	oneSide(t.lt, 5, 1, 2, 6, V3(1, 0, 0))
	oneSide(t.rt, 0, 4, 7, 3, V3(-1, 0, 0))
	oneSide(t.ft, 1, 0, 3, 2, V3(0, 0, -1))
	oneSide(t.bk, 4, 5, 6, 7, V3(0, 0, 1))
}
Exemple #9
0
func NewFont(filename string, size int, c color.Color) *Font {

	var font Font
	font.textures = make(map[rune]gl.Texture)
	font.widths = make(map[rune]int)

	extfont := ttf.OpenFont(filename, size)
	if extfont == nil {
		panic("Could not load font")
	}
	defer extfont.Close()

	font.height = extfont.LineSkip()

	for _, ch := range "abcdefghijklmnopqrdstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :;@'<>,.?/~#{}[]!£$%^&*()_-+=\"\\|" {
		_, _, _, _, advance, err := extfont.GlyphMetrics(uint16(ch))
		if err != 0 {
			panic("Could not get glyph metrics")
		}

		// Create a bitmap with width=advance, height=font.height
		surface := sdl.CreateRGBSurface(sdl.SWSURFACE|sdl.SRCALPHA, advance, font.height, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000)
		//surface.FillRect(&sdl.Rect{0,0, uint16(advance), uint16(font.height)}, 0x0)
		// rect := sdl.Rect{0,0, uint16(advance), uint16(ascent)}
		// rect := sdl.Rect{int16(minx), int16(ascent)-int16(maxy), 0, 0}

		fontSurface := ttf.RenderText_Blended(extfont, string(ch), sdl.ColorFromGoColor(c))
		fontSurface.Blit(nil, surface, nil)

		rgba := image.NewRGBA(image.Rect(0, 0, advance, font.height))
		for x := 0; x < advance; x++ {
			for y := 0; y < font.height; y++ {
				rgba.Set(x, y, fontSurface.At(x, font.height-y))
			}
		}

		font.widths[ch] = advance
		font.textures[ch] = gl.GenTexture()
		font.textures[ch].Bind(gl.TEXTURE_2D)
		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
		gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, advance, font.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, &rgba.Pix[0])
		font.textures[ch].Unbind(gl.TEXTURE_2D)
	}
	return &font
}
Exemple #10
0
func loadTextures() (err error) {
	textures = make([]gl.Texture, len(texturefiles))
	gl.GenTextures(textures)

	for i := range texturefiles {
		textures[i].Bind(gl.TEXTURE_2D)

		if glfw.LoadTexture2D(texturefiles[i], 0) {
			return errors.New("Failed to load texture: " + texturefiles[i])
		}

		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
	}

	return
}
// load in bitmap as a GL texture
func LoadGLTextures(path string) {
	// storage space for the textures
	image, format := LoadImage(path)

	// Create the textures
	gl.GenTextures(textures[:])

	genTexture(textures[0], image, format)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)

	genTexture(textures[1], image, format)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)

	genTexture(textures[2], image, format)
	gl.TexParameteri(gl.TEXTURE_2D, gl.GENERATE_MIPMAP, gl.TRUE)
}
Exemple #12
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
}
Exemple #13
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.fpsmanager.FramerateDelay()
			}
		}
	}
}
Exemple #14
0
func loadTextures() (err error) {
	gl.GenTextures(textures)

	// Texture 1
	textures[0].Bind(gl.TEXTURE_2D)

	if !glfw.LoadTexture2D(texturefile, 0) {
		return errors.New("Failed to load texture: " + texturefile)
	}

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

	// Texture 2
	textures[1].Bind(gl.TEXTURE_2D)

	if !glfw.LoadTexture2D(texturefile, 0) {
		return errors.New("Failed to load texture: " + texturefile)
	}

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

	// Texture 3
	textures[2].Bind(gl.TEXTURE_2D)

	if !glfw.LoadTexture2D(texturefile, glfw.BuildMipmapsBit) {
		return errors.New("Failed to load texture: " + texturefile)
	}

	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR_MIPMAP_NEAREST)

	return
}
Exemple #15
0
func draw() {
	for y := 0; y < Size; y++ {
		for x := 0; x < Size; x++ {

			var color uint8
			if grid.Front()[y][x] {
				color = 0x00
			} else {
				color = 0xFF
			}

			pixels[(y*Size+x)*3+0] = color
			pixels[(y*Size+x)*3+1] = color
			pixels[(y*Size+x)*3+2] = color

		}
	}

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

	gl.TexImage2D(gl.TEXTURE_2D, 0, 3, Size, Size, 0, gl.RGB, gl.UNSIGNED_BYTE, pixels)

	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()
}
Exemple #16
0
func (v *Video) Render() {
	runtime.LockOSThread()

	for running {
		select {
		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)
			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()

			glfw.SwapBuffers()
			v.fpsmanager.FramerateDelay()
		}
	}
}
// load in bitmap as a GL texture
func LoadGLTextures(path string) {
	image := sdl.Load(path)
	if image == nil {
		panic(sdl.GetError())
	}

	// Check that the image's width is a power of 2
	if image.W&(image.W-1) != 0 {
		fmt.Println("warning:", path, "has a width that is not a power of 2")
	}

	// Also check if the height is a power of 2
	if image.H&(image.H-1) != 0 {
		fmt.Println("warning:", path, "has an height that is not a power of 2")
	}

	// get the number of channels in the SDL surface
	nOfColors := image.Format.BytesPerPixel
	var textureFormat gl.GLenum

	if nOfColors == 4 { // contains alpha channel
		if image.Format.Rmask == 0x000000ff {
			textureFormat = gl.RGBA
		} else {
			textureFormat = gl.BGRA
		}
	} else if nOfColors == 3 { // no alpha channel
		if image.Format.Rmask == 0x000000ff {
			textureFormat = gl.RGB
		} else {
			textureFormat = gl.BGR
		}
	} else {
		fmt.Println("warning:", path, "is not truecolor, this will probably break")
	}

	// Create the textures
	gl.GenTextures(textures[:])

	// First texture
	gl.BindTexture(gl.TEXTURE_2D, uint(textures[0]))
	gl.TexImage2D(
		gl.TEXTURE_2D,
		0,
		3,
		int(image.W),
		int(image.H),
		0,
		textureFormat,
		gl.UNSIGNED_BYTE,
		image.Pixels,
	)

	// linear filtering
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)

	// Second texture
	gl.BindTexture(gl.TEXTURE_2D, uint(textures[1]))
	gl.TexImage2D(gl.TEXTURE_2D, 0,
		3,
		int(image.W),
		int(image.H),
		0, textureFormat, gl.UNSIGNED_BYTE,
		image.Pixels,
	)

	// Mipmapped filtering
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)

	// Third texture
	gl.BindTexture(gl.TEXTURE_2D, uint(textures[2]))
	gl.TexImage2D(gl.TEXTURE_2D, 0,
		3,
		int(image.W),
		int(image.H),
		0, textureFormat, gl.UNSIGNED_BYTE,
		image.Pixels,
	)

	// Mipmapped filtering
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)

	glu.Build2DMipmaps(
		gl.TEXTURE_2D,
		3,
		int(image.W),
		int(image.H),
		textureFormat,
		image.Pixels,
	)
}