Compare commits
5 Commits
0497ff9ac7
...
0142d5ea6e
Author | SHA1 | Date | |
---|---|---|---|
0142d5ea6e | |||
9de131d215 | |||
1b1abda7d0 | |||
5da859f0e7 | |||
e43a73d316 |
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,3 +1,3 @@
|
||||
opengl-deferred
|
||||
assets/textures
|
||||
assets/geometries
|
||||
assets
|
||||
!assets/shader
|
@ -1,2 +0,0 @@
|
||||
# Blender 3.4.1 MTL File: 'None'
|
||||
# www.blender.org
|
@ -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
|
@ -1,2 +0,0 @@
|
||||
# Blender 3.4.1 MTL File: 'None'
|
||||
# www.blender.org
|
@ -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
|
@ -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
1
go.mod
@ -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
3
go.sum
@ -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
150
main.go
@ -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
5
types/asset/asset.go
Normal file
@ -0,0 +1,5 @@
|
||||
package asset
|
||||
|
||||
type Asset interface {
|
||||
Delete()
|
||||
}
|
110
types/material/material.go
Normal file
110
types/material/material.go
Normal 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
16
types/material/values.go
Normal 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)
|
||||
}
|
@ -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
|
||||
}
|
||||
|
146
utils/assetmanager/assetmanager.go
Normal file
146
utils/assetmanager/assetmanager.go
Normal 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()
|
||||
}
|
||||
}
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user