mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-01-27 03:02:49 +01:00
Refactoring
This commit is contained in:
parent
ac572a5554
commit
c5f8738ae9
@ -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)
|
||||||
|
@ -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
|
||||||
|
}
|
@ -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 {
|
||||||
|
31
graphics/rendertarget/render_target.go
Normal file
31
graphics/rendertarget/render_target.go
Normal 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)
|
||||||
|
}
|
@ -1,3 +1,3 @@
|
|||||||
package opengl
|
package texture
|
||||||
|
|
||||||
var NextPowerOf2 = nextPowerOf2
|
var NextPowerOf2 = nextPowerOf2
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package opengl_test
|
package texture_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
. "."
|
. "."
|
Loading…
Reference in New Issue
Block a user