Beispiel #1
0
func (f *Framebuffer) Dispose(c *opengl.Context) {
	// Don't delete the default framebuffer.
	if f.native == opengl.ZeroFramebuffer {
		return
	}
	c.DeleteFramebuffer(f.native)
}
Beispiel #2
0
func (i *Image) Pixels(context *opengl.Context) ([]uint8, error) {
	// Flush the enqueued commands so that pixels are certainly read.
	if err := theCommandQueue.Flush(context); err != nil {
		return nil, err
	}
	f := i.framebuffer
	return context.FramebufferPixels(f.native, f.width, f.height)
}
Beispiel #3
0
func shader(c *opengl.Context, id shaderId) string {
	str := shaders[id]
	if !c.GlslHighpSupported() {
		str = strings.Replace(str, "highp ", "", -1)
		str = strings.Replace(str, "lowp ", "", -1)
	}
	return str
}
Beispiel #4
0
func newFramebufferFromTexture(context *opengl.Context, texture *texture) (*framebuffer, error) {
	native, err := context.NewFramebuffer(opengl.Texture(texture.native))
	if err != nil {
		return nil, err
	}
	return &framebuffer{
		native: native,
		width:  texture.width,
		height: texture.height,
	}, nil
}
Beispiel #5
0
func NewFramebufferFromTexture(c *opengl.Context, texture *Texture) (*Framebuffer, error) {
	f, err := c.NewFramebuffer(opengl.Texture(texture.native))
	if err != nil {
		return nil, err
	}
	w, h := texture.Size()
	return &Framebuffer{
		native: f,
		width:  w,
		height: h,
	}, nil
}
Beispiel #6
0
func (f *Framebuffer) Fill(c *opengl.Context, clr color.Color) error {
	if err := f.setAsViewport(c); err != nil {
		return err
	}
	cr, cg, cb, ca := clr.RGBA()
	const max = math.MaxUint16
	r := float64(cr) / max
	g := float64(cg) / max
	b := float64(cb) / max
	a := float64(ca) / max
	return c.FillFramebuffer(r, g, b, a)
}
Beispiel #7
0
func NewTexture(c *opengl.Context, width, height int, filter opengl.Filter) (*Texture, error) {
	w := NextPowerOf2Int(width)
	h := NextPowerOf2Int(height)
	if w < 4 {
		return nil, errors.New("width must be equal or more than 4.")
	}
	if h < 4 {
		return nil, errors.New("height must be equal or more than 4.")
	}
	native, err := c.NewTexture(w, h, nil, filter)
	if err != nil {
		return nil, err
	}
	return &Texture{native, width, height}, nil
}
Beispiel #8
0
func NewTextureFromImage(c *opengl.Context, img image.Image, filter opengl.Filter) (*Texture, error) {
	origSize := img.Bounds().Size()
	if origSize.X < 4 {
		return nil, errors.New("width must be equal or more than 4.")
	}
	if origSize.Y < 4 {
		return nil, errors.New("height must be equal or more than 4.")
	}
	adjustedImage := adjustImageForTexture(img)
	size := adjustedImage.Bounds().Size()
	native, err := c.NewTexture(size.X, size.Y, adjustedImage.Pix, filter)
	if err != nil {
		return nil, err
	}
	return &Texture{native, origSize.X, origSize.Y}, nil
}
Beispiel #9
0
func drawTexture(c *opengl.Context, texture opengl.Texture, projectionMatrix *[4][4]float64, quads TextureQuads, geo Matrix, color Matrix) error {
	// NOTE: WebGL doesn't seem to have Check gl.MAX_ELEMENTS_VERTICES or gl.MAX_ELEMENTS_INDICES so far.
	// Let's use them to compare to len(quads) in the future.

	if !shadersInitialized {
		if err := initialize(c); err != nil {
			return err
		}
		shadersInitialized = true
	}

	if quads.Len() == 0 {
		return nil
	}
	if quadsMaxNum < quads.Len() {
		return errors.New(fmt.Sprintf("len(quads) must be equal to or less than %d", quadsMaxNum))
	}

	f := useProgramForTexture(c, glMatrix(projectionMatrix), texture, geo, color)
	defer f.FinishProgram()

	vertices := vertices[0:0]
	num := 0
	for i := 0; i < quads.Len(); i++ {
		x0, y0, x1, y1 := quads.Vertex(i)
		u0, v0, u1, v1 := quads.Texture(i)
		if x0 == x1 || y0 == y1 || u0 == u1 || v0 == v1 {
			continue
		}
		vertices = append(vertices,
			int16(x0), int16(y0), int16(u0), int16(v0),
			int16(x1), int16(y0), int16(u1), int16(v0),
			int16(x0), int16(y1), int16(u0), int16(v1),
			int16(x1), int16(y1), int16(u1), int16(v1),
		)
		num++
	}
	if len(vertices) == 0 {
		return nil
	}
	c.BufferSubData(c.ArrayBuffer, vertices)
	c.DrawElements(c.Triangles, 6*num)
	return nil
}
Beispiel #10
0
func drawFilledRects(c *opengl.Context, projectionMatrix *[4][4]float64, rects Rects) error {
	if !shadersInitialized {
		if err := initialize(c); err != nil {
			return err
		}
		shadersInitialized = true
	}

	if rects.Len() == 0 {
		return nil
	}

	f := useProgramForRects(c, glMatrix(projectionMatrix))
	defer f.FinishProgram()

	vertices := vertices[0:0]
	num := 0
	for i := 0; i < rects.Len(); i++ {
		x, y, w, h := rects.Rect(i)
		if w == 0 || h == 0 {
			continue
		}
		x0, y0, x1, y1 := x, y, x+w, y+h
		r, g, b, a := rects.Color(i).RGBA()
		vertices = append(vertices,
			int16(x0), int16(y0), int16(r), int16(g), int16(b), int16(a),
			int16(x1), int16(y0), int16(r), int16(g), int16(b), int16(a),
			int16(x0), int16(y1), int16(r), int16(g), int16(b), int16(a),
			int16(x1), int16(y1), int16(r), int16(g), int16(b), int16(a),
		)
		num++
	}
	if len(vertices) == 0 {
		return nil
	}
	c.BufferSubData(c.ArrayBuffer, vertices)
	c.DrawElements(c.Triangles, 6*num)

	return nil
}
Beispiel #11
0
func drawLines(c *opengl.Context, projectionMatrix *[4][4]float64, lines Lines) error {
	if !shadersInitialized {
		if err := initialize(c); err != nil {
			return err
		}
		shadersInitialized = true
	}

	if lines.Len() == 0 {
		return nil
	}

	f := useProgramForLines(c, glMatrix(projectionMatrix))
	defer f.FinishProgram()

	vertices := vertices[0:0]
	num := 0
	for i := 0; i < lines.Len(); i++ {
		x0, y0, x1, y1 := lines.Points(i)
		if x0 == x1 && y0 == y1 {
			continue
		}
		r, g, b, a := lines.Color(i).RGBA()
		vertices = append(vertices,
			int16(x0), int16(y0), int16(r), int16(g), int16(b), int16(a),
			int16(x1), int16(y1), int16(r), int16(g), int16(b), int16(a),
		)
		num++
	}
	if len(vertices) == 0 {
		return nil
	}
	c.BufferSubData(c.ArrayBuffer, vertices)
	c.DrawElements(c.Lines, 2*num)

	return nil
}
Beispiel #12
0
func initialize(c *opengl.Context) error {
	shaderVertexModelviewNative, err := c.NewShader(c.VertexShader, shader(c, shaderVertexModelview))
	if err != nil {
		return err
	}
	defer c.DeleteShader(shaderVertexModelviewNative)

	shaderVertexColorNative, err := c.NewShader(c.VertexShader, shader(c, shaderVertexColor))
	if err != nil {
		return err
	}
	defer c.DeleteShader(shaderVertexColorNative)

	shaderVertexColorLineNative, err := c.NewShader(c.VertexShader, shader(c, shaderVertexColorLine))
	if err != nil {
		return err
	}
	defer c.DeleteShader(shaderVertexColorLineNative)

	shaderFragmentTextureNative, err := c.NewShader(c.FragmentShader, shader(c, shaderFragmentTexture))
	if err != nil {
		return err
	}
	defer c.DeleteShader(shaderFragmentTextureNative)

	shaderFragmentSolidNative, err := c.NewShader(c.FragmentShader, shader(c, shaderFragmentSolid))
	if err != nil {
		return err
	}
	defer c.DeleteShader(shaderFragmentSolidNative)

	programTexture, err = c.NewProgram([]opengl.Shader{
		shaderVertexModelviewNative,
		shaderFragmentTextureNative,
	})
	if err != nil {
		return err
	}

	programSolidRect, err = c.NewProgram([]opengl.Shader{
		shaderVertexColorNative,
		shaderFragmentSolidNative,
	})
	if err != nil {
		return err
	}

	programSolidLine, err = c.NewProgram([]opengl.Shader{
		shaderVertexColorLineNative,
		shaderFragmentSolidNative,
	})
	if err != nil {
		return err
	}

	// 16 [bytse] is an arbitrary number which seems enough to draw anything. Fix this if necessary.
	const stride = 16
	c.NewBuffer(c.ArrayBuffer, 4*stride*quadsMaxNum, c.DynamicDraw)

	indices := make([]uint16, 6*quadsMaxNum)
	for i := uint16(0); i < quadsMaxNum; i++ {
		indices[6*i+0] = 4*i + 0
		indices[6*i+1] = 4*i + 1
		indices[6*i+2] = 4*i + 2
		indices[6*i+3] = 4*i + 1
		indices[6*i+4] = 4*i + 2
		indices[6*i+5] = 4*i + 3
	}
	indexBufferQuads = c.NewBuffer(c.ElementArrayBuffer, indices, c.StaticDraw)

	indices = make([]uint16, indicesNum)
	for i := 0; i < len(indices); i++ {
		indices[i] = uint16(i)
	}
	indexBufferLines = c.NewBuffer(c.ElementArrayBuffer, indices, c.StaticDraw)

	return nil
}
Beispiel #13
0
func useProgramForTexture(c *opengl.Context, projectionMatrix []float32, texture opengl.Texture, geo Matrix, color Matrix) programFinisher {
	if !lastProgram.Equals(programTexture) {
		c.UseProgram(programTexture)
		lastProgram = programTexture
		lastProjectionMatrix = nil
		lastModelviewMatrix = nil
		lastColorMatrix = nil
	}
	program := programTexture

	c.BindElementArrayBuffer(indexBufferQuads)

	if !areSameFloat32Array(lastProjectionMatrix, projectionMatrix) {
		c.UniformFloats(program, "projection_matrix", projectionMatrix)
		if lastProjectionMatrix == nil {
			lastProjectionMatrix = make([]float32, 16)
		}
		copy(lastProjectionMatrix, projectionMatrix)
	}

	ma := float32(geo.Element(0, 0))
	mb := float32(geo.Element(0, 1))
	mc := float32(geo.Element(1, 0))
	md := float32(geo.Element(1, 1))
	tx := float32(geo.Element(0, 2))
	ty := float32(geo.Element(1, 2))
	modelviewMatrix := []float32{
		ma, mc, 0, 0,
		mb, md, 0, 0,
		0, 0, 1, 0,
		tx, ty, 0, 1,
	}
	if !areSameFloat32Array(lastModelviewMatrix, modelviewMatrix) {
		c.UniformFloats(program, "modelview_matrix", modelviewMatrix)
		if lastModelviewMatrix == nil {
			lastModelviewMatrix = make([]float32, 16)
		}
		copy(lastModelviewMatrix, modelviewMatrix)
	}

	c.UniformInt(program, "texture", 0)

	e := [4][5]float32{}
	for i := 0; i < 4; i++ {
		for j := 0; j < 5; j++ {
			e[i][j] = float32(color.Element(i, j))
		}
	}

	colorMatrix := []float32{
		e[0][0], e[1][0], e[2][0], e[3][0],
		e[0][1], e[1][1], e[2][1], e[3][1],
		e[0][2], e[1][2], e[2][2], e[3][2],
		e[0][3], e[1][3], e[2][3], e[3][3],
	}
	if !areSameFloat32Array(lastColorMatrix, colorMatrix) {
		c.UniformFloats(program, "color_matrix", colorMatrix)
		if lastColorMatrix == nil {
			lastColorMatrix = make([]float32, 16)
		}
		copy(lastColorMatrix, colorMatrix)
	}
	colorMatrixTranslation := []float32{
		e[0][4], e[1][4], e[2][4], e[3][4],
	}
	c.UniformFloats(program, "color_matrix_translation", colorMatrixTranslation)

	// We don't have to call gl.ActiveTexture here: GL_TEXTURE0 is the default active texture
	// See also: https://www.opengl.org/sdk/docs/man2/xhtml/glActiveTexture.xml
	c.BindTexture(texture)

	c.EnableVertexAttribArray(program, "vertex")
	c.EnableVertexAttribArray(program, "tex_coord")

	c.VertexAttribPointer(program, "vertex", true, false, int16Size*4, 2, int16Size*0)
	c.VertexAttribPointer(program, "tex_coord", true, true, int16Size*4, 2, int16Size*2)

	return func() {
		c.DisableVertexAttribArray(program, "tex_coord")
		c.DisableVertexAttribArray(program, "vertex")
	}
}
Beispiel #14
0
func (f *framebuffer) setAsViewport(context *opengl.Context) error {
	width := viewportSize
	height := viewportSize
	return context.SetViewport(f.native, width, height)
}
Beispiel #15
0
func (f *Framebuffer) Pixels(c *opengl.Context) ([]uint8, error) {
	w, h := f.Size()
	w, h = NextPowerOf2Int(w), NextPowerOf2Int(h)
	return c.FramebufferPixels(f.native, w, h)
}
Beispiel #16
0
func (f *Framebuffer) setAsViewport(c *opengl.Context) error {
	width := NextPowerOf2Int(f.width)
	height := NextPowerOf2Int(f.height)
	return c.SetViewport(f.native, width, height)
}
Beispiel #17
0
func (t *Texture) ReplacePixels(c *opengl.Context, p []uint8) error {
	c.BindTexture(t.native)
	c.TexSubImage2D(p, t.width, t.height)
	return nil
}
Beispiel #18
0
func (t *Texture) Dispose(c *opengl.Context) {
	c.DeleteTexture(t.native)
}
Beispiel #19
0
func (i *Image) IsInvalidated(context *opengl.Context) bool {
	return !context.IsTexture(i.texture.native)
}
Beispiel #20
0
func useProgramForRects(c *opengl.Context, projectionMatrix []float32) programFinisher {
	if !lastProgram.Equals(programSolidRect) {
		c.UseProgram(programSolidRect)
		lastProgram = programSolidRect
	}
	program := programSolidRect

	c.BindElementArrayBuffer(indexBufferQuads)

	c.UniformFloats(program, "projection_matrix", projectionMatrix)

	c.EnableVertexAttribArray(program, "vertex")
	c.EnableVertexAttribArray(program, "color")

	c.VertexAttribPointer(program, "vertex", true, false, int16Size*6, 2, int16Size*0)
	c.VertexAttribPointer(program, "color", false, true, int16Size*6, 4, int16Size*2)

	return func() {
		c.DisableVertexAttribArray(program, "color")
		c.DisableVertexAttribArray(program, "vertex")
	}
}