openGL Have Fun - A Go package that makes life with OpenGL enjoyable.

Overview

glhf GoDoc Report card

openGL Have Fun - A Go package that makes life with OpenGL enjoyable.

go get github.com/faiface/glhf

Main features

  • Garbage collected OpenGL objects
  • Dynamically sized vertex slices (vertex arrays are boring)
  • Textures, Shaders, Frames (reasonably managed framebuffers)
  • Always possible to use standard OpenGL with glhf

Motivation

OpenGL is verbose, it's usage patterns are repetitive and it's manual memory management doesn't fit Go's design. When making a game development library, it's usually desirable to create some higher-level abstractions around OpenGL. This library is a take on that.

Contribute!

The library is young and many features are still missing. If you find a bug, have a proposal or a feature request, do an issue!. If you know how to implement something that's missing, do a pull request.

Code

The following are parts of the demo program, which can be found in the examples.

// ... GLFW window creation and stuff ...

// vertex shader source
var vertexShader = `
#version 330 core

in vec2 position;
in vec2 texture;

out vec2 Texture;

void main() {
	gl_Position = vec4(position, 0.0, 1.0);
	Texture = texture;
}
`

// fragment shader source
var fragmentShader = `
#version 330 core

in vec2 Texture;

out vec4 color;

uniform sampler2D tex;

void main() {
	color = texture(tex, Texture);
}
`

var (
        // Here we define a vertex format of our vertex slice. It's actually a basic slice
        // literal.
        //
        // The vertex format consists of names and types of the attributes. The name is the
        // name that the attribute is referenced by inside a shader.
        vertexFormat = glhf.AttrFormat{
                {Name: "position", Type: glhf.Vec2},
                {Name: "texture", Type: glhf.Vec2},
        }

        // Here we declare some variables for later use.
        shader  *glhf.Shader
        texture *glhf.Texture
        slice   *glhf.VertexSlice
)

// Here we load an image from a file. The loadImage function is not within the library, it
// just loads and returns a image.NRGBA.
gopherImage, err := loadImage("celebrate.png")
if err != nil {
        panic(err)
}

// Every OpenGL call needs to be done inside the main thread.
mainthread.Call(func() {
        var err error

        // Here we create a shader. The second argument is the format of the uniform
        // attributes. Since our shader has no uniform attributes, the format is empty.
        shader, err = glhf.NewShader(vertexFormat, glhf.AttrFormat{}, vertexShader, fragmentShader)

        // If the shader compilation did not go successfully, an error with a full
        // description is returned.
        if err != nil {
                panic(err)
        }

        // We create a texture from the loaded image.
        texture = glhf.NewTexture(
                gopherImage.Bounds().Dx(),
                gopherImage.Bounds().Dy(),
                true,
                gopherImage.Pix,
        )

        // And finally, we make a vertex slice, which is basically a dynamically sized
        // vertex array. The length of the slice is 6 and the capacity is the same.
        //
        // The slice inherits the vertex format of the supplied shader. Also, it should
        // only be used with that shader.
        slice = glhf.MakeVertexSlice(shader, 6, 6)

        // Before we use a slice, we need to Begin it. The same holds for all objects in
        // GLHF.
        slice.Begin()

        // We assign data to the vertex slice. The values are in the order as in the vertex
        // format of the slice (shader). Each two floats correspond to an attribute of type
        // glhf.Vec2.
        slice.SetVertexData([]float32{
                -1, -1, 0, 1,
                +1, -1, 1, 1,
                +1, +1, 1, 0,

                -1, -1, 0, 1,
                +1, +1, 1, 0,
                -1, +1, 0, 0,
        })

        // When we're done with the slice, we End it.
        slice.End()
})

shouldQuit := false
for !shouldQuit {
        mainthread.Call(func() {
                // ... GLFW stuff ...

                // Clear the window.
                glhf.Clear(1, 1, 1, 1)

                // Here we Begin/End all necessary objects and finally draw the vertex
                // slice.
                shader.Begin()
                texture.Begin()
                slice.Begin()
                slice.Draw()
                slice.End()
                texture.End()
                shader.End()

                // ... GLFW stuff ...
        })
}

FAQ

Which version of OpenGL does GLHF use?

It uses OpenGL 3.3 and uses github.com/go-gl/gl/v3.3-core/gl.

Why do I have to use github.com/faiface/mainthread package with GLHF?

First of all, OpenGL has to be done from one thread and many operating systems require, that the one thread will be the main thread of your application.

But why that specific package? GLHF uses the mainthread package to do the garbage collection of OpenGL objects, which is super convenient. So in order for it to work correctly, you have to initialize the mainthread package through mainthread.Run. However, once you call this function there is no way to run functions on the main thread, except for through the mainthread package.

Why is the important XY feature not included?

I probably didn't need it yet. If you want that features, create an issue or implement it and do a pull request.

Does GLHF create windows for me?

No. You have to use another library for windowing, e.g. github.com/go-gl/glfw/v3.2/glfw.

Why no tests?

If you find a way to automatically test OpenGL, I may add tests.

Issues
  • Data race

    Data race

    I'm trying to test TilePix drawing to a pixel Window using xvfb which creates a headless GUI/display/browser etc etc in travis-ci.

    I'm testing with -race, and I get this data race; here is the output of the failure:

    ==================
    --- FAIL: TestMap_DrawAll (0.42s)
        testing.go:809: race detected during execution of test
    ==================
    WARNING: DATA RACE
    Write at 0x00c00000e180 by main goroutine:
      github.com/faiface/glhf.(*VertexSlice).SetLen()
          /home/travis/gopath/pkg/mod/github.com/faiface/[email protected]/vertex.go:66 +0xc9
      github.com/faiface/pixel/pixelgl.(*GLTriangles).SetLen.func1()
          /home/travis/gopath/pkg/mod/github.com/faiface/[email protected]/pixelgl/gltriangles.go:82 +0xa7
      github.com/faiface/mainthread.Run()
          /home/travis/gopath/pkg/mod/github.com/faiface/[email protected]/mainthread.go:44 +0xf7
      github.com/faiface/pixel/pixelgl.Run()
          /home/travis/gopath/pkg/mod/github.com/faiface/[email protected]/pixelgl/run.go:32 +0x64
      github.com/bcvery1/tilepix_test.TestMain()
          /home/travis/gopath/src/github.com/bcvery1/tilepix/map_test.go:16 +0x92
      main.main()
          _testmain.go:144 +0x32f
    
    Previous read at 0x00c00000e180 by goroutine 12:
      github.com/faiface/pixel/pixelgl.(*GLTriangles).Update()
          /home/travis/gopath/pkg/mod/github.com/faiface/[email protected]/vertex.go:50 +0x93
      github.com/faiface/pixel/pixelgl.NewGLTriangles()
          /home/travis/gopath/pkg/mod/github.com/faiface/[email protected]/pixelgl/gltriangles.go:39 +0x1aa
      github.com/faiface/pixel/pixelgl.(*Window).MakeTriangles()
          /home/travis/gopath/pkg/mod/github.com/faiface/[email protected]/pixelgl/canvas.go:65 +0x9d
      github.com/faiface/pixel.(*Drawer).Draw()
          /home/travis/gopath/pkg/mod/github.com/faiface/[email protected]/drawer.go:74 +0x4b8
      github.com/faiface/pixel.(*Sprite).DrawColorMask()
          /home/travis/gopath/pkg/mod/github.com/faiface/[email protected]/sprite.go:87 +0x1c5
      github.com/bcvery1/tilepix.(*Map).DrawAll()
          /home/travis/gopath/pkg/mod/github.com/faiface/[email protected]/sprite.go:61 +0x8f1
      github.com/bcvery1/tilepix_test.TestMap_DrawAll()
          /home/travis/gopath/src/github.com/bcvery1/tilepix/map_test.go:98 +0x2a4
      testing.tRunner()
          /home/travis/.gimme/versions/go/src/testing/testing.go:865 +0x162
    
    Goroutine 12 (running) created at:
      testing.(*T).Run()
          /home/travis/.gimme/versions/go/src/testing/testing.go:916 +0x651
      testing.runTests.func1()
          /home/travis/.gimme/versions/go/src/testing/testing.go:1157 +0xa6
      testing.tRunner()
          /home/travis/.gimme/versions/go/src/testing/testing.go:865 +0x162
      testing.runTests()
          /home/travis/.gimme/versions/go/src/testing/testing.go:1155 +0x521
      testing.(*M).Run()
          /home/travis/.gimme/versions/go/src/testing/testing.go:1072 +0x2e9
      github.com/bcvery1/tilepix_test.TestMain.func1()
          /home/travis/gopath/src/github.com/bcvery1/tilepix/map_test.go:17 +0x41
      github.com/faiface/mainthread.Run.func1()
          /home/travis/gopath/pkg/mod/github.com/faiface/[email protected]/mainthread.go:37 +0x34
    ==================
    

    Here is the change which is generating this problem: https://github.com/bcvery1/tilepix/pull/81

    opened by bcvery1 6
  • Fix VertexSlice sub-slices rendering excessive data

    Fix VertexSlice sub-slices rendering excessive data

    gl.DrawArrays takes count as the third argument. Current solution may cause that shader (on older GPUs) would try to render data that is outside of VBO memory. So it should be int32(j-i) as in other parts of the code instead of int32(i+j)

    opened by Wieku 1
  • array uniforms support

    array uniforms support

    Not the best naming, but it works. Implementation of https://github.com/faiface/glhf/issues/8 FR Useless without patch in pixel code. Will be done in relevant PR.

    opened by shinomontaz 0
  • Array uniforms feature request

    Array uniforms feature request

    It would be nice to have an array uniforms. Useful for dynamic shadows when obstacles are many. Seems it's can be done by calling gl.Uniform1fv with second param equals to desired array size in shader.go. Something like this:

    case Float:
    		value := value.(float32)
    		gl.Uniform1fv(s.uniformLoc[uniform], 1, &value)
    case FloatArr:
                    value := value.([]float32)
    		length := int32(len(value))
    		gl.Uniform1fv(s.uniformLoc[uniform], length, &value[0])
    
    opened by shinomontaz 0
  • Drawing slice forces GL_TRIANGLES

    Drawing slice forces GL_TRIANGLES

    https://github.com/faiface/glhf/blob/82a6317ac380cdc61567d729fe48833d75b8108e/vertex.go#L266

    Drawing a slice forces the gl.TRIANGLES drawmode, meaning you have to revert to direct gl calls to draw points or other primitives (I've implemented my own method for now to pass a draw mode, I'd make a pull request but I'm not sure what to call the method, I'm just using Draw2(mode uint32)

    opened by HymnsForDisco 0
  • sprite draw is suddenly broken for me

    sprite draw is suddenly broken for me

    Everything was fine 3 days ago, but now both my exercises with pixel engine and glhf demo show the same problem: no errors, windows is created and even filled with Clear color, but no sprites is drawed. Window updates and closes just fine, draw method is called, but no evidence off sprite

    what i'm doing wrong?

    win7 x64, Nvidia last drivers. Sry for mb stupid question!

    opened by shnifer 7
Owner
Michal Štrba
Infinity is smaller than 380012893427665492.
Michal Štrba
Go bindings for OpenGL (generated via glow)

gl This repository holds Go bindings to various OpenGL versions. They are auto-generated using Glow. Features: Go functions that mirror the C specific

OpenGL with Golang 911 Jun 26, 2022
Go bindings to OpenGL Utility Library

GLU This package offers minimal bindings for GLU functions. Usage go get github.com/go-gl-legacy/glu License Copyright 2012 The go-gl Authors. All ri

go-gl legacy 21 Aug 18, 2018
OpenGL binding generator for Go

GoGL GoGL is an OpenGL binding generator for Go. No external dependencies like GLEW are needed. Install the OpenGL bindings For example, OpenGL 2.1 bi

Christoph Schunk 139 Apr 26, 2022
Go cross-platform OpenGL bindings.

gl Package gl is a Go cross-platform binding for OpenGL, with an OpenGL ES 2-like API. It supports: macOS, Linux and Windows via OpenGL 2.1 backend, i

null 157 May 14, 2022
Go cross-platform glfw library for creating an OpenGL context and receiving events.

glfw Package glfw experimentally provides a glfw-like API with desktop (via glfw) and browser (via HTML5 canvas) backends. It is used for creating a G

null 74 Mar 20, 2022
Quake 2 Level Renderer written in Go and OpenGL

go-quake2 Quake 2 Map Renderer written in Go and OpenGL. Features Loads any BSP file from Quake 2 Free roam around the environment Renders only a smal

Samuel Yuan 24 Jan 21, 2022
Canvas is a Go drawing library based on OpenGL or using software rendering that is very similar to the HTML5 canvas API

Go canvas Canvas is a pure Go library that provides drawing functionality as similar as possible to the HTML5 canvas API. It has nothing to do with HT

Thomas Friedel 427 Jun 28, 2022
A Pong clone made from scratch with Go and C using OpenGL 3.3

Go-Pong A Pong video game clone made with Go lang and OpenGL 3.3 using C. Gameplay Offline Key bindings are 'w' and 's' for the left player and 'up ar

Mohammad Issawi 33 Feb 10, 2022
OpenGL renderer

oglr About oglr is a package for Go to load OpenGL functions and render graphics. It is published on https://github.com/vbsw/oglr. Copyright Copyright

Vitali Baumtrok 0 Jun 21, 2022
A pure Go package for coordinate transformations.

WGS84 A pure Go package for coordinate transformations. go get github.com/wroge/wgs84 Usage east, north, h := wgs84.LonLat().To(wgs84.ETRS89UTM(32)).R

Malte Wrogemann 83 Jul 4, 2022
Go package for fast high-level image processing powered by libvips C library

bimg Small Go package for fast high-level image processing using libvips via C bindings, providing a simple programmatic API. bimg was designed to be

Tom 1.9k Jul 4, 2022
Go bindings for GStreamer (retired: currently I don't use/develop this package)

Retired. I don't use/develop this package anymore. Go bindings for GStreamer at a very early stage of maturity. This package is based on GLib bindings

Michał Derkacz 164 May 31, 2022
Imaging is a simple image processing package for Go

Imaging Package imaging provides basic image processing functions (resize, rotate, crop, brightness/contrast adjustments, etc.). All the image process

Grigory Dryapak 4.3k Jun 24, 2022
Go package for decoding and encoding TARGA image format

tga tga is a Go package for decoding and encoding TARGA image format. It supports RLE and raw TARGA images with 8/15/16/24/32 bits per pixel, monochro

Sigrid Solveig Haflínudóttir 30 Mar 5, 2022
Go package for computer vision using OpenCV 4 and beyond.

GoCV The GoCV package provides Go language bindings for the OpenCV 4 computer vision library. The GoCV package supports the latest releases of Go and

The Hybrid Group 4.9k Jul 5, 2022
Go Perceptual image hashing package

goimagehash Inspired by imagehash A image hashing library written in Go. ImageHash supports: Average hashing Difference hashing Perception hashing Wav

Dong-hee Na 508 Jun 23, 2022
generativeart is a Go package to generate many kinds of generative art.

generativeart is a Go package to generate many kinds of generative art. The goal is to collect some excellent generative art (implemented in R or Processing), and rewrite them in Go again

null 755 Jul 6, 2022
golang package to find the K most dominant/prominent colors in an image

prominentcolor Find the K most dominant colors in an image The Kmeans function returns the K most dominant colors in the image, ordered in the order o

Carl 132 Jun 28, 2022
Go package captcha implements generation and verification of image and audio CAPTCHAs.

Package captcha ⚠️ Warning: this captcha can be broken by advanced OCR captcha breaking algorithms. import "github.com/dchest/captcha" Package captch

Dmitry Chestnykh 1.6k Jun 28, 2022