gl

package
v0.0.0-...-d322e89 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 14, 2018 License: BSD-2-Clause Imports: 13 Imported by: 0

Documentation

Overview

Package gl provides simple abstractions over a modern subset of OpenGL.

Example (FirstCube)
package main

import (
	"github.com/cozely/cozely"
	"github.com/cozely/cozely/color"
	"github.com/cozely/cozely/coord"
	"github.com/cozely/cozely/input"
	"github.com/cozely/cozely/space"
	"github.com/cozely/cozely/window"
	"github.com/cozely/cozely/x/gl"
	"github.com/cozely/cozely/x/math32"
)

// Declarations ////////////////////////////////////////////////////////////////

// Input Bindings

var (
	quit   = input.Button("Quit")
	rotate = input.Button("Rotate")
	move   = input.Button("Move")
	zoom   = input.Button("Zoom")
	delta  = input.Delta("Delta")
)

type loop04 struct {
	// OpenGL objects
	pipeline    *gl.Pipeline
	perFrameUBO gl.UniformBuffer

	// Transformation matrices
	screenFromView  space.Matrix // projection matrix
	viewFromWorld   space.Matrix // view matrix
	worldFromObject space.Matrix // model matrix

	// Cube state
	position   coord.XYZ
	yaw, pitch float32
}

// Uniform buffer
type perObject struct {
	screenFromObject space.Matrix
}

// Vertex buffer
type mesh []struct {
	position coord.XYZ  `layout:"0"`
	color    color.LRGB `layout:"1"`
}

// Initialization //////////////////////////////////////////////////////////////

func main() {
	defer cozely.Recover()

	cozely.Configure(cozely.Multisample(8))
	l := loop04{}
	window.Events.Resize = func() {
		s := window.Size()
		gl.Viewport(0, 0, int32(s.X), int32(s.Y))
		r := float32(s.X) / float32(s.Y)
		l.screenFromView = space.Perspective(math32.Pi/4, r, 0.001, 1000.0)
	}
	err := cozely.Run(&l)
	if err != nil {
		panic(err)
	}
}

func (l *loop04) Enter() {
	// Create and configure the pipeline
	l.pipeline = gl.NewPipeline(
		gl.Shader(cozely.Path()+"shader04.vert"),
		gl.Shader(cozely.Path()+"shader04.frag"),
		gl.VertexFormat(0, mesh{}),
		gl.Topology(gl.Triangles),
		gl.CullFace(false, true),
		gl.DepthTest(true),
		gl.DepthWrite(true),
		gl.DepthComparison(gl.LessOrEqual),
	)
	gl.Enable(gl.FramebufferSRGB)

	// Create the uniform buffer
	l.perFrameUBO = gl.NewUniformBuffer(&perObject{}, gl.DynamicStorage)

	// Create and fill the vertex buffer
	vbo := gl.NewVertexBuffer(coloredcube(), 0)

	// Initialize worldFromObject and viewFromWorld matrices
	l.position = coord.XYZ{0, 0, 0}
	l.yaw = -0.6
	l.pitch = 0.3
	l.computeWorldFromObject()
	l.computeViewFromWorld()

	// Bind the vertex buffer to the pipeline
	l.pipeline.Bind()
	vbo.Bind(0, 0)
	l.pipeline.Unbind()
}

func (loop04) Leave() {
}

// Game Loop ///////////////////////////////////////////////////////////////////

func (l *loop04) React() {
	m := delta.XY()
	s := window.Size().Coord()

	if rotate.Pressed() || move.Pressed() || zoom.Pressed() {
		input.GrabMouse(true)
	}
	if rotate.Released() || move.Released() || zoom.Released() {
		input.GrabMouse(false)
	}

	if rotate.Ongoing() {
		l.yaw += 4 * m.X / s.X
		l.pitch += 4 * m.Y / s.Y
		switch {
		case l.pitch < -math32.Pi/2:
			l.pitch = -math32.Pi / 2
		case l.pitch > +math32.Pi/2:
			l.pitch = +math32.Pi / 2
		}
		l.computeWorldFromObject()
	}

	if move.Ongoing() {
		d := m.Times(2).Slashxy(s)
		l.position.X += d.X
		l.position.Y -= d.Y
		l.computeWorldFromObject()
	}

	if zoom.Ongoing() {
		d := m.Times(2).Slashxy(s)
		l.position.X += d.X
		l.position.Z += d.Y
		l.computeWorldFromObject()
	}

	if quit.Pressed() {
		cozely.Stop(nil)
	}
}

func (l *loop04) computeWorldFromObject() {
	rot := space.EulerZXY(l.pitch, l.yaw, 0)
	l.worldFromObject = space.Translation(l.position).Times(rot)
}

func (l *loop04) computeViewFromWorld() {
	l.viewFromWorld = space.LookAt(
		coord.XYZ{0, 0, 3},
		coord.XYZ{0, 0, 0},
		coord.XYZ{0, 1, 0},
	)
}

func (loop04) Update() {
}

func (l *loop04) Render() {
	l.pipeline.Bind()
	gl.ClearDepthBuffer(1.0)
	gl.ClearColorBuffer(color.LRGBA{0.9, 0.9, 0.9, 1.0})

	u := perObject{
		screenFromObject: l.screenFromView.
			Times(l.viewFromWorld).
			Times(l.worldFromObject),
	}
	l.perFrameUBO.SubData(&u, 0)
	l.perFrameUBO.Bind(0)

	gl.Draw(0, 6*2*3)

	l.pipeline.Unbind()
}

////////////////////////////////////////////////////////////////////////////////

var (
	purple = color.LRGB{0.2, 0, 0.6}
	orange = color.LRGB{0.8, 0.3, 0}
	green  = color.LRGB{0, 0.3, 0.1}
)

func coloredcube() mesh {
	return mesh{
		// Front Face
		{coord.XYZ{-0.5, -0.5, +0.5}, purple},
		{coord.XYZ{+0.5, +0.5, +0.5}, purple},
		{coord.XYZ{-0.5, +0.5, +0.5}, purple},
		{coord.XYZ{-0.5, -0.5, +0.5}, purple},
		{coord.XYZ{+0.5, -0.5, +0.5}, purple},
		{coord.XYZ{+0.5, +0.5, +0.5}, purple},
		// Back Face
		{coord.XYZ{-0.5, -0.5, -0.5}, purple},
		{coord.XYZ{-0.5, +0.5, -0.5}, purple},
		{coord.XYZ{+0.5, +0.5, -0.5}, purple},
		{coord.XYZ{-0.5, -0.5, -0.5}, purple},
		{coord.XYZ{+0.5, +0.5, -0.5}, purple},
		{coord.XYZ{+0.5, -0.5, -0.5}, purple},
		// Right Face
		{coord.XYZ{+0.5, -0.5, +0.5}, green},
		{coord.XYZ{+0.5, +0.5, -0.5}, green},
		{coord.XYZ{+0.5, +0.5, +0.5}, green},
		{coord.XYZ{+0.5, -0.5, +0.5}, green},
		{coord.XYZ{+0.5, -0.5, -0.5}, green},
		{coord.XYZ{+0.5, +0.5, -0.5}, green},
		// Left Face
		{coord.XYZ{-0.5, -0.5, +0.5}, green},
		{coord.XYZ{-0.5, +0.5, +0.5}, green},
		{coord.XYZ{-0.5, +0.5, -0.5}, green},
		{coord.XYZ{-0.5, -0.5, +0.5}, green},
		{coord.XYZ{-0.5, +0.5, -0.5}, green},
		{coord.XYZ{-0.5, -0.5, -0.5}, green},
		// Bottom Face
		{coord.XYZ{-0.5, -0.5, +0.5}, orange},
		{coord.XYZ{-0.5, -0.5, -0.5}, orange},
		{coord.XYZ{+0.5, -0.5, +0.5}, orange},
		{coord.XYZ{-0.5, -0.5, -0.5}, orange},
		{coord.XYZ{+0.5, -0.5, -0.5}, orange},
		{coord.XYZ{+0.5, -0.5, +0.5}, orange},
		// Top Face
		{coord.XYZ{-0.5, +0.5, +0.5}, orange},
		{coord.XYZ{+0.5, +0.5, +0.5}, orange},
		{coord.XYZ{-0.5, +0.5, -0.5}, orange},
		{coord.XYZ{-0.5, +0.5, -0.5}, orange},
		{coord.XYZ{+0.5, +0.5, +0.5}, orange},
		{coord.XYZ{+0.5, +0.5, -0.5}, orange},
	}
}
Output:

Example (FirstTriangle)
package main

import (
	"github.com/cozely/cozely"
	"github.com/cozely/cozely/color"
	"github.com/cozely/cozely/window"
	"github.com/cozely/cozely/x/gl"
)

// Declarations ////////////////////////////////////////////////////////////////

type loop01 struct {
	// OpenGL Object
	pipeline *gl.Pipeline
}

// Initialization //////////////////////////////////////////////////////////////

func main() {
	defer cozely.Recover()

	window.Events.Resize = func() {
		s := window.Size()
		gl.Viewport(0, 0, int32(s.X), int32(s.Y))
	}
	l := loop01{}
	err := cozely.Run(&l)
	if err != nil {
		panic(err)
	}
}

func (l *loop01) Enter() {
	// Create and configure the pipeline
	l.pipeline = gl.NewPipeline(
		gl.Shader(cozely.Path()+"shader01.vert"),
		gl.Shader(cozely.Path()+"shader01.frag"),
		gl.Topology(gl.Triangles),
	)
}

func (loop01) Leave() {
}

// Game Loop ///////////////////////////////////////////////////////////////////

func (loop01) React() {
	// if input.Default.Back.Pushed() {
	// 	cozely.Stop(nil)
	// }
}

func (loop01) Update() {
}

func (l *loop01) Render() {
	l.pipeline.Bind()
	gl.ClearColorBuffer(color.LRGBA{0.9, 0.9, 0.9, 1.0})

	gl.Draw(0, 3)
	l.pipeline.Unbind()
}
Output:

Example (IndirectDraw)
package main

import (
	"github.com/cozely/cozely"
	"github.com/cozely/cozely/color"
	"github.com/cozely/cozely/coord"
	"github.com/cozely/cozely/input"
	"github.com/cozely/cozely/space"
	"github.com/cozely/cozely/window"
	"github.com/cozely/cozely/x/gl"
	"github.com/cozely/cozely/x/math32"
)

// Declarations ////////////////////////////////////////////////////////////////

// Input Bindings
// (same as in FirstCube example)

type loop07 struct {
	// OpenGL objects
	pipeline    *gl.Pipeline
	perFrameUBO gl.UniformBuffer

	// Tranformation matrices
	screenFromView  space.Matrix // projection matrix
	viewFromWorld   space.Matrix // view matrix
	worldFromObject space.Matrix // model matirx

	// Cube state
	position   coord.XYZ
	yaw, pitch float32
}

// Uniform buffer
// (same as in FirstCube example)
// type perObject struct {
// 	screenFromObject space.Matrix
// }

// Indirect Command Buffer
var commands = []gl.DrawIndirectCommand{
	{
		VertexCount:   6,
		InstanceCount: 1,
		FirstVertex:   0,
		BaseInstance:  1,
	},
	{
		VertexCount:   6,
		InstanceCount: 1,
		FirstVertex:   6,
		BaseInstance:  1,
	},
	{
		VertexCount:   6,
		InstanceCount: 1,
		FirstVertex:   12,
		BaseInstance:  2,
	},
	{
		VertexCount:   6,
		InstanceCount: 1,
		FirstVertex:   18,
		BaseInstance:  3,
	},
	{
		VertexCount:   6,
		InstanceCount: 1,
		FirstVertex:   24,
		BaseInstance:  4,
	},
	{
		VertexCount:   6,
		InstanceCount: 1,
		FirstVertex:   30,
		BaseInstance:  5,
	},
}

// Instance Buffer
var draws = []struct {
	color color.LRGB `layout:"1" divisor:"1"`
}{
	{color.LRGB{R: 0.2, G: 0, B: 0.6}},
	{color.LRGB{R: 0.2, G: 0, B: 0.6}},
	{color.LRGB{R: 0, G: 0.3, B: 0.1}},
	{color.LRGB{R: 0, G: 0.3, B: 0.1}},
	{color.LRGB{R: 0.8, G: 0.3, B: 0}},
	{color.LRGB{R: 0.8, G: 0.3, B: 0}},
}

// Vertex buffer
type simplemesh []struct {
	position coord.XYZ `layout:"0"`
}

// Initialization //////////////////////////////////////////////////////////////

func main() {
	defer cozely.Recover()

	cozely.Configure(cozely.Multisample(8))
	l := loop07{}
	window.Events.Resize = func() {
		s := window.Size()
		gl.Viewport(0, 0, int32(s.X), int32(s.Y))
		r := float32(s.X) / float32(s.Y)
		l.screenFromView = space.Perspective(math32.Pi/4, r, 0.001, 1000.0)
	}
	err := cozely.Run(&l)
	if err != nil {
		panic(err)
	}
}

func (l *loop07) Enter() {
	// Create and configure the pipeline
	l.pipeline = gl.NewPipeline(
		gl.Shader(cozely.Path()+"shader07.vert"),
		gl.Shader(cozely.Path()+"shader07.frag"),
		gl.VertexFormat(0, simplemesh{}),
		gl.VertexFormat(1, draws),
		gl.Topology(gl.Triangles),
		gl.CullFace(false, true),
		gl.DepthTest(true),
	)
	gl.Enable(gl.FramebufferSRGB)
	//TODO: bug related to depth or face culling when run in test sequence

	// Create the uniform buffer
	l.perFrameUBO = gl.NewUniformBuffer(&perObject{}, gl.DynamicStorage)

	// Create the Indirect Command Buffer
	icbo := gl.NewIndirectBuffer(commands, gl.DynamicStorage)
	ibo := gl.NewVertexBuffer(draws, gl.DynamicStorage)

	// Create and fill the vertex buffer
	vbo := gl.NewVertexBuffer(simplecube(), 0)

	// Initialize worldFromObject and viewFromWorld matrices
	l.position = coord.XYZ{0, 0, 0}
	l.yaw = -0.6
	l.pitch = 0.3
	l.computeWorldFromObject()
	l.computeViewFromWorld()

	// Bind the vertex buffer to the pipeline
	l.pipeline.Bind()
	vbo.Bind(0, 0)
	icbo.Bind()
	ibo.Bind(1, 0)
	l.pipeline.Unbind()
}

func (loop07) Leave() {
}

// Game Loop ///////////////////////////////////////////////////////////////////

func (loop07) Update() {
}

func (l *loop07) React() {
	m := delta.XY()
	s := window.Size().Coord()

	if rotate.Pressed() || move.Pressed() || zoom.Pressed() {
		input.GrabMouse(true)
	}
	if rotate.Released() || move.Released() || zoom.Released() {
		input.GrabMouse(false)
	}

	if rotate.Ongoing() {
		l.yaw += 4 * m.X / s.X
		l.pitch += 4 * m.Y / s.Y
		switch {
		case l.pitch < -math32.Pi/2:
			l.pitch = -math32.Pi / 2
		case l.pitch > +math32.Pi/2:
			l.pitch = +math32.Pi / 2
		}
		l.computeWorldFromObject()
	}

	if move.Ongoing() {
		d := m.Times(2).Slashxy(s)
		l.position.X += d.X
		l.position.Y -= d.Y
		l.computeWorldFromObject()
	}

	if zoom.Ongoing() {
		d := m.Times(2).Slashxy(s)
		l.position.X += d.X
		l.position.Z += d.Y
		l.computeWorldFromObject()
	}

	if quit.Pressed() {
		cozely.Stop(nil)
	}
}

func (l *loop07) Render() {
	l.pipeline.Bind()
	gl.ClearDepthBuffer(1.0)
	gl.ClearColorBuffer(color.LRGBA{0.9, 0.9, 0.9, 1.0})

	u := perObject{
		screenFromObject: l.screenFromView.
			Times(l.viewFromWorld).
			Times(l.worldFromObject),
	}
	l.perFrameUBO.SubData(&u, 0)
	l.perFrameUBO.Bind(0)

	gl.DrawIndirect(0, 6)

	l.pipeline.Unbind()
}

func (l *loop07) computeWorldFromObject() {
	rot := space.EulerZXY(l.pitch, l.yaw, 0)
	l.worldFromObject = space.Translation(l.position).Times(rot)
}

func (l *loop07) computeViewFromWorld() {
	l.viewFromWorld = space.LookAt(
		coord.XYZ{0, 0, 3},
		coord.XYZ{0, 0, 0},
		coord.XYZ{0, 1, 0},
	)
}

////////////////////////////////////////////////////////////////////////////////

func simplecube() simplemesh {
	return simplemesh{
		// Front Face
		{coord.XYZ{-0.5, -0.5, +0.5}},
		{coord.XYZ{+0.5, +0.5, +0.5}},
		{coord.XYZ{-0.5, +0.5, +0.5}},
		{coord.XYZ{-0.5, -0.5, +0.5}},
		{coord.XYZ{+0.5, -0.5, +0.5}},
		{coord.XYZ{+0.5, +0.5, +0.5}},
		// Back Face
		{coord.XYZ{-0.5, -0.5, -0.5}},
		{coord.XYZ{-0.5, +0.5, -0.5}},
		{coord.XYZ{+0.5, +0.5, -0.5}},
		{coord.XYZ{-0.5, -0.5, -0.5}},
		{coord.XYZ{+0.5, +0.5, -0.5}},
		{coord.XYZ{+0.5, -0.5, -0.5}},
		// Right Face
		{coord.XYZ{+0.5, -0.5, +0.5}},
		{coord.XYZ{+0.5, +0.5, -0.5}},
		{coord.XYZ{+0.5, +0.5, +0.5}},
		{coord.XYZ{+0.5, -0.5, +0.5}},
		{coord.XYZ{+0.5, -0.5, -0.5}},
		{coord.XYZ{+0.5, +0.5, -0.5}},
		// Left Face
		{coord.XYZ{-0.5, -0.5, +0.5}},
		{coord.XYZ{-0.5, +0.5, +0.5}},
		{coord.XYZ{-0.5, +0.5, -0.5}},
		{coord.XYZ{-0.5, -0.5, +0.5}},
		{coord.XYZ{-0.5, +0.5, -0.5}},
		{coord.XYZ{-0.5, -0.5, -0.5}},
		// Bottom Face
		{coord.XYZ{-0.5, -0.5, +0.5}},
		{coord.XYZ{-0.5, -0.5, -0.5}},
		{coord.XYZ{+0.5, -0.5, +0.5}},
		{coord.XYZ{-0.5, -0.5, -0.5}},
		{coord.XYZ{+0.5, -0.5, -0.5}},
		{coord.XYZ{+0.5, -0.5, +0.5}},
		// Top Face
		{coord.XYZ{-0.5, +0.5, +0.5}},
		{coord.XYZ{+0.5, +0.5, +0.5}},
		{coord.XYZ{-0.5, +0.5, -0.5}},
		{coord.XYZ{-0.5, +0.5, -0.5}},
		{coord.XYZ{+0.5, +0.5, +0.5}},
		{coord.XYZ{+0.5, +0.5, -0.5}},
	}
}
Output:

Example (InstancedDraw)
package main

import (
	"math/rand"

	"github.com/cozely/cozely/color"
	"github.com/cozely/cozely/coord"
	"github.com/cozely/cozely/input"
	"github.com/cozely/cozely/window"

	"github.com/cozely/cozely"
	"github.com/cozely/cozely/x/gl"
)

// Declarations ////////////////////////////////////////////////////////////////

type loop06 struct {
	// OpenGL objects
	pipeline    *gl.Pipeline
	perFrameUBO gl.UniformBuffer
	rosesINBO   gl.VertexBuffer
	perFrame    perFrame06
}

// Instance Buffer
var roses [64]struct {
	position    coord.XY `layout:"0" divisor:"1"`
	size        float32  `layout:"1"`
	numerator   int32    `layout:"2"`
	denominator int32    `layout:"3"`
	offset      float32  `layout:"4"`
	speed       float32  `layout:"5"`
}

const nbPoints int32 = 512

// Uniform buffer
type perFrame06 struct {
	ratio float32
	time  float32
}

// Initialization //////////////////////////////////////////////////////////////

func main() {
	defer cozely.Recover()

	cozely.Configure(cozely.Multisample(8))
	l := loop06{}
	window.Events.Resize = func() {
		s := window.Size()
		l.perFrame.ratio = float32(s.X) / float32(s.Y)
		gl.Viewport(0, 0, int32(s.X), int32(s.Y))
	}
	err := cozely.Run(&l)
	if err != nil {
		panic(err)
	}
}

func (l *loop06) Enter() {

	// Setup the pipeline
	l.pipeline = gl.NewPipeline(
		gl.Shader(cozely.Path()+"shader06.vert"),
		gl.Shader(cozely.Path()+"shader06.frag"),
		gl.VertexFormat(1, roses[:]),
		gl.Topology(gl.LineStrip),
	)
	gl.Enable(gl.FramebufferSRGB)

	// Create the uniform buffer
	l.perFrameUBO = gl.NewUniformBuffer(&perFrame{}, gl.DynamicStorage)

	// Create the instance buffer
	l.randomizeRosesData()
	l.rosesINBO = gl.NewVertexBuffer(roses[:], gl.DynamicStorage)

	// Bind the instance buffer to the pipeline
	l.pipeline.Bind()
	l.rosesINBO.Bind(1, 0)
	l.pipeline.Unbind()
}

func (loop06) Leave() {
}

// Game Loop ///////////////////////////////////////////////////////////////////

func (l *loop06) React() {
	if input.Select.Pressed() || input.Click.Pressed() {
		l.randomizeRosesData()
		l.rosesINBO.SubData(roses[:], 0)
	}

	if quit.Pressed() {
		cozely.Stop(nil)
	}
}

func (loop06) Update() {
}

func (l *loop06) Render() {
	l.perFrame.time += float32(cozely.RenderDelta())

	l.pipeline.Bind()
	gl.ClearDepthBuffer(1.0)
	gl.ClearColorBuffer(color.LRGBA{0.9, 0.85, 0.80, 1.0})
	gl.Enable(gl.LineSmooth)
	gl.Enable(gl.Blend)
	gl.Blending(gl.SrcAlpha, gl.OneMinusSrcAlpha)

	u := l.perFrame
	l.perFrameUBO.Bind(0)
	l.perFrameUBO.SubData(&u, 0)
	gl.DrawInstanced(0, nbPoints, int32(len(roses)))

	l.pipeline.Unbind()
}

func (l *loop06) randomizeRosesData() {
	for i := 0; i < len(roses); i++ {
		roses[i].position.X = rand.Float32()*2.0 - 1.0
		roses[i].position.Y = rand.Float32()*2.0 - 1.0
		roses[i].size = rand.Float32()*0.20 + 0.1
		roses[i].numerator = rand.Int31n(16) + 1
		roses[i].denominator = rand.Int31n(16) + 1
		roses[i].offset = rand.Float32()*2.8 + 0.2
		roses[i].speed = 0.5 + 1.5*rand.Float32()
		if rand.Int31n(2) > 0 {
			roses[i].speed = -roses[i].speed
		}
	}
}

////////////////////////////////////////////////////////////////////////////////

// func rose(nbPoints int, num int, den int, offset float32) []perVertex {
// 	var m = []perVertex{}
// 	for i := den * nbPoints; i >= 0; i-- {
// 		var k = float32(num) / float32(den)
// 		var theta = float32(i) * 2 * math32.Pi / float32(nbPoints)
// 		var r = (math.Cos(k*theta) + offset) / (1.0 + offset)
// 		var p = plane.Polar{r, theta}
// 		m = append(m, perVertex{p.Coord()})
// 	}
// 	return m
// }
Output:

Example (Streaming)
package main

import (
	"math/rand"

	"github.com/cozely/cozely"
	"github.com/cozely/cozely/color"
	"github.com/cozely/cozely/coord"
	"github.com/cozely/cozely/input"
	"github.com/cozely/cozely/window"
	"github.com/cozely/cozely/x/gl"
	"github.com/cozely/cozely/x/math32"
)

// Declarations ////////////////////////////////////////////////////////////////

// Input Bindings
// (same as in InstancedDraw example)

type loop08 struct {
	// OpenGL objects
	pipeline    *gl.Pipeline
	perFrameUBO gl.UniformBuffer
	pointsVBO   gl.VertexBuffer
	perFrame    perFrame08

	// Application State
	bgColor  color.LRGBA
	rotSpeed float32
	jitter   float32
	angles   []float32
	speeds   []float32

	cleared, updated bool
}

// Uniform buffer
type perFrame08 struct {
	ratio    coord.XY
	Rotation float32
}

// Vertex buffer
var points [512]struct {
	Position coord.XY `layout:"0"`
}

// Initialization //////////////////////////////////////////////////////////////

func main() {
	defer cozely.Recover()

	l := loop08{
		bgColor:  color.LRGBA{0.9, 0.87, 0.85, 1.0},
		rotSpeed: float32(0.003),
		jitter:   float32(0.002),
		angles:   make([]float32, len(points)),
		speeds:   make([]float32, len(points)),
	}

	cozely.Configure(cozely.Multisample(8), gl.NoClear())
	window.Events.Resize = l.resize
	err := cozely.Run(&l)
	if err != nil {
		panic(err)
	}
}

func (l *loop08) Enter() {

	// Create and configure the pipeline
	l.pipeline = gl.NewPipeline(
		gl.Shader(cozely.Path()+"shader08.vert"),
		gl.Shader(cozely.Path()+"shader08.frag"),
		gl.Topology(gl.Points),
		gl.VertexFormat(0, points[:]),
		gl.DepthTest(false),
		gl.DepthWrite(false),
	)

	// Create the uniform buffer
	l.perFrameUBO = gl.NewUniformBuffer(&perFrame08{}, gl.DynamicStorage)
	l.perFrame.Rotation = 0.0

	// Create and fill the vertex buffer
	// points = make(mesh, len(points))
	l.setupPoints()
	l.pointsVBO = gl.NewVertexBuffer(points[:], gl.DynamicStorage)

	// Bind the vertex buffer to the pipeline
	l.pipeline.Bind()
	l.pointsVBO.Bind(0, 0)
	l.pipeline.Unbind()
}

func (loop08) Leave() {
}

// Game Loop ///////////////////////////////////////////////////////////////////

func (l *loop08) React() {
	if input.Select.Pressed() {
		l.setupPoints()
	}

	if quit.Pressed() {
		cozely.Stop(nil)
	}
}

func (l *loop08) Update() {
	for i, pt := range points {
		points[i].Position = coord.XY{
			pt.Position.X +
				l.speeds[i]*math32.Cos(l.angles[i]) +
				l.jitter*(rand.Float32()-0.5),
			pt.Position.Y +
				l.speeds[i]*math32.Sin(l.angles[i]) +
				l.jitter*(rand.Float32()-0.5),
		}
		if points[i].Position.Length() > 0.75 {
			l.angles[i] += math32.Pi / 4.0
		}
	}
	l.pointsVBO.SubData(points[:], 0)

	l.perFrame.Rotation += l.rotSpeed

	l.updated = true
}

func (l *loop08) Render() {
	if !l.cleared {
		gl.ClearColorBuffer(l.bgColor)
		l.cleared = true
	}
	if l.updated {
		l.pipeline.Bind()
		gl.Enable(gl.FramebufferSRGB)
		gl.Enable(gl.Blend)
		gl.Blending(gl.SrcAlpha, gl.OneMinusSrcAlpha)
		gl.PointSize(3.0)

		u := l.perFrame
		l.perFrameUBO.Bind(0)
		l.perFrameUBO.SubData(&u, 0)

		gl.Draw(0, int32(len(points)))

		l.pipeline.Unbind()
		l.updated = false
	}
}

func (l *loop08) setupPoints() {
	n := float32(3 + rand.Intn(13))
	for i := range points {
		points[i].Position = coord.XY{rand.Float32(), rand.Float32()}
		a := math32.Floor(rand.Float32() * n)
		a = a * (2.0 * math32.Pi) / n
		points[i].Position = coord.XY{0.75 * math32.Cos(a), 0.75 * math32.Sin(a)}
		l.angles[i] = a + float32(i)*math32.Pi/float32(len(points)) + math32.Pi/2.0
		l.speeds[i] = 0.004 * rand.Float32()
	}
	l.rotSpeed = 0.01 * (rand.Float32() - 0.5)
	l.jitter = 0.014 * rand.Float32()
	l.cleared = false
}

func (l *loop08) resize() {
	l.setupPoints()

	s := window.Size().Coord()

	// Compute ratio
	if s.X > s.Y {
		l.perFrame.ratio = coord.XY{s.Y / s.X, 1.0}
	} else {
		l.perFrame.ratio = coord.XY{1.0, s.X / s.Y}
	}
	gl.Viewport(0, 0, int32(s.X), int32(s.Y))
}
Output:

Example (Texture)
package main

import (
	"image"
	_ "image/png"
	"os"

	"github.com/cozely/cozely"
	"github.com/cozely/cozely/color"
	"github.com/cozely/cozely/coord"
	"github.com/cozely/cozely/input"
	"github.com/cozely/cozely/space"
	"github.com/cozely/cozely/window"
	"github.com/cozely/cozely/x/gl"
	"github.com/cozely/cozely/x/math32"
)

// Declarations ////////////////////////////////////////////////////////////////

// Input Bindings
// (same as in example 04)

// OpenGL Objects

type loop05 struct {
	// OpenGL objects
	pipeline    *gl.Pipeline
	perFrameUBO gl.UniformBuffer
	sampler     gl.Sampler
	diffuse     gl.Texture2D

	// Transformation matrices
	screenFromView  space.Matrix // projection matrix
	viewFromWorld   space.Matrix // view matrix
	worldFromObject space.Matrix // model matrix

	// Cube state
	position   coord.XYZ
	yaw, pitch float32
}

// Uniform buffer
// (same as in example 04)
// type perObject struct {
// 	screenFromObject space.Matrix
// }

// Vertex buffer
type uvmesh []struct {
	position coord.XYZ `layout:"0"`
	uv       coord.XY  `layout:"1"`
}

// Initialization //////////////////////////////////////////////////////////////

func main() {
	defer cozely.Recover()

	cozely.Configure(cozely.Multisample(8))
	l := loop05{}
	window.Events.Resize = func() {
		s := window.Size()
		gl.Viewport(0, 0, int32(s.X), int32(s.Y))
		r := float32(s.X) / float32(s.Y)
		l.screenFromView = space.Perspective(math32.Pi/4, r, 0.001, 1000.0)
	}
	err := cozely.Run(&l)
	if err != nil {
		panic(err)
	}
}

func (l *loop05) Enter() {
	// Create and configure the pipeline
	l.pipeline = gl.NewPipeline(
		gl.Shader(cozely.Path()+"shader05.vert"),
		gl.Shader(cozely.Path()+"shader05.frag"),
		gl.VertexFormat(0, uvmesh{}),
		gl.Topology(gl.Triangles),
		gl.CullFace(false, true),
		gl.DepthTest(true),
		gl.DepthWrite(true),
		gl.DepthComparison(gl.LessOrEqual),
	)
	gl.Enable(gl.FramebufferSRGB)

	// Create the uniform buffer
	l.perFrameUBO = gl.NewUniformBuffer(&perObject{}, gl.DynamicStorage)

	// Create and fill the vertex buffer
	vbo := gl.NewVertexBuffer(uvcube(), gl.StaticStorage)

	// Create and bind the sampler
	l.sampler = gl.NewSampler(
		gl.Minification(gl.LinearMipmapLinear),
		gl.Anisotropy(16.0),
	)

	// Create and load the textures
	l.diffuse = gl.NewTexture2D(8, gl.SRGBA8, 512, 512)
	r, err := os.Open(cozely.Path() + "testpattern.png")
	if err != nil {
		panic(cozely.Wrap("opening texture", err))
	}
	defer r.Close()
	img, _, err := image.Decode(r)
	if err != nil {
		panic(cozely.Wrap("decoding texture", err))
	}
	l.diffuse.SubImage(0, 0, 0, img)
	l.diffuse.GenerateMipmap()

	// Initialize worldFromObject and viewFromWorld matrices
	l.position = coord.XYZ{0, 0, 0}
	l.yaw = -0.6
	l.pitch = 0.3
	l.computeWorldFromObject()
	l.computeViewFromWorld()

	// Bind the vertex buffer to the pipeline
	l.pipeline.Bind()
	vbo.Bind(0, 0)
	l.pipeline.Unbind()
}

func (loop05) Leave() {
}

// Game Loop ///////////////////////////////////////////////////////////////////

func (l *loop05) React() {
	m := delta.XY()
	s := window.Size().Coord()

	if rotate.Pressed() || move.Pressed() || zoom.Pressed() {
		input.GrabMouse(true)
	}
	if rotate.Released() || move.Released() || zoom.Released() {
		input.GrabMouse(false)
	}

	if rotate.Ongoing() {
		l.yaw += 4 * m.X / s.X
		l.pitch += 4 * m.Y / s.Y
		switch {
		case l.pitch < -math32.Pi/2:
			l.pitch = -math32.Pi / 2
		case l.pitch > +math32.Pi/2:
			l.pitch = +math32.Pi / 2
		}
		l.computeWorldFromObject()
	}

	if move.Ongoing() {
		d := m.Times(2).Slashxy(s)
		l.position.X += d.X
		l.position.Y -= d.Y
		l.computeWorldFromObject()
	}

	if zoom.Ongoing() {
		d := m.Times(2).Slashxy(s)
		l.position.X += d.X
		l.position.Z += d.Y
		l.computeWorldFromObject()
	}

	if quit.Pressed() {
		cozely.Stop(nil)
	}
}

func (l *loop05) computeWorldFromObject() {
	rot := space.EulerZXY(l.pitch, l.yaw, 0)
	l.worldFromObject = space.Translation(l.position).Times(rot)
}

func (l *loop05) computeViewFromWorld() {
	l.viewFromWorld = space.LookAt(
		coord.XYZ{0, 0, 3},
		coord.XYZ{0, 0, 0},
		coord.XYZ{0, 1, 0},
	)
}

func (loop05) Update() {
}

func (l *loop05) Render() {
	l.pipeline.Bind()
	gl.ClearDepthBuffer(1.0)
	gl.ClearColorBuffer(color.LRGBA{0.9, 0.9, 0.9, 1.0})

	u := perObject{
		screenFromObject: l.screenFromView.
			Times(l.viewFromWorld).
			Times(l.worldFromObject),
	}
	l.perFrameUBO.SubData(&u, 0)
	l.perFrameUBO.Bind(0)

	l.diffuse.Bind(0)
	l.sampler.Bind(0)
	gl.Draw(0, 6*2*3)

	l.pipeline.Unbind()
}

////////////////////////////////////////////////////////////////////////////////

func uvcube() uvmesh {
	return uvmesh{
		// Front Face
		{coord.XYZ{-0.5, -0.5, +0.5}, coord.XY{0, 1}},
		{coord.XYZ{+0.5, -0.5, +0.5}, coord.XY{1, 1}},
		{coord.XYZ{+0.5, +0.5, +0.5}, coord.XY{1, 0}},
		{coord.XYZ{-0.5, -0.5, +0.5}, coord.XY{0, 1}},
		{coord.XYZ{+0.5, +0.5, +0.5}, coord.XY{1, 0}},
		{coord.XYZ{-0.5, +0.5, +0.5}, coord.XY{0, 0}},
		// Back Face
		{coord.XYZ{+0.5, -0.5, -0.5}, coord.XY{0, 1}},
		{coord.XYZ{-0.5, -0.5, -0.5}, coord.XY{1, 1}},
		{coord.XYZ{-0.5, +0.5, -0.5}, coord.XY{1, 0}},
		{coord.XYZ{+0.5, -0.5, -0.5}, coord.XY{0, 1}},
		{coord.XYZ{-0.5, +0.5, -0.5}, coord.XY{1, 0}},
		{coord.XYZ{+0.5, +0.5, -0.5}, coord.XY{0, 0}},
		// Right Face
		{coord.XYZ{+0.5, -0.5, +0.5}, coord.XY{0, 1}},
		{coord.XYZ{+0.5, -0.5, -0.5}, coord.XY{1, 1}},
		{coord.XYZ{+0.5, +0.5, -0.5}, coord.XY{1, 0}},
		{coord.XYZ{+0.5, -0.5, +0.5}, coord.XY{0, 1}},
		{coord.XYZ{+0.5, +0.5, -0.5}, coord.XY{1, 0}},
		{coord.XYZ{+0.5, +0.5, +0.5}, coord.XY{0, 0}},
		// Left Face
		{coord.XYZ{-0.5, -0.5, -0.5}, coord.XY{0, 1}},
		{coord.XYZ{-0.5, -0.5, +0.5}, coord.XY{1, 1}},
		{coord.XYZ{-0.5, +0.5, +0.5}, coord.XY{1, 0}},
		{coord.XYZ{-0.5, -0.5, -0.5}, coord.XY{0, 1}},
		{coord.XYZ{-0.5, +0.5, +0.5}, coord.XY{1, 0}},
		{coord.XYZ{-0.5, +0.5, -0.5}, coord.XY{0, 0}},
		// Bottom Face
		{coord.XYZ{-0.5, -0.5, -0.5}, coord.XY{0, 1}},
		{coord.XYZ{+0.5, -0.5, -0.5}, coord.XY{1, 1}},
		{coord.XYZ{+0.5, -0.5, +0.5}, coord.XY{1, 0}},
		{coord.XYZ{-0.5, -0.5, -0.5}, coord.XY{0, 1}},
		{coord.XYZ{+0.5, -0.5, +0.5}, coord.XY{1, 0}},
		{coord.XYZ{-0.5, -0.5, +0.5}, coord.XY{0, 0}},
		// Top Face
		{coord.XYZ{-0.5, +0.5, +0.5}, coord.XY{0, 1}},
		{coord.XYZ{+0.5, +0.5, +0.5}, coord.XY{1, 1}},
		{coord.XYZ{+0.5, +0.5, -0.5}, coord.XY{1, 0}},
		{coord.XYZ{-0.5, +0.5, +0.5}, coord.XY{0, 1}},
		{coord.XYZ{+0.5, +0.5, -0.5}, coord.XY{1, 0}},
		{coord.XYZ{-0.5, +0.5, -0.5}, coord.XY{0, 0}},
	}
}
Output:

Example (UniformBuffer)
package main

import (
	"github.com/cozely/cozely"
	"github.com/cozely/cozely/color"
	"github.com/cozely/cozely/coord"
	"github.com/cozely/cozely/plane"
	"github.com/cozely/cozely/window"
	"github.com/cozely/cozely/x/gl"
)

// Declarations ////////////////////////////////////////////////////////////////

type loop03 struct {
	// OpenGL objects
	pipeline    *gl.Pipeline
	perFrameUBO gl.UniformBuffer
	// Animation state
	angle float64
}

// Uniform buffer
type perFrame struct {
	transform plane.GPUMatrix
}

// Vertex buffer
type coloredmesh2d []struct {
	position coord.XY   `layout:"0"`
	color    color.LRGB `layout:"1"`
}

// Initialization //////////////////////////////////////////////////////////////

func main() {
	defer cozely.Recover()

	window.Events.Resize = func() {
		s := window.Size()
		gl.Viewport(0, 0, int32(s.X), int32(s.Y))
	}
	l := loop03{}
	err := cozely.Run(&l)
	if err != nil {
		panic(err)
	}
}

func (l *loop03) Enter() {
	var triangle coloredmesh2d

	// Create and configure the pipeline
	l.pipeline = gl.NewPipeline(
		gl.Shader(cozely.Path()+"shader03.vert"),
		gl.Shader(cozely.Path()+"shader03.frag"),
		gl.VertexFormat(0, triangle),
		gl.Topology(gl.Triangles),
	)
	gl.Enable(gl.FramebufferSRGB)

	// Create the uniform buffer
	l.perFrameUBO = gl.NewUniformBuffer(&perFrame{}, gl.DynamicStorage)

	// Fill and create the vertex buffer
	triangle = coloredmesh2d{
		{coord.XY{0, 0.75}, color.LRGB{0.3, 0, 0.8}},
		{coord.XY{-0.65, -0.465}, color.LRGB{0.8, 0.3, 0}},
		{coord.XY{0.65, -0.465}, color.LRGB{0, 0.6, 0.2}},
	}
	vbo := gl.NewVertexBuffer(triangle, gl.StaticStorage)

	// Bind the vertex buffer to the pipeline
	l.pipeline.Bind()
	vbo.Bind(0, 0)
	l.pipeline.Unbind()
}

func (loop03) Leave() {
}

// Game Loop ///////////////////////////////////////////////////////////////////

func (loop03) React() {
}

func (loop03) Update() {
}

func (l *loop03) Render() {
	l.angle -= 1.0 * cozely.RenderDelta()

	l.pipeline.Bind()
	gl.ClearColorBuffer(color.LRGBA{0.9, 0.9, 0.9, 1.0})

	u := perFrame{
		transform: plane.Rotation(float32(l.angle)).GPU(),
	}
	l.perFrameUBO.SubData(&u, 0)
	l.perFrameUBO.Bind(0)

	gl.Draw(0, 3)
	l.pipeline.Unbind()
}
Output:

Example (VertexBuffer)
package main

import (
	"github.com/cozely/cozely"
	"github.com/cozely/cozely/color"
	"github.com/cozely/cozely/coord"
	"github.com/cozely/cozely/window"
	"github.com/cozely/cozely/x/gl"
)

// Declarations ////////////////////////////////////////////////////////////////

type loop02 struct {
	pipeline *gl.Pipeline
}

// Vertex buffer
type mesh2d []struct {
	position coord.XY   `layout:"0"`
	color    color.LRGB `layout:"1"`
}

// Initialization //////////////////////////////////////////////////////////////

func main() {
	defer cozely.Recover()

	window.Events.Resize = func() {
		s := window.Size()
		gl.Viewport(0, 0, int32(s.X), int32(s.Y))
	}
	l := loop02{}
	err := cozely.Run(&l)
	if err != nil {
		panic(err)
	}
}

func (l *loop02) Enter() {
	var triangle mesh2d

	// Create and configure the pipeline
	l.pipeline = gl.NewPipeline(
		gl.Shader(cozely.Path()+"shader02.vert"),
		gl.Shader(cozely.Path()+"shader02.frag"),
		gl.VertexFormat(0, triangle),
		gl.Topology(gl.Triangles),
	)
	gl.Enable(gl.FramebufferSRGB)

	// Create and fill the vertex buffer
	triangle = mesh2d{
		{coord.XY{0, 0.65}, color.LRGB{R: 0.3, G: 0, B: 0.8}},
		{coord.XY{-0.65, -0.475}, color.LRGB{R: 0.8, G: 0.3, B: 0}},
		{coord.XY{0.65, -0.475}, color.LRGB{R: 0, G: 0.6, B: 0.2}},
	}
	vbo := gl.NewVertexBuffer(triangle, gl.StaticStorage)

	// Bind the vertex buffer to the pipeline
	l.pipeline.Bind()
	vbo.Bind(0, 0)
	l.pipeline.Unbind()
}

func (loop02) Leave() {
}

// Game Loop ///////////////////////////////////////////////////////////////////

func (loop02) React() {
}

func (loop02) Update() {
}

func (l *loop02) Render() {
	l.pipeline.Bind()
	gl.ClearColorBuffer(color.LRGBA{0.9, 0.9, 0.9, 1.0})

	gl.Draw(0, 3)
	l.pipeline.Unbind()
}
Output:

Index

Examples

Constants

This section is empty.

Variables

View Source
var DefaultFramebuffer = Framebuffer{
	// contains filtered or unexported fields
}

Functions

func BindComputeSubroutines

func BindComputeSubroutines(s []uint32)

BindComputeSubroutines binds the compute shader subroutines to indices in s.

func BindFragmentSubroutines

func BindFragmentSubroutines(s []uint32)

BindFragmentSubroutines binds the fragment shader subroutines to indices in s.

func BindGeometrySubroutines

func BindGeometrySubroutines(s []uint32)

BindGeometrySubroutines binds the geometry shader subroutines to indices in s.

func BindTessControlSubroutines

func BindTessControlSubroutines(s []uint32)

BindTessControlSubroutines binds the tesselation control shader subroutines to indices in s.

func BindTessEvaluationSubroutines

func BindTessEvaluationSubroutines(s []uint32)

BindTessEvaluationSubroutines binds the tesselation evaluation shader subroutines to indices in s.

func BindVertexSubroutines

func BindVertexSubroutines(s []uint32)

BindVertexSubroutines binds the vertex shader subroutines to indices in s.

func Blending

func Blending(src, dst BlendFactor)

Blending specifies the formula used for blending pixels.

Note that you must also `Enable(Blend)`. The default values are `One` and `Zero`. For alpha-blending and antialiasing, the most useful choice is `Blending(SrcAlpha, OneMinusSrcAlpha)`.

func ClearColorBuffer

func ClearColorBuffer(c struct{ R, G, B, A float32 })

ClearColorBuffer clears the color buffer with c.

func ClearDepthBuffer

func ClearDepthBuffer(d float32)

ClearDepthBuffer clears the depth buffer with d.

func ClearStencilBuffer

func ClearStencilBuffer(m int32)

ClearStencilBuffer clears the stencil buffer with m.

func DepthRange

func DepthRange(near, far float64)

DepthRange specifies the mapping of depth values from normalized device coordinates to window coordinates.

func Disable

func Disable(c Capability)

Disable an OpenGL Capability

func Draw

func Draw(first int32, count int32)

Draw asks the GPU to draw a sequence of primitives.

func DrawIndexed

func DrawIndexed(first int32, count int32)

DrawIndexed asks the GPU to draw a sequence of primitives with indexed vertices.

func DrawIndirect

func DrawIndirect(firstdraw uintptr, drawcount int32)

DrawIndirect asks the GPU to read the Indirect Buffer starting at firstdraw, and make drawcount draw calls.

func DrawInstanced

func DrawInstanced(first int32, count int32, instances int32)

DrawInstanced asks the GPU to draw several instances of a sequence of primitives.

func Enable

func Enable(c Capability)

Enable an OpenGL Capability

func Err

func Err() error

Err returns the first unchecked error of the package since last call to the function. The error is then considered checked, and further calls to Err will return nil until the next error occurs.

Note: errors occuring while there already is an unchecked error will not be recorded. However, if the debug mode is active, all errors will be logged.

func MemoryBarrier

func MemoryBarrier()

func PointSize

func PointSize(s float32)

PointSize sets the size used when drawing points.

func Viewport

func Viewport(ox, oy, width, height int32)

Viewport sets the size in pixels of the GL viewport.

Note that this function is automatically called each time the window is resized.

Types

type Access

type Access C.GLenum

A Access specifies...

const (
	ReadOnly  Access = C.GL_READ_ONLY
	WriteOnly Access = C.GL_WRITE_ONLY
	ReadWrite Access = C.GL_READ_WRITE
)

Used in ...

type BlendFactor

type BlendFactor C.GLenum

A BlendFactor is a formula used when blending pixels.

Used in `Blending`.

type BufferFlags

type BufferFlags C.GLbitfield

BufferFlags specify which settings to use when creating a new buffer. Values can be ORed together.

const (
	StaticStorage  BufferFlags = C.GL_NONE                // Content will not be updated
	MapRead        BufferFlags = C.GL_MAP_READ_BIT        // Data store will be mapped for reading
	MapWrite       BufferFlags = C.GL_MAP_WRITE_BIT       // Data store will be mapped for writing
	MapPersistent  BufferFlags = C.GL_MAP_PERSISTENT_BIT  // Data store will be accessed by both application and GPU while mapped
	MapCoherent    BufferFlags = C.GL_MAP_COHERENT_BIT    // No synchronization needed when persistently mapped
	DynamicStorage BufferFlags = C.GL_DYNAMIC_STORAGE_BIT // Content will be updated
	ClientStorage  BufferFlags = C.GL_CLIENT_STORAGE_BIT  // Prefer storage on application side
)

Used in `NewUniformBuffer` and `NewVertexBuffer`.

type BufferMask

type BufferMask C.GLbitfield
const (
	ColorBufferBit   BufferMask = C.GL_COLOR_BUFFER_BIT
	DepthBufferBit   BufferMask = C.GL_DEPTH_BUFFER_BIT
	StencilBufferBit BufferMask = C.GL_STENCIL_BUFFER_BIT
)

type BufferTexture

type BufferTexture struct {
	// contains filtered or unexported fields
}

BufferTexture is a block of memory own by the GPU.

func NewBufferTexture

func NewBufferTexture(data interface{}, fmt TextureFormat, f BufferFlags) BufferTexture

NewBufferTexture asks the GPU to allocate a new block of memory.

func (BufferTexture) Bind

func (bt BufferTexture) Bind(index uint32)

Bind the buffer texture.

func (*BufferTexture) Delete

func (bt *BufferTexture) Delete()

Delete frees the buffer.

func (*BufferTexture) SubData

func (bt *BufferTexture) SubData(data interface{}, atOffset uintptr)

SubData updates the buffer with data, starting at a specified offset.

It is your responsibility to ensure that the size of data plus the offset does not exceed the buffer size.

type Capability

type Capability C.GLenum

A Capability is an OpenGL functionality that can be enabled or disabled.

const (
	Blend                  Capability = C.GL_BLEND
	ColorLogicOp           Capability = C.GL_COLOR_LOGIC_OP
	DebugOutput            Capability = C.GL_DEBUG_OUTPUT
	DebugOutputSynchronous Capability = C.GL_DEBUG_OUTPUT_SYNCHRONOUS
	Dither                 Capability = C.GL_DITHER
	FramebufferSRGB        Capability = C.GL_FRAMEBUFFER_SRGB
	LineSmooth             Capability = C.GL_LINE_SMOOTH
	Multisample            Capability = C.GL_MULTISAMPLE
	SampleAlphaToCoverage  Capability = C.GL_SAMPLE_ALPHA_TO_COVERAGE
	SampleAlphaToOne       Capability = C.GL_SAMPLE_ALPHA_TO_ONE
	SampleCoverage         Capability = C.GL_SAMPLE_COVERAGE
	SampleShading          Capability = C.GL_SAMPLE_SHADING
	SampleMask             Capability = C.GL_SAMPLE_MASK
	ScissorTest            Capability = C.GL_SCISSOR_TEST
	TextureCubeMapSeamless Capability = C.GL_TEXTURE_CUBE_MAP_SEAMLESS
)

Used in `Enable` and `Disable`.

type ComparisonOp

type ComparisonOp C.GLuint

A ComparisonOp specifies an operator for depth texture comparison.

const (
	LessOrEqual    ComparisonOp = C.GL_LEQUAL
	GreaterOrEqual ComparisonOp = C.GL_GEQUAL
	Less           ComparisonOp = C.GL_LESS
	Greater        ComparisonOp = C.GL_GREATER
	Equal          ComparisonOp = C.GL_EQUAL
	NotEqual       ComparisonOp = C.GL_NOTEQUAL
	Always         ComparisonOp = C.GL_ALWAYS
	Never          ComparisonOp = C.GL_NEVER
)

Used in `Sampler.Comparison` and `DepthComparison`.

type CounterBuffer

type CounterBuffer struct {
	// contains filtered or unexported fields
}

A CounterBuffer is a block of memory owned by the GPU.

func NewCounterBuffer

func NewCounterBuffer(nb int, f BufferFlags) CounterBuffer

NewCounterBuffer asks the GPU to allocate a new block of memory.

func (*CounterBuffer) Bind

func (sb *CounterBuffer) Bind(binding uint32)

Bind to a storage binding index.

This index should correspond to one indicated by a layout qualifier in the shaders.

func (*CounterBuffer) Delete

func (sb *CounterBuffer) Delete()

Delete frees the buffer.

func (*CounterBuffer) SubData

func (sb *CounterBuffer) SubData(data []uint32, atOffset uintptr)

SubData updates the buffer with data, starting at a specified offset.

It is your responsibility to ensure that the size of data plus the offset does not exceed the buffer size.

type DrawIndirectCommand

type DrawIndirectCommand struct {
	VertexCount   uint32
	InstanceCount uint32
	FirstVertex   uint32
	BaseInstance  uint32
}

A DrawIndirectCommand describes a single draw call. A slice of these is used to fill indirect buffers.

type FilterMode

type FilterMode C.GLuint

A FilterMode specifies how to filter textures when minifying or magnifying.

const (
	Nearest             FilterMode = C.GL_NEAREST
	Linear              FilterMode = C.GL_LINEAR
	NearestMimapNearest FilterMode = C.GL_NEAREST_MIPMAP_NEAREST
	LinearMipmapNearest FilterMode = C.GL_LINEAR_MIPMAP_NEAREST
	NearestMipmapLinear FilterMode = C.GL_NEAREST_MIPMAP_LINEAR
	LinearMipmapLinear  FilterMode = C.GL_LINEAR_MIPMAP_LINEAR
)

Used in `Sampler.Minification` and `Sampler.Magnification` (only `Nearest` and `Linear` are valid for magnification).

type Framebuffer

type Framebuffer struct {
	// contains filtered or unexported fields
}

func NewFramebuffer

func NewFramebuffer() Framebuffer

func (Framebuffer) Bind

func (fb Framebuffer) Bind(t FramebufferTarget)

func (Framebuffer) Blit

func (fb Framebuffer) Blit(dst Framebuffer, srcX1, srcY1, srcX2, srcY2, dstX1, dstY1, dstX2, dstY2 int32, m BufferMask, f FilterMode)

func (Framebuffer) CheckStatus

func (Framebuffer) ClearColor

func (fb Framebuffer) ClearColor(drawbuffer int32, r, g, b, a float32)

func (Framebuffer) ClearColorUint

func (fb Framebuffer) ClearColorUint(r, g, b, a uint32)

func (Framebuffer) ClearDepth

func (fb Framebuffer) ClearDepth(d float32)

func (Framebuffer) Delete

func (fb Framebuffer) Delete()

func (Framebuffer) DrawBuffer

func (fb Framebuffer) DrawBuffer(a FramebufferAttachment)

func (Framebuffer) DrawBuffers

func (fb Framebuffer) DrawBuffers(a []FramebufferAttachment)

func (Framebuffer) ReadBuffer

func (fb Framebuffer) ReadBuffer(a FramebufferAttachment)

func (Framebuffer) Renderbuffer

func (fb Framebuffer) Renderbuffer(a FramebufferAttachment, r Renderbuffer)

func (Framebuffer) SetEmptySize

func (fb Framebuffer) SetEmptySize(w, h int16)

func (Framebuffer) Texture

func (fb Framebuffer) Texture(a FramebufferAttachment, t Texture2D, level int32)

type FramebufferStatus

type FramebufferStatus C.GLenum
const (
	FramebufferComplete                    FramebufferStatus = C.GL_FRAMEBUFFER_COMPLETE
	FramebufferUndefined                   FramebufferStatus = C.GL_FRAMEBUFFER_UNDEFINED
	FramebufferIncompleteAttachment        FramebufferStatus = C.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT
	FramebufferIncompleteMissingAttachment FramebufferStatus = C.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT
	FramebufferIncompleteDrawBuffer        FramebufferStatus = C.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER
	FramebufferIncompleteReadBuffer        FramebufferStatus = C.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER
	FramebufferUnsupported                 FramebufferStatus = C.GL_FRAMEBUFFER_UNSUPPORTED
	FramebufferIncompleteMultisample       FramebufferStatus = C.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE
	FramebufferIncompleteLayerTargets      FramebufferStatus = C.GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS
)

func (FramebufferStatus) String

func (fbs FramebufferStatus) String() string

type FramebufferTarget

type FramebufferTarget C.GLenum
const (
	DrawFramebuffer     FramebufferTarget = C.GL_DRAW_FRAMEBUFFER
	ReadFramebuffer     FramebufferTarget = C.GL_READ_FRAMEBUFFER
	DrawReadFramebuffer FramebufferTarget = C.GL_FRAMEBUFFER
)

type IndexBuffer

type IndexBuffer struct {
	// contains filtered or unexported fields
}

An IndexBuffer is a block of memory owned by the GPU, used to store vertex indices.

func NewIndexBuffer

func NewIndexBuffer(data interface{}, f BufferFlags) IndexBuffer

NewIndexBuffer asks the GPU to allocate a new block of memory.

If data is a uinptr, it is interpreted as the desired size for the buffer (in bytes), and the content is not initialized. Otherwise data must be a slice of uint8, uint16 or uin32. In all cases the size of the buffer is fixed at creation.

func (*IndexBuffer) Bind

func (eb *IndexBuffer) Bind()

Bind the element buffer.

func (*IndexBuffer) Delete

func (eb *IndexBuffer) Delete()

Delete frees the buffer.

func (*IndexBuffer) SubData

func (eb *IndexBuffer) SubData(data interface{}, atOffset uintptr)

SubData updates the buffer with data, starting at a specified offset.

It is your responsibility to ensure that the size of data plus the offset does not exceed the buffer size.

type IndirectBuffer

type IndirectBuffer struct {
	// contains filtered or unexported fields
}

An IndirectBuffer is a block of memory owned by the GPU.

func NewIndirectBuffer

func NewIndirectBuffer(data interface{}, f BufferFlags) IndirectBuffer

NewIndirectBuffer asks the GPU to allocate a new block of memory.

If data is a

In all cases the size of the buffer is fixed at creation.

func (*IndirectBuffer) Bind

func (ib *IndirectBuffer) Bind()

Bind the indirect buffer.

The buffer should use the same struct type than the one used in the corresponding call to Pipeline.IndirectFormat.

func (*IndirectBuffer) Delete

func (ib *IndirectBuffer) Delete()

Delete frees the buffer.

func (*IndirectBuffer) SubData

func (ib *IndirectBuffer) SubData(data interface{}, atOffset uintptr)

SubData updates the buffer with data, starting at a specified offset.

It is your responsibility to ensure that the size of data plus the offset does not exceed the buffer size.

type Option

type Option = func() error

An Option represents a configuration option used to change some parameters of the framework: see cozely.Configure.

func NoClear

func NoClear() Option

NoClear prevents the default behavior of clearing the default framebuffer at the start of each frame.

type Pipeline

type Pipeline struct {
	// contains filtered or unexported fields
}

A Pipeline consists of shaders and state for the GPU.

func NewPipeline

func NewPipeline(o ...PipelineConfig) *Pipeline

NewPipeline returns a pipeline with created from a specific set of shaders.

func (*Pipeline) Bind

func (p *Pipeline) Bind()

Bind the pipeline for use by the GPU in all following draw commands.

func (*Pipeline) Delete

func (p *Pipeline) Delete()

Delete closes the pipeline.

func (*Pipeline) Unbind

func (p *Pipeline) Unbind()

Unbind the pipeline.

type PipelineConfig

type PipelineConfig func(*Pipeline)

A PipelineConfig represents a configuration option used when creating a new pipeline.

func ComputeShader

func ComputeShader(r io.Reader) PipelineConfig

ComputeShader compiles a comput shader.

func CullFace

func CullFace(front, back bool) PipelineConfig

CullFace specifies if front and/or back faces are culled.

See also `FrontFace`.

func DepthClamp

func DepthClamp(enable bool) PipelineConfig

func DepthComparison

func DepthComparison(op ComparisonOp) PipelineConfig

DepthComparison specifies the function used to compare pixel depth.

Note that you must also `Enable(DepthTest)`. The default value is `Less`.

func DepthTest

func DepthTest(enable bool) PipelineConfig

func DepthWrite

func DepthWrite(enable bool) PipelineConfig

func FragmentShader

func FragmentShader(r io.Reader) PipelineConfig

FragmentShader compiles a fragment shader.

func FrontFace

func FrontFace(d WindingDirection) PipelineConfig

FrontFace specifies which winding direction is considered front.

See also `CullFace`.

func GeometryShader

func GeometryShader(r io.Reader) PipelineConfig

GeometryShader compiles a geometry shader.

func PrimitiveRestart

func PrimitiveRestart(enable bool) PipelineConfig

func RasterizerDiscard

func RasterizerDiscard(enable bool) PipelineConfig

func Shader

func Shader(path string) PipelineConfig

Shader compiles a shader. The path is slash-separated, and the file extension determine the type of shader:

- ".vert" for a vertex shader - ".frag" for a fragment shader - ".comp" for a compute shader - ".geom" for a geometry shader - ".tesc" for a tesselation control shader - ".tese" for a tesselation evaluation shader

func ShareShadersWith

func ShareShadersWith(other *Pipeline) PipelineConfig

func ShareVertexFormatsWith

func ShareVertexFormatsWith(other *Pipeline) PipelineConfig

func StencilTest

func StencilTest(enable bool) PipelineConfig

func TessControlShader

func TessControlShader(r io.Reader) PipelineConfig

TessControlShader compiles a tesselation control shader.

func TessEvaluationShader

func TessEvaluationShader(r io.Reader) PipelineConfig

TessEvaluationShader compiles a tesselation evaluation shader.

func Topology

func Topology(m Primitive) PipelineConfig

func VertexFormat

func VertexFormat(binding uint32, format interface{}) PipelineConfig

VertexFormat prepares everything the pipeline needs to use a vertex buffer of a specific format, and assign a binding index to it.

The format must be a slice of struct, and the struct must have with layout tags.

func VertexShader

func VertexShader(r io.Reader) PipelineConfig

VertexShader compiles a vertex shader.

type Primitive

type Primitive C.GLenum

A Primitive specifies what kind of object to draw.

const (
	Points               Primitive = C.GL_POINTS
	Lines                Primitive = C.GL_LINES
	LineLoop             Primitive = C.GL_LINE_LOOP
	LineStrip            Primitive = C.GL_LINE_STRIP
	Triangles            Primitive = C.GL_TRIANGLES
	TriangleStrip        Primitive = C.GL_TRIANGLE_STRIP
	TriangleFan          Primitive = C.GL_TRIANGLE_FAN
	LinesAdjency         Primitive = C.GL_LINES_ADJACENCY
	LineStripAdjency     Primitive = C.GL_LINE_STRIP_ADJACENCY
	TrianglesAdjency     Primitive = C.GL_TRIANGLES_ADJACENCY
	TriangleStripAdjency Primitive = C.GL_TRIANGLE_STRIP_ADJACENCY
	Patches              Primitive = C.GL_PATCHES
)

Used in `Topology`.

type Renderbuffer

type Renderbuffer struct {
	// contains filtered or unexported fields
}

A Renderbuffer is a two-dimensional texture that can only be used for rendering (attached a Framebuffer)

func NewRenderbuffer

func NewRenderbuffer(f TextureFormat, width, height int32) Renderbuffer

NewRenderbuffer returns a new render buffer.

func (*Renderbuffer) Delete

func (r *Renderbuffer) Delete()

Delete frees the render buffer

type Sampler

type Sampler struct {
	// contains filtered or unexported fields
}

A Sampler describes a way to sample textures inside shaders.

func NewSampler

func NewSampler(o ...SamplerOption) Sampler

NewSampler returns a new sampler.

func (Sampler) Bind

func (sa Sampler) Bind(binding uint32)

Bind a sampler to a texture unit index.

type SamplerOption

type SamplerOption func(sa *Sampler)

A SamplerOption is a setting used when creating a new `Sampler`.

func Anisotropy

func Anisotropy(max float32) SamplerOption

Anisotropy specifies the maximum anisotropy level.

func BorderColor

func BorderColor(color struct{ R, G, B, A float32 }) SamplerOption

BorderColor sets the color used for texture filtering when ClampToborder wrapping mode is used.

func Comparison

func Comparison(op ComparisonOp) SamplerOption

Comparison specifies the mode and operator used when comparing depth textures.

func LevelOfDetail

func LevelOfDetail(min, max float32) SamplerOption

LevelOfDetail specifies the minimum and maximum LOD to use.

The default values are -1000 and 1000.

func Magnification

func Magnification(fm FilterMode) SamplerOption

Magnification specifies which filter is used when minifying the texture.

The default value is `Linear`.

func Minification

func Minification(fm FilterMode) SamplerOption

Minification specifies which filter is used when minifying the texture.

The default value is `NearestMipmapLinear`.

func Wrapping

func Wrapping(s, t, p WrapMode) SamplerOption

Wrapping sets the wrapping modes for texture coordinates.

The default value is `Repeat` for all coordinates.

type StorageBuffer

type StorageBuffer struct {
	// contains filtered or unexported fields
}

A StorageBuffer is a block of memory owned by the GPU.

func NewStorageBuffer

func NewStorageBuffer(data interface{}, f BufferFlags) StorageBuffer

NewStorageBuffer asks the GPU to allocate a new block of memory.

If data is a uinptr, it is interpreted as the desired size for the buffer (in bytes), and the content is not initialized. Otherwise data must be a pointer to a struct of pure values (no nested references). In all cases the size of the buffer is fixed at creation.

func (*StorageBuffer) Bind

func (sb *StorageBuffer) Bind(binding uint32)

Bind to a storage binding index.

This index should correspond to one indicated by a layout qualifier in the shaders.

func (*StorageBuffer) ClearUint32

func (sb *StorageBuffer) ClearUint32(data uint32)

func (*StorageBuffer) Delete

func (sb *StorageBuffer) Delete()

Delete frees the buffer.

func (*StorageBuffer) SubData

func (sb *StorageBuffer) SubData(data interface{}, atOffset uintptr)

SubData updates the buffer with data, starting at a specified offset.

It is your responsibility to ensure that the size of data plus the offset does not exceed the buffer size.

type Texture1D

type Texture1D struct {
	// contains filtered or unexported fields
}

A Texture1D is a one-dimensional texture.

func NewTexture1D

func NewTexture1D(levels int32, f TextureFormat, width int32) Texture1D

NewTexture1D returns a new one-dimensional texture.

func (*Texture1D) Bind

func (t *Texture1D) Bind(index uint32)

Bind to a texture unit.

func (*Texture1D) Delete

func (t *Texture1D) Delete()

Delete frees the texture

func (*Texture1D) GenerateMipmap

func (t *Texture1D) GenerateMipmap()

GenerateMipmap generates mipmaps for the texture.

func (*Texture1D) SubImage

func (t *Texture1D) SubImage(level int32, ox int32, img image.Image)

SubImage loads an image into a texture at a specific position offset and mipmap level.

type Texture2D

type Texture2D struct {
	// contains filtered or unexported fields
}

A Texture2D is a two-dimensional texture.

func NewTexture2D

func NewTexture2D(levels int32, f TextureFormat, width, height int32) Texture2D

NewTexture2D returns a new two-dimensional texture.

func (*Texture2D) Bind

func (t *Texture2D) Bind(index uint32)

Bind to a texture unit.

func (*Texture2D) BindImage

func (t *Texture2D) BindImage(index uint32, level int32, a Access, f TextureFormat)

BindImage to an image unit.

func (*Texture2D) ClearByte

func (t *Texture2D) ClearByte(level int32, r uint8)

func (*Texture2D) Delete

func (t *Texture2D) Delete()

Delete frees the texture

func (*Texture2D) GenerateMipmap

func (t *Texture2D) GenerateMipmap()

GenerateMipmap generates mipmaps for the texture.

func (*Texture2D) SubImage

func (t *Texture2D) SubImage(level int32, ox, oy int32, img image.Image)

SubImage loads an image into a texture at a specific position offset and mipmap level.

type Texture3D

type Texture3D struct {
	// contains filtered or unexported fields
}

A Texture3D is a three-dimensional texture.

func NewTexture3D

func NewTexture3D(levels int32, f TextureFormat, width, height, depth int32) Texture3D

NewTexture3D returns a new three-dimensional texture.

func (*Texture3D) Bind

func (t *Texture3D) Bind(index uint32)

Bind to a texture unit.

func (*Texture3D) Delete

func (t *Texture3D) Delete()

Delete frees the texture

func (*Texture3D) GenerateMipmap

func (t *Texture3D) GenerateMipmap()

GenerateMipmap generates mipmaps for the texture.

func (*Texture3D) SubImage

func (t *Texture3D) SubImage(level int32, ox, oy, oz int32, img image.Image)

SubImage loads an image into a texture at a specific position offset and mipmap level.

type TextureArray1D

type TextureArray1D struct {
	// contains filtered or unexported fields
}

A TextureArray1D is an array of one-dimensional textures.

func NewTextureArray1D

func NewTextureArray1D(levels int32, f TextureFormat, width int32, count int32) TextureArray1D

NewTextureArray1D returns a new array of one-dimensional textures.

func (*TextureArray1D) Bind

func (t *TextureArray1D) Bind(index uint32)

Bind to a texture unit.

func (*TextureArray1D) Delete

func (t *TextureArray1D) Delete()

Delete frees the texture

func (*TextureArray1D) GenerateMipmap

func (t *TextureArray1D) GenerateMipmap()

GenerateMipmap generates mipmaps for the texture.

func (*TextureArray1D) SubImage

func (t *TextureArray1D) SubImage(level int32, ox int32, index int32, img image.Image)

SubImage loads an image into a texture at a specific position offset, index and mipmap level.

type TextureArray2D

type TextureArray2D struct {
	// contains filtered or unexported fields
}

A TextureArray2D is an array of two-dimensional textures.

func NewTextureArray2D

func NewTextureArray2D(levels int32, f TextureFormat, width, height int32, count int32) TextureArray2D

NewTextureArray2D returns a new array of two-dimensional textures.

func (*TextureArray2D) Bind

func (t *TextureArray2D) Bind(index uint32)

Bind to a texture unit.

func (*TextureArray2D) Delete

func (t *TextureArray2D) Delete()

Delete frees the texture

func (*TextureArray2D) GenerateMipmap

func (t *TextureArray2D) GenerateMipmap()

GenerateMipmap generates mipmaps for the texture.

func (*TextureArray2D) SubImage

func (t *TextureArray2D) SubImage(level int32, ox, oy int32, index int32, img image.Image)

SubImage loads an image into a texture at a specific position offset, array index and mipmap level.

type TextureFormat

type TextureFormat C.GLenum

A TextureFormat specifies the format used to store textures in memory.

type UniformBuffer

type UniformBuffer struct {
	// contains filtered or unexported fields
}

A UniformBuffer is a block of memory owned by the GPU.

func NewUniformBuffer

func NewUniformBuffer(data interface{}, f BufferFlags) UniformBuffer

NewUniformBuffer asks the GPU to allocate a new block of memory.

If data is a uinptr, it is interpreted as the desired size for the buffer (in bytes), and the content is not initialized. Otherwise data must be a pointer to a struct of pure values (no nested references). In all cases the size of the buffer is fixed at creation.

func (*UniformBuffer) Bind

func (ub *UniformBuffer) Bind(binding uint32)

Bind to a uniform binding index.

This index should correspond to one indicated by a layout qualifier in the shaders.

func (*UniformBuffer) Delete

func (ub *UniformBuffer) Delete()

Delete frees the buffer.

func (*UniformBuffer) SubData

func (ub *UniformBuffer) SubData(data interface{}, atOffset uintptr)

SubData updates the buffer with data, starting at a specified offset.

It is your responsibility to ensure that the size of data plus the offset does not exceed the buffer size.

type VertexBuffer

type VertexBuffer struct {
	// contains filtered or unexported fields
}

A VertexBuffer is a block of memory owned by the GPU.

func NewVertexBuffer

func NewVertexBuffer(data interface{}, f BufferFlags) VertexBuffer

NewVertexBuffer asks the GPU to allocate a new block of memory.

If data is a uinptr, it is interpreted as the desired size for the buffer (in bytes), and the content is not initialized. Otherwise data must be a slice of pure values (no nested references). In all cases the size of the buffer is fixed at creation.

func (*VertexBuffer) Bind

func (vb *VertexBuffer) Bind(binding uint32, offset uintptr)

Bind to a vertex buffer binding index.

The buffer should use the same struct type than the one used in the corresponding call to Pipeline.VertexFormat.

func (*VertexBuffer) Delete

func (vb *VertexBuffer) Delete()

Delete frees the buffer.

func (*VertexBuffer) SubData

func (vb *VertexBuffer) SubData(data interface{}, atOffset uintptr)

SubData updates the buffer with data, starting at a specified offset.

It is your responsibility to ensure that the size of data plus the offset does not exceed the buffer size.

type WindingDirection

type WindingDirection C.GLenum

A WindingDirection specifies a rotation direction.

const (
	Clockwise        WindingDirection = C.GL_CW
	CounterClockwise WindingDirection = C.GL_CCW
)

Used in `FrontFace`.

type WrapMode

type WrapMode C.GLuint

A WrapMode specifies the way a texture wraps.

const (
	ClampToBorder     WrapMode = C.GL_CLAMP_TO_BORDER
	ClampToEdge       WrapMode = C.GL_CLAMP_TO_EDGE
	MirrorClampToEdge WrapMode = C.GL_MIRROR_CLAMP_TO_EDGE
	Repeat            WrapMode = C.GL_REPEAT
	MirroredRepeat    WrapMode = C.GL_MIRRORED_REPEAT
)

Used in `Sampler.Wrap`.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL