Refactoring

This commit is contained in:
Hajime Hoshi 2013-10-26 04:15:27 +09:00
parent ac572a5554
commit c5f8738ae9
7 changed files with 253 additions and 161 deletions

View File

@ -9,6 +9,8 @@ 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/opengl/shader"
"github.com/hajimehoshi/go-ebiten/graphics/rendertarget"
"github.com/hajimehoshi/go-ebiten/graphics/texture" "github.com/hajimehoshi/go-ebiten/graphics/texture"
"image" "image"
"math" "math"
@ -21,10 +23,10 @@ type Context struct {
screenHeight int screenHeight int
screenScale int screenScale int
textures map[graphics.TextureId]*texture.Texture textures map[graphics.TextureId]*texture.Texture
renderTargets map[graphics.RenderTargetId]*RenderTarget renderTargets map[graphics.RenderTargetId]*rendertarget.RenderTarget
renderTargetToTexture map[graphics.RenderTargetId]graphics.TextureId renderTargetToTexture map[graphics.RenderTargetId]graphics.TextureId
currentOffscreen *RenderTarget currentOffscreen *rendertarget.RenderTarget
mainFramebufferTexture *RenderTarget mainFramebufferTexture *rendertarget.RenderTarget
projectionMatrix [16]float32 projectionMatrix [16]float32
} }
@ -34,7 +36,7 @@ func newContext(screenWidth, screenHeight, screenScale int) *Context {
screenHeight: screenHeight, screenHeight: screenHeight,
screenScale: screenScale, screenScale: screenScale,
textures: map[graphics.TextureId]*texture.Texture{}, textures: map[graphics.TextureId]*texture.Texture{},
renderTargets: map[graphics.RenderTargetId]*RenderTarget{}, renderTargets: map[graphics.RenderTargetId]*rendertarget.RenderTarget{},
renderTargetToTexture: map[graphics.RenderTargetId]graphics.TextureId{}, renderTargetToTexture: map[graphics.RenderTargetId]graphics.TextureId{},
} }
return context return context
@ -55,7 +57,7 @@ func (context *Context) Init() {
panic("creating main framebuffer failed: " + err.Error()) panic("creating main framebuffer failed: " + err.Error())
} }
initializeShaders() shader.Initialize()
context.screenId, err = context.NewRenderTarget( context.screenId, err = context.NewRenderTarget(
context.screenWidth, context.screenHeight) context.screenWidth, context.screenHeight)
@ -82,37 +84,21 @@ func (context *Context) Fill(r, g, b uint8) {
C.glClear(C.GL_COLOR_BUFFER_BIT) C.glClear(C.GL_COLOR_BUFFER_BIT)
} }
func (context *Context) DrawTexture( type TextureDrawing struct {
textureId graphics.TextureId, context *Context
geometryMatrix matrix.Geometry, colorMatrix matrix.Color) { geometryMatrix matrix.Geometry
texture, ok := context.textures[textureId] colorMatrix matrix.Color
if !ok {
panic("invalid texture ID")
}
// TODO: fix this
source := graphics.Rect{0, 0, texture.Width(), texture.Height()}
locations := []graphics.TexturePart{{0, 0, source}}
context.DrawTextureParts(textureId, locations,
geometryMatrix, colorMatrix)
} }
func (context *Context) DrawTextureParts( func (t *TextureDrawing) Draw(native interface{}, quads []texture.Quad) {
textureId graphics.TextureId, parts []graphics.TexturePart, if len(quads) == 0 {
geometryMatrix matrix.Geometry, colorMatrix matrix.Color) {
texture, ok := context.textures[textureId]
if !ok {
panic("invalid texture ID")
}
if len(parts) == 0 {
return return
} }
shaderProgram := t.context.setShaderProgram(t.geometryMatrix, t.colorMatrix)
C.glBindTexture(C.GL_TEXTURE_2D, native.(C.GLuint))
shaderProgram := context.setShaderProgram(geometryMatrix, colorMatrix) vertexAttrLocation := shader.GetAttributeLocation(shaderProgram, "vertex")
C.glBindTexture(C.GL_TEXTURE_2D, texture.Native().(C.GLuint)) textureAttrLocation := shader.GetAttributeLocation(shaderProgram, "texture")
vertexAttrLocation := getAttributeLocation(shaderProgram, "vertex")
textureAttrLocation := getAttributeLocation(shaderProgram, "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)
@ -122,29 +108,28 @@ func (context *Context) DrawTextureParts(
texCoords := []float32{} texCoords := []float32{}
indicies := []uint32{} indicies := []uint32{}
// TODO: Check len(parts) and GL_MAX_ELEMENTS_INDICES // TODO: Check len(parts) and GL_MAX_ELEMENTS_INDICES
for i, part := range parts { for i, quad := range quads {
x1 := float32(part.LocationX) x1 := quad.VertexX1
x2 := float32(part.LocationX + part.Source.Width) x2 := quad.VertexX2
y1 := float32(part.LocationY) y1 := quad.VertexY1
y2 := float32(part.LocationY + part.Source.Height) y2 := quad.VertexY2
vertices = append(vertices, vertices = append(vertices,
x1, y1, x1, y1,
x2, y1, x2, y1,
x1, y2, x1, y2,
x2, y2, x2, y2,
) )
src := part.Source u1 := quad.TextureCoordU1
tu1 := float32(texture.U(src.X)) u2 := quad.TextureCoordU2
tu2 := float32(texture.U(src.X + src.Width)) v1 := quad.TextureCoordV1
tv1 := float32(texture.V(src.Y)) v2 := quad.TextureCoordV2
tv2 := float32(texture.V(src.Y + src.Height))
texCoords = append(texCoords, texCoords = append(texCoords,
tu1, tv1, u1, v1,
tu2, tv1, u2, v1,
tu1, tv2, u1, v2,
tu2, tv2, u2, v2,
) )
base := uint32(i*4) base := uint32(i * 4)
indicies = append(indicies, indicies = append(indicies,
base, base+1, base+2, base, base+1, base+2,
base+1, base+2, base+3, base+1, base+2, base+3,
@ -164,6 +149,28 @@ func (context *Context) DrawTextureParts(
C.glDisableClientState(C.GL_VERTEX_ARRAY) C.glDisableClientState(C.GL_VERTEX_ARRAY)
} }
func (context *Context) DrawTexture(
textureId graphics.TextureId,
geometryMatrix matrix.Geometry, colorMatrix matrix.Color) {
texture, ok := context.textures[textureId]
if !ok {
panic("invalid texture ID")
}
drawing := &TextureDrawing{context, geometryMatrix, colorMatrix}
texture.Draw(drawing.Draw)
}
func (context *Context) DrawTextureParts(
textureId graphics.TextureId, parts []graphics.TexturePart,
geometryMatrix matrix.Geometry, colorMatrix matrix.Color) {
texture, ok := context.textures[textureId]
if !ok {
panic("invalid texture ID")
}
drawing := &TextureDrawing{context, geometryMatrix, colorMatrix}
texture.DrawParts(parts, drawing.Draw)
}
func (context *Context) ResetOffscreen() { func (context *Context) ResetOffscreen() {
context.SetOffscreen(context.screenId) context.SetOffscreen(context.screenId)
} }
@ -173,12 +180,13 @@ func (context *Context) SetOffscreen(renderTargetId graphics.RenderTargetId) {
context.setOffscreen(renderTarget) context.setOffscreen(renderTarget)
} }
func (context *Context) setOffscreen(renderTarget *RenderTarget) { func (context *Context) setOffscreen(renderTarget *rendertarget.RenderTarget) {
context.currentOffscreen = renderTarget context.currentOffscreen = renderTarget
C.glFlush() C.glFlush()
C.glBindFramebuffer(C.GL_FRAMEBUFFER, renderTarget.framebuffer) framebuffer := renderTarget.Framebuffer().(C.GLuint)
C.glBindFramebuffer(C.GL_FRAMEBUFFER, framebuffer)
err := C.glCheckFramebufferStatus(C.GL_FRAMEBUFFER) err := C.glCheckFramebufferStatus(C.GL_FRAMEBUFFER)
if err != C.GL_FRAMEBUFFER_COMPLETE { if err != C.GL_FRAMEBUFFER_COMPLETE {
panic(fmt.Sprintf("glBindFramebuffer failed: %d", err)) panic(fmt.Sprintf("glBindFramebuffer failed: %d", err))
@ -188,23 +196,34 @@ func (context *Context) setOffscreen(renderTarget *RenderTarget) {
C.glBlendFuncSeparate(C.GL_SRC_ALPHA, C.GL_ONE_MINUS_SRC_ALPHA, C.glBlendFuncSeparate(C.GL_SRC_ALPHA, C.GL_ONE_MINUS_SRC_ALPHA,
C.GL_ZERO, C.GL_ONE) C.GL_ZERO, C.GL_ONE)
context.currentOffscreen.SetAsViewport(context) isUsingMainFramebuffer := context.currentOffscreen == context.mainFramebufferTexture
setter := &viewportSetter{
isUsingMainFramebuffer,
context.screenHeight * context.screenScale,
context,
}
context.currentOffscreen.SetAsViewport(setter.Set)
} }
func (context *Context) SetViewport(x, y, width, height int) { type viewportSetter struct {
isUsingMainFramebuffer bool
actualScreenHeight int
context *Context
}
func (v *viewportSetter) Set(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 := graphics.OrthoProjectionMatrix(x, width, y, height) matrix := graphics.OrthoProjectionMatrix(x, width, y, height)
if context.currentOffscreen == context.mainFramebufferTexture { if v.isUsingMainFramebuffer {
// Flip Y and move to fit with the top of the window. // 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 matrix[1][3] += float64(v.actualScreenHeight) / float64(height) * 2
matrix[1][3] += float64(actualHeight) / float64(height) * 2
} }
for j := 0; j < 4; j++ { for j := 0; j < 4; j++ {
for i := 0; i < 4; i++ { for i := 0; i < 4; i++ {
context.projectionMatrix[i+j*4] = float32(matrix[i][j]) v.context.projectionMatrix[i+j*4] = float32(matrix[i][j])
} }
} }
@ -220,64 +239,8 @@ func (context *Context) flush() {
} }
func (context *Context) setShaderProgram( func (context *Context) setShaderProgram(
geometryMatrix matrix.Geometry, colorMatrix matrix.Color) (program C.GLuint) { geometryMatrix matrix.Geometry, colorMatrix matrix.Color) (program shader.Program) {
if colorMatrix.IsIdentity() { return shader.Use(context.projectionMatrix, geometryMatrix, colorMatrix)
program = regularShaderProgram
} else {
program = colorMatrixShaderProgram
}
// TODO: cache and skip?
C.glUseProgram(program)
C.glUniformMatrix4fv(getUniformLocation(program, "projection_matrix"),
1, C.GL_FALSE,
(*C.GLfloat)(&context.projectionMatrix[0]))
a := float32(geometryMatrix.Elements[0][0])
b := float32(geometryMatrix.Elements[0][1])
c := float32(geometryMatrix.Elements[1][0])
d := float32(geometryMatrix.Elements[1][1])
tx := float32(geometryMatrix.Elements[0][2])
ty := float32(geometryMatrix.Elements[1][2])
glModelviewMatrix := [...]float32{
a, c, 0, 0,
b, d, 0, 0,
0, 0, 1, 0,
tx, ty, 0, 1,
}
C.glUniformMatrix4fv(getUniformLocation(program, "modelview_matrix"),
1, C.GL_FALSE,
(*C.GLfloat)(&glModelviewMatrix[0]))
C.glUniform1i(getUniformLocation(program, "texture"), 0)
if program != colorMatrixShaderProgram {
return
}
e := [4][5]float32{}
for i := 0; i < 4; i++ {
for j := 0; j < 5; j++ {
e[i][j] = float32(colorMatrix.Elements[i][j])
}
}
glColorMatrix := [...]float32{
e[0][0], e[1][0], e[2][0], e[3][0],
e[0][1], e[1][1], e[2][1], e[3][1],
e[0][2], e[1][2], e[2][2], e[3][2],
e[0][3], e[1][3], e[2][3], e[3][3],
}
C.glUniformMatrix4fv(getUniformLocation(program, "color_matrix"),
1, C.GL_FALSE, (*C.GLfloat)(&glColorMatrix[0]))
glColorMatrixTranslation := [...]float32{
e[0][4], e[1][4], e[2][4], e[3][4],
}
C.glUniform4fv(getUniformLocation(program, "color_matrix_translation"),
1, (*C.GLfloat)(&glColorMatrixTranslation[0]))
return
} }
func (context *Context) NewRenderTarget(width, height int) ( func (context *Context) NewRenderTarget(width, height int) (
@ -289,7 +252,7 @@ func (context *Context) NewRenderTarget(width, height int) (
renderTargetId := graphics.RenderTargetId(<-newId) renderTargetId := graphics.RenderTargetId(<-newId)
textureId := graphics.TextureId(<-newId) textureId := graphics.TextureId(<-newId)
context.renderTargets[renderTargetId] = renderTarget context.renderTargets[renderTargetId] = renderTarget
context.textures[textureId] = renderTarget.texture context.textures[textureId] = renderTarget.Texture()
context.renderTargetToTexture[renderTargetId] = textureId context.renderTargetToTexture[renderTargetId] = textureId
context.setOffscreen(renderTarget) context.setOffscreen(renderTarget)

View File

@ -1,4 +1,4 @@
package opengl package shader
// #cgo LDFLAGS: -framework OpenGL // #cgo LDFLAGS: -framework OpenGL
// //
@ -6,9 +6,19 @@ package opengl
// #include <stdlib.h> // #include <stdlib.h>
import "C" import "C"
import ( import (
"github.com/hajimehoshi/go-ebiten/graphics/matrix"
"unsafe" "unsafe"
) )
type Program int
const (
ProgramRegular Program = iota
ProgramColorMatrix
)
type Location int
type shader struct { type shader struct {
id C.GLuint id C.GLuint
name string name string
@ -110,7 +120,7 @@ func createProgram(shaders ...*shader) C.GLuint {
return program return program
} }
func initializeShaders() { func Initialize() {
// TODO: when should this function be called? // TODO: when should this function be called?
vertexShader.id = C.glCreateShader(C.GL_VERTEX_SHADER) vertexShader.id = C.glCreateShader(C.GL_VERTEX_SHADER)
if vertexShader.id == 0 { if vertexShader.id == 0 {
@ -149,20 +159,34 @@ var (
} }
) )
func getLocation(program C.GLuint, name string, qualifierVariableType int) C.GLint { func toInnerProgram(program Program) C.GLuint {
switch program {
case ProgramRegular:
return regularShaderProgram
case ProgramColorMatrix:
return colorMatrixShaderProgram
default:
panic("no reach")
}
return C.GLuint(0)
}
func getLocation(program Program, name string, qualifierVariableType int) int {
if location, ok := shaderLocationCache[qualifierVariableType][name]; ok { if location, ok := shaderLocationCache[qualifierVariableType][name]; ok {
return location return int(location)
} }
locationName := C.CString(name) locationName := C.CString(name)
defer C.free(unsafe.Pointer(locationName)) defer C.free(unsafe.Pointer(locationName))
location := C.GLint(-1) location := C.GLint(-1)
innerProgram := toInnerProgram(program)
switch qualifierVariableType { switch qualifierVariableType {
case qualifierVariableTypeAttribute: case qualifierVariableTypeAttribute:
location = C.glGetAttribLocation(program, (*C.GLchar)(locationName)) location = C.glGetAttribLocation(innerProgram, (*C.GLchar)(locationName))
case qualifierVariableTypeUniform: case qualifierVariableTypeUniform:
location = C.glGetUniformLocation(program, (*C.GLchar)(locationName)) location = C.glGetUniformLocation(innerProgram, (*C.GLchar)(locationName))
default: default:
panic("no reach") panic("no reach")
} }
@ -171,13 +195,70 @@ func getLocation(program C.GLuint, name string, qualifierVariableType int) C.GLi
} }
shaderLocationCache[qualifierVariableType][name] = location shaderLocationCache[qualifierVariableType][name] = location
return location return int(location)
} }
func getAttributeLocation(program C.GLuint, name string) C.GLint { func GetAttributeLocation(program Program, name string) int {
return getLocation(program, name, qualifierVariableTypeAttribute) return getLocation(program, name, qualifierVariableTypeAttribute)
} }
func getUniformLocation(program C.GLuint, name string) C.GLint { func getUniformLocation(program Program, name string) int {
return getLocation(program, name, qualifierVariableTypeUniform) return getLocation(program, name, qualifierVariableTypeUniform)
} }
func Use(projectionMatrix [16]float32, geometryMatrix matrix.Geometry, colorMatrix matrix.Color) Program {
program := ProgramRegular
if !colorMatrix.IsIdentity() {
program = ProgramColorMatrix
}
C.glUseProgram(toInnerProgram(program))
C.glUniformMatrix4fv(C.GLint(getUniformLocation(program, "projection_matrix")),
1, C.GL_FALSE, (*C.GLfloat)(&projectionMatrix[0]))
a := float32(geometryMatrix.Elements[0][0])
b := float32(geometryMatrix.Elements[0][1])
c := float32(geometryMatrix.Elements[1][0])
d := float32(geometryMatrix.Elements[1][1])
tx := float32(geometryMatrix.Elements[0][2])
ty := float32(geometryMatrix.Elements[1][2])
glModelviewMatrix := [...]float32{
a, c, 0, 0,
b, d, 0, 0,
0, 0, 1, 0,
tx, ty, 0, 1,
}
C.glUniformMatrix4fv(C.GLint(getUniformLocation(program, "modelview_matrix")),
1, C.GL_FALSE,
(*C.GLfloat)(&glModelviewMatrix[0]))
C.glUniform1i(C.GLint(getUniformLocation(program, "texture")), 0)
if program != ProgramColorMatrix {
return program
}
e := [4][5]float32{}
for i := 0; i < 4; i++ {
for j := 0; j < 5; j++ {
e[i][j] = float32(colorMatrix.Elements[i][j])
}
}
glColorMatrix := [...]float32{
e[0][0], e[1][0], e[2][0], e[3][0],
e[0][1], e[1][1], e[2][1], e[3][1],
e[0][2], e[1][2], e[2][2], e[3][2],
e[0][3], e[1][3], e[2][3], e[3][3],
}
C.glUniformMatrix4fv(C.GLint(getUniformLocation(program, "color_matrix")),
1, C.GL_FALSE, (*C.GLfloat)(&glColorMatrix[0]))
glColorMatrixTranslation := [...]float32{
e[0][4], e[1][4], e[2][4], e[3][4],
}
C.glUniform4fv(C.GLint(getUniformLocation(program, "color_matrix_translation")),
1, (*C.GLfloat)(&glColorMatrixTranslation[0]))
return program
}

View File

@ -5,22 +5,12 @@ package opengl
// #include <OpenGL/gl.h> // #include <OpenGL/gl.h>
import "C" import "C"
import ( import (
"github.com/hajimehoshi/go-ebiten/graphics/rendertarget"
"github.com/hajimehoshi/go-ebiten/graphics/texture" "github.com/hajimehoshi/go-ebiten/graphics/texture"
"image" "image"
"unsafe" "unsafe"
) )
type RenderTarget struct {
texture *texture.Texture
framebuffer C.GLuint
}
func (renderTarget *RenderTarget) SetAsViewport(setter interface{
SetViewport(x, y, width, height int)
}) {
renderTarget.texture.SetAsViewport(0, 0, setter)
}
func createNativeTexture(textureWidth, textureHeight int, pixels []uint8) C.GLuint { func createNativeTexture(textureWidth, textureHeight int, pixels []uint8) C.GLuint {
nativeTexture := C.GLuint(0) nativeTexture := C.GLuint(0)
@ -57,27 +47,21 @@ func (creator *NativeTextureCreator) CreateFromImage(img *image.NRGBA) (interfac
return createNativeTexture(size.X, size.Y, img.Pix), nil return createNativeTexture(size.X, size.Y, img.Pix), nil
} }
func newRenderTarget(width, height int) (*RenderTarget, error) { func newRenderTarget(width, height int) (*rendertarget.RenderTarget, error) {
texture, err := texture.New(width, height, &NativeTextureCreator{}) texture, err := texture.New(width, height, &NativeTextureCreator{})
if err != nil { if err != nil {
return nil, err return nil, err
} }
framebuffer := createFramebuffer(texture.Native().(C.GLuint)) framebuffer := createFramebuffer(texture.Native().(C.GLuint))
return &RenderTarget{ return rendertarget.NewWithFramebuffer(texture, framebuffer), nil
texture: texture,
framebuffer: framebuffer,
}, nil
} }
func newRenderTargetWithFramebuffer(width, height int, framebuffer C.GLuint) (*RenderTarget, error) { func newRenderTargetWithFramebuffer(width, height int, framebuffer C.GLuint) (*rendertarget.RenderTarget, error) {
texture, err := texture.New(width, height, &NativeTextureCreator{}) texture, err := texture.New(width, height, &NativeTextureCreator{})
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &RenderTarget{ return rendertarget.NewWithFramebuffer(texture, framebuffer), nil
texture: texture,
framebuffer: framebuffer,
}, nil
} }
func createFramebuffer(nativeTexture C.GLuint) C.GLuint { func createFramebuffer(nativeTexture C.GLuint) C.GLuint {

View File

@ -0,0 +1,31 @@
package rendertarget
import (
"github.com/hajimehoshi/go-ebiten/graphics/texture"
)
type RenderTarget struct {
texture *texture.Texture
framebuffer interface{}
}
func NewWithFramebuffer(texture *texture.Texture, framebuffer interface{}) *RenderTarget {
return &RenderTarget{
texture: texture,
framebuffer: framebuffer,
}
}
// TODO: Remove this
func (renderTarget *RenderTarget) Texture() *texture.Texture {
return renderTarget.texture
}
// TODO: Remove this
func (renderTarget *RenderTarget) Framebuffer() interface{} {
return renderTarget.framebuffer
}
func (renderTarget *RenderTarget) SetAsViewport(setter func(x, y, width, height int)) {
renderTarget.texture.SetAsViewport(setter)
}

View File

@ -1,3 +1,3 @@
package opengl package texture
var NextPowerOf2 = nextPowerOf2 var NextPowerOf2 = nextPowerOf2

View File

@ -1,6 +1,7 @@
package texture package texture
import ( import (
"github.com/hajimehoshi/go-ebiten/graphics"
"image" "image"
"image/draw" "image/draw"
) )
@ -64,14 +65,6 @@ func NewFromImage(img image.Image, creator interface {
return texture, nil return texture, nil
} }
func (texture *Texture) Width() int {
return texture.width
}
func (texture *Texture) Height() int {
return texture.height
}
func (texture *Texture) textureWidth() int { func (texture *Texture) textureWidth() int {
return int(nextPowerOf2(uint64(texture.width))) return int(nextPowerOf2(uint64(texture.width)))
} }
@ -80,20 +73,60 @@ func (texture *Texture) textureHeight() int {
return int(nextPowerOf2(uint64(texture.height))) return int(nextPowerOf2(uint64(texture.height)))
} }
// TODO: Remove this
func (texture *Texture) Native() interface{} { func (texture *Texture) Native() interface{} {
return texture.native return texture.native
} }
func (texture *Texture) U(x int) float64 { func (texture *Texture) u(x int) float32 {
return float64(x) / float64(texture.textureWidth()) return float32(x) / float32(texture.textureWidth())
} }
func (texture *Texture) V(y int) float64 { func (texture *Texture) v(y int) float32 {
return float64(y) / float64(texture.textureHeight()) return float32(y) / float32(texture.textureHeight())
} }
func (texture *Texture) SetAsViewport(x, y int, setter interface{ func (texture *Texture) SetAsViewport(setter func(x, y, width, height int)) {
SetViewport(x, y, width, height int) setter(0, 0, texture.textureWidth(), texture.textureHeight())
}) { }
setter.SetViewport(x, y, texture.textureWidth(), texture.textureHeight())
type Quad struct {
VertexX1 float32
VertexX2 float32
VertexY1 float32
VertexY2 float32
TextureCoordU1 float32
TextureCoordU2 float32
TextureCoordV1 float32
TextureCoordV2 float32
}
func (texture *Texture) Draw(draw func(native interface{}, quads []Quad)) {
x1 := float32(0)
x2 := float32(texture.width)
y1 := float32(0)
y2 := float32(texture.height)
u1 := texture.u(0)
u2 := texture.u(texture.width)
v1 := texture.v(0)
v2 := texture.v(texture.height)
quad := Quad{x1, x2, y1, y2, u1, u2, v1, v2}
draw(texture.native, []Quad{quad})
}
func (texture *Texture) DrawParts(parts []graphics.TexturePart, draw func(native interface{}, quads []Quad)) {
quads := []Quad{}
for _, part := range parts {
x1 := float32(part.LocationX)
x2 := float32(part.LocationX + part.Source.Width)
y1 := float32(part.LocationY)
y2 := float32(part.LocationY + part.Source.Height)
u1 := texture.u(part.Source.X)
u2 := texture.u(part.Source.X + part.Source.Width)
v1 := texture.v(part.Source.Y)
v2 := texture.v(part.Source.Y + part.Source.Height)
quad := Quad{x1, x2, y1, y2, u1, u2, v1, v2}
quads = append(quads, quad)
}
draw(texture.native, quads)
} }

View File

@ -1,4 +1,4 @@
package opengl_test package texture_test
import ( import (
. "." . "."