mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 10:48:53 +01:00
Add examples/glut/main.go
This commit is contained in:
parent
b8a1a1806c
commit
e9fa26142e
73
examples/glut/main.go
Normal file
73
examples/glut/main.go
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
// #cgo LDFLAGS: -framework GLUT -framework OpenGL
|
||||||
|
//
|
||||||
|
// #include <stdlib.h>
|
||||||
|
// #include <GLUT/glut.h>
|
||||||
|
//
|
||||||
|
// void display(void);
|
||||||
|
//
|
||||||
|
// static void setDisplayFunc(void) {
|
||||||
|
// glutDisplayFunc(display);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
import "C"
|
||||||
|
import (
|
||||||
|
"image/color"
|
||||||
|
"os"
|
||||||
|
"unsafe"
|
||||||
|
"github.com/hajimehoshi/go-ebiten/graphics"
|
||||||
|
)
|
||||||
|
|
||||||
|
var device *graphics.Device
|
||||||
|
|
||||||
|
type DemoGame struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (game *DemoGame) Update() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (game *DemoGame) Draw(g *graphics.GraphicsContext, offscreen *graphics.Texture) {
|
||||||
|
g.Fill(&color.RGBA{R: 0, G: 0, B: 255, A: 255})
|
||||||
|
}
|
||||||
|
|
||||||
|
//export display
|
||||||
|
func display() {
|
||||||
|
device.Update()
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
cargs := []*C.char{}
|
||||||
|
for _, arg := range os.Args {
|
||||||
|
cargs = append(cargs, C.CString(arg))
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
for _, carg := range cargs {
|
||||||
|
C.free(unsafe.Pointer(carg))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
cargc := C.int(len(cargs))
|
||||||
|
|
||||||
|
screenWidth := 256
|
||||||
|
screenHeight := 256
|
||||||
|
screenScale := 1
|
||||||
|
|
||||||
|
C.glutInit(&cargc, &cargs[0])
|
||||||
|
C.glutInitDisplayMode(C.GLUT_RGBA);
|
||||||
|
C.glutInitWindowSize(C.int(screenWidth * screenScale),
|
||||||
|
C.int(screenHeight * screenScale))
|
||||||
|
|
||||||
|
title := C.CString("Ebiten Demo")
|
||||||
|
defer C.free(unsafe.Pointer(title))
|
||||||
|
C.glutCreateWindow(title)
|
||||||
|
|
||||||
|
C.setDisplayFunc()
|
||||||
|
|
||||||
|
game := &DemoGame{}
|
||||||
|
device = graphics.NewDevice(screenWidth, screenHeight, screenScale,
|
||||||
|
func(g *graphics.GraphicsContext, offscreen *graphics.Texture) {
|
||||||
|
game.Draw(g, offscreen)
|
||||||
|
})
|
||||||
|
|
||||||
|
C.glutMainLoop()
|
||||||
|
}
|
@ -6,7 +6,7 @@ package graphics
|
|||||||
// #include <stdlib.h>
|
// #include <stdlib.h>
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
type device struct {
|
type Device struct {
|
||||||
screenWidth int
|
screenWidth int
|
||||||
screenHeight int
|
screenHeight int
|
||||||
screenScale int
|
screenScale int
|
||||||
@ -15,9 +15,9 @@ type device struct {
|
|||||||
drawFunc func(*GraphicsContext, *Texture)
|
drawFunc func(*GraphicsContext, *Texture)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method should be called on the UI thread??
|
func NewDevice(screenWidth, screenHeight, screenScale int,
|
||||||
func newDevice(screenWidth, screenHeight, screenScale int, drawFunc func(*GraphicsContext, *Texture)) *device {
|
drawFunc func(*GraphicsContext, *Texture)) *Device {
|
||||||
return &device{
|
device := &Device{
|
||||||
screenWidth: screenWidth,
|
screenWidth: screenWidth,
|
||||||
screenHeight: screenHeight,
|
screenHeight: screenHeight,
|
||||||
screenScale: screenScale,
|
screenScale: screenScale,
|
||||||
@ -25,29 +25,29 @@ func newDevice(screenWidth, screenHeight, screenScale int, drawFunc func(*Graphi
|
|||||||
offscreenTexture: NewTexture(screenWidth, screenHeight),
|
offscreenTexture: NewTexture(screenWidth, screenHeight),
|
||||||
drawFunc: drawFunc,
|
drawFunc: drawFunc,
|
||||||
}
|
}
|
||||||
|
return device
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method should be called on the UI thread??
|
func (device *Device) Update() {
|
||||||
func (d *device) Update() {
|
g := device.graphicsContext
|
||||||
g := d.graphicsContext
|
|
||||||
// g.initialize()
|
|
||||||
C.glEnable(C.GL_TEXTURE_2D)
|
C.glEnable(C.GL_TEXTURE_2D)
|
||||||
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MIN_FILTER, C.GL_NEAREST)
|
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MIN_FILTER, C.GL_NEAREST)
|
||||||
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MAG_FILTER, C.GL_NEAREST)
|
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MAG_FILTER, C.GL_NEAREST)
|
||||||
g.SetOffscreen(d.offscreenTexture)
|
g.SetOffscreen(device.offscreenTexture)
|
||||||
g.Clear()
|
g.Clear()
|
||||||
d.drawFunc(g, d.offscreenTexture)
|
// TODO: lock this!
|
||||||
|
device.drawFunc(g, device.offscreenTexture)
|
||||||
g.flush()
|
g.flush()
|
||||||
|
|
||||||
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MIN_FILTER, C.GL_LINEAR)
|
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MIN_FILTER, C.GL_LINEAR)
|
||||||
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MAG_FILTER, C.GL_LINEAR)
|
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MAG_FILTER, C.GL_LINEAR)
|
||||||
g.resetOffscreen()
|
g.resetOffscreen()
|
||||||
g.Clear()
|
g.Clear()
|
||||||
|
|
||||||
geometryMatrix := IdentityGeometryMatrix()
|
geometryMatrix := IdentityGeometryMatrix()
|
||||||
geometryMatrix.SetA(AffineMatrixElement(g.screenScale))
|
geometryMatrix.SetA(AffineMatrixElement(g.screenScale))
|
||||||
geometryMatrix.SetD(AffineMatrixElement(g.screenScale))
|
geometryMatrix.SetD(AffineMatrixElement(g.screenScale))
|
||||||
g.DrawTexture(d.offscreenTexture,
|
g.DrawTexture(device.offscreenTexture,
|
||||||
0, 0, d.screenWidth, d.screenHeight,
|
0, 0, device.screenWidth, device.screenHeight,
|
||||||
geometryMatrix, IdentityColorMatrix())
|
geometryMatrix, IdentityColorMatrix())
|
||||||
g.flush()
|
g.flush()
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,13 @@ package graphics
|
|||||||
|
|
||||||
// #cgo LDFLAGS: -framework OpenGL
|
// #cgo LDFLAGS: -framework OpenGL
|
||||||
//
|
//
|
||||||
// #include <OpenGL/gl.h>
|
|
||||||
// #include <stdlib.h>
|
// #include <stdlib.h>
|
||||||
|
// #include <OpenGL/gl.h>
|
||||||
import "C"
|
import "C"
|
||||||
import (
|
import (
|
||||||
"image/color"
|
"image/color"
|
||||||
"math"
|
"math"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
"../ui"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type GraphicsContext struct {
|
type GraphicsContext struct {
|
||||||
@ -35,30 +34,30 @@ func newGraphicsContext(screenWidth, screenHeight, screenScale int) *GraphicsCon
|
|||||||
mainFramebuffer := C.GLint(0)
|
mainFramebuffer := C.GLint(0)
|
||||||
C.glGetIntegerv(C.GL_FRAMEBUFFER_BINDING, &mainFramebuffer)
|
C.glGetIntegerv(C.GL_FRAMEBUFFER_BINDING, &mainFramebuffer)
|
||||||
context.mainFramebuffer = C.GLuint(mainFramebuffer)
|
context.mainFramebuffer = C.GLuint(mainFramebuffer)
|
||||||
|
|
||||||
|
initializeShaders()
|
||||||
|
|
||||||
return context
|
return context
|
||||||
}
|
}
|
||||||
|
|
||||||
func (context *GraphicsContext) Clear() {
|
func (context *GraphicsContext) Clear() {
|
||||||
ui.ExecuteOnUIThread(func() {
|
C.glClearColor(0, 0, 0, 1)
|
||||||
C.glClearColor(0, 0, 0, 1)
|
C.glClear(C.GL_COLOR_BUFFER_BIT)
|
||||||
C.glClear(C.GL_COLOR_BUFFER_BIT)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (context *GraphicsContext) Fill(color color.Color) {
|
func (context *GraphicsContext) Fill(color color.Color) {
|
||||||
r, g, b, a := color.RGBA()
|
r, g, b, a := color.RGBA()
|
||||||
ui.ExecuteOnUIThread(func() {
|
max := 65535.0
|
||||||
max := 65535.0
|
C.glClearColor(
|
||||||
C.glClearColor(
|
C.GLclampf(float64(r) / max),
|
||||||
C.GLclampf(float64(r) / max),
|
C.GLclampf(float64(g) / max),
|
||||||
C.GLclampf(float64(g) / max),
|
C.GLclampf(float64(b) / max),
|
||||||
C.GLclampf(float64(b) / max),
|
C.GLclampf(float64(a) / max))
|
||||||
C.GLclampf(float64(a) / max))
|
C.glClear(C.GL_COLOR_BUFFER_BIT)
|
||||||
C.glClear(C.GL_COLOR_BUFFER_BIT)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (context *GraphicsContext) DrawRect(x, y, width, height int, color color.Color) {
|
func (context *GraphicsContext) DrawRect(x, y, width, height int, color color.Color) {
|
||||||
|
// TODO: implement!
|
||||||
}
|
}
|
||||||
|
|
||||||
func (context *GraphicsContext) DrawTexture(texture *Texture,
|
func (context *GraphicsContext) DrawTexture(texture *Texture,
|
||||||
@ -67,90 +66,88 @@ func (context *GraphicsContext) DrawTexture(texture *Texture,
|
|||||||
geometryMatrix = geometryMatrix.Clone()
|
geometryMatrix = geometryMatrix.Clone()
|
||||||
colorMatrix = colorMatrix.Clone()
|
colorMatrix = colorMatrix.Clone()
|
||||||
|
|
||||||
ui.ExecuteOnUIThread(func() {
|
context.setShaderProgram(geometryMatrix, colorMatrix)
|
||||||
context.setShaderProgram(geometryMatrix, colorMatrix)
|
C.glBindTexture(C.GL_TEXTURE_2D, texture.id)
|
||||||
C.glBindTexture(C.GL_TEXTURE_2D, texture.id)
|
|
||||||
|
|
||||||
x1 := float32(0)
|
x1 := float32(0)
|
||||||
x2 := float32(srcWidth)
|
x2 := float32(srcWidth)
|
||||||
y1 := float32(0)
|
y1 := float32(0)
|
||||||
y2 := float32(srcHeight)
|
y2 := float32(srcHeight)
|
||||||
vertex := [...]float32{
|
vertex := [...]float32{
|
||||||
x1, y1,
|
x1, y1,
|
||||||
x2, y1,
|
x2, y1,
|
||||||
x1, y2,
|
x1, y2,
|
||||||
x2, y2,
|
x2, y2,
|
||||||
}
|
}
|
||||||
|
|
||||||
tu1 := float32(srcX) / float32(texture.TextureWidth)
|
tu1 := float32(srcX) / float32(texture.TextureWidth)
|
||||||
tu2 := float32(srcX + srcWidth) / float32(texture.TextureWidth)
|
tu2 := float32(srcX + srcWidth) / float32(texture.TextureWidth)
|
||||||
tv1 := float32(srcY) / float32(texture.TextureHeight)
|
tv1 := float32(srcY) / float32(texture.TextureHeight)
|
||||||
tv2 := float32(srcY + srcHeight) / float32(texture.TextureHeight)
|
tv2 := float32(srcY + srcHeight) / float32(texture.TextureHeight)
|
||||||
texCoord := [...]float32{
|
texCoord := [...]float32{
|
||||||
tu1, tv1,
|
tu1, tv1,
|
||||||
tu2, tv1,
|
tu2, tv1,
|
||||||
tu1, tv2,
|
tu1, tv2,
|
||||||
tu2, tv2,
|
tu2, tv2,
|
||||||
}
|
}
|
||||||
|
|
||||||
vertexAttrLocation := getAttributeLocation(context.currentShaderProgram, "vertex")
|
vertexAttrLocation := getAttributeLocation(context.currentShaderProgram, "vertex")
|
||||||
textureAttrLocation := getAttributeLocation(context.currentShaderProgram, "texture")
|
textureAttrLocation := getAttributeLocation(context.currentShaderProgram, "texture")
|
||||||
|
|
||||||
C.glEnableClientState(C.GL_VERTEX_ARRAY)
|
C.glEnableClientState(C.GL_VERTEX_ARRAY)
|
||||||
C.glEnableClientState(C.GL_TEXTURE_COORD_ARRAY)
|
C.glEnableClientState(C.GL_TEXTURE_COORD_ARRAY)
|
||||||
C.glEnableVertexAttribArray(C.GLuint(vertexAttrLocation))
|
C.glEnableVertexAttribArray(C.GLuint(vertexAttrLocation))
|
||||||
C.glEnableVertexAttribArray(C.GLuint(textureAttrLocation))
|
C.glEnableVertexAttribArray(C.GLuint(textureAttrLocation))
|
||||||
C.glVertexAttribPointer(C.GLuint(vertexAttrLocation), 2, C.GL_FLOAT, C.GL_FALSE,
|
C.glVertexAttribPointer(C.GLuint(vertexAttrLocation), 2, C.GL_FLOAT, C.GL_FALSE,
|
||||||
0, unsafe.Pointer(&vertex[0]))
|
0, unsafe.Pointer(&vertex[0]))
|
||||||
C.glVertexAttribPointer(C.GLuint(textureAttrLocation), 2, C.GL_FLOAT, C.GL_FALSE,
|
C.glVertexAttribPointer(C.GLuint(textureAttrLocation), 2, C.GL_FLOAT, C.GL_FALSE,
|
||||||
0, unsafe.Pointer(&texCoord[0]))
|
0, unsafe.Pointer(&texCoord[0]))
|
||||||
C.glDrawArrays(C.GL_TRIANGLE_STRIP, 0, 4)
|
C.glDrawArrays(C.GL_TRIANGLE_STRIP, 0, 4)
|
||||||
C.glDisableVertexAttribArray(C.GLuint(textureAttrLocation))
|
C.glDisableVertexAttribArray(C.GLuint(textureAttrLocation))
|
||||||
C.glDisableVertexAttribArray(C.GLuint(vertexAttrLocation))
|
C.glDisableVertexAttribArray(C.GLuint(vertexAttrLocation))
|
||||||
C.glDisableClientState(C.GL_TEXTURE_COORD_ARRAY)
|
C.glDisableClientState(C.GL_TEXTURE_COORD_ARRAY)
|
||||||
C.glDisableClientState(C.GL_VERTEX_ARRAY)
|
C.glDisableClientState(C.GL_VERTEX_ARRAY)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (context *GraphicsContext) SetOffscreen(texture *Texture) {
|
func (context *GraphicsContext) SetOffscreen(texture *Texture) {
|
||||||
ui.ExecuteOnUIThread(func() {
|
framebuffer := C.GLuint(0)
|
||||||
framebuffer := C.GLuint(0)
|
if texture != nil {
|
||||||
if texture != nil {
|
framebuffer = context.getFramebuffer(texture)
|
||||||
framebuffer = context.getFramebuffer(texture)
|
} else {
|
||||||
} else {
|
framebuffer = context.mainFramebuffer
|
||||||
framebuffer = context.mainFramebuffer
|
}
|
||||||
}
|
C.glBindFramebuffer(C.GL_FRAMEBUFFER, framebuffer)
|
||||||
C.glBindFramebuffer(C.GL_FRAMEBUFFER, framebuffer)
|
if C.glCheckFramebufferStatus(C.GL_FRAMEBUFFER) != C.GL_FRAMEBUFFER_COMPLETE {
|
||||||
// TODO: assert glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE
|
panic("glBindFramebuffer failed")
|
||||||
C.glEnable(C.GL_BLEND)
|
}
|
||||||
C.glBlendFunc(C.GL_SRC_ALPHA, C.GL_ONE_MINUS_SRC_ALPHA)
|
C.glEnable(C.GL_BLEND)
|
||||||
|
C.glBlendFunc(C.GL_SRC_ALPHA, C.GL_ONE_MINUS_SRC_ALPHA)
|
||||||
|
|
||||||
width, height, tx, ty := 0, 0, 0, 0
|
width, height, tx, ty := 0, 0, 0, 0
|
||||||
if framebuffer != context.mainFramebuffer {
|
if framebuffer != context.mainFramebuffer {
|
||||||
width = texture.TextureWidth
|
width = texture.TextureWidth
|
||||||
height = texture.TextureHeight
|
height = texture.TextureHeight
|
||||||
tx = -1
|
tx = -1
|
||||||
ty = -1
|
ty = -1
|
||||||
} else {
|
} else {
|
||||||
width = context.screenWidth * context.screenScale
|
width = context.screenWidth * context.screenScale
|
||||||
height = -1 * context.screenHeight * context.screenScale
|
height = -1 * context.screenHeight * context.screenScale
|
||||||
tx = -1
|
tx = -1
|
||||||
ty = 1
|
ty = 1
|
||||||
}
|
}
|
||||||
C.glViewport(0, 0,
|
C.glViewport(0, 0,
|
||||||
C.GLsizei(math.Abs(float64(width))),
|
C.GLsizei(math.Abs(float64(width))),
|
||||||
C.GLsizei(math.Abs(float64(height))))
|
C.GLsizei(math.Abs(float64(height))))
|
||||||
e11 := float32(2.0 / width)
|
e11 := float32(2.0) / float32(width)
|
||||||
e22 := float32(2.0 / height)
|
e22 := float32(2.0) / float32(height)
|
||||||
e41 := float32(tx)
|
e41 := float32(tx)
|
||||||
e42 := float32(ty)
|
e42 := float32(ty)
|
||||||
context.projectionMatrix = [...]float32{
|
context.projectionMatrix = [...]float32{
|
||||||
e11, 0, 0, 0,
|
e11, 0, 0, 0,
|
||||||
0, e22, 0, 0,
|
0, e22, 0, 0,
|
||||||
0, 0, 1, 0,
|
0, 0, 1, 0,
|
||||||
e41, e42, 0, 1,
|
e41, e42, 0, 1,
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (context *GraphicsContext) resetOffscreen() {
|
func (context *GraphicsContext) resetOffscreen() {
|
||||||
|
@ -7,7 +7,7 @@ import "C"
|
|||||||
import (
|
import (
|
||||||
"image"
|
"image"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
"../ui"
|
"github.com/hajimehoshi/go-ebiten/ui"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Clp2(x uint64) uint64 {
|
func Clp2(x uint64) uint64 {
|
||||||
@ -47,14 +47,18 @@ func createTexture(width, height int, pixels []uint8) *Texture{
|
|||||||
}
|
}
|
||||||
|
|
||||||
ch := make(chan C.GLuint)
|
ch := make(chan C.GLuint)
|
||||||
|
// TODO: should wait?
|
||||||
|
go func() {
|
||||||
|
texture.id = <-ch
|
||||||
|
}()
|
||||||
ui.ExecuteOnUIThread(func() {
|
ui.ExecuteOnUIThread(func() {
|
||||||
textureID := C.GLuint(0)
|
textureID := C.GLuint(0)
|
||||||
C.glGenTextures(1, (*C.GLuint)(&textureID))
|
C.glGenTextures(1, (*C.GLuint)(&textureID))
|
||||||
|
if textureID == 0 {
|
||||||
|
panic("glGenTexture failed")
|
||||||
|
}
|
||||||
C.glPixelStorei(C.GL_UNPACK_ALIGNMENT, 4)
|
C.glPixelStorei(C.GL_UNPACK_ALIGNMENT, 4)
|
||||||
C.glBindTexture(C.GL_TEXTURE_2D, C.GLuint(textureID))
|
C.glBindTexture(C.GL_TEXTURE_2D, C.GLuint(textureID))
|
||||||
if textureID != 0 {
|
|
||||||
panic("glBindTexture failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
ptr := unsafe.Pointer(nil)
|
ptr := unsafe.Pointer(nil)
|
||||||
if pixels != nil {
|
if pixels != nil {
|
||||||
@ -71,10 +75,6 @@ func createTexture(width, height int, pixels []uint8) *Texture{
|
|||||||
ch<- textureID
|
ch<- textureID
|
||||||
close(ch)
|
close(ch)
|
||||||
})
|
})
|
||||||
// TODO: should wait?
|
|
||||||
go func() {
|
|
||||||
texture.id = <-ch
|
|
||||||
}()
|
|
||||||
|
|
||||||
return texture
|
return texture
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user