Compare commits
No commits in common. "0142d5ea6e00dd0386bcb95244737aa6ea39f662" and "0497ff9ac78c040c456ce781e50eb384f0ee68e1" have entirely different histories.
0142d5ea6e
...
0497ff9ac7
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,3 +1,3 @@
|
|||||||
opengl-deferred
|
opengl-deferred
|
||||||
assets
|
assets/textures
|
||||||
!assets/shader
|
assets/geometries
|
2
assets/geometries/cube.mtl
Normal file
2
assets/geometries/cube.mtl
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# Blender 3.4.1 MTL File: 'None'
|
||||||
|
# www.blender.org
|
47
assets/geometries/cube.obj
Normal file
47
assets/geometries/cube.obj
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
# 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
|
2
assets/geometries/plane.mtl
Normal file
2
assets/geometries/plane.mtl
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# Blender 3.4.1 MTL File: 'None'
|
||||||
|
# www.blender.org
|
16
assets/geometries/plane.obj
Normal file
16
assets/geometries/plane.obj
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# 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
|
2
assets/geometries/suzanne.mtl
Normal file
2
assets/geometries/suzanne.mtl
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# Blender 3.4.1 MTL File: 'None'
|
||||||
|
# www.blender.org
|
3485
assets/geometries/suzanne.obj
Normal file
3485
assets/geometries/suzanne.obj
Normal file
File diff suppressed because it is too large
Load Diff
9965
assets/geometries/teapot.obj
Normal file
9965
assets/geometries/teapot.obj
Normal file
File diff suppressed because it is too large
Load Diff
1
go.mod
1
go.mod
@ -10,5 +10,4 @@ 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,6 +16,3 @@ 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=
|
|
||||||
|
152
main.go
152
main.go
@ -2,13 +2,14 @@ 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/material"
|
"git.tek.govt.hu/dowerx/opengl-deferred/types/shader"
|
||||||
am "git.tek.govt.hu/dowerx/opengl-deferred/utils/assetmanager"
|
"git.tek.govt.hu/dowerx/opengl-deferred/types/texture"
|
||||||
"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"
|
||||||
@ -16,13 +17,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
WIDTH = 1280
|
WIDTH = 1600
|
||||||
HEIGHT = 720
|
HEIGHT = 900
|
||||||
TITLE = "opengl-deferred"
|
TITLE = "opengl-deferred"
|
||||||
FOV = 75.0
|
FOV = 45.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 {
|
||||||
@ -47,18 +49,65 @@ 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, 1)
|
gl.ClearColor(0, 0, 0, 0)
|
||||||
|
|
||||||
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 := am.Init("assets")
|
// shader
|
||||||
|
vertexSource, err := os.ReadFile("assets/shader/deferred/deferred.vs")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
defer assetManager.Destroy()
|
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)
|
||||||
|
|
||||||
screen, err := geometry.Screen()
|
screen, err := geometry.Screen()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -66,6 +115,49 @@ 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},
|
||||||
@ -84,12 +176,7 @@ 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(10, 10, mgl32.Vec3{0, 0, -10}, mgl32.Vec2{0, 0}, window)
|
controls := fpscontrols.Get(15, 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()
|
||||||
@ -102,14 +189,26 @@ func main() {
|
|||||||
|
|
||||||
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
|
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
|
||||||
|
|
||||||
// apply the material
|
albedo.Bind(gl.TEXTURE0)
|
||||||
demoMaterial.Apply()
|
normal.Bind(gl.TEXTURE1)
|
||||||
// transfer uniforms
|
specular.Bind(gl.TEXTURE2)
|
||||||
demoMaterial.Shader.Mat4("projection", projection)
|
roughness.Bind(gl.TEXTURE3)
|
||||||
demoMaterial.Shader.Mat4("view", controls.View())
|
metalic.Bind(gl.TEXTURE4)
|
||||||
demoMaterial.Shader.Mat4("model", model)
|
|
||||||
|
|
||||||
teapot.Draw()
|
// 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)
|
||||||
|
for _, g := range geometries {
|
||||||
|
g.Draw()
|
||||||
|
}
|
||||||
|
|
||||||
// second pass
|
// second pass
|
||||||
gl.Disable(gl.DEPTH_TEST)
|
gl.Disable(gl.DEPTH_TEST)
|
||||||
@ -118,13 +217,18 @@ func main() {
|
|||||||
|
|
||||||
gbuff.BindTextures()
|
gbuff.BindTextures()
|
||||||
|
|
||||||
screenMaterial.Apply()
|
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)
|
||||||
|
|
||||||
pos := controls.Position()
|
pos := controls.Position()
|
||||||
screenMaterial.Shader.Vec3("view_pos", &pos[0])
|
screenShader.Vec3("view_pos", &pos[0])
|
||||||
|
|
||||||
for _, light := range lights {
|
for _, light := range lights {
|
||||||
screenMaterial.Shader.Light(&light)
|
screenShader.Light(&light)
|
||||||
}
|
}
|
||||||
|
|
||||||
screen.Draw()
|
screen.Draw()
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
package asset
|
|
||||||
|
|
||||||
type Asset interface {
|
|
||||||
Delete()
|
|
||||||
}
|
|
@ -1,110 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
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,7 +3,6 @@ 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"
|
||||||
@ -22,7 +21,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)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,7 +91,7 @@ func compileShader(source string, shaderType uint32) (uint32, error) {
|
|||||||
return shader, nil
|
return shader, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(vertexSource string, fragmentSource string) (shader Shader, _ error) {
|
func New(vertexSource string, fragmantSource 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)
|
||||||
@ -100,17 +99,17 @@ func New(vertexSource string, fragmentSource string) (shader Shader, _ error) {
|
|||||||
return shader, err
|
return shader, err
|
||||||
}
|
}
|
||||||
|
|
||||||
fragmentShader, err := compileShader(fragmentSource, gl.FRAGMENT_SHADER)
|
fragmantShader, err := compileShader(fragmantSource, 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, fragmentShader)
|
gl.AttachShader(shader.program, fragmantShader)
|
||||||
gl.LinkProgram(shader.program)
|
gl.LinkProgram(shader.program)
|
||||||
defer gl.DeleteShader(vertexShader)
|
defer gl.DeleteShader(vertexShader)
|
||||||
defer gl.DeleteShader(fragmentShader)
|
defer gl.DeleteShader(fragmantShader)
|
||||||
|
|
||||||
var status int32
|
var status int32
|
||||||
gl.GetProgramiv(shader.program, gl.LINK_STATUS, &status)
|
gl.GetProgramiv(shader.program, gl.LINK_STATUS, &status)
|
||||||
@ -126,21 +125,3 @@ func New(vertexSource string, fragmentSource 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
|
|
||||||
}
|
|
||||||
|
@ -1,146 +0,0 @@
|
|||||||
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,54 +28,19 @@ var instance *FPSControls
|
|||||||
func (c *FPSControls) Update() {
|
func (c *FPSControls) Update() {
|
||||||
time := glfw.GetTime()
|
time := glfw.GetTime()
|
||||||
|
|
||||||
var deltaTime float32 = float32(time - c.lastTime)
|
deltaTime := time - c.lastTime
|
||||||
c.lastTime = time
|
c.lastTime = time
|
||||||
|
|
||||||
_, right, _ := c.directions()
|
forward, right, up := 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))
|
||||||
|
|
||||||
move := mgl32.Vec3{0, 0, 0}
|
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)
|
||||||
|
|
||||||
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 {
|
||||||
@ -88,9 +53,43 @@ 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