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/utils/fpscontrols" "github.com/go-gl/gl/v4.6-core/gl" "github.com/go-gl/glfw/v3.3/glfw" "github.com/go-gl/mathgl/mgl32" ) const ( WIDTH = 1600 HEIGHT = 900 TITLE = "opengl-deferred" FOV = 45.0 ) func main() { // init glfw runtime.LockOSThread() if err := glfw.Init(); err != nil { panic(err) } defer glfw.Terminate() glfw.WindowHint(glfw.Resizable, glfw.False) glfw.WindowHint(glfw.ContextVersionMajor, 4) glfw.WindowHint(glfw.ContextVersionMinor, 6) glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile) glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True) window, err := glfw.CreateWindow(WIDTH, HEIGHT, TITLE, nil, nil) if err != nil { panic(err) } window.MakeContextCurrent() // init gl if err := gl.Init(); err != nil { panic(err) } gl.Enable(gl.DEPTH_TEST) gl.Enable(gl.CULL_FACE) gl.DepthFunc(gl.LESS) gl.ClearColor(0, 0, 0, 0) fmt.Println("OpenGL version:", gl.GoStr(gl.GetString(gl.VERSION))) // load assets // shader vertexSource, err := os.ReadFile("assets/shader/deferred/deferred.vs") 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) screen, err := geometry.Screen() if err != nil { panic(err) } 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}, {Color: [3]float32{1, 0, 0}, Position: mgl32.Vec3{5, 5, 5}, Intensity: 30, Type: light.POINT}, {Color: [3]float32{0, 0, 1}, Position: mgl32.Vec3{-5, 5, -5}, Intensity: 30, Type: light.POINT}, } // gbuffer gbuff, err := gbuffer.New(WIDTH, HEIGHT) if err != nil { panic(err) } defer gbuff.Delete() gbuff.Bind() // 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) for !window.ShouldClose() { glfw.PollEvents() controls.Update() // first pass gl.Enable(gl.DEPTH_TEST) gbuff.Bind() 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) // 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 gl.Disable(gl.DEPTH_TEST) gl.BindFramebuffer(gl.FRAMEBUFFER, 0) gl.Clear(gl.COLOR_BUFFER_BIT) 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) pos := controls.Position() screenShader.Vec3("view_pos", &pos[0]) for _, light := range lights { screenShader.Light(&light) } screen.Draw() window.SwapBuffers() } defer fmt.Println("exiting...") }