Fix license.

Fix lighting.

Start bounding box, not working yet.
main
Sean Hickey 2021-11-21 23:36:51 -08:00
parent 26ae65e90b
commit 897ea4222c
13 changed files with 193 additions and 63 deletions

View File

@ -21,6 +21,11 @@ to my fragment shader. I had learned the Phong shading model at
university, but this showed me how to actually apply it with OpenGL university, but this showed me how to actually apply it with OpenGL
shaders. shaders.
[The OpenGL SuperBible][7] is a book that I've had for over a
decade. After finally wrapping my head around shaders from
LearnOpenGL.com, I went back to this book and reworked a lot of the
lighting models to get them into a much more understandable state.
[1]: https://open.gl/introduction [1]: https://open.gl/introduction
[2]: https://learnopengl.com/Lighting/Basic-Lighting [2]: https://learnopengl.com/Lighting/Basic-Lighting
@ -28,3 +33,4 @@ shaders.
[4]: https://github.com/veandco/go-sdl2 [4]: https://github.com/veandco/go-sdl2
[5]: https://github.com/veandco/go-sdl2-examples [5]: https://github.com/veandco/go-sdl2-examples
[6]: https://github.com/go-gl/example [6]: https://github.com/go-gl/example
[7]: https://www.opengl.org/sdk/docs/books/SuperBible/

View File

@ -1,4 +1,4 @@
all: build all: release
dependencies: dependencies:
go mod tidy go mod tidy
@ -10,4 +10,15 @@ release: dependencies
go build -x -v -ldflags "-s -w" go build -x -v -ldflags "-s -w"
cross_windows: cross_windows:
./build_cross_windows.sh export CGO_ENABLED=1
export CC=x86_64-w64-mingw32-gcc
export GOOS=windows
export GOARCH=amd64
go build -x -v -ldflags "-s -w"
cross_windows_x86:
export CGO_ENABLED=1
export CC=i686-w64-mingw32-gcc
export GOOS=windows
export GOARCH=386
go build -x -v -ldflags "-s -w"

View File

@ -8,13 +8,13 @@ and OpenGL stuff. It ended up being a bit nicer than I expected.
## License/Copyright ## License/Copyright
This project is licensed under the [ISC License][1], a permissive open This project is licensed under the [2-Clause BSD License][1], a
source license. Essentially you can use this code for any purpose so permissive open source license. Essentially you can use this code for
long as you acknowledge me for creating it. You can find the full text any purpose so long as you acknowledge me for creating it. You can
in `License.md`. find the full text in `License.md`.
Another file called `Attribution.md` contains links to the other Another file called `Attribution.md` contains links to the other
projects used to build this one. projects used to build this one.
[1]: https://opensource.org/licenses/ISC [1]: https://opensource.org/licenses/BSD-2-Clause

View File

@ -1,11 +1,11 @@
#!/usr/bin/env sh #!/usr/bin/env sh
export CGO_ENABLED=1 export CGO_ENABLED=1
export CC=i686-w64-mingw32-gcc #export CC=i686-w64-mingw32-gcc
#export CC=x86_64-w64-mingw32-gcc export CC=x86_64-w64-mingw32-gcc
#export CXX=x86_64-w64-mingw32-g++
export GOOS=windows export GOOS=windows
export GOARCH=386 #export GOARCH=386
export GOARCH=amd64
#export CGO_LDFLAGS="-lmingw32 -lSDL2 -lSDL2main" #export CGO_LDFLAGS="-lmingw32 -lSDL2 -lSDL2main"
#export CGO_CFLAGS="-I/usr/x86_64-w64-mingw32/include -D_REENTRANT" #export CGO_CFLAGS="-I/usr/x86_64-w64-mingw32/include -D_REENTRANT"

2
go.mod
View File

@ -3,7 +3,7 @@ module gitea.wisellama.rocks/Wisellama/carpy-breakout
go 1.17 go 1.17
require ( require (
github.com/go-gl/gl v0.0.0-20210813123233-e4099ee2221f github.com/go-gl/gl v0.0.0-20211025173605-bda47ffaa784
github.com/go-gl/mathgl v1.0.0 github.com/go-gl/mathgl v1.0.0
github.com/veandco/go-sdl2 v0.4.10 github.com/veandco/go-sdl2 v0.4.10
) )

4
go.sum
View File

@ -1,5 +1,5 @@
github.com/go-gl/gl v0.0.0-20210813123233-e4099ee2221f h1:s0O46d8fPwk9kU4k1jj76wBquMVETx7uveQD9MCIQoU= github.com/go-gl/gl v0.0.0-20211025173605-bda47ffaa784 h1:1Zi56D0LNfvkzM+BdoxKryvUEdyWO7LP8oRT+oSYJW0=
github.com/go-gl/gl v0.0.0-20210813123233-e4099ee2221f/go.mod h1:wjpnOv6ONl2SuJSxqCPVaPZibGFdSci9HFocT9qtVYM= github.com/go-gl/gl v0.0.0-20211025173605-bda47ffaa784/go.mod h1:9YTyiznxEY1fVinfM7RvRcjRHbw2xLBJ3AAGIT0I4Nw=
github.com/go-gl/mathgl v1.0.0 h1:t9DznWJlXxxjeeKLIdovCOVJQk/GzDEL7h/h+Ro2B68= github.com/go-gl/mathgl v1.0.0 h1:t9DznWJlXxxjeeKLIdovCOVJQk/GzDEL7h/h+Ro2B68=
github.com/go-gl/mathgl v1.0.0/go.mod h1:yhpkQzEiH9yPyxDUGzkmgScbaBVlhC06qodikEM0ZwQ= github.com/go-gl/mathgl v1.0.0/go.mod h1:yhpkQzEiH9yPyxDUGzkmgScbaBVlhC06qodikEM0ZwQ=
github.com/veandco/go-sdl2 v0.4.10 h1:8QoD2bhWl7SbQDflIAUYWfl9Vq+mT8/boJFAUzAScgY= github.com/veandco/go-sdl2 v0.4.10 h1:8QoD2bhWl7SbQDflIAUYWfl9Vq+mT8/boJFAUzAScgY=

77
main.go
View File

@ -17,8 +17,6 @@ import (
) )
var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file") var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
var openglMode = flag.Bool("opengl", true, "Draw game using OpenGL rendering")
var sdlMode = flag.Bool("sdl", false, "Draw game using SDL rendering")
const GameTitle = "Carpy Breakout" const GameTitle = "Carpy Breakout"
const LogFile = "output.log" const LogFile = "output.log"
@ -44,11 +42,7 @@ func main() {
// goroutine. // goroutine.
runtime.LockOSThread() runtime.LockOSThread()
if *sdlMode { runOpenGL()
runSDL()
} else if *openglMode {
runOpenGL()
}
} }
func runOpenGL() { func runOpenGL() {
@ -59,18 +53,7 @@ func runOpenGL() {
} }
defer sdl.Quit() defer sdl.Quit()
// Disable the Linux compositor flicker. sdlSettings()
// https://github.com/mosra/magnum/issues/184#issuecomment-425952900
sdl.SetHint(sdl.HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0")
sdl.DisableScreenSaver()
// Capture the mouse for movement
sdl.SetRelativeMouseMode(true)
// Init and configure global settings
gl.Init()
sdl.GLSetAttribute(sdl.GL_MULTISAMPLESAMPLES, 2) // Smooth
gameWindow, err := game_window.NewGameWindow(GameTitle) gameWindow, err := game_window.NewGameWindow(GameTitle)
if err != nil { if err != nil {
@ -78,6 +61,20 @@ func runOpenGL() {
} }
defer gameWindow.Destroy() defer gameWindow.Destroy()
// GL Init requires an active OpenGL context (e.g. the game window)
err = gl.Init()
if err != nil {
log.Fatalf("Failed to initialize OpenGL: %v", err)
}
glVersion := gl.GetString(gl.VERSION)
if glVersion == nil {
log.Printf("Error getting OpenGL version.\n")
}
log.Printf("OpenGL Version: %v\n", gl.GoStr(glVersion))
// Then we can setup the OpenGL specific stuff in the game window
gameWindow.GLInit()
sunLight := gl_objects.NewPointLight(mgl32.Vec3{-10, 10, 30}) sunLight := gl_objects.NewPointLight(mgl32.Vec3{-10, 10, 30})
sunLight.GLInit(gameWindow.GLProgram) sunLight.GLInit(gameWindow.GLProgram)
@ -91,19 +88,22 @@ func runOpenGL() {
// log.Fatal(err) // log.Fatal(err)
// } // }
// TODO bounding box
// Brick Targets // Brick Targets
targets := breakout.NewTargets(4, 5, mgl32.Vec3{0, 6, 0}) targets := breakout.NewTargets(4, 5, mgl32.Vec3{0, 6, 0})
targets.GLInit(gameWindow.GLProgram) targets.GLInit(gameWindow.GLProgram)
for _, brick := range targets.Bricks { for _, brick := range targets.Bricks {
gameWindow.AddObject(brick) gameWindow.AddObject(brick)
} }
positiveBoundary := mgl32.Vec3{8, 16, 0} positiveBoundary := targets.TopRight
negativeBoundary := mgl32.Vec3{-8, -16, 0} negativeBoundary := positiveBoundary.Mul(-1)
gameWindow.PositiveBoundary = positiveBoundary gameWindow.PositiveBoundary = positiveBoundary
gameWindow.NegativeBoundary = negativeBoundary gameWindow.NegativeBoundary = negativeBoundary
// Bounding Box
boundingBoxMaterial := gl_objects.NewMaterial()
boundingBoxMaterial.Color = mgl32.Vec4{0.3, 0.3, 0.3, 1}
boundingBox := breakout.NewBoundingBox(negativeBoundary, positiveBoundary, boundingBoxMaterial)
// Paddle // Paddle
paddleMaterial := gl_objects.NewMaterial() paddleMaterial := gl_objects.NewMaterial()
paddleMaterial.Color = mgl32.Vec4{0, 1, 0, 1} paddleMaterial.Color = mgl32.Vec4{0, 1, 0, 1}
@ -119,12 +119,7 @@ func runOpenGL() {
ball.GLInit(gameWindow.GLProgram) ball.GLInit(gameWindow.GLProgram)
gameWindow.AddObject(ball) gameWindow.AddObject(ball)
// Global options after setup is all done glSettings()
gl.ClearColor(0.0, 0.0, 0.0, 1.0)
gl.Enable(gl.DEPTH_TEST)
gl.DepthFunc(gl.LESS)
gl.LineWidth(2.0)
for gameWindow.IsRunning() { for gameWindow.IsRunning() {
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
@ -148,7 +143,25 @@ func setupLogging() {
log.Println("=== START ===") log.Println("=== START ===")
} }
func runSDL() { func glSettings() {
// I really need to think through how to separate the physical objects from how they are drawn. // Global options after setup is all done
log.Println("TODO runSDL()") gl.ClearColor(0.0, 0.0, 0.0, 1.0)
gl.Enable(gl.DEPTH_TEST)
gl.DepthFunc(gl.LESS)
gl.LineWidth(2.0)
}
func sdlSettings() {
// Smooth
sdl.GLSetAttribute(sdl.GL_MULTISAMPLEBUFFERS, 1)
sdl.GLSetAttribute(sdl.GL_MULTISAMPLESAMPLES, 4)
// Disable the Linux compositor flicker.
// https://github.com/mosra/magnum/issues/184#issuecomment-425952900
sdl.SetHint(sdl.HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0")
sdl.DisableScreenSaver()
// Capture the mouse for movement
sdl.SetRelativeMouseMode(true)
} }

View File

@ -0,0 +1,80 @@
package breakout
import (
"github.com/go-gl/mathgl/mgl32"
"gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/gl_objects"
)
type BoundingBox struct {
Boxes []*gl_objects.Box
}
func NewBoundingBox(lowerLeft, topRight mgl32.Vec3, material gl_objects.Material) *BoundingBox {
var brickWidth float32 = 4.0
var brickHeight float32 = 1.0
var brickDepth float32 = 4.0
var widthOffset float32 = 0.5
var heightOffset float32 = 1
bw := brickWidth + widthOffset
bh := brickHeight + heightOffset
lowerLeftPos := mgl32.Vec3{
bw/2 - float32(numColumns)*(bw)/2,
bh/2 - float32(numRows)*(bh)/2,
0,
}
lowerLeftPos = lowerLeftPos.Add(adjustPos)
topRightPos := mgl32.Vec3{
bw/2 + float32(numColumns)*(bw)/2,
bh/2 + float32(numRows)*(bh)/2,
0,
}
topRightPos = topRightPos.Add(adjustPos)
targets.TopRight = topRightPos
targets.LowerLeft = lowerLeftPos
materials := make([]*gl_objects.Material, numColumns)
for i := 0; i < numColumns; i++ {
red := 0 + float32(i)/float32(numColumns)
blue := 1 - float32(i)/float32(numColumns)
m := gl_objects.NewMaterial()
m.Color = mgl32.Vec4{red, 0, blue, 1}
materials[i] = m
}
n := 0
for i := 0; i < numRows; i++ {
for j := 0; j < numColumns; j++ {
position := lowerLeftPos.Add(mgl32.Vec3{
float32(j) * bw,
float32(i) * bh,
0})
targets.Bricks[n] = NewBrick(brickWidth, brickHeight, brickDepth, position, materials[i])
n++
}
}
boundingBox := BoundingBox{
Boxes: boxes,
}
return &boundingBox
}
func (t *BoundingBox) GLInit(glProgram uint32) {
for _, brick := range t.Bricks {
brick.GLInit(glProgram)
}
}
func (t *BoundingBox) GLDraw() {
for _, brick := range t.Bricks {
brick.GLDraw()
}
}

View File

@ -7,9 +7,11 @@ import (
) )
type Targets struct { type Targets struct {
Rows int Rows int
Columns int Columns int
Bricks []*Brick Bricks []*Brick
TopRight mgl32.Vec3
LowerLeft mgl32.Vec3
} }
func NewTargets(numRows, numColumns int, adjustPos mgl32.Vec3) *Targets { func NewTargets(numRows, numColumns int, adjustPos mgl32.Vec3) *Targets {
@ -36,6 +38,16 @@ func NewTargets(numRows, numColumns int, adjustPos mgl32.Vec3) *Targets {
} }
lowerLeftPos = lowerLeftPos.Add(adjustPos) lowerLeftPos = lowerLeftPos.Add(adjustPos)
topRightPos := mgl32.Vec3{
bw/2 + float32(numColumns)*(bw)/2,
bh/2 + float32(numRows)*(bh)/2,
0,
}
topRightPos = topRightPos.Add(adjustPos)
targets.TopRight = topRightPos
targets.LowerLeft = lowerLeftPos
materials := make([]*gl_objects.Material, numColumns) materials := make([]*gl_objects.Material, numColumns)
for i := 0; i < numColumns; i++ { for i := 0; i < numColumns; i++ {

View File

@ -52,6 +52,7 @@ func NewGameWindow(title string) (*GameWindow, error) {
log.Println("Failed creating SDL window") log.Println("Failed creating SDL window")
return nil, err return nil, err
} }
gameWindow.SDLWindow = window
context, err := window.GLCreateContext() context, err := window.GLCreateContext()
if err != nil { if err != nil {
@ -60,18 +61,20 @@ func NewGameWindow(title string) (*GameWindow, error) {
} }
gameWindow.GLContext = &context gameWindow.GLContext = &context
return &gameWindow, err
}
func (w *GameWindow) GLInit() error {
program, err := gl_helpers.NewDefaultProgram() program, err := gl_helpers.NewDefaultProgram()
if err != nil { if err != nil {
panic(err) return err
} }
gl.UseProgram(program) gl.UseProgram(program)
gameWindow.SDLWindow = window w.GLProgram = program
gameWindow.GLProgram = program
gameWindow.WindowProjection() w.WindowProjection()
return nil
return &gameWindow, err
} }
func (w *GameWindow) AddObject(object gl_objects.GLObject) { func (w *GameWindow) AddObject(object gl_objects.GLObject) {

View File

@ -23,16 +23,22 @@ func NewProgram(vertexShaderSource string, fragmentShaderSource string) (uint32,
if err != nil { if err != nil {
return 0, err return 0, err
} }
defer gl.DeleteShader(vertexShader)
fragmentShader, err := compileShader(fragmentShaderSource, gl.FRAGMENT_SHADER) fragmentShader, err := compileShader(fragmentShaderSource, gl.FRAGMENT_SHADER)
if err != nil { if err != nil {
return 0, err return 0, err
} }
defer gl.DeleteShader(fragmentShader)
program := gl.CreateProgram() program := gl.CreateProgram()
gl.AttachShader(program, vertexShader) gl.AttachShader(program, vertexShader)
defer gl.DetachShader(program, vertexShader)
gl.AttachShader(program, fragmentShader) gl.AttachShader(program, fragmentShader)
defer gl.DetachShader(program, fragmentShader)
gl.LinkProgram(program) gl.LinkProgram(program)
var status int32 var status int32
@ -47,19 +53,20 @@ func NewProgram(vertexShaderSource string, fragmentShaderSource string) (uint32,
return 0, fmt.Errorf("failed to link program: %v", log) return 0, fmt.Errorf("failed to link program: %v", log)
} }
gl.DeleteShader(vertexShader)
gl.DeleteShader(fragmentShader)
return program, nil return program, nil
} }
func compileShader(source string, shaderType uint32) (uint32, error) { func compileShader(source string, shaderType uint32) (uint32, error) {
shader := gl.CreateShader(shaderType) shader := gl.CreateShader(shaderType)
if shader == 0 {
return 0, fmt.Errorf("Error creating shader - type: %v", shaderType)
}
sourceWithZero := source + "\x00" sourceWithZero := source + "\x00"
csources, free := gl.Strs(sourceWithZero) csources, free := gl.Strs(sourceWithZero)
defer free()
gl.ShaderSource(shader, 1, csources, nil) gl.ShaderSource(shader, 1, csources, nil)
free()
gl.CompileShader(shader) gl.CompileShader(shader)
var status int32 var status int32

View File

@ -30,7 +30,6 @@ func NewFace(
center, center,
normal, normal,
mgl32.Vec2{0, 1}) mgl32.Vec2{0, 1})
v1_2 := *v1
// bottom left // bottom left
v2 := newFaceVertex( v2 := newFaceVertex(
@ -47,7 +46,6 @@ func NewFace(
center, center,
normal, normal,
mgl32.Vec2{1, 0}) mgl32.Vec2{1, 0})
v3_2 := *v3
// top right // top right
v4 := newFaceVertex( v4 := newFaceVertex(
@ -58,7 +56,7 @@ func NewFace(
mgl32.Vec2{1, 1}) mgl32.Vec2{1, 1})
t1 := NewTriangle(v1, v2, v3) t1 := NewTriangle(v1, v2, v3)
t2 := NewTriangle(&v3_2, v4, &v1_2) t2 := NewTriangle(v3, v4, v1)
face := Face{ face := Face{
Material: material, Material: material,

View File

@ -17,7 +17,7 @@ type PointLight struct {
func NewPointLight(position mgl32.Vec3) *PointLight { func NewPointLight(position mgl32.Vec3) *PointLight {
d := PointLight{ d := PointLight{
Position: position, Position: position,
AmbientColor: mgl32.Vec4{0.1, 0.1, 0.1, 1}, AmbientColor: mgl32.Vec4{0.2, 0.2, 0.2, 1},
DiffuseColor: mgl32.Vec4{1, 1, 1, 1}, DiffuseColor: mgl32.Vec4{1, 1, 1, 1},
SpecularColor: mgl32.Vec4{1, 1, 1, 1}, SpecularColor: mgl32.Vec4{1, 1, 1, 1},
} }