mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 19:28:57 +01:00
Apply 'Tell, don't ask'
This commit is contained in:
parent
9aded38cc2
commit
b15febed51
@ -44,3 +44,17 @@ type TextureId int
|
|||||||
// A render target is essentially same as a texture, but it is assumed that the
|
// A render target is essentially same as a texture, but it is assumed that the
|
||||||
// all alpha of a render target is maximum.
|
// all alpha of a render target is maximum.
|
||||||
type RenderTargetId int
|
type RenderTargetId int
|
||||||
|
|
||||||
|
func OrthoProjectionMatrix(left, right, bottom, top int) [4][4]float64 {
|
||||||
|
e11 := float64(2) / float64(right-left)
|
||||||
|
e22 := float64(2) / float64(top-bottom)
|
||||||
|
e14 := -1 * float64(right+left) / float64(right-left)
|
||||||
|
e24 := -1 * float64(top+bottom) / float64(top-bottom)
|
||||||
|
|
||||||
|
return [4][4]float64{
|
||||||
|
{e11, 0, 0, e14},
|
||||||
|
{0, e22, 0, e24},
|
||||||
|
{0, 0, 1, 0},
|
||||||
|
{0, 0, 0, 1},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/hajimehoshi/go-ebiten/graphics"
|
"github.com/hajimehoshi/go-ebiten/graphics"
|
||||||
"github.com/hajimehoshi/go-ebiten/graphics/matrix"
|
"github.com/hajimehoshi/go-ebiten/graphics/matrix"
|
||||||
|
"github.com/hajimehoshi/go-ebiten/graphics/texture"
|
||||||
"image"
|
"image"
|
||||||
"math"
|
"math"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
@ -19,7 +20,7 @@ type Context struct {
|
|||||||
screenWidth int
|
screenWidth int
|
||||||
screenHeight int
|
screenHeight int
|
||||||
screenScale int
|
screenScale int
|
||||||
textures map[graphics.TextureId]*Texture
|
textures map[graphics.TextureId]*texture.Texture
|
||||||
renderTargets map[graphics.RenderTargetId]*RenderTarget
|
renderTargets map[graphics.RenderTargetId]*RenderTarget
|
||||||
renderTargetToTexture map[graphics.RenderTargetId]graphics.TextureId
|
renderTargetToTexture map[graphics.RenderTargetId]graphics.TextureId
|
||||||
currentOffscreen *RenderTarget
|
currentOffscreen *RenderTarget
|
||||||
@ -32,7 +33,7 @@ func newContext(screenWidth, screenHeight, screenScale int) *Context {
|
|||||||
screenWidth: screenWidth,
|
screenWidth: screenWidth,
|
||||||
screenHeight: screenHeight,
|
screenHeight: screenHeight,
|
||||||
screenScale: screenScale,
|
screenScale: screenScale,
|
||||||
textures: map[graphics.TextureId]*Texture{},
|
textures: map[graphics.TextureId]*texture.Texture{},
|
||||||
renderTargets: map[graphics.RenderTargetId]*RenderTarget{},
|
renderTargets: map[graphics.RenderTargetId]*RenderTarget{},
|
||||||
renderTargetToTexture: map[graphics.RenderTargetId]graphics.TextureId{},
|
renderTargetToTexture: map[graphics.RenderTargetId]graphics.TextureId{},
|
||||||
}
|
}
|
||||||
@ -45,14 +46,17 @@ func (context *Context) Init() {
|
|||||||
mainFramebuffer := C.GLint(0)
|
mainFramebuffer := C.GLint(0)
|
||||||
C.glGetIntegerv(C.GL_FRAMEBUFFER_BINDING, &mainFramebuffer)
|
C.glGetIntegerv(C.GL_FRAMEBUFFER_BINDING, &mainFramebuffer)
|
||||||
|
|
||||||
context.mainFramebufferTexture = newRenderTargetWithFramebuffer(
|
var err error
|
||||||
|
context.mainFramebufferTexture, err = newRenderTargetWithFramebuffer(
|
||||||
context.screenWidth*context.screenScale,
|
context.screenWidth*context.screenScale,
|
||||||
context.screenHeight*context.screenScale,
|
context.screenHeight*context.screenScale,
|
||||||
C.GLuint(mainFramebuffer))
|
C.GLuint(mainFramebuffer))
|
||||||
|
if err != nil {
|
||||||
|
panic("creating main framebuffer failed: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
initializeShaders()
|
initializeShaders()
|
||||||
|
|
||||||
var err error
|
|
||||||
context.screenId, err = context.NewRenderTarget(
|
context.screenId, err = context.NewRenderTarget(
|
||||||
context.screenWidth, context.screenHeight)
|
context.screenWidth, context.screenHeight)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -85,7 +89,8 @@ func (context *Context) DrawTexture(
|
|||||||
if !ok {
|
if !ok {
|
||||||
panic("invalid texture ID")
|
panic("invalid texture ID")
|
||||||
}
|
}
|
||||||
source := graphics.Rect{0, 0, texture.width, texture.height}
|
// TODO: fix this
|
||||||
|
source := graphics.Rect{0, 0, texture.Width(), texture.Height()}
|
||||||
locations := []graphics.TexturePart{{0, 0, source}}
|
locations := []graphics.TexturePart{{0, 0, source}}
|
||||||
context.DrawTextureParts(textureId, locations,
|
context.DrawTextureParts(textureId, locations,
|
||||||
geometryMatrix, colorMatrix)
|
geometryMatrix, colorMatrix)
|
||||||
@ -175,26 +180,12 @@ func (context *Context) setOffscreen(renderTarget *RenderTarget) {
|
|||||||
context.currentOffscreen.SetAsViewport(context)
|
context.currentOffscreen.SetAsViewport(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
func orthoProjectionMatrix(left, right, bottom, top int) [4][4]float64 {
|
|
||||||
e11 := float64(2) / float64(right-left)
|
|
||||||
e22 := float64(2) / float64(top-bottom)
|
|
||||||
e14 := -1 * float64(right+left) / float64(right-left)
|
|
||||||
e24 := -1 * float64(top+bottom) / float64(top-bottom)
|
|
||||||
|
|
||||||
return [4][4]float64{
|
|
||||||
{e11, 0, 0, e14},
|
|
||||||
{0, e22, 0, e24},
|
|
||||||
{0, 0, 1, 0},
|
|
||||||
{0, 0, 0, 1},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (context *Context) SetViewport(x, y, width, height int) {
|
func (context *Context) SetViewport(x, y, width, height int) {
|
||||||
C.glViewport(C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height))
|
C.glViewport(C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height))
|
||||||
|
|
||||||
matrix := orthoProjectionMatrix(x, width, y, height)
|
matrix := graphics.OrthoProjectionMatrix(x, width, y, height)
|
||||||
if context.currentOffscreen == context.mainFramebufferTexture {
|
if context.currentOffscreen == context.mainFramebufferTexture {
|
||||||
// Flip Y and translate
|
// Flip Y and move to fit with the top of the window.
|
||||||
matrix[1][1] *= -1
|
matrix[1][1] *= -1
|
||||||
actualHeight := context.screenHeight * context.screenScale
|
actualHeight := context.screenHeight * context.screenScale
|
||||||
matrix[1][3] += float64(actualHeight) / float64(height) * 2
|
matrix[1][3] += float64(actualHeight) / float64(height) * 2
|
||||||
@ -300,7 +291,7 @@ func (context *Context) NewRenderTarget(width, height int) (
|
|||||||
|
|
||||||
func (context *Context) NewTextureFromImage(img image.Image) (
|
func (context *Context) NewTextureFromImage(img image.Image) (
|
||||||
graphics.TextureId, error) {
|
graphics.TextureId, error) {
|
||||||
texture, err := newTextureFromImage(img)
|
texture, err := texture.NewFromImage(img, &NativeTextureCreator{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -5,62 +5,23 @@ package opengl
|
|||||||
// #include <OpenGL/gl.h>
|
// #include <OpenGL/gl.h>
|
||||||
import "C"
|
import "C"
|
||||||
import (
|
import (
|
||||||
|
"github.com/hajimehoshi/go-ebiten/graphics/texture"
|
||||||
"image"
|
"image"
|
||||||
"image/draw"
|
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
func nextPowerOf2(x uint64) uint64 {
|
|
||||||
x -= 1
|
|
||||||
x |= (x >> 1)
|
|
||||||
x |= (x >> 2)
|
|
||||||
x |= (x >> 4)
|
|
||||||
x |= (x >> 8)
|
|
||||||
x |= (x >> 16)
|
|
||||||
x |= (x >> 32)
|
|
||||||
return x + 1
|
|
||||||
}
|
|
||||||
|
|
||||||
type Texture struct {
|
|
||||||
native interface{}
|
|
||||||
width int
|
|
||||||
height int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (texture *Texture) Native() interface{} {
|
|
||||||
return texture.native
|
|
||||||
}
|
|
||||||
|
|
||||||
func (texture *Texture) textureWidth() int {
|
|
||||||
return int(nextPowerOf2(uint64(texture.width)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (texture *Texture) textureHeight() int {
|
|
||||||
return int(nextPowerOf2(uint64(texture.height)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (texture *Texture) U(x int) float64 {
|
|
||||||
return float64(x) / float64(texture.textureWidth())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (texture *Texture) V(y int) float64 {
|
|
||||||
return float64(y) / float64(texture.textureHeight())
|
|
||||||
}
|
|
||||||
|
|
||||||
type RenderTarget struct {
|
type RenderTarget struct {
|
||||||
texture *Texture
|
texture *texture.Texture
|
||||||
framebuffer C.GLuint
|
framebuffer C.GLuint
|
||||||
}
|
}
|
||||||
|
|
||||||
func (renderTarget *RenderTarget) SetAsViewport(setter interface{
|
func (renderTarget *RenderTarget) SetAsViewport(setter interface{
|
||||||
SetViewport(x, y, width, height int)
|
SetViewport(x, y, width, height int)
|
||||||
}) {
|
}) {
|
||||||
texture := renderTarget.texture
|
renderTarget.texture.SetAsViewport(0, 0, setter)
|
||||||
x, y, width, height := 0, 0, texture.textureWidth(), texture.textureHeight()
|
|
||||||
setter.SetViewport(x, y, width, height)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func createNativeTexture(textureWidth, textureHeight int, pixels unsafe.Pointer) C.GLuint {
|
func createNativeTexture(textureWidth, textureHeight int, pixels []uint8) C.GLuint {
|
||||||
nativeTexture := C.GLuint(0)
|
nativeTexture := C.GLuint(0)
|
||||||
|
|
||||||
C.glGenTextures(1, (*C.GLuint)(&nativeTexture))
|
C.glGenTextures(1, (*C.GLuint)(&nativeTexture))
|
||||||
@ -70,9 +31,13 @@ func createNativeTexture(textureWidth, textureHeight int, pixels unsafe.Pointer)
|
|||||||
C.glPixelStorei(C.GL_UNPACK_ALIGNMENT, 4)
|
C.glPixelStorei(C.GL_UNPACK_ALIGNMENT, 4)
|
||||||
C.glBindTexture(C.GL_TEXTURE_2D, C.GLuint(nativeTexture))
|
C.glBindTexture(C.GL_TEXTURE_2D, C.GLuint(nativeTexture))
|
||||||
|
|
||||||
|
ptr := unsafe.Pointer(nil)
|
||||||
|
if pixels != nil {
|
||||||
|
ptr = unsafe.Pointer(&pixels[0])
|
||||||
|
}
|
||||||
C.glTexImage2D(C.GL_TEXTURE_2D, 0, C.GL_RGBA,
|
C.glTexImage2D(C.GL_TEXTURE_2D, 0, C.GL_RGBA,
|
||||||
C.GLsizei(textureWidth), C.GLsizei(textureHeight),
|
C.GLsizei(textureWidth), C.GLsizei(textureHeight),
|
||||||
0, C.GL_RGBA, C.GL_UNSIGNED_BYTE, pixels)
|
0, C.GL_RGBA, C.GL_UNSIGNED_BYTE, ptr)
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
@ -81,17 +46,22 @@ func createNativeTexture(textureWidth, textureHeight int, pixels unsafe.Pointer)
|
|||||||
return nativeTexture
|
return nativeTexture
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTexture(width, height int) *Texture {
|
type NativeTextureCreator struct{}
|
||||||
texture := &Texture{
|
|
||||||
width: width,
|
func (creator *NativeTextureCreator) Create(textureWidth, textureHeight int) (interface{}, error) {
|
||||||
height: height,
|
return createNativeTexture(textureWidth, textureHeight, nil), nil
|
||||||
}
|
}
|
||||||
texture.native = createNativeTexture(texture.textureWidth(), texture.textureHeight(), nil)
|
|
||||||
return texture
|
func (creator *NativeTextureCreator) CreateFromImage(img *image.NRGBA) (interface{}, error) {
|
||||||
|
size := img.Bounds().Size()
|
||||||
|
return createNativeTexture(size.X, size.Y, img.Pix), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRenderTarget(width, height int) (*RenderTarget, error) {
|
func newRenderTarget(width, height int) (*RenderTarget, error) {
|
||||||
texture := createTexture(width, height)
|
texture, err := texture.New(width, height, &NativeTextureCreator{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
framebuffer := createFramebuffer(texture.Native().(C.GLuint))
|
framebuffer := createFramebuffer(texture.Native().(C.GLuint))
|
||||||
return &RenderTarget{
|
return &RenderTarget{
|
||||||
texture: texture,
|
texture: texture,
|
||||||
@ -99,41 +69,15 @@ func newRenderTarget(width, height int) (*RenderTarget, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTextureFromImage(img image.Image) (*Texture, error) {
|
func newRenderTargetWithFramebuffer(width, height int, framebuffer C.GLuint) (*RenderTarget, error) {
|
||||||
size := img.Bounds().Size()
|
texture, err := texture.New(width, height, &NativeTextureCreator{})
|
||||||
width, height := size.X, size.Y
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
texture := &Texture{
|
|
||||||
width: width,
|
|
||||||
height: height,
|
|
||||||
}
|
|
||||||
|
|
||||||
adjustedImageBound := image.Rectangle{
|
|
||||||
image.ZP,
|
|
||||||
image.Point{texture.textureWidth(), texture.textureHeight()},
|
|
||||||
}
|
|
||||||
adjustedImage := image.NewNRGBA(adjustedImageBound)
|
|
||||||
dstBound := image.Rectangle{
|
|
||||||
image.ZP,
|
|
||||||
img.Bounds().Size(),
|
|
||||||
}
|
|
||||||
draw.Draw(adjustedImage, dstBound, img, image.ZP, draw.Src)
|
|
||||||
pixelsPtr := unsafe.Pointer(&adjustedImage.Pix[0])
|
|
||||||
texture.native = createNativeTexture(
|
|
||||||
texture.textureWidth(), texture.textureHeight(), pixelsPtr)
|
|
||||||
return texture, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func newRenderTargetWithFramebuffer(width, height int,
|
|
||||||
framebuffer C.GLuint) *RenderTarget {
|
|
||||||
texture := &Texture{
|
|
||||||
width: width,
|
|
||||||
height: height,
|
|
||||||
}
|
}
|
||||||
return &RenderTarget{
|
return &RenderTarget{
|
||||||
texture: texture,
|
texture: texture,
|
||||||
framebuffer: framebuffer,
|
framebuffer: framebuffer,
|
||||||
}
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createFramebuffer(nativeTexture C.GLuint) C.GLuint {
|
func createFramebuffer(nativeTexture C.GLuint) C.GLuint {
|
||||||
|
99
graphics/texture/texture.go
Normal file
99
graphics/texture/texture.go
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
package texture
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image"
|
||||||
|
"image/draw"
|
||||||
|
)
|
||||||
|
|
||||||
|
func nextPowerOf2(x uint64) uint64 {
|
||||||
|
x -= 1
|
||||||
|
x |= (x >> 1)
|
||||||
|
x |= (x >> 2)
|
||||||
|
x |= (x >> 4)
|
||||||
|
x |= (x >> 8)
|
||||||
|
x |= (x >> 16)
|
||||||
|
x |= (x >> 32)
|
||||||
|
return x + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
type Texture struct {
|
||||||
|
native interface{}
|
||||||
|
width int
|
||||||
|
height int
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(width, height int, creator interface {
|
||||||
|
Create(textureWidth, textureHeight int) (interface{}, error)
|
||||||
|
}) (*Texture, error) {
|
||||||
|
texture := &Texture{
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
texture.native, err = creator.Create(texture.textureWidth(), texture.textureHeight())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return texture, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFromImage(img image.Image, creator interface {
|
||||||
|
CreateFromImage(img *image.NRGBA) (interface{}, error)
|
||||||
|
}) (*Texture, error) {
|
||||||
|
size := img.Bounds().Size()
|
||||||
|
width, height := size.X, size.Y
|
||||||
|
texture := &Texture{
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
}
|
||||||
|
adjustedImageBound := image.Rectangle{
|
||||||
|
image.ZP,
|
||||||
|
image.Point{texture.textureWidth(), texture.textureHeight()},
|
||||||
|
}
|
||||||
|
adjustedImage := image.NewNRGBA(adjustedImageBound)
|
||||||
|
dstBound := image.Rectangle{
|
||||||
|
image.ZP,
|
||||||
|
img.Bounds().Size(),
|
||||||
|
}
|
||||||
|
draw.Draw(adjustedImage, dstBound, img, image.ZP, draw.Src)
|
||||||
|
var err error
|
||||||
|
texture.native, err = creator.CreateFromImage(adjustedImage)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return texture, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (texture *Texture) Width() int {
|
||||||
|
return texture.width
|
||||||
|
}
|
||||||
|
|
||||||
|
func (texture *Texture) Height() int {
|
||||||
|
return texture.height
|
||||||
|
}
|
||||||
|
|
||||||
|
func (texture *Texture) textureWidth() int {
|
||||||
|
return int(nextPowerOf2(uint64(texture.width)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (texture *Texture) textureHeight() int {
|
||||||
|
return int(nextPowerOf2(uint64(texture.height)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (texture *Texture) Native() interface{} {
|
||||||
|
return texture.native
|
||||||
|
}
|
||||||
|
|
||||||
|
func (texture *Texture) U(x int) float64 {
|
||||||
|
return float64(x) / float64(texture.textureWidth())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (texture *Texture) V(y int) float64 {
|
||||||
|
return float64(y) / float64(texture.textureHeight())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (texture *Texture) SetAsViewport(x, y int, setter interface{
|
||||||
|
SetViewport(x, y, width, height int)
|
||||||
|
}) {
|
||||||
|
setter.SetViewport(x, y, texture.textureWidth(), texture.textureHeight())
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
// This package is experimental.
|
// This package is experimental.
|
||||||
package glut
|
package glut
|
||||||
|
|
||||||
|
// #cgo CFLAGS: -Wno-deprecated-declarations
|
||||||
// #cgo LDFLAGS: -framework GLUT -framework OpenGL
|
// #cgo LDFLAGS: -framework GLUT -framework OpenGL
|
||||||
//
|
//
|
||||||
// #include <stdlib.h>
|
// #include <stdlib.h>
|
||||||
|
Loading…
Reference in New Issue
Block a user