Compare commits

..

5 Commits

Author SHA1 Message Date
0142d5ea6e remove assets 2024-12-17 03:00:24 +01:00
9de131d215 materials 2024-12-17 02:59:59 +01:00
1b1abda7d0 better asset manager 2024-12-17 01:16:17 +01:00
5da859f0e7 basic assetmaanager 2024-12-16 13:24:09 +01:00
e43a73d316 better fpscontrols 2024-12-16 13:23:34 +01:00
17 changed files with 376 additions and 13698 deletions

4
.gitignore vendored
View File

@ -1,3 +1,3 @@
opengl-deferred
assets/textures
assets/geometries
assets
!assets/shader

View File

@ -1,2 +0,0 @@
# Blender 3.4.1 MTL File: 'None'
# www.blender.org

View File

@ -1,47 +0,0 @@
# Blender 3.4.1
# www.blender.org
mtllib cube.mtl
o Cube
v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -0.0000 -1.0000 -0.0000
vn -0.0000 1.0000 -0.0000
vt 0.000000 0.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 0.000000 0.000000
vt 0.000000 1.000000
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 0.000000 1.000000
vt 1.000000 1.000000
vt 1.000000 0.000000
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 1.000000 1.000000
s 0
f 2/2/1 3/6/1 1/1/1
f 4/8/2 7/14/2 3/4/2
f 8/16/3 5/9/3 7/14/3
f 6/12/4 1/1/4 5/10/4
f 7/15/5 1/1/5 3/5/5
f 4/8/6 6/13/6 8/16/6
f 2/2/1 4/7/1 3/6/1
f 4/8/2 8/16/2 7/14/2
f 8/16/3 6/11/3 5/9/3
f 6/12/4 2/2/4 1/1/4
f 7/15/5 5/10/5 1/1/5
f 4/8/6 2/3/6 6/13/6

View File

@ -1,2 +0,0 @@
# Blender 3.4.1 MTL File: 'None'
# www.blender.org

View File

@ -1,16 +0,0 @@
# Blender 3.4.1
# www.blender.org
mtllib plane.mtl
o Plane
v -10.000000 0.000000 10.000000
v 10.000000 0.000000 10.000000
v -10.000000 0.000000 -10.000000
v 10.000000 0.000000 -10.000000
vn -0.0000 1.0000 -0.0000
vt 0.999900 0.000100
vt 0.999900 0.999900
vt 0.000100 0.000100
vt 0.000100 0.999900
s 0
f 2/2/1 3/3/1 1/1/1
f 2/2/1 4/4/1 3/3/1

View File

@ -1,2 +0,0 @@
# Blender 3.4.1 MTL File: 'None'
# www.blender.org

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1
go.mod
View File

@ -10,4 +10,5 @@ require (
github.com/go-gl/mathgl v1.1.0 // indirect
github.com/udhos/gwob v1.0.0 // indirect
golang.org/x/image v0.21.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

3
go.sum
View File

@ -16,3 +16,6 @@ golang.org/x/image v0.0.0-20190321063152-3fc05d484e9f/go.mod h1:kZ7UVZpmo3dzQBMx
golang.org/x/image v0.21.0 h1:c5qV36ajHpdj4Qi0GnE0jUc/yuo33OLFaa0d+crTD5s=
golang.org/x/image v0.21.0/go.mod h1:vUbsLavqK/W303ZroQQVKQ+Af3Yl6Uz1Ppu5J/cLz78=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

150
main.go
View File

@ -2,14 +2,13 @@ package main
import (
"fmt"
"os"
"runtime"
"git.tek.govt.hu/dowerx/opengl-deferred/types/gbuffer"
"git.tek.govt.hu/dowerx/opengl-deferred/types/geometry"
"git.tek.govt.hu/dowerx/opengl-deferred/types/light"
"git.tek.govt.hu/dowerx/opengl-deferred/types/shader"
"git.tek.govt.hu/dowerx/opengl-deferred/types/texture"
"git.tek.govt.hu/dowerx/opengl-deferred/types/material"
am "git.tek.govt.hu/dowerx/opengl-deferred/utils/assetmanager"
"git.tek.govt.hu/dowerx/opengl-deferred/utils/fpscontrols"
"github.com/go-gl/gl/v4.6-core/gl"
"github.com/go-gl/glfw/v3.3/glfw"
@ -17,14 +16,13 @@ import (
)
const (
WIDTH = 1600
HEIGHT = 900
WIDTH = 1280
HEIGHT = 720
TITLE = "opengl-deferred"
FOV = 45.0
FOV = 75.0
)
func main() {
// init glfw
runtime.LockOSThread()
if err := glfw.Init(); err != nil {
@ -49,65 +47,18 @@ func main() {
panic(err)
}
gl.Enable(gl.DEPTH_TEST)
gl.Enable(gl.CULL_FACE)
gl.DepthFunc(gl.LESS)
gl.ClearColor(0, 0, 0, 0)
gl.ClearColor(0, 0, 0, 1)
fmt.Println("OpenGL version:", gl.GoStr(gl.GetString(gl.VERSION)))
// load assets
// shader
vertexSource, err := os.ReadFile("assets/shader/deferred/deferred.vs")
assetManager, err := am.Init("assets")
if err != nil {
panic(err)
}
fragmentSource, err := os.ReadFile("assets/shader/deferred/deferred.fs")
if err != nil {
panic(err)
}
deferredShader, err := shader.New(string(vertexSource), string(fragmentSource))
if err != nil {
panic(err)
}
defer deferredShader.Delete()
vertexSource, err = os.ReadFile("assets/shader/pbr/pbr.vs")
if err != nil {
panic(err)
}
// fragmentSource, err = os.ReadFile("assets/shader/screen/screen-debug.fs")
// fragmentSource, err = os.ReadFile("assets/shader/screen/screen.fs")
fragmentSource, err = os.ReadFile("assets/shader/pbr/pbr.fs")
if err != nil {
panic(err)
}
screenShader, err := shader.New(string(vertexSource), string(fragmentSource))
if err != nil {
panic(err)
}
defer screenShader.Delete()
// geometry
var geometries []geometry.Geometry
cube, err := geometry.LoadOBJ("assets/geometries/cube.obj")
if err != nil {
panic(err)
}
defer cube.Delete()
geometries = append(geometries, cube)
plane, err := geometry.LoadOBJ("assets/geometries/plane.obj")
if err != nil {
panic(err)
}
defer plane.Delete()
geometries = append(geometries, plane)
defer assetManager.Destroy()
screen, err := geometry.Screen()
if err != nil {
@ -115,49 +66,6 @@ func main() {
}
defer screen.Delete()
// textures
albedo, err := texture.Load("assets/textures/TCom_Pavement_PaintedConcrete3_512_albedo.tif")
if err != nil {
panic(err)
}
defer albedo.Delete()
normal, err := texture.Load("assets/textures/TCom_Pavement_PaintedConcrete3_512_normal.tif")
if err != nil {
panic(err)
}
defer normal.Delete()
specular, err := texture.Load("assets/textures/TCom_Pavement_PaintedConcrete3_512_roughness.tif")
if err != nil {
panic(err)
}
defer specular.Delete()
roughness, err := texture.Load("assets/textures/TCom_Pavement_PaintedConcrete3_512_roughness.tif")
if err != nil {
panic(err)
}
defer roughness.Delete()
metalic, err := texture.Load("assets/textures/TCom_Pavement_PaintedConcrete3_512_roughness.tif")
if err != nil {
panic(err)
}
defer metalic.Delete()
white, err := texture.Load("assets/textures/white.png")
if err != nil {
panic(err)
}
defer white.Delete()
black, err := texture.Load("assets/textures/black.png")
if err != nil {
panic(err)
}
defer black.Delete()
// lights
lights := []light.Light{
{Color: [3]float32{1, 1, 1}, Position: mgl32.Vec3{0, 10, 0}, Intensity: 40, Type: light.POINT},
@ -176,7 +84,12 @@ func main() {
// transformations
projection := mgl32.Perspective(mgl32.DegToRad(FOV), float32(WIDTH)/HEIGHT, 0.1, 1000)
model := mgl32.Ident4()
controls := fpscontrols.Get(15, 10, mgl32.Vec3{0, 0, -10}, mgl32.Vec2{0, 0}, window)
controls := fpscontrols.Get(10, 10, mgl32.Vec3{0, 0, -10}, mgl32.Vec2{0, 0}, window)
demoMaterial := am.GetAsset[material.Material](assetManager, "assets/material/demo")
screenMaterial := am.GetAsset[material.Material](assetManager, "assets/material/screen")
teapot := am.GetAsset[geometry.Geometry](assetManager, "assets/geometry/teapot")
for !window.ShouldClose() {
glfw.PollEvents()
@ -189,26 +102,14 @@ func main() {
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
albedo.Bind(gl.TEXTURE0)
normal.Bind(gl.TEXTURE1)
specular.Bind(gl.TEXTURE2)
roughness.Bind(gl.TEXTURE3)
metalic.Bind(gl.TEXTURE4)
// apply the material
demoMaterial.Apply()
// transfer uniforms
deferredShader.Use()
deferredShader.Mat4("projection", projection)
deferredShader.Mat4("view", controls.View())
deferredShader.Mat4("model", model)
demoMaterial.Shader.Mat4("projection", projection)
demoMaterial.Shader.Mat4("view", controls.View())
demoMaterial.Shader.Mat4("model", model)
deferredShader.Int("s_albedo", 0)
deferredShader.Int("s_normal", 1)
deferredShader.Int("s_specular", 2)
deferredShader.Int("s_roughness", 3)
deferredShader.Int("s_metalic", 4)
for _, g := range geometries {
g.Draw()
}
teapot.Draw()
// second pass
gl.Disable(gl.DEPTH_TEST)
@ -217,18 +118,13 @@ func main() {
gbuff.BindTextures()
screenShader.Use()
screenShader.Int("s_albedo", 0)
screenShader.Int("s_depth", 1)
screenShader.Int("s_normal", 2)
screenShader.Int("s_material", 3)
screenShader.Int("s_position", 4)
screenMaterial.Apply()
pos := controls.Position()
screenShader.Vec3("view_pos", &pos[0])
screenMaterial.Shader.Vec3("view_pos", &pos[0])
for _, light := range lights {
screenShader.Light(&light)
screenMaterial.Shader.Light(&light)
}
screen.Draw()

5
types/asset/asset.go Normal file
View File

@ -0,0 +1,5 @@
package asset
type Asset interface {
Delete()
}

110
types/material/material.go Normal file
View File

@ -0,0 +1,110 @@
package material
import (
"errors"
"os"
"git.tek.govt.hu/dowerx/opengl-deferred/types/asset"
"git.tek.govt.hu/dowerx/opengl-deferred/types/shader"
"git.tek.govt.hu/dowerx/opengl-deferred/types/texture"
"github.com/go-gl/gl/v4.6-core/gl"
"gopkg.in/yaml.v3"
)
type MaterialDefiniton struct {
Shader string `yaml:"shader"`
Textures []struct {
Slot uint32 `yaml:"slot"`
Texture string `yaml:"texture"`
} `yaml:"textures"`
Values []struct {
Type string `yaml:"type"`
Name string `yaml:"name"`
Value interface{} `yaml:"value"`
} `yaml:"values"`
}
type Material struct {
Shader *shader.Shader
ShaderName string
Textures []struct {
Slot uint32
Texture *texture.Texture
TextureName string
}
Values []Value
}
func (m Material) Delete() {}
func (m *Material) Apply() {
m.Shader.Use()
for _, t := range m.Textures {
t.Texture.Bind(gl.TEXTURE0 + t.Slot)
}
for _, v := range m.Values {
v.Apply(m.Shader)
}
}
func Load(path string, assets map[string]asset.Asset) (Material, error) {
var definition MaterialDefiniton
var material Material
data, err := os.ReadFile(path)
if err != nil {
return material, err
}
if err = yaml.Unmarshal(data, &definition); err != nil {
return material, err
}
material.ShaderName = definition.Shader
for _, t := range definition.Textures {
material.Textures = append(material.Textures, struct {
Slot uint32
Texture *texture.Texture
TextureName string
}{Slot: t.Slot, TextureName: t.Texture})
}
for _, vdef := range definition.Values {
var value Value
switch vdef.Type {
case "int":
intval, ok := vdef.Value.(int32)
if !ok {
return material, err
}
value = IntValue{Name: vdef.Name, Value: intval}
default:
return material, errors.New("Unknown value: " + vdef.Type)
}
material.Values = append(material.Values, value)
}
return material, err
}
func (m *Material) AttachAssets(assets map[string]asset.Asset) error {
tmpShader, ok := assets[m.ShaderName].(shader.Shader)
if !ok {
return errors.New("Failed to attach shader to material: " + m.ShaderName)
}
m.Shader = &tmpShader
for i, t := range m.Textures {
tmpTexture, ok := assets[t.TextureName].(texture.Texture)
if !ok {
return errors.New("Failed to attach texture to material: " + t.TextureName)
}
m.Textures[i].Texture = &tmpTexture
}
return nil
}

16
types/material/values.go Normal file
View File

@ -0,0 +1,16 @@
package material
import "git.tek.govt.hu/dowerx/opengl-deferred/types/shader"
type Value interface {
Apply(s *shader.Shader)
}
type IntValue struct {
Name string
Value int32
}
func (v IntValue) Apply(s *shader.Shader) {
s.Int(v.Name, v.Value)
}

View File

@ -3,6 +3,7 @@ package shader
import (
"errors"
"fmt"
"os"
"strings"
"git.tek.govt.hu/dowerx/opengl-deferred/types/light"
@ -21,7 +22,7 @@ func (s *Shader) Use() {
s.lightCount = 0
}
func (s *Shader) Delete() {
func (s Shader) Delete() {
gl.DeleteProgram(s.program)
}
@ -91,7 +92,7 @@ func compileShader(source string, shaderType uint32) (uint32, error) {
return shader, nil
}
func New(vertexSource string, fragmantSource string) (shader Shader, _ error) {
func New(vertexSource string, fragmentSource string) (shader Shader, _ error) {
shader.uniforms = make(map[string]int32)
vertexShader, err := compileShader(vertexSource, gl.VERTEX_SHADER)
@ -99,17 +100,17 @@ func New(vertexSource string, fragmantSource string) (shader Shader, _ error) {
return shader, err
}
fragmantShader, err := compileShader(fragmantSource, gl.FRAGMENT_SHADER)
fragmentShader, err := compileShader(fragmentSource, gl.FRAGMENT_SHADER)
if err != nil {
return shader, err
}
shader.program = gl.CreateProgram()
gl.AttachShader(shader.program, vertexShader)
gl.AttachShader(shader.program, fragmantShader)
gl.AttachShader(shader.program, fragmentShader)
gl.LinkProgram(shader.program)
defer gl.DeleteShader(vertexShader)
defer gl.DeleteShader(fragmantShader)
defer gl.DeleteShader(fragmentShader)
var status int32
gl.GetProgramiv(shader.program, gl.LINK_STATUS, &status)
@ -125,3 +126,21 @@ func New(vertexSource string, fragmantSource string) (shader Shader, _ error) {
return shader, nil
}
func FromFiles(vertexPath, fragmentPath string) (shader Shader, _ error) {
vertexSource, err := os.ReadFile(vertexPath)
if err != nil {
return shader, err
}
fragmentSource, err := os.ReadFile(fragmentPath)
if err != nil {
return shader, err
}
shader, err = New(string(vertexSource), string(fragmentSource))
if err != nil {
return shader, err
}
return shader, nil
}

View File

@ -0,0 +1,146 @@
package assetmanager
import (
"fmt"
"os"
"path/filepath"
"regexp"
"slices"
"strings"
"git.tek.govt.hu/dowerx/opengl-deferred/types/asset"
"git.tek.govt.hu/dowerx/opengl-deferred/types/geometry"
"git.tek.govt.hu/dowerx/opengl-deferred/types/material"
"git.tek.govt.hu/dowerx/opengl-deferred/types/shader"
"git.tek.govt.hu/dowerx/opengl-deferred/types/texture"
)
type AssetManager struct {
assets map[string]asset.Asset
}
var instance *AssetManager
var (
TEXTURE_EXTENSIONS = []string{"png", "tif"}
GEOMETRY_EXTENSIONS = []string{"obj"}
SHADER_EXTENSIONS = []string{"sdr"}
MATERIAL_EXTENSIONS = []string{"mtl"}
SCENE_EXTENSIONS = []string{"scn"}
VERTEX_REGEX = regexp.MustCompile("vertex_file (?P<path>.*)$")
FRAGMENT_REGEX = regexp.MustCompile("fragment_file (?P<path>.*)$")
)
func (a *AssetManager) loadItem(path string, itemToLoad os.DirEntry) error {
if itemToLoad.Type().IsDir() {
items, err := os.ReadDir(filepath.Join(path, itemToLoad.Name()))
if err != nil {
return err
}
for _, item := range items {
if err = a.loadItem(filepath.Join(path, itemToLoad.Name()), item); err != nil {
return err
}
}
} else if itemToLoad.Type().IsRegular() {
parts := strings.Split(itemToLoad.Name(), ".")
extension := parts[len(parts)-1]
var asset asset.Asset
var err error
if slices.Contains(TEXTURE_EXTENSIONS, extension) {
asset, err = texture.Load(filepath.Join(path, itemToLoad.Name()))
} else if slices.Contains(GEOMETRY_EXTENSIONS, extension) {
asset, err = geometry.LoadOBJ(filepath.Join(path, itemToLoad.Name()))
} else if slices.Contains(SHADER_EXTENSIONS, extension) {
definition, err := os.ReadFile(filepath.Join(path, itemToLoad.Name()))
if err != nil {
return err
}
var vertexPath, fragmentPath string
for _, line := range strings.Split(string(definition), "\n") {
var matches []string
if matches = VERTEX_REGEX.FindStringSubmatch(line); matches != nil {
vertexPath = matches[VERTEX_REGEX.SubexpIndex("path")]
} else if matches = FRAGMENT_REGEX.FindStringSubmatch(line); matches != nil {
fragmentPath = matches[FRAGMENT_REGEX.SubexpIndex("path")]
}
}
asset, err = shader.FromFiles(filepath.Join(path, vertexPath), filepath.Join(path, fragmentPath))
if err != nil {
return err
}
} else if slices.Contains(MATERIAL_EXTENSIONS, extension) {
asset, err = material.Load(filepath.Join(path, itemToLoad.Name()), a.assets)
} else {
return nil
}
if err != nil {
return err
}
a.assets[filepath.Join(path, itemToLoad.Name()[:len(itemToLoad.Name())-len(extension)-1])] = asset
}
return nil
}
func Init(path string) (*AssetManager, error) {
if instance != nil {
instance.Destroy()
}
instance = &AssetManager{make(map[string]asset.Asset)}
items, err := os.ReadDir(path)
if err != nil {
return nil, err
}
for _, item := range items {
err = instance.loadItem(path, item)
if err != nil {
return nil, err
}
}
for k, asset := range instance.assets {
material, ok := asset.(material.Material)
if ok {
material.AttachAssets(instance.assets)
instance.assets[k] = material
}
}
fmt.Println("Loaded assets:")
for k := range instance.assets {
fmt.Printf(" %s\n", k)
}
return instance, err
}
func Get() *AssetManager {
return instance
}
func GetAsset[T asset.Asset](a *AssetManager, name string) *T {
value, ok := a.assets[name].(T)
if !ok {
return nil
}
return &value
}
func (a *AssetManager) Destroy() {
for _, item := range a.assets {
item.Delete()
}
}

View File

@ -14,12 +14,12 @@ type FPSControls struct {
position mgl32.Vec3
rotation mgl32.Vec2
currentMove mgl32.Vec3
currentLook mgl32.Vec2
lastMousePos mgl32.Vec2
view mgl32.Mat4
window *glfw.Window
lastTime float64
}
@ -28,19 +28,54 @@ var instance *FPSControls
func (c *FPSControls) Update() {
time := glfw.GetTime()
deltaTime := time - c.lastTime
var deltaTime float32 = float32(time - c.lastTime)
c.lastTime = time
forward, right, up := c.directions()
_, right, _ := c.directions()
globalUp := mgl32.Vec3{0, 1, 0}
move := right.Mul(c.currentMove.X()).Add(globalUp.Mul(c.currentMove.Y())).Add(forward.Mul(c.currentMove.Z()))
c.position = c.position.Add(move.Mul(float32(deltaTime) * c.moveSpeed))
c.rotation = c.rotation.Add(c.currentLook.Mul(float32(deltaTime) * c.lookSpeed))
c.currentLook = mgl32.Vec2{}
c.view = mgl32.LookAtV(c.position, c.position.Add(forward), up)
move := mgl32.Vec3{0, 0, 0}
if c.window.GetKey(glfw.KeyA) == glfw.Press {
move[0] += 1
}
if c.window.GetKey(glfw.KeyD) == glfw.Press {
move[0] -= 1
}
if c.window.GetKey(glfw.KeySpace) == glfw.Press {
move[1] += 1
}
if c.window.GetKey(glfw.KeyLeftShift) == glfw.Press {
move[1] -= 1
}
if c.window.GetKey(glfw.KeyW) == glfw.Press {
move[2] += 1
}
if c.window.GetKey(glfw.KeyS) == glfw.Press {
move[2] -= 1
}
move = right.Mul(move.X()).Add(globalUp.Mul(move.Y())).Add(right.Cross(globalUp).Mul(move.Z()))
c.position = c.position.Add(move.Mul(deltaTime * c.moveSpeed))
x, y := c.window.GetCursorPos()
look := mgl32.Vec2{
float32(y) - c.lastMousePos.X(),
c.lastMousePos.Y() - float32(x),
}.Mul(deltaTime * c.lookSpeed)
c.rotation = c.rotation.Add(look)
c.rotation = mgl32.Vec2{
min(max(-89.9, c.rotation.X()), 89.9),
float32(int32(c.rotation.Y())%360) + c.rotation.Y() - float32(int32(c.rotation.Y())),
}
c.lastMousePos[0] = float32(y)
c.lastMousePos[1] = float32(x)
forward, _, _ := c.directions()
c.view = mgl32.LookAtV(c.position, c.position.Add(forward), globalUp)
}
func Get(lookSpeed, moveSpeed float32, position mgl32.Vec3, rotation mgl32.Vec2, window *glfw.Window) *FPSControls {
@ -53,43 +88,9 @@ func Get(lookSpeed, moveSpeed float32, position mgl32.Vec3, rotation mgl32.Vec2,
lookSpeed: lookSpeed,
position: position,
rotation: rotation,
window: window,
}
window.SetKeyCallback(func(window *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {
var val float32
switch action {
case glfw.Repeat:
return
case glfw.Press:
val = 1
case glfw.Release:
val = 0
}
switch key {
case glfw.KeyW:
instance.currentMove[2] = val
case glfw.KeyS:
instance.currentMove[2] = -val
case glfw.KeyA:
instance.currentMove[0] = val
case glfw.KeyD:
instance.currentMove[0] = -val
case glfw.KeySpace:
instance.currentMove[1] = val
case glfw.KeyLeftShift:
instance.currentMove[1] = -val
}
})
window.SetCursorPosCallback(func(window *glfw.Window, y float64, x float64) {
pos := mgl32.Vec2{float32(x), float32(y)}
instance.currentLook = instance.lastMousePos.Sub(pos)
instance.currentLook[0] *= -1
instance.lastMousePos = pos
})
window.SetInputMode(glfw.CursorMode, glfw.CursorDisabled)
return instance