materials

This commit is contained in:
BENEDEK László 2024-12-17 02:59:59 +01:00
parent 1b1abda7d0
commit 9de131d215
7 changed files with 165 additions and 56 deletions

4
.gitignore vendored
View File

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

1
go.mod
View File

@ -10,4 +10,5 @@ require (
github.com/go-gl/mathgl v1.1.0 // indirect github.com/go-gl/mathgl v1.1.0 // indirect
github.com/udhos/gwob v1.0.0 // indirect github.com/udhos/gwob v1.0.0 // indirect
golang.org/x/image v0.21.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 h1:c5qV36ajHpdj4Qi0GnE0jUc/yuo33OLFaa0d+crTD5s=
golang.org/x/image v0.21.0/go.mod h1:vUbsLavqK/W303ZroQQVKQ+Af3Yl6Uz1Ppu5J/cLz78= 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= 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=

50
main.go
View File

@ -7,7 +7,8 @@ import (
"git.tek.govt.hu/dowerx/opengl-deferred/types/gbuffer" "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/geometry"
"git.tek.govt.hu/dowerx/opengl-deferred/types/light" "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" "git.tek.govt.hu/dowerx/opengl-deferred/utils/fpscontrols"
"github.com/go-gl/gl/v4.6-core/gl" "github.com/go-gl/gl/v4.6-core/gl"
"github.com/go-gl/glfw/v3.3/glfw" "github.com/go-gl/glfw/v3.3/glfw"
@ -15,10 +16,10 @@ import (
) )
const ( const (
WIDTH = 1600 WIDTH = 1280
HEIGHT = 900 HEIGHT = 720
TITLE = "opengl-deferred" TITLE = "opengl-deferred"
FOV = 45.0 FOV = 75.0
) )
func main() { func main() {
@ -53,7 +54,7 @@ func main() {
fmt.Println("OpenGL version:", gl.GoStr(gl.GetString(gl.VERSION))) fmt.Println("OpenGL version:", gl.GoStr(gl.GetString(gl.VERSION)))
// load assets // load assets
assetManager, err := assetmanager.Init("assets") assetManager, err := am.Init("assets")
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -85,9 +86,10 @@ func main() {
model := mgl32.Ident4() model := mgl32.Ident4()
controls := fpscontrols.Get(10, 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)
deferredShader := assetManager.GetShader("assets/shader/deferred") demoMaterial := am.GetAsset[material.Material](assetManager, "assets/material/demo")
screenShader := assetManager.GetShader("assets/shader/screen") screenMaterial := am.GetAsset[material.Material](assetManager, "assets/material/screen")
teapot := assetManager.GetGeometry("assets/geometry/teapot")
teapot := am.GetAsset[geometry.Geometry](assetManager, "assets/geometry/teapot")
for !window.ShouldClose() { for !window.ShouldClose() {
glfw.PollEvents() glfw.PollEvents()
@ -100,23 +102,12 @@ func main() {
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
assetManager.GetTexture("assets/texture/albedo").Bind(gl.TEXTURE0) // apply the material
assetManager.GetTexture("assets/texture/normal").Bind(gl.TEXTURE1) demoMaterial.Apply()
assetManager.GetTexture("assets/texture/roughness").Bind(gl.TEXTURE2)
assetManager.GetTexture("assets/texture/roughness").Bind(gl.TEXTURE3)
assetManager.GetTexture("assets/texture/roughness").Bind(gl.TEXTURE4)
// transfer uniforms // transfer uniforms
deferredShader.Use() demoMaterial.Shader.Mat4("projection", projection)
deferredShader.Mat4("projection", projection) demoMaterial.Shader.Mat4("view", controls.View())
deferredShader.Mat4("view", controls.View()) demoMaterial.Shader.Mat4("model", model)
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)
teapot.Draw() teapot.Draw()
@ -127,18 +118,13 @@ func main() {
gbuff.BindTextures() gbuff.BindTextures()
screenShader.Use() screenMaterial.Apply()
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)
pos := controls.Position() pos := controls.Position()
screenShader.Vec3("view_pos", &pos[0]) screenMaterial.Shader.Vec3("view_pos", &pos[0])
for _, light := range lights { for _, light := range lights {
screenShader.Light(&light) screenMaterial.Shader.Light(&light)
} }
screen.Draw() screen.Draw()

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

@ -10,6 +10,7 @@ import (
"git.tek.govt.hu/dowerx/opengl-deferred/types/asset" "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/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/shader"
"git.tek.govt.hu/dowerx/opengl-deferred/types/texture" "git.tek.govt.hu/dowerx/opengl-deferred/types/texture"
) )
@ -24,6 +25,8 @@ var (
TEXTURE_EXTENSIONS = []string{"png", "tif"} TEXTURE_EXTENSIONS = []string{"png", "tif"}
GEOMETRY_EXTENSIONS = []string{"obj"} GEOMETRY_EXTENSIONS = []string{"obj"}
SHADER_EXTENSIONS = []string{"sdr"} SHADER_EXTENSIONS = []string{"sdr"}
MATERIAL_EXTENSIONS = []string{"mtl"}
SCENE_EXTENSIONS = []string{"scn"}
VERTEX_REGEX = regexp.MustCompile("vertex_file (?P<path>.*)$") VERTEX_REGEX = regexp.MustCompile("vertex_file (?P<path>.*)$")
FRAGMENT_REGEX = regexp.MustCompile("fragment_file (?P<path>.*)$") FRAGMENT_REGEX = regexp.MustCompile("fragment_file (?P<path>.*)$")
@ -73,6 +76,8 @@ func (a *AssetManager) loadItem(path string, itemToLoad os.DirEntry) error {
if err != nil { if err != nil {
return err return err
} }
} else if slices.Contains(MATERIAL_EXTENSIONS, extension) {
asset, err = material.Load(filepath.Join(path, itemToLoad.Name()), a.assets)
} else { } else {
return nil 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:") fmt.Println("Loaded assets:")
for k := range instance.assets { for k := range instance.assets {
fmt.Printf(" %s\n", k) fmt.Printf(" %s\n", k)
@ -118,28 +131,8 @@ func Get() *AssetManager {
return instance return instance
} }
func (a *AssetManager) GetAsset(name string) asset.Asset { func GetAsset[T asset.Asset](a *AssetManager, name string) *T {
return a.assets[name] value, ok := a.assets[name].(T)
}
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)
if !ok { if !ok {
return nil return nil
} }