From 9de131d215729aa7f4d5d02d3b454ef1b279ea66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?BENEDEK=20L=C3=A1szl=C3=B3?= Date: Tue, 17 Dec 2024 02:59:59 +0100 Subject: [PATCH] materials --- .gitignore | 4 +- go.mod | 1 + go.sum | 3 + main.go | 50 +++++-------- types/material/material.go | 110 +++++++++++++++++++++++++++++ types/material/values.go | 16 +++++ utils/assetmanager/assetmanager.go | 37 ++++------ 7 files changed, 165 insertions(+), 56 deletions(-) create mode 100644 types/material/material.go create mode 100644 types/material/values.go diff --git a/.gitignore b/.gitignore index 1d541c9..9b23970 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ opengl-deferred -assets/textures -assets/geometries \ No newline at end of file +assets +!assets/shader \ No newline at end of file diff --git a/go.mod b/go.mod index c614525..876c865 100644 --- a/go.mod +++ b/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 ) diff --git a/go.sum b/go.sum index 20caccf..8a74d62 100644 --- a/go.sum +++ b/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= diff --git a/main.go b/main.go index 0c66c75..fb04bf9 100644 --- a/main.go +++ b/main.go @@ -7,7 +7,8 @@ import ( "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/utils/assetmanager" + "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" @@ -15,10 +16,10 @@ import ( ) const ( - WIDTH = 1600 - HEIGHT = 900 + WIDTH = 1280 + HEIGHT = 720 TITLE = "opengl-deferred" - FOV = 45.0 + FOV = 75.0 ) func main() { @@ -53,7 +54,7 @@ func main() { fmt.Println("OpenGL version:", gl.GoStr(gl.GetString(gl.VERSION))) // load assets - assetManager, err := assetmanager.Init("assets") + assetManager, err := am.Init("assets") if err != nil { panic(err) } @@ -85,9 +86,10 @@ func main() { model := mgl32.Ident4() controls := fpscontrols.Get(10, 10, mgl32.Vec3{0, 0, -10}, mgl32.Vec2{0, 0}, window) - deferredShader := assetManager.GetShader("assets/shader/deferred") - screenShader := assetManager.GetShader("assets/shader/screen") - teapot := assetManager.GetGeometry("assets/geometry/teapot") + 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() @@ -100,23 +102,12 @@ func main() { gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) - assetManager.GetTexture("assets/texture/albedo").Bind(gl.TEXTURE0) - assetManager.GetTexture("assets/texture/normal").Bind(gl.TEXTURE1) - assetManager.GetTexture("assets/texture/roughness").Bind(gl.TEXTURE2) - assetManager.GetTexture("assets/texture/roughness").Bind(gl.TEXTURE3) - assetManager.GetTexture("assets/texture/roughness").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) - - 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) + demoMaterial.Shader.Mat4("projection", projection) + demoMaterial.Shader.Mat4("view", controls.View()) + demoMaterial.Shader.Mat4("model", model) teapot.Draw() @@ -127,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() diff --git a/types/material/material.go b/types/material/material.go new file mode 100644 index 0000000..84f9a4a --- /dev/null +++ b/types/material/material.go @@ -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 +} diff --git a/types/material/values.go b/types/material/values.go new file mode 100644 index 0000000..b531dbc --- /dev/null +++ b/types/material/values.go @@ -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) +} diff --git a/utils/assetmanager/assetmanager.go b/utils/assetmanager/assetmanager.go index 4bc5ed1..a611ade 100644 --- a/utils/assetmanager/assetmanager.go +++ b/utils/assetmanager/assetmanager.go @@ -10,6 +10,7 @@ import ( "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" ) @@ -24,6 +25,8 @@ 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.*)$") FRAGMENT_REGEX = regexp.MustCompile("fragment_file (?P.*)$") @@ -73,6 +76,8 @@ func (a *AssetManager) loadItem(path string, itemToLoad os.DirEntry) error { 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 } @@ -106,6 +111,14 @@ func Init(path string) (*AssetManager, error) { } } + 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) @@ -118,28 +131,8 @@ func Get() *AssetManager { return instance } -func (a *AssetManager) GetAsset(name string) asset.Asset { - return a.assets[name] -} - -func (a *AssetManager) GetTexture(name string) *texture.Texture { - value, ok := a.GetAsset(name).(texture.Texture) - if !ok { - return nil - } - return &value -} - -func (a *AssetManager) GetGeometry(name string) *geometry.Geometry { - value, ok := a.GetAsset(name).(geometry.Geometry) - if !ok { - return nil - } - return &value -} - -func (a *AssetManager) GetShader(name string) *shader.Shader { - value, ok := a.GetAsset(name).(shader.Shader) +func GetAsset[T asset.Asset](a *AssetManager, name string) *T { + value, ok := a.assets[name].(T) if !ok { return nil }