3D Mesh Golang

Table of Contents

1 Go 3D

Adventures in OpenGL

2 Why?

3 3rd Party Libs

require (
	github.com/chsc/gogl v0.0.0-20131111203533-c411acc846b6
	github.com/veandco/go-sdl2 v0.3.3
)
Take a look

4 Overview - GPU Hookup

  • Create shared memory
  • Fill shared memory
  • Call a shader program

5 Overview - 3D Pipeline

  • Pass useful "static" matrices / values
  • Vertex shader
  • Fragement shader
  • Run shader

6 Setup

func initOpenGl(width, height int32) error {
	gl.Init()
	gl.Viewport(0, 0, gl.Sizei(width), gl.Sizei(height))

	// OpenGL flags
	gl.Enable(gl.DEPTH_TEST)
	gl.DepthFunc(gl.LESS)
	gl.Enable(gl.BLEND)
	gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)

	if gl.GetError() != gl.NO_ERROR {
		return errors.New("Initialsation failed")
	}

	return nil
}
View Code

7 Create a buffer

var vertexBuffer gl.Uint
gl.GenBuffers(1, &vertexBuffer)
gl.BindBuffer(gl.ARRAY_BUFFER, vertexBuffer)
gl.BufferData(gl.ARRAY_BUFFER,
	gl.Sizeiptr(len(verts)*SizeOfFloat),
	gl.Pointer(&verts[0]),
	gl.STATIC_DRAW)

if gl.GetError() != gl.NO_ERROR {
	log.Printf("Vertex bind buffer")
}
View Code

8 Fill the buffer

buffer := make([]float32, vlen*int(geometry.VertexSize), vlen*int(geometry.VertexSize))

for i := 0; i < vlen; i++ {
	row := int(i * int(geometry.VertexSize))
	buffer[row] = float32(vertices[i].Pos.X)
	buffer[row+1] = float32(vertices[i].Pos.Y)
	buffer[row+2] = float32(vertices[i].Pos.Z)
	...
	buffer[row+8] = float32(vertices[i].Normal.X)
	buffer[row+9] = float32(vertices[i].Normal.Y)
	buffer[row+10] = float32(vertices[i].Normal.Z)
	...
}
return buffer
View Code Cube Data

9 Run a shader

mtw := matrixAsArray(modelToWorld)
viewa := matrixAsArray(view)
proja := matrixAsArray(proj)

gl.UniformMatrix4fv(material.Shader.Program.UniWorld, gl.Sizei(1), gl.FALSE, &mtw[0])
gl.UniformMatrix4fv(material.Shader.Program.UniView, gl.Sizei(1), gl.FALSE, &viewa[0])
gl.UniformMatrix4fv(material.Shader.Program.UniProject, gl.Sizei(1), gl.FALSE, &proja[0])
return r.Draw(mesh, material, drawGl)
View Code Vertex Code Fragment Code

10 3) Profit

  • Yeah, there is no profit
  • … but we can render a Cube

11 Gleaming the Cube

  • To move the cube we need the maths.

12 Gotcha - CGo Buffer pointers

gl.DrawElements(gl.TRIANGLES,
	gl.Sizei(mesh.Resource.Size),
	gl.UNSIGNED_SHORT,
	gl.Offset(nil, 0))

13 Gotcha - No Generics

camera.ActiveCamera
ccomp := s.ActiveCamera.GetComponent(core.ComponentTypeCamera)
cc, ok := ccomp.(*core.ComponentCamera)
const (
    ComponentTypeCamera = "*core.ComponentCamera"
    ComponentTypeRender = "*render.ComponentRender"
)
func (ge *Entity) GetComponent(t string) Componenter {
	tt := ""
	for q := 0; q < len(ge.components); q++ {
		tt = fmt.Sprintf("%T", ge.components[q])
		switch tt {
		case t:
			return ge.components[q]
		}
	}
	return nil
}

14 Gotcha - Limitations

  • Macs only (report) support for OpenGL 2.1
  • New Macs are not going to support OpenGL - metal bindings?
  • Golang with Vulcan vulkan-go and asche

15 Links

Date: Sept 7, 2019

Author: @robrohan

Created: 2019-11-20 Wed 06:40

Validate