之前使用的是SDL,仅支持2D的,从这里开始换成GLFW以支持后续的3D操作,删除之前的所有内容,新建g3d文件夹,如下图:
main.go:
package main
import (
engine "g3d/engine/game"
"runtime"
)
func init() {
runtime.LockOSThread()
}
func main() {
var game engine.Game
if game.Initialize() {
game.RunLoop()
}
game.Shutdown()
}
game.go:
package engine
import (
"fmt"
"image"
"os"
"github.com/go-gl/gl/v3.3-core/gl"
"github.com/go-gl/glfw/v3.3/glfw"
"github.com/mat/besticon/ico"
)
var mIsRunning = false
var mIsFullScreen = false
var mWidth = 1024
var mHeight = 768
type Game struct {
MWindow *glfw.Window
}
//初始化引擎
func (g *Game) Initialize() bool {
//获取glfw版本
fmt.Println(glfw.GetVersionString())
//初始化glfw
var err error
if err = glfw.Init(); err != nil {
fmt.Printf("Unable to initialize glfw: %v", err)
return false
}
glfw.WindowHint(glfw.RedBits, 8)
glfw.WindowHint(glfw.GreenBits, 8)
glfw.WindowHint(glfw.BlueBits, 8)
glfw.WindowHint(glfw.AlphaBits, 8)
glfw.WindowHint(glfw.DepthBits, 24)
glfw.WindowHint(glfw.DoubleBuffer, 1)
//设置版本
glfw.WindowHint(glfw.ContextVersionMajor, 3)
glfw.WindowHint(glfw.ContextVersionMinor, 3)
glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
//窗口模式
if g.MWindow, err = glfw.CreateWindow(mWidth, mHeight, "go glfw", nil, nil); err != nil {
fmt.Printf("Failed to create window: %v", err)
return false
}
//设置图标
if ok, _ := PathExists("./app.ico"); ok {
if f, err := os.Open("./app.ico"); err == nil {
defer f.Close()
if img, err := ico.Decode(f); err == nil {
g.MWindow.SetIcon([]image.Image{img})
}
}
}
//回调函数
g.MWindow.SetCloseCallback(CloseCallback) //关闭回调
g.MWindow.SetSizeCallback(SizeCallback) //调整回调
g.MWindow.SetKeyCallback(KeyCallback) //按键回调
g.MWindow.SetMouseButtonCallback(MouseButtonCallback) //鼠标按键
g.MWindow.SetCursorPosCallback(CursorPosCallback) //鼠标位置
g.MWindow.SetCursorEnterCallback(CursorEnterCallback) //鼠标进入
g.MWindow.SetScrollCallback(ScrollCallback) //鼠标滚动
//上下文
g.MWindow.MakeContextCurrent()
//初始化opengl
if err = gl.Init(); err != nil {
fmt.Printf("Unable to initialize gl: %v", err)
return false
}
version := gl.GoStr(gl.GetString(gl.VERSION))
fmt.Println(version)
//保持运行
mIsRunning = true
return true
}
//引擎循环
func (g *Game) RunLoop() {
for mIsRunning {
//清屏
gl.ClearColor(0.86, 0.86, 0.86, 1.0)
gl.Clear(gl.COLOR_BUFFER_BIT)
//....
g.ProcessInput()
g.UpdateGame()
g.GenerateOutput()
//交换缓存
g.MWindow.SwapBuffers()
glfw.PollEvents()
}
}
//引擎销毁
func (g *Game) Shutdown() {
g.MWindow.Destroy()
glfw.Terminate()
}
func (g *Game) ProcessInput() {
}
func (g *Game) UpdateGame() {
}
func (g *Game) GenerateOutput() {
}
func CloseCallback(w *glfw.Window) {
mIsRunning = false
}
func SizeCallback(w *glfw.Window, width int, height int) {
fmt.Println(width, height)
}
func KeyCallback(w *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {
switch key {
case glfw.KeyEscape:
if action == glfw.Press {
CloseCallback(w)
}
case glfw.KeyF11:
if action == glfw.Press {
mIsFullScreen = !mIsFullScreen
if mIsFullScreen {
w.SetMonitor(glfw.GetPrimaryMonitor(),
0,
0,
glfw.GetPrimaryMonitor().GetVideoMode().Width,
glfw.GetPrimaryMonitor().GetVideoMode().Height,
60)
} else {
posX := (glfw.GetPrimaryMonitor().GetVideoMode().Width - mWidth) / 2
posY := (glfw.GetPrimaryMonitor().GetVideoMode().Height - mHeight) / 2
w.SetMonitor(nil, posX, posY, mWidth, mHeight, 60)
}
}
}
}
func MouseButtonCallback(w *glfw.Window, button glfw.MouseButton, action glfw.Action, mods glfw.ModifierKey) {
fmt.Println(button, action)
}
func CursorPosCallback(w *glfw.Window, xpos float64, ypos float64) {
fmt.Println(xpos, ypos)
}
func CursorEnterCallback(w *glfw.Window, entered bool) {
fmt.Println(entered)
}
func ScrollCallback(w *glfw.Window, xoff float64, yoff float64) {
fmt.Println(xoff, yoff)
}
func PathExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}