Exemple #1
0
// Create a vertex/fragment shader program
func createProgram(info *shaderInfo) (gl.Program, error) {
	vshader := gl.CreateShader(gl.VERTEX_SHADER)
	vshader.Source(info.vertCode)
	vshader.Compile()
	if vshader.Get(gl.COMPILE_STATUS) != gl.TRUE {
		return gl.Program(0), errors.New("Unable to compile vertex shader. " + vshader.GetInfoLog())
	}
	defer vshader.Delete() // no need to use it after linking

	fshader := gl.CreateShader(gl.FRAGMENT_SHADER)
	fshader.Source(info.fragCode)
	fshader.Compile()
	if fshader.Get(gl.COMPILE_STATUS) != gl.TRUE {
		return gl.Program(0), errors.New("Unable to compile fragment shader. " + fshader.GetInfoLog())
	}
	defer fshader.Delete() // no need to use it after linking

	program := gl.CreateProgram()
	program.AttachShader(vshader)
	program.AttachShader(fshader)
	program.Link()

	if program.Get(gl.LINK_STATUS) != gl.TRUE {
		return gl.Program(0), errors.New("Unable to link program. " + fshader.GetInfoLog())
	}

	return program, nil
}
Exemple #2
0
func compileProgram(dir, program string) (glProg gl.Program, err error) {
	vertexShader, err := compileVertexShader(filepath.Join(dir, program+".vertex"))
	if err != nil {
		return
	}
	defer vertexShader.Delete()
	fragShader, err := compileFragmentShader(filepath.Join(dir, program+".fragment"))
	if err != nil {
		return
	}
	defer fragShader.Delete()

	glProg = gl.CreateProgram()
	glProg.AttachShader(vertexShader)
	glProg.AttachShader(fragShader)

	glProg.Link()

	if glProg.Get(gl.LINK_STATUS) != gl.TRUE {
		return glProg, fmt.Errorf("Unable to link glProg. Cause: %v", glProg.GetInfoLog())
	}
	glProg.Use()

	return
}
Exemple #3
0
func MakeProgram(vertFname, fragFname string) gl.Program {
	vertSource, err := ioutil.ReadFile(vertFname)
	if err != nil {
		panic(err)
	}

	fragSource, err := ioutil.ReadFile(fragFname)
	if err != nil {
		panic(err)
	}

	vertShader, fragShader := gl.CreateShader(gl.VERTEX_SHADER), gl.CreateShader(gl.FRAGMENT_SHADER)
	vertShader.Source(string(vertSource))
	fragShader.Source(string(fragSource))

	vertShader.Compile()
	fragShader.Compile()

	prog := gl.CreateProgram()
	prog.AttachShader(vertShader)
	prog.AttachShader(fragShader)
	prog.Link()
	prog.Validate()
	fmt.Println(prog.GetInfoLog())

	return prog
}
Exemple #4
0
func MakeProgram(vertex, geometry, fragment string) gl.Program {
	vert_shader := MakeShader(gl.VERTEX_SHADER, vertex)
	geom_shader := MakeShader(gl.GEOMETRY_SHADER, geometry)
	frag_shader := MakeShader(gl.FRAGMENT_SHADER, fragment)

	prog := gl.CreateProgram()
	prog.AttachShader(vert_shader)
	prog.AttachShader(geom_shader)
	prog.AttachShader(frag_shader)
	prog.Link()

	OpenGLSentinel()

	// Note: These functions aren't implemented in master of banathar/gl
	// prog.ParameterEXT(gl.GEOMETRY_INPUT_TYPE_EXT, gl.POINTS)
	// prog.ParameterEXT(gl.GEOMETRY_OUTPUT_TYPE_EXT, gl.POINTS)
	// prog.ParameterEXT(gl.GEOMETRY_VERTICES_OUT_EXT, 4)

	// OpenGLSentinel()

	linkstat := prog.Get(gl.LINK_STATUS)
	if linkstat != 1 {
		log.Panic("Program link failed, status=", linkstat,
			"Info log: ", prog.GetInfoLog())
	}

	prog.Validate()
	valstat := prog.Get(gl.VALIDATE_STATUS)
	if valstat != 1 {
		log.Panic("Program validation failed: ", valstat)
	}

	return prog
}
Exemple #5
0
func BuildShader(attrs VertexAttributes, srcs ...ShaderSource) *Shader {
	shader := &Shader{
		vertexAttrs:  attrs.clone(),
		vertexFormat: attrs.Format(),
	}
	shader.prog = gl.CreateProgram()
	ss := make([]gl.Shader, len(srcs))
	for i, src := range srcs {
		s := gl.CreateShader(src.typ())
		s.Source(src.source())
		s.Compile()
		println(s.GetInfoLog())
		shader.prog.AttachShader(s)
		ss[i] = s
	}
	shader.prog.Link()
	println(shader.prog.GetInfoLog())

	// No longer need shader objects with a fully built program.
	for _, s := range ss {
		shader.prog.DetachShader(s)
		s.Delete()
	}
	return shader
}
Exemple #6
0
// Setup and initialize the default shaders.
func InitShaders() error {
	vertexShader, err := createShader(gl.VERTEX_SHADER,
		ShaderLocation+"default.vs")
	if err != nil {
		return err
	}
	fragmentShader, err := createShader(gl.FRAGMENT_SHADER,
		ShaderLocation+"default.fs")
	if err != nil {
		return err
	}

	DefaultShaderProgram = gl.CreateProgram()
	DefaultShaderProgram.AttachShader(vertexShader)
	DefaultShaderProgram.AttachShader(fragmentShader)
	DefaultShaderProgram.Link()
	if infoLog := DefaultShaderProgram.GetInfoLog(); len(infoLog) > 0 {
		return fmt.Errorf(infoLog)
	}
	DefaultShaderProgram.Validate()
	DefaultShaderProgram.BindAttribLocation(0, "position")
	DefaultShaderProgram.BindAttribLocation(1, "color")

	posLoc = DefaultShaderProgram.GetAttribLocation("position")
	colorLoc = DefaultShaderProgram.GetAttribLocation("color")

	projLoc = DefaultShaderProgram.GetUniformLocation("mPerspective")
	viewLoc = DefaultShaderProgram.GetUniformLocation("mView")
	return nil
}
Exemple #7
0
func InitProgram() {
	vertexShader = MakeShader(gl.VERTEX_SHADER, "resources/shaders/blocks.vert")
	fragShader = MakeShader(gl.FRAGMENT_SHADER, "resources/shaders/blocks.frag")

	program = gl.CreateProgram()
	program.AttachShader(vertexShader)
	program.AttachShader(fragShader)
	program.Link()
}
func NewGLSLProgram(vertexProgram, fragmentProgram string) *GLSLProgram {
	program := new(GLSLProgram)
	program.uniforms = make(uniformMap)

	program.program = gl.CreateProgram()
	program.vertexShader = program.buildShader(gl.VERTEX_SHADER, vertexProgram)
	program.fragmentShader = program.buildShader(gl.FRAGMENT_SHADER, fragmentProgram)

	program.attachAndLinkShaders()
	program.validateShaders()

	return program
}
Exemple #9
0
func NewProgram(vs, fs gl.Shader) gl.Program {
	program := gl.CreateProgram()

	program.AttachShader(vs)
	program.AttachShader(fs)
	program.Link()
	link_ok := program.Get(gl.LINK_STATUS)
	if link_ok == 0 {
		log.Printf("glLinkProgram:")
	}

	return program
}
Exemple #10
0
func createProgram(vertShaderSrc string, fragShaderSrc string) gl.Program {
	vertShader := loadShader(gl.VERTEX_SHADER, vertShaderSrc)
	fragShader := loadShader(gl.FRAGMENT_SHADER, fragShaderSrc)

	prog := gl.CreateProgram()

	prog.AttachShader(vertShader)
	prog.AttachShader(fragShader)
	prog.Link()

	if prog.Get(gl.LINK_STATUS) != gl.TRUE {
		log := prog.GetInfoLog()
		panic(fmt.Errorf("Failed to link program: %v", log))
	}

	return prog
}
Exemple #11
0
func LoadProgram(shaders ...gl.Shader) (gl.Program, error) {
	p := gl.CreateProgram()
	for _, shader := range shaders {
		p.AttachShader(shader)
	}

	p.Link()
	if p.Get(gl.LINK_STATUS) != 1 {
		return p, errors.New(p.GetInfoLog())
	}

	p.Validate()
	if p.Get(gl.VALIDATE_STATUS) != 1 {
		return p, errors.New(p.GetInfoLog())
	}

	return p, nil
}
Exemple #12
0
func setupProgram() (prog gl.Program) {
	vertexSource := `
        #version 430 core
        
        layout (location = 0) in vec4 offset;

        const vec4 vertecies[3] = vec4[3](
            vec4(0.25, 0.5, 0.5, 1.0),
            vec4(-0.25, 0.5, 0.5, 1.0),
            vec4(-0.25, -0.5, 0.5, 1.0)
        );
        
        void main(){
            gl_Position = vertecies[gl_VertexID] + offset;
        }`
	fragmentSource := `
        #version 430 core
        
        out vec4 color;

        void main(){
            color = vec4(1.0, 0.0, 0.0, 0.0); // red, blue, green, ??
        }`
	vert, frag := gl.CreateShader(gl.VERTEX_SHADER), gl.CreateShader(gl.FRAGMENT_SHADER)
	defer vert.Delete()
	defer frag.Delete()
	vert.Source(vertexSource)
	frag.Source(fragmentSource)
	vert.Compile()
	frag.Compile()

	prog = gl.CreateProgram()
	prog.AttachShader(vert)
	prog.AttachShader(frag)
	prog.Link()
	prog.Use()
	f.Println(prog.GetInfoLog())

	return
}
Exemple #13
0
func NewProgram(shaders ...Shader) gl.Program {
	program := gl.CreateProgram()
	for _, shader := range shaders {
		program.AttachShader(shader.Compile())
	}

	program.Link()
	OpenGLSentinel()

	linkstat := program.Get(gl.LINK_STATUS)
	if linkstat != 1 {
		log.Panic("Program link failed, status=", linkstat,
			"Info log: ", program.GetInfoLog())
	}

	program.Validate()
	valstat := program.Get(gl.VALIDATE_STATUS)
	if valstat != 1 {
		log.Panic("Program validation failed: ", valstat)
	}
	return program
}
Exemple #14
0
func NewBasicMaterial(vertexShader, fragmentShader string) *BasicMaterial {
	return &BasicMaterial{Program: Program{gl.CreateProgram()}, vertexShader: vertexShader, fragmentShader: fragmentShader}
}
Exemple #15
0
func (self Programs) Serve(srefs ShaderRefs) (gl.Program, error) {
	pref := makeProgramRef(srefs)
	program, ok := self.programs[pref]
	if ok {
		return program, nil
	}

	// Make sure that all the shaders are available and compile.
	nb_shaders := len(srefs)
	shaders := make([]gl.Shader, nb_shaders, nb_shaders)
	for i, sref := range srefs {
		shader, err := self.shaders.Serve(sref)
		if err != nil {
			return 0, err
		}
		shaders[i] = shader
	}

	program = gl.CreateProgram()
	if err := CheckGlError(); err != nil {
		if program == 0 {
			err.Description = "CreateProgram failed."
		} else {
			err.Description = "CreateProgram succeeded but OpenGL reports an error."
		}
		return program, err
	} else {
		if program == 0 {
			return 0, fmt.Errorf("CreateProgram failed but OpenGL reports no error.")
		}
	}

	for _, shader := range shaders {
		program.AttachShader(shader)
		if err := CheckGlError(); err != nil {
			program.Delete()
			gl.GetError() // Ignore Delete error.
			err.Description = "Program.AttachShader failed."
			return 0, err
		}
	}

	program.Link()
	if err := CheckGlError(); err != nil {
		infolog := program.GetInfoLog()
		program.Delete()
		gl.GetError() // Ignore Delete error.
		err.Description = fmt.Sprintf("Program.Link failed. Log: %v", infolog)
		return 0, err
	}
	link_status := program.Get(gl.LINK_STATUS)
	if err := CheckGlError(); err != nil {
		program.Delete()
		gl.GetError()
		err.Description = "Program.Get(LINK_STATUS) failed."
		return 0, err
	}
	if link_status == gl.FALSE {
		infolog := program.GetInfoLog()
		program.Delete()
		gl.GetError()
		err := fmt.Errorf("Program linking failed.  Log: %v", infolog)
		return 0, err
	}
	self.programs[pref] = program
	return program, nil
}
Exemple #16
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()
	}
}