internal/ui: use a Kage shader for Fill

Updates #2364
This commit is contained in:
Hajime Hoshi 2022-10-02 16:05:32 +09:00
parent 7b6f726729
commit eea11ba6cb
2 changed files with 37 additions and 34 deletions

View File

@ -31,7 +31,7 @@ import (
"github.com/hajimehoshi/ebiten/v2/internal/hooks" "github.com/hajimehoshi/ebiten/v2/internal/hooks"
) )
const screenShader = `package main const screenShaderSrc = `package main
var Scale vec2 var Scale vec2
@ -65,6 +65,36 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
} }
` `
var (
screenShader *Shader
nearestShader *Shader
linearShader *Shader
)
func init() {
{
ir, err := graphics.CompileShader([]byte(screenShaderSrc))
if err != nil {
panic(fmt.Sprintf("ui: compiling the screen shader failed: %v", err))
}
screenShader = NewShader(ir)
}
{
ir, err := graphics.CompileShader([]byte(builtinshader.Shader(graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, false)))
if err != nil {
panic(fmt.Sprintf("ui: compiling the nearest shader failed: %v", err))
}
nearestShader = NewShader(ir)
}
{
ir, err := graphics.CompileShader([]byte(builtinshader.Shader(graphicsdriver.FilterLinear, graphicsdriver.AddressUnsafe, false)))
if err != nil {
panic(fmt.Sprintf("ui: compiling the linear shader failed: %v", err))
}
linearShader = NewShader(ir)
}
}
type Game interface { type Game interface {
NewOffscreenImage(width, height int) *Image NewOffscreenImage(width, height int) *Image
Layout(outsideWidth, outsideHeight int) (int, int) Layout(outsideWidth, outsideHeight int) (int, int)
@ -84,10 +114,6 @@ type context struct {
outsideWidth float64 outsideWidth float64
outsideHeight float64 outsideHeight float64
screenShader *Shader
nearestShader *Shader
linearShader *Shader
m sync.Mutex m sync.Mutex
} }
@ -150,29 +176,6 @@ func (c *context) updateFrameImpl(graphicsDriver graphicsdriver.Graphics, update
} }
}() }()
// Create a shader for the screen if necessary.
if c.screenShader == nil {
ir, err := graphics.CompileShader([]byte(screenShader))
if err != nil {
return err
}
c.screenShader = NewShader(ir)
}
if c.nearestShader == nil {
ir, err := graphics.CompileShader([]byte(builtinshader.Shader(graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, false)))
if err != nil {
return err
}
c.nearestShader = NewShader(ir)
}
if c.linearShader == nil {
ir, err := graphics.CompileShader([]byte(builtinshader.Shader(graphicsdriver.FilterLinear, graphicsdriver.AddressUnsafe, false)))
if err != nil {
return err
}
c.linearShader = NewShader(ir)
}
// ForceUpdate can be invoked even if the context is not initialized yet (#1591). // ForceUpdate can be invoked even if the context is not initialized yet (#1591).
if w, h := c.layoutGame(outsideWidth, outsideHeight, deviceScaleFactor); w == 0 || h == 0 { if w, h := c.layoutGame(outsideWidth, outsideHeight, deviceScaleFactor); w == 0 || h == 0 {
return nil return nil
@ -253,15 +256,15 @@ func (c *context) drawGame(graphicsDriver graphicsdriver.Graphics) {
var shader *Shader var shader *Shader
switch { switch {
case !theGlobalState.isScreenFilterEnabled(): case !theGlobalState.isScreenFilterEnabled():
shader = c.nearestShader shader = nearestShader
case math.Floor(s) == s: case math.Floor(s) == s:
shader = c.nearestShader shader = nearestShader
case s > 1: case s > 1:
shader = c.screenShader shader = screenShader
default: default:
// screenShader works with >=1 scale, but does not well with <1 scale. // screenShader works with >=1 scale, but does not well with <1 scale.
// Use regular FilterLinear instead so far (#669). // Use regular FilterLinear instead so far (#669).
shader = c.linearShader shader = linearShader
} }
dstRegion := graphicsdriver.Region{ dstRegion := graphicsdriver.Region{
@ -282,7 +285,7 @@ func (c *context) drawGame(graphicsDriver graphicsdriver.Graphics) {
dstWidth, dstHeight := c.screen.width, c.screen.height dstWidth, dstHeight := c.screen.width, c.screen.height
srcWidth, srcHeight := c.offscreen.width, c.offscreen.height srcWidth, srcHeight := c.offscreen.width, c.offscreen.height
var uniforms [][]float32 var uniforms [][]float32
if shader == c.screenShader { if shader == screenShader {
uniforms = shader.ConvertUniforms(map[string]interface{}{ uniforms = shader.ConvertUniforms(map[string]interface{}{
"Scale": []float32{ "Scale": []float32{
float32(dstWidth) / float32(srcWidth), float32(dstWidth) / float32(srcWidth),

View File

@ -236,5 +236,5 @@ func (i *Image) Fill(r, g, b, a float32, x, y, width, height int) {
srcs := [graphics.ShaderImageCount]*Image{emptyImage} srcs := [graphics.ShaderImageCount]*Image{emptyImage}
i.DrawTriangles(srcs, vs, is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeCopy, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dstRegion, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, nil, nil, false, true) i.DrawTriangles(srcs, vs, is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeCopy, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dstRegion, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, nearestShader, nil, false, true)
} }