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
|
opengl-deferred
|
||||||
assets/textures
|
assets
|
||||||
assets/geometries
|
!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/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
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 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=
|
||||||
|
150
main.go
150
main.go
@ -2,14 +2,13 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"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/types/shader"
|
"git.tek.govt.hu/dowerx/opengl-deferred/types/material"
|
||||||
"git.tek.govt.hu/dowerx/opengl-deferred/types/texture"
|
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"
|
||||||
@ -17,14 +16,13 @@ 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() {
|
||||||
|
|
||||||
// init glfw
|
// init glfw
|
||||||
runtime.LockOSThread()
|
runtime.LockOSThread()
|
||||||
if err := glfw.Init(); err != nil {
|
if err := glfw.Init(); err != nil {
|
||||||
@ -49,65 +47,18 @@ func main() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
gl.Enable(gl.DEPTH_TEST)
|
|
||||||
gl.Enable(gl.CULL_FACE)
|
gl.Enable(gl.CULL_FACE)
|
||||||
gl.DepthFunc(gl.LESS)
|
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)))
|
fmt.Println("OpenGL version:", gl.GoStr(gl.GetString(gl.VERSION)))
|
||||||
|
|
||||||
// load assets
|
// load assets
|
||||||
// shader
|
assetManager, err := am.Init("assets")
|
||||||
vertexSource, err := os.ReadFile("assets/shader/deferred/deferred.vs")
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
fragmentSource, err := os.ReadFile("assets/shader/deferred/deferred.fs")
|
defer assetManager.Destroy()
|
||||||
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)
|
|
||||||
|
|
||||||
screen, err := geometry.Screen()
|
screen, err := geometry.Screen()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -115,49 +66,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
defer screen.Delete()
|
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
|
||||||
lights := []light.Light{
|
lights := []light.Light{
|
||||||
{Color: [3]float32{1, 1, 1}, Position: mgl32.Vec3{0, 10, 0}, Intensity: 40, Type: light.POINT},
|
{Color: [3]float32{1, 1, 1}, Position: mgl32.Vec3{0, 10, 0}, Intensity: 40, Type: light.POINT},
|
||||||
@ -176,7 +84,12 @@ func main() {
|
|||||||
// transformations
|
// transformations
|
||||||
projection := mgl32.Perspective(mgl32.DegToRad(FOV), float32(WIDTH)/HEIGHT, 0.1, 1000)
|
projection := mgl32.Perspective(mgl32.DegToRad(FOV), float32(WIDTH)/HEIGHT, 0.1, 1000)
|
||||||
model := mgl32.Ident4()
|
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() {
|
for !window.ShouldClose() {
|
||||||
glfw.PollEvents()
|
glfw.PollEvents()
|
||||||
@ -189,26 +102,14 @@ func main() {
|
|||||||
|
|
||||||
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
|
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
|
||||||
|
|
||||||
albedo.Bind(gl.TEXTURE0)
|
// apply the material
|
||||||
normal.Bind(gl.TEXTURE1)
|
demoMaterial.Apply()
|
||||||
specular.Bind(gl.TEXTURE2)
|
|
||||||
roughness.Bind(gl.TEXTURE3)
|
|
||||||
metalic.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)
|
teapot.Draw()
|
||||||
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()
|
|
||||||
}
|
|
||||||
|
|
||||||
// second pass
|
// second pass
|
||||||
gl.Disable(gl.DEPTH_TEST)
|
gl.Disable(gl.DEPTH_TEST)
|
||||||
@ -217,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()
|
||||||
|
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 (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.tek.govt.hu/dowerx/opengl-deferred/types/light"
|
"git.tek.govt.hu/dowerx/opengl-deferred/types/light"
|
||||||
@ -21,7 +22,7 @@ func (s *Shader) Use() {
|
|||||||
s.lightCount = 0
|
s.lightCount = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Shader) Delete() {
|
func (s Shader) Delete() {
|
||||||
gl.DeleteProgram(s.program)
|
gl.DeleteProgram(s.program)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +92,7 @@ func compileShader(source string, shaderType uint32) (uint32, error) {
|
|||||||
return shader, nil
|
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)
|
shader.uniforms = make(map[string]int32)
|
||||||
|
|
||||||
vertexShader, err := compileShader(vertexSource, gl.VERTEX_SHADER)
|
vertexShader, err := compileShader(vertexSource, gl.VERTEX_SHADER)
|
||||||
@ -99,17 +100,17 @@ func New(vertexSource string, fragmantSource string) (shader Shader, _ error) {
|
|||||||
return shader, err
|
return shader, err
|
||||||
}
|
}
|
||||||
|
|
||||||
fragmantShader, err := compileShader(fragmantSource, gl.FRAGMENT_SHADER)
|
fragmentShader, err := compileShader(fragmentSource, gl.FRAGMENT_SHADER)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return shader, err
|
return shader, err
|
||||||
}
|
}
|
||||||
|
|
||||||
shader.program = gl.CreateProgram()
|
shader.program = gl.CreateProgram()
|
||||||
gl.AttachShader(shader.program, vertexShader)
|
gl.AttachShader(shader.program, vertexShader)
|
||||||
gl.AttachShader(shader.program, fragmantShader)
|
gl.AttachShader(shader.program, fragmentShader)
|
||||||
gl.LinkProgram(shader.program)
|
gl.LinkProgram(shader.program)
|
||||||
defer gl.DeleteShader(vertexShader)
|
defer gl.DeleteShader(vertexShader)
|
||||||
defer gl.DeleteShader(fragmantShader)
|
defer gl.DeleteShader(fragmentShader)
|
||||||
|
|
||||||
var status int32
|
var status int32
|
||||||
gl.GetProgramiv(shader.program, gl.LINK_STATUS, &status)
|
gl.GetProgramiv(shader.program, gl.LINK_STATUS, &status)
|
||||||
@ -125,3 +126,21 @@ func New(vertexSource string, fragmantSource string) (shader Shader, _ error) {
|
|||||||
|
|
||||||
return shader, nil
|
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
|
position mgl32.Vec3
|
||||||
rotation mgl32.Vec2
|
rotation mgl32.Vec2
|
||||||
|
|
||||||
currentMove mgl32.Vec3
|
|
||||||
currentLook mgl32.Vec2
|
|
||||||
lastMousePos mgl32.Vec2
|
lastMousePos mgl32.Vec2
|
||||||
|
|
||||||
view mgl32.Mat4
|
view mgl32.Mat4
|
||||||
|
|
||||||
|
window *glfw.Window
|
||||||
|
|
||||||
lastTime float64
|
lastTime float64
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,19 +28,54 @@ var instance *FPSControls
|
|||||||
func (c *FPSControls) Update() {
|
func (c *FPSControls) Update() {
|
||||||
time := glfw.GetTime()
|
time := glfw.GetTime()
|
||||||
|
|
||||||
deltaTime := time - c.lastTime
|
var deltaTime float32 = float32(time - c.lastTime)
|
||||||
c.lastTime = time
|
c.lastTime = time
|
||||||
|
|
||||||
forward, right, up := c.directions()
|
_, right, _ := c.directions()
|
||||||
|
|
||||||
globalUp := mgl32.Vec3{0, 1, 0}
|
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))
|
move := mgl32.Vec3{0, 0, 0}
|
||||||
c.currentLook = mgl32.Vec2{}
|
|
||||||
c.view = mgl32.LookAtV(c.position, c.position.Add(forward), up)
|
|
||||||
|
|
||||||
|
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 {
|
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,
|
lookSpeed: lookSpeed,
|
||||||
position: position,
|
position: position,
|
||||||
rotation: rotation,
|
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)
|
window.SetInputMode(glfw.CursorMode, glfw.CursorDisabled)
|
||||||
|
|
||||||
return instance
|
return instance
|
||||||
|
Loading…
Reference in New Issue
Block a user