mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 04:57:26 +01:00
ebiten: Allow SubImage at DrawTriangles
This commit is contained in:
parent
41564533f9
commit
0db7dc22b2
28
image.go
28
image.go
@ -420,10 +420,6 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o
|
|||||||
options = &DrawTrianglesOptions{}
|
options = &DrawTrianglesOptions{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.Shader != nil && img != nil && img.isSubImage() {
|
|
||||||
panic("ebiten: rendering a sub-image with a shader is not implemented (DrawTriangles)")
|
|
||||||
}
|
|
||||||
|
|
||||||
mode := driver.CompositeMode(options.CompositeMode)
|
mode := driver.CompositeMode(options.CompositeMode)
|
||||||
|
|
||||||
filter := driver.FilterNearest
|
filter := driver.FilterNearest
|
||||||
@ -450,7 +446,11 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o
|
|||||||
copy(is, indices)
|
copy(is, indices)
|
||||||
|
|
||||||
var sr driver.Region
|
var sr driver.Region
|
||||||
b := img.Bounds()
|
var b image.Rectangle
|
||||||
|
if img != nil {
|
||||||
|
b = img.Bounds()
|
||||||
|
}
|
||||||
|
|
||||||
// Pass the source region only when the shader is used, since this affects the condition of merging graphics
|
// Pass the source region only when the shader is used, since this affects the condition of merging graphics
|
||||||
// commands (#1293).
|
// commands (#1293).
|
||||||
if options.Shader != nil || options.Address != AddressUnsafe {
|
if options.Shader != nil || options.Address != AddressUnsafe {
|
||||||
@ -463,11 +463,17 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o
|
|||||||
}
|
}
|
||||||
|
|
||||||
var srcs [graphics.ShaderImageNum]*mipmap.Mipmap
|
var srcs [graphics.ShaderImageNum]*mipmap.Mipmap
|
||||||
|
|
||||||
var imgw, imgh int
|
var imgw, imgh int
|
||||||
|
var sx, sy float32
|
||||||
if img != nil {
|
if img != nil {
|
||||||
srcs[0] = img.mipmap
|
srcs[0] = img.mipmap
|
||||||
imgw, imgh = img.Size()
|
imgw, imgh = img.Size()
|
||||||
|
sx = float32(b.Min.X)
|
||||||
|
sy = float32(b.Min.Y)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var offsets [graphics.ShaderImageNum - 1][2]float32
|
||||||
for i, img := range options.Images {
|
for i, img := range options.Images {
|
||||||
if img == nil {
|
if img == nil {
|
||||||
continue
|
continue
|
||||||
@ -475,23 +481,23 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o
|
|||||||
if img.isDisposed() {
|
if img.isDisposed() {
|
||||||
panic("ebiten: the given image to DrawTriangles must not be disposed")
|
panic("ebiten: the given image to DrawTriangles must not be disposed")
|
||||||
}
|
}
|
||||||
if img.isSubImage() {
|
|
||||||
// TODO: Implement this.
|
|
||||||
panic("ebiten: rendering a sub-image is not implemented (DrawTriangles)")
|
|
||||||
}
|
|
||||||
if w, h := img.Size(); imgw != w || imgh != h {
|
if w, h := img.Size(); imgw != w || imgh != h {
|
||||||
panic("ebiten: all the source images must be the same size")
|
panic("ebiten: all the source images must be the same size")
|
||||||
}
|
}
|
||||||
srcs[i+1] = img.mipmap
|
srcs[i+1] = img.mipmap
|
||||||
|
|
||||||
|
b := img.Bounds()
|
||||||
|
offsets[i][0] = -sx + float32(b.Min.X)
|
||||||
|
offsets[i][1] = -sy + float32(b.Min.Y)
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.Shader == nil {
|
if options.Shader == nil {
|
||||||
i.mipmap.DrawTriangles(srcs, vs, is, options.ColorM.impl, mode, filter, driver.Address(options.Address), sr, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
i.mipmap.DrawTriangles(srcs, vs, is, options.ColorM.impl, mode, filter, driver.Address(options.Address), sr, offsets, nil, nil, false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
us := options.Shader.convertUniforms(options.Uniforms)
|
us := options.Shader.convertUniforms(options.Uniforms)
|
||||||
i.mipmap.DrawTriangles(srcs, vs, is, nil, mode, driver.FilterNearest, driver.AddressUnsafe, sr, [graphics.ShaderImageNum - 1][2]float32{}, options.Shader.shader, us, false)
|
i.mipmap.DrawTriangles(srcs, vs, is, nil, mode, driver.FilterNearest, driver.AddressUnsafe, sr, offsets, options.Shader.shader, us, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DrawRectShaderOptions represents options for DrawRectShader
|
// DrawRectShaderOptions represents options for DrawRectShader
|
||||||
|
@ -803,7 +803,6 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
|
|||||||
func TestShaderSubImage(t *testing.T) {
|
func TestShaderSubImage(t *testing.T) {
|
||||||
const w, h = 16, 16
|
const w, h = 16, 16
|
||||||
|
|
||||||
dst, _ := NewImage(w, h, FilterDefault)
|
|
||||||
s, err := NewShader([]byte(`package main
|
s, err := NewShader([]byte(`package main
|
||||||
|
|
||||||
func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
|
func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
|
||||||
@ -829,6 +828,7 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
src0.ReplacePixels(pix0)
|
src0.ReplacePixels(pix0)
|
||||||
|
src0 = src0.SubImage(image.Rect(2, 2, 10, 10)).(*Image)
|
||||||
|
|
||||||
src1, _ := NewImage(w, h, FilterDefault)
|
src1, _ := NewImage(w, h, FilterDefault)
|
||||||
pix1 := make([]byte, 4*w*h)
|
pix1 := make([]byte, 4*w*h)
|
||||||
@ -843,22 +843,82 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
src1.ReplacePixels(pix1)
|
src1.ReplacePixels(pix1)
|
||||||
|
src1 = src1.SubImage(image.Rect(6, 6, 14, 14)).(*Image)
|
||||||
|
|
||||||
op := &DrawRectShaderOptions{}
|
testPixels := func(testname string, dst *Image) {
|
||||||
op.Images[0] = src0.SubImage(image.Rect(2, 2, 10, 10)).(*Image)
|
for j := 0; j < h; j++ {
|
||||||
op.Images[1] = src1.SubImage(image.Rect(6, 6, 14, 14)).(*Image)
|
for i := 0; i < w; i++ {
|
||||||
dst.DrawRectShader(w/2, h/2, s, op)
|
got := dst.At(i, j).(color.RGBA)
|
||||||
|
var want color.RGBA
|
||||||
for j := 0; j < h; j++ {
|
if i < w/2 && j < h/2 {
|
||||||
for i := 0; i < w; i++ {
|
want = color.RGBA{0xff, 0xff, 0, 0xff}
|
||||||
got := dst.At(i, j).(color.RGBA)
|
}
|
||||||
var want color.RGBA
|
if got != want {
|
||||||
if i < w/2 && j < h/2 {
|
t.Errorf("%s dst.At(%d, %d): got: %v, want: %v", testname, i, j, got, want)
|
||||||
want = color.RGBA{0xff, 0xff, 0, 0xff}
|
}
|
||||||
}
|
|
||||||
if got != want {
|
|
||||||
t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.Run("DrawRectShader", func(t *testing.T) {
|
||||||
|
dst, _ := NewImage(w, h, FilterDefault)
|
||||||
|
op := &DrawRectShaderOptions{}
|
||||||
|
op.Images[0] = src0
|
||||||
|
op.Images[1] = src1
|
||||||
|
dst.DrawRectShader(w/2, h/2, s, op)
|
||||||
|
testPixels("DrawRectShader", dst)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("DrawTriangles", func(t *testing.T) {
|
||||||
|
dst, _ := NewImage(w, h, FilterDefault)
|
||||||
|
vs := []Vertex{
|
||||||
|
{
|
||||||
|
DstX: 0,
|
||||||
|
DstY: 0,
|
||||||
|
SrcX: 2,
|
||||||
|
SrcY: 2,
|
||||||
|
ColorR: 1,
|
||||||
|
ColorG: 1,
|
||||||
|
ColorB: 1,
|
||||||
|
ColorA: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
DstX: w / 2,
|
||||||
|
DstY: 0,
|
||||||
|
SrcX: 10,
|
||||||
|
SrcY: 2,
|
||||||
|
ColorR: 1,
|
||||||
|
ColorG: 1,
|
||||||
|
ColorB: 1,
|
||||||
|
ColorA: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
DstX: 0,
|
||||||
|
DstY: h / 2,
|
||||||
|
SrcX: 2,
|
||||||
|
SrcY: 10,
|
||||||
|
ColorR: 1,
|
||||||
|
ColorG: 1,
|
||||||
|
ColorB: 1,
|
||||||
|
ColorA: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
DstX: w / 2,
|
||||||
|
DstY: h / 2,
|
||||||
|
SrcX: 10,
|
||||||
|
SrcY: 10,
|
||||||
|
ColorR: 1,
|
||||||
|
ColorG: 1,
|
||||||
|
ColorB: 1,
|
||||||
|
ColorA: 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
is := []uint16{0, 1, 2, 1, 2, 3}
|
||||||
|
|
||||||
|
op := &DrawTrianglesOptions{}
|
||||||
|
op.Shader = s
|
||||||
|
op.Images[0] = src1
|
||||||
|
dst.DrawTriangles(vs, is, src0, op)
|
||||||
|
testPixels("DrawTriangles", dst)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user