mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 10:48:53 +01:00
internal/shader: implement a new built-in function discard
Closes #1969
This commit is contained in:
parent
2b248ef783
commit
205245b094
@ -469,6 +469,14 @@ func (cs *compileState) parseExpr(block *block, expr ast.Expr, markLocalVariable
|
||||
case shaderir.Texture2DF:
|
||||
// TODO: Check arg types.
|
||||
t = shaderir.Type{Main: shaderir.Vec4}
|
||||
case shaderir.DiscardF:
|
||||
if len(args) != 0 {
|
||||
cs.addError(e.Pos(), fmt.Sprintf("number of %s's arguments must be 0 but %d", callee.BuiltinFunc, len(args)))
|
||||
}
|
||||
stmts = append(stmts, shaderir.Stmt{
|
||||
Type: shaderir.Discard,
|
||||
})
|
||||
return nil, nil, stmts, true
|
||||
default:
|
||||
// TODO: Check arg types.
|
||||
// If the argument is a non-typed constant value, treat is as a float value (#1874).
|
||||
|
@ -503,7 +503,7 @@ func (c *compileContext) block(p *shaderir.Program, topBlock, block *shaderir.Bl
|
||||
lines = append(lines, fmt.Sprintf("%sreturn %s;", idt, expr(&s.Exprs[0])))
|
||||
}
|
||||
case shaderir.Discard:
|
||||
lines = append(lines, idt+"discard;")
|
||||
lines = append(lines, idt+"discard_fragment();")
|
||||
default:
|
||||
lines = append(lines, fmt.Sprintf("%s?(unexpected stmt: %d)", idt, s.Type))
|
||||
}
|
||||
|
@ -265,6 +265,7 @@ const (
|
||||
Dfdx BuiltinFunc = "dfdx"
|
||||
Dfdy BuiltinFunc = "dfdy"
|
||||
Fwidth BuiltinFunc = "fwidth"
|
||||
DiscardF BuiltinFunc = "discard"
|
||||
)
|
||||
|
||||
func ParseBuiltinFunc(str string) (BuiltinFunc, bool) {
|
||||
@ -317,7 +318,8 @@ func ParseBuiltinFunc(str string) (BuiltinFunc, bool) {
|
||||
Texture2DF,
|
||||
Dfdx,
|
||||
Dfdy,
|
||||
Fwidth:
|
||||
Fwidth,
|
||||
DiscardF:
|
||||
return BuiltinFunc(str), true
|
||||
}
|
||||
return "", false
|
||||
|
@ -1129,3 +1129,55 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Issue #1969
|
||||
func TestShaderDiscard(t *testing.T) {
|
||||
const w, h = 16, 16
|
||||
|
||||
dst := ebiten.NewImage(w, h)
|
||||
dst.Fill(color.RGBA{0xff, 0, 0, 0xff})
|
||||
|
||||
src := ebiten.NewImage(w, h)
|
||||
pix := make([]byte, 4*w*h)
|
||||
for j := 0; j < h; j++ {
|
||||
for i := 0; i < w; i++ {
|
||||
if i >= w/2 || j >= h/2 {
|
||||
continue
|
||||
}
|
||||
pix[4*(j*w+i)+3] = 0xff
|
||||
}
|
||||
}
|
||||
src.WritePixels(pix)
|
||||
|
||||
s, err := ebiten.NewShader([]byte(`package main
|
||||
|
||||
func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
|
||||
p := imageSrc0At(texCoord)
|
||||
if p.a == 0 {
|
||||
discard()
|
||||
} else {
|
||||
return vec4(0, 1, 0, 1)
|
||||
}
|
||||
}
|
||||
`))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
op := &ebiten.DrawRectShaderOptions{}
|
||||
op.Images[0] = src
|
||||
dst.DrawRectShader(w, h, s, op)
|
||||
|
||||
for j := 0; j < h; j++ {
|
||||
for i := 0; i < w; i++ {
|
||||
got := dst.At(i, j).(color.RGBA)
|
||||
want := color.RGBA{0, 0xff, 0x00, 0xff}
|
||||
if i >= w/2 || j >= h/2 {
|
||||
want = color.RGBA{0xff, 0, 0x00, 0xff}
|
||||
}
|
||||
if !sameColors(got, want, 2) {
|
||||
t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user