mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 18:58:54 +01:00
Introduce Photoshop-like alpha blending
This commit is contained in:
parent
dc0e67f600
commit
6673a39fa2
@ -32,7 +32,7 @@ func textWidth(str string) int {
|
|||||||
return charWidth * len(str)
|
return charWidth * len(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
func drawText(context ebiten.GraphicsContext, textures *Textures, str string, x, y, scale int, clr color.Color) {
|
func drawText(context ebiten.GraphicsContext, textures *Textures, str string, ox, oy, scale int, clr color.Color) {
|
||||||
fontTextureId := textures.GetTexture("font")
|
fontTextureId := textures.GetTexture("font")
|
||||||
parts := []ebiten.TexturePart{}
|
parts := []ebiten.TexturePart{}
|
||||||
|
|
||||||
@ -53,11 +53,9 @@ func drawText(context ebiten.GraphicsContext, textures *Textures, str string, x,
|
|||||||
locationX += charWidth
|
locationX += charWidth
|
||||||
}
|
}
|
||||||
|
|
||||||
geoMat := ebiten.GeometryMatrixI()
|
geoMat := ebiten.ScaleGeometry(float64(scale), float64(scale))
|
||||||
geoMat.Concat(ebiten.ScaleGeometry(float64(scale), float64(scale)))
|
geoMat.Concat(ebiten.TranslateGeometry(float64(ox), float64(oy)))
|
||||||
geoMat.Concat(ebiten.TranslateGeometry(float64(x), float64(y)))
|
clrMat := ebiten.ScaleColor(clr)
|
||||||
clrMat := ebiten.ColorMatrixI()
|
|
||||||
clrMat.Concat(ebiten.ScaleColor(clr))
|
|
||||||
context.DrawTexture(fontTextureId, parts, geoMat, clrMat)
|
context.DrawTexture(fontTextureId, parts, geoMat, clrMat)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package ebiten
|
package ebiten
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/hajimehoshi/ebiten/internal"
|
||||||
"github.com/hajimehoshi/ebiten/internal/opengl"
|
"github.com/hajimehoshi/ebiten/internal/opengl"
|
||||||
"github.com/hajimehoshi/ebiten/internal/opengl/internal/shader"
|
"github.com/hajimehoshi/ebiten/internal/opengl/internal/shader"
|
||||||
)
|
)
|
||||||
@ -92,11 +93,11 @@ func (r *RenderTarget) Size() (width int, height int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func u(x float64, width int) float32 {
|
func u(x float64, width int) float32 {
|
||||||
return float32(x) / float32(opengl.AdjustSizeForTexture(width))
|
return float32(x) / float32(internal.AdjustSizeForTexture(width))
|
||||||
}
|
}
|
||||||
|
|
||||||
func v(y float64, height int) float32 {
|
func v(y float64, height int) float32 {
|
||||||
return float32(y) / float32(opengl.AdjustSizeForTexture(height))
|
return float32(y) / float32(internal.AdjustSizeForTexture(height))
|
||||||
}
|
}
|
||||||
|
|
||||||
func textureQuads(parts []TexturePart, width, height int) []shader.TextureQuad {
|
func textureQuads(parts []TexturePart, width, height int) []shader.TextureQuad {
|
||||||
|
@ -22,8 +22,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func newGraphicsContext(screenWidth, screenHeight, screenScale int) (*graphicsContext, error) {
|
func newGraphicsContext(screenWidth, screenHeight, screenScale int) (*graphicsContext, error) {
|
||||||
// The defualt framebuffer should be 0.
|
r, t, err := opengl.NewZeroRenderTarget(screenWidth*screenScale, screenHeight*screenScale, true)
|
||||||
r := opengl.NewRenderTarget(screenWidth*screenScale, screenHeight*screenScale, true)
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
screen, err := idsInstance.createRenderTarget(screenWidth, screenHeight, gl.NEAREST)
|
screen, err := idsInstance.createRenderTarget(screenWidth, screenHeight, gl.NEAREST)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -32,7 +34,7 @@ func newGraphicsContext(screenWidth, screenHeight, screenScale int) (*graphicsCo
|
|||||||
|
|
||||||
c := &graphicsContext{
|
c := &graphicsContext{
|
||||||
currents: make([]*RenderTarget, 1),
|
currents: make([]*RenderTarget, 1),
|
||||||
defaultR: &RenderTarget{r, nil},
|
defaultR: &RenderTarget{r, &Texture{t}},
|
||||||
screen: screen,
|
screen: screen,
|
||||||
screenWidth: screenWidth,
|
screenWidth: screenWidth,
|
||||||
screenHeight: screenHeight,
|
screenHeight: screenHeight,
|
||||||
|
4
ids.go
4
ids.go
@ -67,7 +67,9 @@ func (i *ids) drawTexture(target *RenderTarget, texture *Texture, parts []Textur
|
|||||||
}
|
}
|
||||||
projectionMatrix := target.glRenderTarget.ProjectionMatrix()
|
projectionMatrix := target.glRenderTarget.ProjectionMatrix()
|
||||||
quads := textureQuads(parts, glTexture.Width(), glTexture.Height())
|
quads := textureQuads(parts, glTexture.Width(), glTexture.Height())
|
||||||
shader.DrawTexture(glTexture.Native(), projectionMatrix, quads, &geo, &color)
|
w, h := target.Size()
|
||||||
|
shader.DrawTexture(glTexture.Native(), target.texture.glTexture.Native(), w, h, projectionMatrix, quads, &geo, &color)
|
||||||
|
gl.Flush()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
32
internal/math.go
Normal file
32
internal/math.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2014 Hajime Hoshi
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package internal
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
func AdjustSizeForTexture(size int) int {
|
||||||
|
return int(NextPowerOf2(uint64(size)))
|
||||||
|
}
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package opengl_test
|
package internal_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
. "."
|
. "."
|
||||||
@ -35,8 +35,7 @@ func TestNextPowerOf2(t *testing.T) {
|
|||||||
got := NextPowerOf2(testCase.arg)
|
got := NextPowerOf2(testCase.arg)
|
||||||
wanted := testCase.expected
|
wanted := testCase.expected
|
||||||
if wanted != got {
|
if wanted != got {
|
||||||
t.Errorf("Clp(%d) = %d, wanted %d",
|
t.Errorf("Clp(%d) = %d, wanted %d", testCase.arg, got, wanted)
|
||||||
testCase.arg, got, wanted)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -18,6 +18,7 @@ package shader
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/go-gl/gl"
|
"github.com/go-gl/gl"
|
||||||
|
"github.com/hajimehoshi/ebiten/internal"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -38,7 +39,7 @@ type Matrix interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Use VBO
|
// TODO: Use VBO
|
||||||
func DrawTexture(native gl.Texture, projectionMatrix [4][4]float64, quads []TextureQuad, geo Matrix, color Matrix) {
|
func DrawTexture(native gl.Texture, target gl.Texture, width, height int, projectionMatrix [4][4]float64, quads []TextureQuad, geo Matrix, color Matrix) {
|
||||||
once.Do(func() {
|
once.Do(func() {
|
||||||
initialize()
|
initialize()
|
||||||
})
|
})
|
||||||
@ -47,27 +48,39 @@ func DrawTexture(native gl.Texture, projectionMatrix [4][4]float64, quads []Text
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
// TODO: Check performance
|
// TODO: Check performance
|
||||||
shaderProgram := use(glMatrix(projectionMatrix), geo, color)
|
shaderProgram := use(glMatrix(projectionMatrix), width, height, geo, color)
|
||||||
|
|
||||||
|
gl.ActiveTexture(gl.TEXTURE0)
|
||||||
native.Bind(gl.TEXTURE_2D)
|
native.Bind(gl.TEXTURE_2D)
|
||||||
defer gl.Texture(0).Bind(gl.TEXTURE_2D)
|
|
||||||
|
gl.ActiveTexture(gl.TEXTURE1)
|
||||||
|
target.Bind(gl.TEXTURE_2D)
|
||||||
|
|
||||||
|
texture0UniformLocation := getUniformLocation(shaderProgram, "texture0")
|
||||||
|
texture1UniformLocation := getUniformLocation(shaderProgram, "texture1")
|
||||||
|
texture0UniformLocation.Uniform1i(0)
|
||||||
|
texture1UniformLocation.Uniform1i(1)
|
||||||
|
|
||||||
vertexAttrLocation := getAttributeLocation(shaderProgram, "vertex")
|
vertexAttrLocation := getAttributeLocation(shaderProgram, "vertex")
|
||||||
texCoordAttrLocation := getAttributeLocation(shaderProgram, "tex_coord")
|
texCoord0AttrLocation := getAttributeLocation(shaderProgram, "tex_coord0")
|
||||||
|
texCoord1AttrLocation := getAttributeLocation(shaderProgram, "tex_coord1")
|
||||||
|
|
||||||
gl.EnableClientState(gl.VERTEX_ARRAY)
|
gl.EnableClientState(gl.VERTEX_ARRAY)
|
||||||
gl.EnableClientState(gl.TEXTURE_COORD_ARRAY)
|
gl.EnableClientState(gl.TEXTURE_COORD_ARRAY)
|
||||||
vertexAttrLocation.EnableArray()
|
vertexAttrLocation.EnableArray()
|
||||||
texCoordAttrLocation.EnableArray()
|
texCoord0AttrLocation.EnableArray()
|
||||||
|
texCoord1AttrLocation.EnableArray()
|
||||||
defer func() {
|
defer func() {
|
||||||
texCoordAttrLocation.DisableArray()
|
texCoord1AttrLocation.DisableArray()
|
||||||
|
texCoord0AttrLocation.DisableArray()
|
||||||
vertexAttrLocation.DisableArray()
|
vertexAttrLocation.DisableArray()
|
||||||
gl.DisableClientState(gl.TEXTURE_COORD_ARRAY)
|
gl.DisableClientState(gl.TEXTURE_COORD_ARRAY)
|
||||||
gl.DisableClientState(gl.VERTEX_ARRAY)
|
gl.DisableClientState(gl.VERTEX_ARRAY)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
vertices := []float32{}
|
vertices := []float32{}
|
||||||
texCoords := []float32{}
|
texCoords0 := []float32{}
|
||||||
|
texCoords1 := []float32{}
|
||||||
indicies := []uint32{}
|
indicies := []uint32{}
|
||||||
// TODO: Check len(quads) and gl.MAX_ELEMENTS_INDICES?
|
// TODO: Check len(quads) and gl.MAX_ELEMENTS_INDICES?
|
||||||
for i, quad := range quads {
|
for i, quad := range quads {
|
||||||
@ -85,12 +98,24 @@ func DrawTexture(native gl.Texture, projectionMatrix [4][4]float64, quads []Text
|
|||||||
u2 := quad.TextureCoordU2
|
u2 := quad.TextureCoordU2
|
||||||
v1 := quad.TextureCoordV1
|
v1 := quad.TextureCoordV1
|
||||||
v2 := quad.TextureCoordV2
|
v2 := quad.TextureCoordV2
|
||||||
texCoords = append(texCoords,
|
texCoords0 = append(texCoords0,
|
||||||
u1, v1,
|
u1, v1,
|
||||||
u2, v1,
|
u2, v1,
|
||||||
u1, v2,
|
u1, v2,
|
||||||
u2, v2,
|
u2, v2,
|
||||||
)
|
)
|
||||||
|
w := float32(internal.AdjustSizeForTexture(width))
|
||||||
|
h := float32(internal.AdjustSizeForTexture(height))
|
||||||
|
xx1 := x1 / w
|
||||||
|
xx2 := x2 / w
|
||||||
|
yy1 := y1 / h
|
||||||
|
yy2 := y2 / h
|
||||||
|
texCoords1 = append(texCoords1,
|
||||||
|
xx1, yy1,
|
||||||
|
xx2, yy1,
|
||||||
|
xx1, yy2,
|
||||||
|
xx2, yy2,
|
||||||
|
)
|
||||||
base := uint32(i * 4)
|
base := uint32(i * 4)
|
||||||
indicies = append(indicies,
|
indicies = append(indicies,
|
||||||
base, base+1, base+2,
|
base, base+1, base+2,
|
||||||
@ -98,6 +123,7 @@ func DrawTexture(native gl.Texture, projectionMatrix [4][4]float64, quads []Text
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
vertexAttrLocation.AttribPointer(2, gl.FLOAT, false, 0, vertices)
|
vertexAttrLocation.AttribPointer(2, gl.FLOAT, false, 0, vertices)
|
||||||
texCoordAttrLocation.AttribPointer(2, gl.FLOAT, false, 0, texCoords)
|
texCoord0AttrLocation.AttribPointer(2, gl.FLOAT, false, 0, texCoords0)
|
||||||
|
texCoord1AttrLocation.AttribPointer(2, gl.FLOAT, false, 0, texCoords1)
|
||||||
gl.DrawElements(gl.TRIANGLES, len(indicies), gl.UNSIGNED_INT, indicies)
|
gl.DrawElements(gl.TRIANGLES, len(indicies), gl.UNSIGNED_INT, indicies)
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ package shader
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/go-gl/gl"
|
"github.com/go-gl/gl"
|
||||||
|
"github.com/hajimehoshi/ebiten/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
type program struct {
|
type program struct {
|
||||||
@ -80,7 +81,7 @@ func getUniformLocation(program gl.Program, name string) gl.UniformLocation {
|
|||||||
return location
|
return location
|
||||||
}
|
}
|
||||||
|
|
||||||
func use(projectionMatrix [16]float32, geo Matrix, color Matrix) gl.Program {
|
func use(projectionMatrix [16]float32, width, height int, geo Matrix, color Matrix) gl.Program {
|
||||||
// TODO: Check the performance.
|
// TODO: Check the performance.
|
||||||
program := programColorMatrix
|
program := programColorMatrix
|
||||||
|
|
||||||
@ -99,6 +100,15 @@ func use(projectionMatrix [16]float32, geo Matrix, color Matrix) gl.Program {
|
|||||||
tx, ty, 0, 1,
|
tx, ty, 0, 1,
|
||||||
}
|
}
|
||||||
getUniformLocation(program.native, "modelview_matrix").UniformMatrix4fv(false, glModelviewMatrix)
|
getUniformLocation(program.native, "modelview_matrix").UniformMatrix4fv(false, glModelviewMatrix)
|
||||||
|
txn := tx / float32(internal.AdjustSizeForTexture(width))
|
||||||
|
tyn := ty / float32(internal.AdjustSizeForTexture(height))
|
||||||
|
glModelviewMatrixN := [...]float32{
|
||||||
|
a, c, 0, 0,
|
||||||
|
b, d, 0, 0,
|
||||||
|
0, 0, 1, 0,
|
||||||
|
txn, tyn, 0, 1,
|
||||||
|
}
|
||||||
|
getUniformLocation(program.native, "modelview_matrix_n").UniformMatrix4fv(false, glModelviewMatrixN)
|
||||||
|
|
||||||
getUniformLocation(program.native, "texture").Uniform1i(0)
|
getUniformLocation(program.native, "texture").Uniform1i(0)
|
||||||
|
|
||||||
|
@ -42,41 +42,53 @@ var shaders = map[shaderId]*shader{
|
|||||||
source: `
|
source: `
|
||||||
uniform mat4 projection_matrix;
|
uniform mat4 projection_matrix;
|
||||||
uniform mat4 modelview_matrix;
|
uniform mat4 modelview_matrix;
|
||||||
|
uniform mat4 modelview_matrix_n;
|
||||||
attribute vec2 vertex;
|
attribute vec2 vertex;
|
||||||
attribute vec2 tex_coord;
|
attribute vec2 tex_coord0;
|
||||||
varying vec2 vertex_out_tex_coord;
|
attribute vec2 tex_coord1;
|
||||||
|
varying vec2 vertex_out_tex_coord0;
|
||||||
|
varying vec2 vertex_out_tex_coord1;
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
vertex_out_tex_coord = tex_coord;
|
vertex_out_tex_coord0 = tex_coord0;
|
||||||
|
vertex_out_tex_coord1 = (modelview_matrix_n * vec4(tex_coord1, 0, 1)).xy;
|
||||||
gl_Position = projection_matrix * modelview_matrix * vec4(vertex, 0, 1);
|
gl_Position = projection_matrix * modelview_matrix * vec4(vertex, 0, 1);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
|
// TODO: Now this shader is not used
|
||||||
shaderFragment: {
|
shaderFragment: {
|
||||||
shaderType: gl.FRAGMENT_SHADER,
|
shaderType: gl.FRAGMENT_SHADER,
|
||||||
source: `
|
source: `
|
||||||
uniform sampler2D texture;
|
uniform sampler2D texture;
|
||||||
varying vec2 vertex_out_tex_coord;
|
varying vec2 vertex_out_tex_coord0;
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
gl_FragColor = texture2D(texture, vertex_out_tex_coord);
|
gl_FragColor = texture2D(texture, vertex_out_tex_coord0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
shaderColorMatrix: {
|
shaderColorMatrix: {
|
||||||
shaderType: gl.FRAGMENT_SHADER,
|
shaderType: gl.FRAGMENT_SHADER,
|
||||||
source: `
|
source: `
|
||||||
uniform sampler2D texture;
|
uniform sampler2D texture0;
|
||||||
|
uniform sampler2D texture1;
|
||||||
uniform mat4 color_matrix;
|
uniform mat4 color_matrix;
|
||||||
uniform vec4 color_matrix_translation;
|
uniform vec4 color_matrix_translation;
|
||||||
varying vec2 vertex_out_tex_coord;
|
varying vec2 vertex_out_tex_coord0;
|
||||||
|
varying vec2 vertex_out_tex_coord1;
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
vec4 color = texture2D(texture, vertex_out_tex_coord);
|
vec4 color0 = texture2D(texture0, vertex_out_tex_coord0);
|
||||||
gl_FragColor = (color_matrix * color) + color_matrix_translation;
|
vec4 color1 = texture2D(texture1, vertex_out_tex_coord1);
|
||||||
|
color0 = (color_matrix * color0) + color_matrix_translation;
|
||||||
|
|
||||||
|
gl_FragColor.a = color0.a + color1.a - color0.a * color1.a;
|
||||||
|
gl_FragColor.rgb = (color0.a * color0.rgb + (1.0 - color0.a) * color1.a * color1.rgb) / gl_FragColor.a;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
|
// TODO: Now this shader is not used
|
||||||
shaderSolidColor: {
|
shaderSolidColor: {
|
||||||
shaderType: gl.FRAGMENT_SHADER,
|
shaderType: gl.FRAGMENT_SHADER,
|
||||||
source: `
|
source: `
|
||||||
|
@ -16,6 +16,7 @@ limitations under the License.
|
|||||||
|
|
||||||
package shader
|
package shader
|
||||||
|
|
||||||
|
// TODO: Rename X1, X2 -> X0, X1
|
||||||
type TextureQuad struct {
|
type TextureQuad struct {
|
||||||
VertexX1 float32
|
VertexX1 float32
|
||||||
VertexX2 float32
|
VertexX2 float32
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/go-gl/gl"
|
"github.com/go-gl/gl"
|
||||||
|
"github.com/hajimehoshi/ebiten/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
func orthoProjectionMatrix(left, right, bottom, top int) [4][4]float64 {
|
func orthoProjectionMatrix(left, right, bottom, top int) [4][4]float64 {
|
||||||
@ -43,12 +44,23 @@ type RenderTarget struct {
|
|||||||
flipY bool
|
flipY bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRenderTarget(width, height int, flipY bool) *RenderTarget {
|
func NewZeroRenderTarget(width, height int, flipY bool) (*RenderTarget, *Texture, error) {
|
||||||
return &RenderTarget{
|
r := &RenderTarget{
|
||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
flipY: flipY,
|
flipY: flipY,
|
||||||
}
|
}
|
||||||
|
// The framebuffer 0 can't be enlarged, so any filter is acceptable.
|
||||||
|
t, err := NewTexture(width, height, gl.NEAREST)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
// TODO: Does this affect the current rendering target?
|
||||||
|
gl.Framebuffer(0).Bind()
|
||||||
|
if err := framebufferTexture(t.native); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return r, t, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRenderTargetFromTexture(texture *Texture) (*RenderTarget, error) {
|
func NewRenderTargetFromTexture(texture *Texture) (*RenderTarget, error) {
|
||||||
@ -80,22 +92,28 @@ func (r *RenderTarget) Dispose() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func createFramebuffer(nativeTexture gl.Texture) (gl.Framebuffer, error) {
|
func createFramebuffer(nativeTexture gl.Texture) (gl.Framebuffer, error) {
|
||||||
|
// TODO: Does this affect the current rendering target?
|
||||||
framebuffer := gl.GenFramebuffer()
|
framebuffer := gl.GenFramebuffer()
|
||||||
framebuffer.Bind()
|
framebuffer.Bind()
|
||||||
|
|
||||||
gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, nativeTexture, 0)
|
if err := framebufferTexture(nativeTexture); err != nil {
|
||||||
if gl.CheckFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE {
|
return 0, err
|
||||||
return 0, errors.New("creating framebuffer failed")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set this framebuffer opaque because alpha values on a target might be
|
|
||||||
// confusing.
|
|
||||||
gl.ClearColor(0, 0, 0, 1)
|
|
||||||
gl.Clear(gl.COLOR_BUFFER_BIT)
|
|
||||||
|
|
||||||
return framebuffer, nil
|
return framebuffer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func framebufferTexture(nativeTexture gl.Texture) error {
|
||||||
|
gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, nativeTexture, 0)
|
||||||
|
if gl.CheckFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE {
|
||||||
|
return errors.New("creating framebuffer failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
gl.ClearColor(0, 0, 0, 0)
|
||||||
|
gl.Clear(gl.COLOR_BUFFER_BIT)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *RenderTarget) SetAsViewport() error {
|
func (r *RenderTarget) SetAsViewport() error {
|
||||||
gl.Flush()
|
gl.Flush()
|
||||||
r.framebuffer.Bind()
|
r.framebuffer.Bind()
|
||||||
@ -104,21 +122,19 @@ func (r *RenderTarget) SetAsViewport() error {
|
|||||||
return errors.New(fmt.Sprintf("glBindFramebuffer failed: %d", err))
|
return errors.New(fmt.Sprintf("glBindFramebuffer failed: %d", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
gl.BlendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ZERO, gl.ONE)
|
width := internal.AdjustSizeForTexture(r.width)
|
||||||
|
height := internal.AdjustSizeForTexture(r.height)
|
||||||
width := AdjustSizeForTexture(r.width)
|
|
||||||
height := AdjustSizeForTexture(r.height)
|
|
||||||
gl.Viewport(0, 0, width, height)
|
gl.Viewport(0, 0, width, height)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RenderTarget) ProjectionMatrix() [4][4]float64 {
|
func (r *RenderTarget) ProjectionMatrix() [4][4]float64 {
|
||||||
width := AdjustSizeForTexture(r.width)
|
width := internal.AdjustSizeForTexture(r.width)
|
||||||
height := AdjustSizeForTexture(r.height)
|
height := internal.AdjustSizeForTexture(r.height)
|
||||||
m := orthoProjectionMatrix(0, width, 0, height)
|
m := orthoProjectionMatrix(0, width, 0, height)
|
||||||
if r.flipY {
|
if r.flipY {
|
||||||
m[1][1] *= -1
|
m[1][1] *= -1
|
||||||
m[1][3] += float64(r.height) / float64(AdjustSizeForTexture(r.height)) * 2
|
m[1][3] += float64(r.height) / float64(internal.AdjustSizeForTexture(r.height)) * 2
|
||||||
}
|
}
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
@ -18,32 +18,18 @@ package opengl
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/go-gl/gl"
|
"github.com/go-gl/gl"
|
||||||
|
"github.com/hajimehoshi/ebiten/internal"
|
||||||
"image"
|
"image"
|
||||||
"image/draw"
|
"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
|
|
||||||
}
|
|
||||||
|
|
||||||
func AdjustSizeForTexture(size int) int {
|
|
||||||
return int(NextPowerOf2(uint64(size)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func adjustImageForTexture(img image.Image) *image.NRGBA {
|
func adjustImageForTexture(img image.Image) *image.NRGBA {
|
||||||
width, height := img.Bounds().Size().X, img.Bounds().Size().Y
|
width, height := img.Bounds().Size().X, img.Bounds().Size().Y
|
||||||
adjustedImageBounds := image.Rectangle{
|
adjustedImageBounds := image.Rectangle{
|
||||||
image.ZP,
|
image.ZP,
|
||||||
image.Point{
|
image.Point{
|
||||||
AdjustSizeForTexture(width),
|
internal.AdjustSizeForTexture(width),
|
||||||
AdjustSizeForTexture(height),
|
internal.AdjustSizeForTexture(height),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if nrgba, ok := img.(*image.NRGBA); ok && img.Bounds() == adjustedImageBounds {
|
if nrgba, ok := img.(*image.NRGBA); ok && img.Bounds() == adjustedImageBounds {
|
||||||
@ -95,8 +81,8 @@ func createNativeTexture(textureWidth, textureHeight int, pixels []uint8, filter
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewTexture(width, height int, filter int) (*Texture, error) {
|
func NewTexture(width, height int, filter int) (*Texture, error) {
|
||||||
w := AdjustSizeForTexture(width)
|
w := internal.AdjustSizeForTexture(width)
|
||||||
h := AdjustSizeForTexture(height)
|
h := internal.AdjustSizeForTexture(height)
|
||||||
native := createNativeTexture(w, h, nil, filter)
|
native := createNativeTexture(w, h, nil, filter)
|
||||||
return &Texture{native, width, height}, nil
|
return &Texture{native, width, height}, nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user