Example #1
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
}
Example #2
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()
	}
}