parent
26ae65e90b
commit
897ea4222c
|
@ -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
|
||||
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
|
||||
[2]: https://learnopengl.com/Lighting/Basic-Lighting
|
||||
|
@ -28,3 +33,4 @@ shaders.
|
|||
[4]: https://github.com/veandco/go-sdl2
|
||||
[5]: https://github.com/veandco/go-sdl2-examples
|
||||
[6]: https://github.com/go-gl/example
|
||||
[7]: https://www.opengl.org/sdk/docs/books/SuperBible/
|
||||
|
|
15
Makefile
15
Makefile
|
@ -1,4 +1,4 @@
|
|||
all: build
|
||||
all: release
|
||||
|
||||
dependencies:
|
||||
go mod tidy
|
||||
|
@ -10,4 +10,15 @@ release: dependencies
|
|||
go build -x -v -ldflags "-s -w"
|
||||
|
||||
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"
|
||||
|
|
10
Readme.md
10
Readme.md
|
@ -8,13 +8,13 @@ and OpenGL stuff. It ended up being a bit nicer than I expected.
|
|||
|
||||
## License/Copyright
|
||||
|
||||
This project is licensed under the [ISC License][1], a permissive open
|
||||
source license. Essentially you can use this code for any purpose so
|
||||
long as you acknowledge me for creating it. You can find the full text
|
||||
in `License.md`.
|
||||
This project is licensed under the [2-Clause BSD License][1], a
|
||||
permissive open source license. Essentially you can use this code for
|
||||
any purpose so long as you acknowledge me for creating it. You can
|
||||
find the full text in `License.md`.
|
||||
|
||||
Another file called `Attribution.md` contains links to the other
|
||||
projects used to build this one.
|
||||
|
||||
|
||||
[1]: https://opensource.org/licenses/ISC
|
||||
[1]: https://opensource.org/licenses/BSD-2-Clause
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
export CGO_ENABLED=1
|
||||
export CC=i686-w64-mingw32-gcc
|
||||
#export CC=x86_64-w64-mingw32-gcc
|
||||
#export CXX=x86_64-w64-mingw32-g++
|
||||
#export CC=i686-w64-mingw32-gcc
|
||||
export CC=x86_64-w64-mingw32-gcc
|
||||
export GOOS=windows
|
||||
export GOARCH=386
|
||||
#export GOARCH=386
|
||||
export GOARCH=amd64
|
||||
#export CGO_LDFLAGS="-lmingw32 -lSDL2 -lSDL2main"
|
||||
#export CGO_CFLAGS="-I/usr/x86_64-w64-mingw32/include -D_REENTRANT"
|
||||
|
||||
|
|
2
go.mod
2
go.mod
|
@ -3,7 +3,7 @@ module gitea.wisellama.rocks/Wisellama/carpy-breakout
|
|||
go 1.17
|
||||
|
||||
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/veandco/go-sdl2 v0.4.10
|
||||
)
|
||||
|
|
4
go.sum
4
go.sum
|
@ -1,5 +1,5 @@
|
|||
github.com/go-gl/gl v0.0.0-20210813123233-e4099ee2221f h1:s0O46d8fPwk9kU4k1jj76wBquMVETx7uveQD9MCIQoU=
|
||||
github.com/go-gl/gl v0.0.0-20210813123233-e4099ee2221f/go.mod h1:wjpnOv6ONl2SuJSxqCPVaPZibGFdSci9HFocT9qtVYM=
|
||||
github.com/go-gl/gl v0.0.0-20211025173605-bda47ffaa784 h1:1Zi56D0LNfvkzM+BdoxKryvUEdyWO7LP8oRT+oSYJW0=
|
||||
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/go.mod h1:yhpkQzEiH9yPyxDUGzkmgScbaBVlhC06qodikEM0ZwQ=
|
||||
github.com/veandco/go-sdl2 v0.4.10 h1:8QoD2bhWl7SbQDflIAUYWfl9Vq+mT8/boJFAUzAScgY=
|
||||
|
|
77
main.go
77
main.go
|
@ -17,8 +17,6 @@ import (
|
|||
)
|
||||
|
||||
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 LogFile = "output.log"
|
||||
|
@ -44,11 +42,7 @@ func main() {
|
|||
// goroutine.
|
||||
runtime.LockOSThread()
|
||||
|
||||
if *sdlMode {
|
||||
runSDL()
|
||||
} else if *openglMode {
|
||||
runOpenGL()
|
||||
}
|
||||
runOpenGL()
|
||||
}
|
||||
|
||||
func runOpenGL() {
|
||||
|
@ -59,18 +53,7 @@ func runOpenGL() {
|
|||
}
|
||||
defer sdl.Quit()
|
||||
|
||||
// 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)
|
||||
|
||||
// Init and configure global settings
|
||||
gl.Init()
|
||||
sdl.GLSetAttribute(sdl.GL_MULTISAMPLESAMPLES, 2) // Smooth
|
||||
sdlSettings()
|
||||
|
||||
gameWindow, err := game_window.NewGameWindow(GameTitle)
|
||||
if err != nil {
|
||||
|
@ -78,6 +61,20 @@ func runOpenGL() {
|
|||
}
|
||||
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.GLInit(gameWindow.GLProgram)
|
||||
|
||||
|
@ -91,19 +88,22 @@ func runOpenGL() {
|
|||
// log.Fatal(err)
|
||||
// }
|
||||
|
||||
// TODO bounding box
|
||||
|
||||
// Brick Targets
|
||||
targets := breakout.NewTargets(4, 5, mgl32.Vec3{0, 6, 0})
|
||||
targets.GLInit(gameWindow.GLProgram)
|
||||
for _, brick := range targets.Bricks {
|
||||
gameWindow.AddObject(brick)
|
||||
}
|
||||
positiveBoundary := mgl32.Vec3{8, 16, 0}
|
||||
negativeBoundary := mgl32.Vec3{-8, -16, 0}
|
||||
positiveBoundary := targets.TopRight
|
||||
negativeBoundary := positiveBoundary.Mul(-1)
|
||||
gameWindow.PositiveBoundary = positiveBoundary
|
||||
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
|
||||
paddleMaterial := gl_objects.NewMaterial()
|
||||
paddleMaterial.Color = mgl32.Vec4{0, 1, 0, 1}
|
||||
|
@ -119,12 +119,7 @@ func runOpenGL() {
|
|||
ball.GLInit(gameWindow.GLProgram)
|
||||
gameWindow.AddObject(ball)
|
||||
|
||||
// Global options after setup is all done
|
||||
gl.ClearColor(0.0, 0.0, 0.0, 1.0)
|
||||
gl.Enable(gl.DEPTH_TEST)
|
||||
gl.DepthFunc(gl.LESS)
|
||||
gl.LineWidth(2.0)
|
||||
|
||||
glSettings()
|
||||
for gameWindow.IsRunning() {
|
||||
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
|
||||
|
||||
|
@ -148,7 +143,25 @@ func setupLogging() {
|
|||
log.Println("=== START ===")
|
||||
}
|
||||
|
||||
func runSDL() {
|
||||
// I really need to think through how to separate the physical objects from how they are drawn.
|
||||
log.Println("TODO runSDL()")
|
||||
func glSettings() {
|
||||
// Global options after setup is all done
|
||||
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)
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
|
@ -7,9 +7,11 @@ import (
|
|||
)
|
||||
|
||||
type Targets struct {
|
||||
Rows int
|
||||
Columns int
|
||||
Bricks []*Brick
|
||||
Rows int
|
||||
Columns int
|
||||
Bricks []*Brick
|
||||
TopRight mgl32.Vec3
|
||||
LowerLeft mgl32.Vec3
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
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++ {
|
||||
|
|
|
@ -52,6 +52,7 @@ func NewGameWindow(title string) (*GameWindow, error) {
|
|||
log.Println("Failed creating SDL window")
|
||||
return nil, err
|
||||
}
|
||||
gameWindow.SDLWindow = window
|
||||
|
||||
context, err := window.GLCreateContext()
|
||||
if err != nil {
|
||||
|
@ -60,18 +61,20 @@ func NewGameWindow(title string) (*GameWindow, error) {
|
|||
}
|
||||
gameWindow.GLContext = &context
|
||||
|
||||
return &gameWindow, err
|
||||
}
|
||||
|
||||
func (w *GameWindow) GLInit() error {
|
||||
program, err := gl_helpers.NewDefaultProgram()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return err
|
||||
}
|
||||
gl.UseProgram(program)
|
||||
|
||||
gameWindow.SDLWindow = window
|
||||
gameWindow.GLProgram = program
|
||||
w.GLProgram = program
|
||||
|
||||
gameWindow.WindowProjection()
|
||||
|
||||
return &gameWindow, err
|
||||
w.WindowProjection()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *GameWindow) AddObject(object gl_objects.GLObject) {
|
||||
|
|
|
@ -23,16 +23,22 @@ func NewProgram(vertexShaderSource string, fragmentShaderSource string) (uint32,
|
|||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer gl.DeleteShader(vertexShader)
|
||||
|
||||
fragmentShader, err := compileShader(fragmentShaderSource, gl.FRAGMENT_SHADER)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer gl.DeleteShader(fragmentShader)
|
||||
|
||||
program := gl.CreateProgram()
|
||||
|
||||
gl.AttachShader(program, vertexShader)
|
||||
defer gl.DetachShader(program, vertexShader)
|
||||
|
||||
gl.AttachShader(program, fragmentShader)
|
||||
defer gl.DetachShader(program, fragmentShader)
|
||||
|
||||
gl.LinkProgram(program)
|
||||
|
||||
var status int32
|
||||
|
@ -47,19 +53,20 @@ func NewProgram(vertexShaderSource string, fragmentShaderSource string) (uint32,
|
|||
return 0, fmt.Errorf("failed to link program: %v", log)
|
||||
}
|
||||
|
||||
gl.DeleteShader(vertexShader)
|
||||
gl.DeleteShader(fragmentShader)
|
||||
|
||||
return program, nil
|
||||
}
|
||||
|
||||
func compileShader(source string, shaderType uint32) (uint32, error) {
|
||||
shader := gl.CreateShader(shaderType)
|
||||
if shader == 0 {
|
||||
return 0, fmt.Errorf("Error creating shader - type: %v", shaderType)
|
||||
}
|
||||
|
||||
sourceWithZero := source + "\x00"
|
||||
csources, free := gl.Strs(sourceWithZero)
|
||||
defer free()
|
||||
|
||||
gl.ShaderSource(shader, 1, csources, nil)
|
||||
free()
|
||||
gl.CompileShader(shader)
|
||||
|
||||
var status int32
|
||||
|
|
|
@ -30,7 +30,6 @@ func NewFace(
|
|||
center,
|
||||
normal,
|
||||
mgl32.Vec2{0, 1})
|
||||
v1_2 := *v1
|
||||
|
||||
// bottom left
|
||||
v2 := newFaceVertex(
|
||||
|
@ -47,7 +46,6 @@ func NewFace(
|
|||
center,
|
||||
normal,
|
||||
mgl32.Vec2{1, 0})
|
||||
v3_2 := *v3
|
||||
|
||||
// top right
|
||||
v4 := newFaceVertex(
|
||||
|
@ -58,7 +56,7 @@ func NewFace(
|
|||
mgl32.Vec2{1, 1})
|
||||
|
||||
t1 := NewTriangle(v1, v2, v3)
|
||||
t2 := NewTriangle(&v3_2, v4, &v1_2)
|
||||
t2 := NewTriangle(v3, v4, v1)
|
||||
|
||||
face := Face{
|
||||
Material: material,
|
||||
|
|
|
@ -17,7 +17,7 @@ type PointLight struct {
|
|||
func NewPointLight(position mgl32.Vec3) *PointLight {
|
||||
d := PointLight{
|
||||
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},
|
||||
SpecularColor: mgl32.Vec4{1, 1, 1, 1},
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue