This commit is contained in:
Hajime Hoshi 2013-06-19 23:51:41 +09:00
parent e91ab21d8d
commit 6ed9102f01
10 changed files with 90 additions and 91 deletions

View File

@ -1,9 +1,9 @@
package ebiten package ebiten
import ( import (
"time"
"github.com/hajimehoshi/go-ebiten/graphics" "github.com/hajimehoshi/go-ebiten/graphics"
"github.com/hajimehoshi/go-ebiten/graphics/opengl" "github.com/hajimehoshi/go-ebiten/graphics/opengl"
"time"
) )
type Game interface { type Game interface {
@ -26,7 +26,7 @@ func OpenGLRun(game Game, ui UI) {
func(g graphics.GraphicsContext, offscreen graphics.TextureID) { func(g graphics.GraphicsContext, offscreen graphics.TextureID) {
ticket := <-ch ticket := <-ch
game.Draw(g, offscreen) game.Draw(g, offscreen)
ch<- ticket ch <- ticket
}) })
go func() { go func() {
@ -36,11 +36,11 @@ func OpenGLRun(game Game, ui UI) {
<-tick <-tick
ticket := <-ch ticket := <-ch
game.Update() game.Update()
ch<- ticket ch <- ticket
} }
}() }()
game.Init(device.TextureFactory()) game.Init(device.TextureFactory())
ch<- true ch <- true
ui.Run(device) ui.Run(device)
} }

View File

@ -15,21 +15,21 @@ package main
// //
import "C" import "C"
import ( import (
"github.com/hajimehoshi/go-ebiten"
"github.com/hajimehoshi/go-ebiten/graphics"
"image" "image"
"image/color" "image/color"
_ "image/png" _ "image/png"
"os" "os"
"runtime" "runtime"
"unsafe" "unsafe"
"github.com/hajimehoshi/go-ebiten"
"github.com/hajimehoshi/go-ebiten/graphics"
) )
type GlutUI struct{ type GlutUI struct {
screenWidth int screenWidth int
screenHeight int screenHeight int
screenScale int screenScale int
device graphics.Device device graphics.Device
} }
var currentUI *GlutUI var currentUI *GlutUI
@ -57,15 +57,15 @@ func (ui *GlutUI) Init() {
}() }()
cargc := C.int(len(cargs)) cargc := C.int(len(cargs))
ui.screenWidth = 256 ui.screenWidth = 256
ui.screenHeight = 240 ui.screenHeight = 240
ui.screenScale = 2 ui.screenScale = 2
C.glutInit(&cargc, &cargs[0]) C.glutInit(&cargc, &cargs[0])
C.glutInitDisplayMode(C.GLUT_RGBA); C.glutInitDisplayMode(C.GLUT_RGBA)
C.glutInitWindowSize( C.glutInitWindowSize(
C.int(ui.screenWidth * ui.screenScale), C.int(ui.screenWidth*ui.screenScale),
C.int(ui.screenHeight * ui.screenScale)) C.int(ui.screenHeight*ui.screenScale))
title := C.CString("Ebiten Demo") title := C.CString("Ebiten Demo")
defer C.free(unsafe.Pointer(title)) defer C.free(unsafe.Pointer(title))
@ -93,7 +93,7 @@ func (ui *GlutUI) Run(device graphics.Device) {
type DemoGame struct { type DemoGame struct {
ebitenTexture graphics.Texture ebitenTexture graphics.Texture
x int x int
} }
func (game *DemoGame) Init(tf graphics.TextureFactory) { func (game *DemoGame) Init(tf graphics.TextureFactory) {
@ -102,7 +102,7 @@ func (game *DemoGame) Init(tf graphics.TextureFactory) {
panic(err) panic(err)
} }
defer file.Close() defer file.Close()
img, _, err := image.Decode(file) img, _, err := image.Decode(file)
if err != nil { if err != nil {
panic(err) panic(err)

View File

@ -1,8 +1,8 @@
package graphics_test package graphics_test
import ( import (
"testing"
. "." . "."
"testing"
) )
func setElements(matrix *AffineMatrix, elements [][]float64) { func setElements(matrix *AffineMatrix, elements [][]float64) {

View File

@ -1,8 +1,8 @@
package graphics_test package graphics_test
import ( import (
"testing"
. "." . "."
"testing"
) )
func TestGeometryMatrixElements(t *testing.T) { func TestGeometryMatrixElements(t *testing.T) {

View File

@ -25,8 +25,8 @@ type TextureFactory interface {
} }
type Texture struct { type Texture struct {
ID TextureID ID TextureID
Width int Width int
Height int Height int
} }

View File

@ -10,22 +10,22 @@ import (
) )
type Device struct { type Device struct {
screenWidth int screenWidth int
screenHeight int screenHeight int
screenScale int screenScale int
graphicsContext *GraphicsContext graphicsContext *GraphicsContext
offscreenTexture graphics.Texture offscreenTexture graphics.Texture
drawFunc func(graphics.GraphicsContext, graphics.TextureID) drawFunc func(graphics.GraphicsContext, graphics.TextureID)
} }
func NewDevice(screenWidth, screenHeight, screenScale int, func NewDevice(screenWidth, screenHeight, screenScale int,
drawFunc func(graphics.GraphicsContext, graphics.TextureID)) *Device { drawFunc func(graphics.GraphicsContext, graphics.TextureID)) *Device {
device := &Device{ device := &Device{
screenWidth: screenWidth, screenWidth: screenWidth,
screenHeight: screenHeight, screenHeight: screenHeight,
screenScale: screenScale, screenScale: screenScale,
graphicsContext: newGraphicsContext(screenWidth, screenHeight, screenScale), graphicsContext: newGraphicsContext(screenWidth, screenHeight, screenScale),
drawFunc: drawFunc, drawFunc: drawFunc,
} }
device.offscreenTexture = device.offscreenTexture =
device.graphicsContext.NewTexture(screenWidth, screenHeight) device.graphicsContext.NewTexture(screenWidth, screenHeight)
@ -41,7 +41,7 @@ func (device *Device) Update() {
g.Clear() g.Clear()
device.drawFunc(g, device.offscreenTexture.ID) device.drawFunc(g, device.offscreenTexture.ID)
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()

View File

@ -7,32 +7,32 @@ package opengl
import "C" import "C"
import ( import (
"fmt" "fmt"
"github.com/hajimehoshi/go-ebiten/graphics"
"image" "image"
"image/color" "image/color"
"unsafe" "unsafe"
"github.com/hajimehoshi/go-ebiten/graphics"
) )
type GraphicsContext struct { type GraphicsContext struct {
screenWidth int screenWidth int
screenHeight int screenHeight int
screenScale int screenScale int
textures map[graphics.TextureID]*Texture textures map[graphics.TextureID]*Texture
projectionMatrix [16]float32 projectionMatrix [16]float32
currentShaderProgram C.GLuint currentShaderProgram C.GLuint
mainFramebuffer C.GLuint mainFramebuffer C.GLuint
framebuffers map[C.GLuint]C.GLuint framebuffers map[C.GLuint]C.GLuint
} }
// This method should be called on the UI thread. // This method should be called on the UI thread.
func newGraphicsContext(screenWidth, screenHeight, screenScale int) *GraphicsContext { func newGraphicsContext(screenWidth, screenHeight, screenScale int) *GraphicsContext {
context := &GraphicsContext{ context := &GraphicsContext{
screenWidth: screenWidth, screenWidth: screenWidth,
screenHeight: screenHeight, screenHeight: screenHeight,
screenScale: screenScale, screenScale: screenScale,
textures: map[graphics.TextureID]*Texture{}, textures: map[graphics.TextureID]*Texture{},
mainFramebuffer: 0, mainFramebuffer: 0,
framebuffers: map[C.GLuint]C.GLuint{}, framebuffers: map[C.GLuint]C.GLuint{},
} }
// main framebuffer should be created sooner than any other framebuffers! // main framebuffer should be created sooner than any other framebuffers!
mainFramebuffer := C.GLint(0) mainFramebuffer := C.GLint(0)
@ -53,10 +53,10 @@ func (context *GraphicsContext) Fill(clr color.Color) {
r, g, b, a := clr.RGBA() r, g, b, a := clr.RGBA()
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)
} }
@ -69,7 +69,7 @@ func (context *GraphicsContext) DrawTexture(
srcX, srcY, srcWidth, srcHeight int, srcX, srcY, srcWidth, srcHeight int,
geometryMatrix *graphics.GeometryMatrix, colorMatrix *graphics.ColorMatrix) { geometryMatrix *graphics.GeometryMatrix, colorMatrix *graphics.ColorMatrix) {
geometryMatrix = geometryMatrix.Clone() geometryMatrix = geometryMatrix.Clone()
colorMatrix = colorMatrix.Clone() colorMatrix = colorMatrix.Clone()
texture := context.textures[textureID] texture := context.textures[textureID]
@ -87,10 +87,10 @@ func (context *GraphicsContext) DrawTexture(
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,
@ -138,8 +138,7 @@ func (context *GraphicsContext) setOffscreenFramebuffer(framebuffer C.GLuint,
C.glFlush() C.glFlush()
C.glBindFramebuffer(C.GL_FRAMEBUFFER, framebuffer) C.glBindFramebuffer(C.GL_FRAMEBUFFER, framebuffer)
if err := C.glCheckFramebufferStatus(C.GL_FRAMEBUFFER); if err := C.glCheckFramebufferStatus(C.GL_FRAMEBUFFER); err != C.GL_FRAMEBUFFER_COMPLETE {
err != C.GL_FRAMEBUFFER_COMPLETE {
panic(fmt.Sprintf("glBindFramebuffer failed: %d", err)) panic(fmt.Sprintf("glBindFramebuffer failed: %d", err))
} }
C.glEnable(C.GL_BLEND) C.glEnable(C.GL_BLEND)
@ -147,15 +146,15 @@ func (context *GraphicsContext) setOffscreenFramebuffer(framebuffer C.GLuint,
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 = textureWidth width = textureWidth
height = textureHeight height = 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.GLsizei(abs(width)), C.GLsizei(abs(height))) C.glViewport(0, 0, C.GLsizei(abs(width)), C.GLsizei(abs(height)))
e11 := float32(2.0) / float32(width) e11 := float32(2.0) / float32(width)
@ -163,9 +162,9 @@ func (context *GraphicsContext) setOffscreenFramebuffer(framebuffer C.GLuint,
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,
} }
} }
@ -196,16 +195,16 @@ func (context *GraphicsContext) setShaderProgram(
1, C.GL_FALSE, 1, C.GL_FALSE,
(*C.GLfloat)(&context.projectionMatrix[0])) (*C.GLfloat)(&context.projectionMatrix[0]))
a := float32(geometryMatrix.A()) a := float32(geometryMatrix.A())
b := float32(geometryMatrix.B()) b := float32(geometryMatrix.B())
c := float32(geometryMatrix.C()) c := float32(geometryMatrix.C())
d := float32(geometryMatrix.D()) d := float32(geometryMatrix.D())
tx := float32(geometryMatrix.Tx()) tx := float32(geometryMatrix.Tx())
ty := float32(geometryMatrix.Ty()) ty := float32(geometryMatrix.Ty())
glModelviewMatrix := [...]float32{ glModelviewMatrix := [...]float32{
a, c, 0, 0, a, c, 0, 0,
b, d, 0, 0, b, d, 0, 0,
0, 0, 1, 0, 0, 0, 1, 0,
tx, ty, 0, 1, tx, ty, 0, 1,
} }
C.glUniformMatrix4fv(getUniformLocation(program, "modelview_matrix"), C.glUniformMatrix4fv(getUniformLocation(program, "modelview_matrix"),
@ -241,7 +240,7 @@ func (context *GraphicsContext) setShaderProgram(
1, (*C.GLfloat)(&glColorMatrixTranslation[0])) 1, (*C.GLfloat)(&glColorMatrixTranslation[0]))
} }
func (context *GraphicsContext) getFramebuffer(textureID C.GLuint) C.GLuint{ func (context *GraphicsContext) getFramebuffer(textureID C.GLuint) C.GLuint {
framebuffer, ok := context.framebuffers[textureID] framebuffer, ok := context.framebuffers[textureID]
if ok { if ok {
return framebuffer return framebuffer

View File

@ -10,14 +10,14 @@ import (
) )
type shader struct { type shader struct {
id C.GLuint id C.GLuint
name string name string
source string source string
} }
var ( var (
vertexShader = &shader{ vertexShader = &shader{
id: 0, id: 0,
name: "vertex_shader", name: "vertex_shader",
source: ` source: `
attribute /*highp*/ vec2 vertex; attribute /*highp*/ vec2 vertex;
@ -33,7 +33,7 @@ void main(void) {
`, `,
} }
fragmentShader = &shader{ fragmentShader = &shader{
id: 0, id: 0,
name: "fragment_shader", name: "fragment_shader",
source: ` source: `
uniform /*lowp*/ sampler2D texture; uniform /*lowp*/ sampler2D texture;
@ -45,7 +45,7 @@ void main(void) {
`, `,
} }
colorMatrixShader = &shader{ colorMatrixShader = &shader{
id: 0, id: 0,
name: "color_matrix_shader", name: "color_matrix_shader",
source: ` source: `
uniform /*highp*/ sampler2D texture; uniform /*highp*/ sampler2D texture;
@ -62,7 +62,7 @@ void main(void) {
) )
var ( var (
regularShaderProgram = C.GLuint(0) regularShaderProgram = C.GLuint(0)
colorMatrixShaderProgram = C.GLuint(0) colorMatrixShaderProgram = C.GLuint(0)
) )

View File

@ -21,15 +21,15 @@ func Clp2(x uint64) uint64 {
} }
type Texture struct { type Texture struct {
id C.GLuint id C.GLuint
width int width int
height int height int
textureWidth int textureWidth int
textureHeight int textureHeight int
} }
func createTexture(width, height int, pixels []uint8) *Texture { func createTexture(width, height int, pixels []uint8) *Texture {
textureWidth := int(Clp2(uint64(width))) textureWidth := int(Clp2(uint64(width)))
textureHeight := int(Clp2(uint64(height))) textureHeight := int(Clp2(uint64(height)))
if pixels != nil { if pixels != nil {
if width != textureWidth { if width != textureWidth {
@ -40,10 +40,10 @@ func createTexture(width, height int, pixels []uint8) *Texture {
} }
} }
texture := &Texture{ texture := &Texture{
id: 0, id: 0,
width: width, width: width,
height: height, height: height,
textureWidth: textureWidth, textureWidth: textureWidth,
textureHeight: textureHeight, textureHeight: textureHeight,
} }
@ -54,7 +54,7 @@ func createTexture(width, height int, pixels []uint8) *Texture {
} }
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))
ptr := unsafe.Pointer(nil) ptr := unsafe.Pointer(nil)
if pixels != nil { if pixels != nil {
ptr = unsafe.Pointer(&pixels[0]) ptr = unsafe.Pointer(&pixels[0])

View File

@ -1,14 +1,14 @@
package opengl_test package opengl_test
import ( import (
"testing"
. "." . "."
"testing"
) )
func TestClp2(t *testing.T) { func TestClp2(t *testing.T) {
testCases := []struct { testCases := []struct {
expected uint64 expected uint64
arg uint64 arg uint64
}{ }{
{256, 255}, {256, 255},
{256, 256}, {256, 256},
@ -22,6 +22,6 @@ func TestClp2(t *testing.T) {
t.Errorf("Clp(%d) = %d, wanted %d", t.Errorf("Clp(%d) = %d, wanted %d",
testCase.arg, got, wanted) testCase.arg, got, wanted)
} }
} }
} }