mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 18:58:54 +01:00
ebiten: Bug fix: Stencil buffers should not be cleared until all the vertices are rendered
Updates #1684
This commit is contained in:
parent
b466a0cbd7
commit
daa883d799
127
image_test.go
127
image_test.go
@ -2240,3 +2240,130 @@ func TestImageSubImageFill(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestImageEvenOdd(t *testing.T) {
|
||||
emptyImage := NewImage(3, 3)
|
||||
emptyImage.Fill(color.White)
|
||||
emptySubImage := emptyImage.SubImage(image.Rect(1, 1, 2, 2)).(*Image)
|
||||
|
||||
vs0 := []Vertex{
|
||||
{
|
||||
DstX: 1, DstY: 1, SrcX: 1, SrcY: 1,
|
||||
ColorR: 1, ColorG: 0, ColorB: 0, ColorA: 1,
|
||||
},
|
||||
{
|
||||
DstX: 15, DstY: 1, SrcX: 1, SrcY: 1,
|
||||
ColorR: 1, ColorG: 0, ColorB: 0, ColorA: 1,
|
||||
},
|
||||
{
|
||||
DstX: 1, DstY: 15, SrcX: 1, SrcY: 1,
|
||||
ColorR: 1, ColorG: 0, ColorB: 0, ColorA: 1,
|
||||
},
|
||||
{
|
||||
DstX: 15, DstY: 15, SrcX: 1, SrcY: 1,
|
||||
ColorR: 1, ColorG: 0, ColorB: 0, ColorA: 1,
|
||||
},
|
||||
}
|
||||
is0 := []uint16{0, 1, 2, 1, 2, 3}
|
||||
|
||||
vs1 := []Vertex{
|
||||
{
|
||||
DstX: 2, DstY: 2, SrcX: 1, SrcY: 1,
|
||||
ColorR: 0, ColorG: 1, ColorB: 0, ColorA: 1,
|
||||
},
|
||||
{
|
||||
DstX: 14, DstY: 2, SrcX: 1, SrcY: 1,
|
||||
ColorR: 0, ColorG: 1, ColorB: 0, ColorA: 1,
|
||||
},
|
||||
{
|
||||
DstX: 2, DstY: 14, SrcX: 1, SrcY: 1,
|
||||
ColorR: 0, ColorG: 1, ColorB: 0, ColorA: 1,
|
||||
},
|
||||
{
|
||||
DstX: 14, DstY: 14, SrcX: 1, SrcY: 1,
|
||||
ColorR: 0, ColorG: 1, ColorB: 0, ColorA: 1,
|
||||
},
|
||||
}
|
||||
is1 := []uint16{4, 5, 6, 5, 6, 7}
|
||||
|
||||
vs2 := []Vertex{
|
||||
{
|
||||
DstX: 3, DstY: 3, SrcX: 1, SrcY: 1,
|
||||
ColorR: 0, ColorG: 0, ColorB: 1, ColorA: 1,
|
||||
},
|
||||
{
|
||||
DstX: 13, DstY: 3, SrcX: 1, SrcY: 1,
|
||||
ColorR: 0, ColorG: 0, ColorB: 1, ColorA: 1,
|
||||
},
|
||||
{
|
||||
DstX: 3, DstY: 13, SrcX: 1, SrcY: 1,
|
||||
ColorR: 0, ColorG: 0, ColorB: 1, ColorA: 1,
|
||||
},
|
||||
{
|
||||
DstX: 13, DstY: 13, SrcX: 1, SrcY: 1,
|
||||
ColorR: 0, ColorG: 0, ColorB: 1, ColorA: 1,
|
||||
},
|
||||
}
|
||||
is2 := []uint16{8, 9, 10, 9, 10, 11}
|
||||
|
||||
// Draw all the vertices once. The even-odd rule is applied for all the vertices once.
|
||||
dst := NewImage(16, 16)
|
||||
op := &DrawTrianglesOptions{
|
||||
EvenOdd: true,
|
||||
}
|
||||
dst.DrawTriangles(append(append(vs0, vs1...), vs2...), append(append(is0, is1...), is2...), emptySubImage, op)
|
||||
for j := 0; j < 16; j++ {
|
||||
for i := 0; i < 16; i++ {
|
||||
got := dst.At(i, j)
|
||||
var want color.RGBA
|
||||
switch {
|
||||
case 3 <= i && i < 13 && 3 <= j && j < 13:
|
||||
want = color.RGBA{0, 0, 0xff, 0xff}
|
||||
case 2 <= i && i < 14 && 2 <= j && j < 14:
|
||||
want = color.RGBA{0, 0, 0, 0}
|
||||
case 1 <= i && i < 15 && 1 <= j && j < 15:
|
||||
want = color.RGBA{0xff, 0, 0, 0xff}
|
||||
default:
|
||||
want = color.RGBA{0, 0, 0, 0}
|
||||
}
|
||||
if got != want {
|
||||
t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Do the same thing with a little shift. This confirms that the underlying stencil buffer is cleared correctly.
|
||||
for i := range vs0 {
|
||||
vs0[i].DstX++
|
||||
vs0[i].DstY++
|
||||
}
|
||||
for i := range vs1 {
|
||||
vs1[i].DstX++
|
||||
vs1[i].DstY++
|
||||
}
|
||||
for i := range vs2 {
|
||||
vs2[i].DstX++
|
||||
vs2[i].DstY++
|
||||
}
|
||||
dst.Clear()
|
||||
dst.DrawTriangles(append(append(vs0, vs1...), vs2...), append(append(is0, is1...), is2...), emptySubImage, op)
|
||||
for j := 0; j < 16; j++ {
|
||||
for i := 0; i < 16; i++ {
|
||||
got := dst.At(i, j)
|
||||
var want color.RGBA
|
||||
switch {
|
||||
case 4 <= i && i < 14 && 4 <= j && j < 14:
|
||||
want = color.RGBA{0, 0, 0xff, 0xff}
|
||||
case 3 <= i && i < 15 && 3 <= j && j < 15:
|
||||
want = color.RGBA{0, 0, 0, 0}
|
||||
case 2 <= i && i < 16 && 2 <= j && j < 16:
|
||||
want = color.RGBA{0xff, 0, 0, 0xff}
|
||||
default:
|
||||
want = color.RGBA{0, 0, 0, 0}
|
||||
}
|
||||
if got != want {
|
||||
t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -745,15 +745,15 @@ func (g *Graphics) draw(rps mtl.RenderPipelineState, dst *Image, dstRegion drive
|
||||
case drawWithStencil:
|
||||
desc := mtl.DepthStencilDescriptor{
|
||||
BackFaceStencil: mtl.StencilDescriptor{
|
||||
StencilFailureOperation: mtl.StencilOperationZero,
|
||||
DepthFailureOperation: mtl.StencilOperationZero,
|
||||
DepthStencilPassOperation: mtl.StencilOperationZero,
|
||||
StencilFailureOperation: mtl.StencilOperationKeep,
|
||||
DepthFailureOperation: mtl.StencilOperationKeep,
|
||||
DepthStencilPassOperation: mtl.StencilOperationKeep,
|
||||
StencilCompareFunction: mtl.CompareFunctionNotEqual,
|
||||
},
|
||||
FrontFaceStencil: mtl.StencilDescriptor{
|
||||
StencilFailureOperation: mtl.StencilOperationZero,
|
||||
DepthFailureOperation: mtl.StencilOperationZero,
|
||||
DepthStencilPassOperation: mtl.StencilOperationZero,
|
||||
StencilFailureOperation: mtl.StencilOperationKeep,
|
||||
DepthFailureOperation: mtl.StencilOperationKeep,
|
||||
DepthStencilPassOperation: mtl.StencilOperationKeep,
|
||||
StencilCompareFunction: mtl.CompareFunctionNotEqual,
|
||||
},
|
||||
}
|
||||
|
@ -264,7 +264,6 @@ func (c *context) bindStencilBuffer(f framebufferNative, r renderbufferNative) e
|
||||
if s := gl.CheckFramebufferStatusEXT(gl.FRAMEBUFFER); s != gl.FRAMEBUFFER_COMPLETE {
|
||||
return errors.New(fmt.Sprintf("opengl: glFramebufferRenderbuffer failed: %d", s))
|
||||
}
|
||||
gl.Clear(gl.STENCIL_BUFFER_BIT)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -550,6 +549,7 @@ func (c *context) disableStencilTest() {
|
||||
}
|
||||
|
||||
func (c *context) beginStencilWithEvenOddRule() {
|
||||
gl.Clear(gl.STENCIL_BUFFER_BIT)
|
||||
gl.StencilFunc(gl.ALWAYS, 0x00, 0xff)
|
||||
gl.StencilOp(gl.KEEP, gl.KEEP, gl.INVERT)
|
||||
gl.ColorMask(false, false, false, false)
|
||||
@ -557,6 +557,6 @@ func (c *context) beginStencilWithEvenOddRule() {
|
||||
|
||||
func (c *context) endStencilWithEvenOddRule() {
|
||||
gl.StencilFunc(gl.NOTEQUAL, 0x00, 0xff)
|
||||
gl.StencilOp(gl.ZERO, gl.ZERO, gl.ZERO)
|
||||
gl.StencilOp(gl.KEEP, gl.KEEP, gl.KEEP)
|
||||
gl.ColorMask(true, true, true, true)
|
||||
}
|
||||
|
@ -298,7 +298,6 @@ func (c *context) bindStencilBuffer(f framebufferNative, r renderbufferNative) e
|
||||
if s := gl.checkFramebufferStatus.Invoke(gles.FRAMEBUFFER); s.Int() != gles.FRAMEBUFFER_COMPLETE {
|
||||
return errors.New(fmt.Sprintf("opengl: framebufferRenderbuffer failed: %d", s.Int()))
|
||||
}
|
||||
gl.clear.Invoke(gles.STENCIL_BUFFER_BIT)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -660,6 +659,7 @@ func (c *context) disableStencilTest() {
|
||||
|
||||
func (c *context) beginStencilWithEvenOddRule() {
|
||||
gl := c.gl
|
||||
gl.clear.Invoke(gles.STENCIL_BUFFER_BIT)
|
||||
gl.stencilFunc.Invoke(gles.ALWAYS, 0x00, 0xff)
|
||||
gl.stencilOp.Invoke(gles.KEEP, gles.KEEP, gles.INVERT)
|
||||
gl.colorMask.Invoke(false, false, false, false)
|
||||
@ -668,6 +668,6 @@ func (c *context) beginStencilWithEvenOddRule() {
|
||||
func (c *context) endStencilWithEvenOddRule() {
|
||||
gl := c.gl
|
||||
gl.stencilFunc.Invoke(gles.NOTEQUAL, 0x00, 0xff)
|
||||
gl.stencilOp.Invoke(gles.ZERO, gles.ZERO, gles.ZERO)
|
||||
gl.stencilOp.Invoke(gles.KEEP, gles.KEEP, gles.KEEP)
|
||||
gl.colorMask.Invoke(true, true, true, true)
|
||||
}
|
||||
|
@ -246,7 +246,6 @@ func (c *context) bindStencilBuffer(f framebufferNative, r renderbufferNative) e
|
||||
if s := c.ctx.CheckFramebufferStatus(gles.FRAMEBUFFER); s != gles.FRAMEBUFFER_COMPLETE {
|
||||
return errors.New(fmt.Sprintf("opengl: glFramebufferRenderbuffer failed: %d", s))
|
||||
}
|
||||
c.ctx.Clear(gles.STENCIL_BUFFER_BIT)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -511,6 +510,7 @@ func (c *context) disableStencilTest() {
|
||||
}
|
||||
|
||||
func (c *context) beginStencilWithEvenOddRule() {
|
||||
c.ctx.Clear(gles.STENCIL_BUFFER_BIT)
|
||||
c.ctx.StencilFunc(gles.ALWAYS, 0x00, 0xff)
|
||||
c.ctx.StencilOp(gles.KEEP, gles.KEEP, gles.INVERT)
|
||||
c.ctx.ColorMask(false, false, false, false)
|
||||
@ -518,6 +518,6 @@ func (c *context) beginStencilWithEvenOddRule() {
|
||||
|
||||
func (c *context) endStencilWithEvenOddRule() {
|
||||
c.ctx.StencilFunc(gles.NOTEQUAL, 0x00, 0xff)
|
||||
c.ctx.StencilOp(gles.ZERO, gles.ZERO, gles.ZERO)
|
||||
c.ctx.StencilOp(gles.KEEP, gles.KEEP, gles.KEEP)
|
||||
c.ctx.ColorMask(true, true, true, true)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user