Пример #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
}
Пример #2
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
}
Пример #3
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
}
Пример #4
0
func (shaders Shaders) Serve(ref ShaderRef) (gl.Shader, error) {
	shader, ok := shaders[ref]
	if ok {
		return shader, nil
	}

	shader_seed, ok := SHADER_SOURCES[ref]
	if !ok {
		return 0, fmt.Errorf("Shader Reference '%#v' not found.", ref)
	}

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

	shader.Source(shader_seed.Source)
	if err := CheckGlError(); err != nil {
		shader.Delete()
		gl.GetError() // Delete may also raise an error, ignore.
		err.Description = "Shader.Source failed."
		return 0, err
	}

	shader.Compile()
	if err := CheckGlError(); err != nil {
		infolog := shader.GetInfoLog()
		shader.Delete()
		gl.GetError() // GetInfoLog and delete may raise an error.
		err.Description = fmt.Sprintf("Shader.Compile failed. Log: %v", infolog)
		return 0, err
	}
	compileStatus := shader.Get(gl.COMPILE_STATUS)
	if err := CheckGlError(); err != nil {
		shader.Delete()
		gl.GetError()
		err.Description = "shader.Get(gl.COMPILE_STATUS) failed."
		return 0, err
	}
	if compileStatus == gl.FALSE {
		infolog := shader.GetInfoLog()
		shader.Delete()
		gl.GetError()
		err := fmt.Errorf("Shader compiling failed.  Log: %v", infolog)
		return 0, err
	}
	shaders[ref] = shader
	return shader, nil
}
Пример #5
0
func NewShader(shaderType gl.GLenum, source string) (gl.Shader, error) {
	s := gl.CreateShader(shaderType)
	s.Source(source)
	s.Compile()
	compile_ok := s.Get(gl.COMPILE_STATUS)
	if compile_ok == 0 {
		return gl.Shader(0), errors.New(s.GetInfoLog())
	}
	return s, nil
}
Пример #6
0
func LoadShader(code string, shaderType gl.GLenum) (gl.Shader, error) {
	shader := gl.CreateShader(shaderType)
	shader.Source(string(code))
	shader.Compile()

	if shader.Get(gl.COMPILE_STATUS) != 1 {
		return shader, errors.New(shader.GetInfoLog())
	}

	return shader, nil
}
Пример #7
0
func (b *BasicMaterial) Load() error {
	program := b.Program
	vrt := gl.CreateShader(gl.VERTEX_SHADER)
	frg := gl.CreateShader(gl.FRAGMENT_SHADER)

	vrt.Source(b.vertexShader)
	frg.Source(b.fragmentShader)

	vrt.Compile()
	if vrt.Get(gl.COMPILE_STATUS) != 1 {
		return fmt.Errorf("Error in Compiling Vertex Shader:%s\n", vrt.GetInfoLog())
	}
	frg.Compile()
	if frg.Get(gl.COMPILE_STATUS) != 1 {
		return fmt.Errorf("Error in Compiling Fragment Shader:%s\n", frg.GetInfoLog())
	}

	program.AttachShader(vrt)
	program.AttachShader(frg)

	program.BindAttribLocation(0, "vertexPos")
	program.BindAttribLocation(1, "vertexUV")

	program.Link()

	b.Verts = program.GetAttribLocation("vertexPos")
	b.UV = program.GetAttribLocation("vertexUV")
	b.ViewMatrix = program.GetUniformLocation("MView")
	b.ProjMatrix = program.GetUniformLocation("MProj")
	b.ModelMatrix = program.GetUniformLocation("MModel")
	b.Texture = program.GetUniformLocation("mytexture")
	b.AddColor = program.GetUniformLocation("addcolor")
	b.Tiling = program.GetUniformLocation("tiling")
	b.Offset = program.GetUniformLocation("offset")

	b.Offset.Uniform2f(0, 0)
	b.Tiling.Uniform2f(1, 1)
	b.AddColor.Uniform4f(1, 1, 1, 1)

	return nil
}
Пример #8
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
}
Пример #9
0
func compileVertexShader(fileName string) (vshader gl.Shader, err error) {
	vshader = gl.CreateShader(gl.VERTEX_SHADER)
	buf, err := ioutil.ReadFile(fileName)
	if err != nil {
		return
	}
	vshader.Source(string(buf))
	vshader.Compile()
	if vshader.Get(gl.COMPILE_STATUS) != gl.TRUE {
		return vshader, fmt.Errorf("Unable to compile vertex shader. Cause: %v", vshader.GetInfoLog())
	}
	return
}
Пример #10
0
func createShader(type_ gl.GLenum, fn string) (gl.Shader, error) {
	shader := gl.CreateShader(type_)
	source, err := ioutil.ReadFile(fn)
	if err != nil {
		return shader, err
	}
	shader.Source(string(source))
	shader.Compile()
	if infoLog := shader.GetInfoLog(); len(infoLog) > 0 {
		return shader, fmt.Errorf(infoLog)
	}
	return shader, nil
}
Пример #11
0
func (self *GLSLProgram) buildShader(shaderType gl.GLenum, source string) gl.Shader {
	shader := gl.CreateShader(shaderType)
	shader.Source(source)
	shader.Compile()

	compileStatus := shader.Get(gl.COMPILE_STATUS)
	if compileStatus != 1 {
		log.Print("Shader compilation status: ", compileStatus)
		log.Print("Info Log: ", shader.GetInfoLog())
		log.Panic("Error creating shader!")
	}

	return shader
}
Пример #12
0
func MakeShader(shader_type gl.GLenum, source string) gl.Shader {

	shader := gl.CreateShader(shader_type)
	shader.Source(source)
	shader.Compile()
	OpenGLSentinel()

	compstat := shader.Get(gl.COMPILE_STATUS)
	if compstat != 1 {
		log.Print("vert shader compilation status: ", compstat)
		log.Print("Info log: ", shader.GetInfoLog())
		log.Panic("Problem creating shader?")
	}
	return shader
}
Пример #13
0
func loadShader(shaderType gl.GLenum, source string) gl.Shader {
	shader := gl.CreateShader(shaderType)
	if err := gl.GetError(); err != gl.NO_ERROR {
		panic(fmt.Errorf("gl error: %v", err))
	}

	shader.Source(source)
	shader.Compile()

	if shader.Get(gl.COMPILE_STATUS) != gl.TRUE {
		log := shader.GetInfoLog()
		panic(fmt.Errorf("Failed to compile shader: %v, shader: %v", log, source))
	}

	return shader
}
Пример #14
0
func MakeShader(shaderType gl.GLenum, filename string) gl.Shader {
	file, err := os.Open(filename)
	if err != nil {
		fmt.Fprintf(os.Stderr, "[e] %v\n", err)
	}
	defer file.Close()

	data := make([]byte, 2048)
	count, err := file.Read(data)
	if err != nil {
		log.Fatal(err)
	}
	source := string(data[:count])

	shader := gl.CreateShader(shaderType)
	shader.Source(source)
	shader.Compile()
	fmt.Println(shader.GetInfoLog())

	return shader
}
Пример #15
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()
	}
}