diff --git a/image.go b/image.go index 0774f64e5..bea6e4374 100644 --- a/image.go +++ b/image.go @@ -21,7 +21,6 @@ import ( "github.com/hajimehoshi/ebiten/v2/internal/affine" "github.com/hajimehoshi/ebiten/v2/internal/atlas" - "github.com/hajimehoshi/ebiten/v2/internal/builtinshader" "github.com/hajimehoshi/ebiten/v2/internal/graphics" "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver" "github.com/hajimehoshi/ebiten/v2/internal/ui" @@ -234,22 +233,7 @@ func (i *Image) DrawImage(img *Image, options *DrawImageOptions) { srcs := [graphics.ShaderImageCount]*ui.Image{img.image} - useColorM := !colorm.IsIdentity() - var shader *ui.Shader - var uniforms [][]float32 - if useColorM { - s := builtinShader(graphicsdriver.Filter(filter), graphicsdriver.AddressUnsafe) - var body [16]float32 - var translation [4]float32 - colorm.Elements(body[:], translation[:]) - uniforms = s.convertUniforms(map[string]interface{}{ - builtinshader.UniformColorMBody: body[:], - builtinshader.UniformColorMTranslation: translation[:], - }) - shader = s.shader - } - - i.image.DrawTriangles(srcs, vs, is, affine.ColorMIdentity{}, mode, filter, graphicsdriver.AddressUnsafe, i.adjustedRegion(), graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, shader, uniforms, false, canSkipMipmap(options.GeoM, filter)) + i.image.DrawTriangles(srcs, vs, is, colorm, mode, filter, graphicsdriver.AddressUnsafe, i.adjustedRegion(), graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, nil, nil, false, canSkipMipmap(options.GeoM, filter)) } // Vertex represents a vertex passed to DrawTriangles. @@ -414,22 +398,7 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o srcs := [graphics.ShaderImageCount]*ui.Image{img.image} - useColorM := !colorm.IsIdentity() - var shader *ui.Shader - var uniforms [][]float32 - if useColorM { - s := builtinShader(graphicsdriver.Filter(filter), graphicsdriver.Address(address)) - var body [16]float32 - var translation [4]float32 - colorm.Elements(body[:], translation[:]) - uniforms = s.convertUniforms(map[string]interface{}{ - builtinshader.UniformColorMBody: body[:], - builtinshader.UniformColorMTranslation: translation[:], - }) - shader = s.shader - } - - i.image.DrawTriangles(srcs, vs, is, affine.ColorMIdentity{}, mode, filter, address, i.adjustedRegion(), sr, [graphics.ShaderImageCount - 1][2]float32{}, shader, uniforms, options.FillRule == EvenOdd, false) + i.image.DrawTriangles(srcs, vs, is, colorm, mode, filter, address, i.adjustedRegion(), sr, [graphics.ShaderImageCount - 1][2]float32{}, nil, nil, options.FillRule == EvenOdd, false) } // DrawTrianglesShaderOptions represents options for DrawTrianglesShader. diff --git a/internal/builtinshader/shader.go b/internal/builtinshader/shader.go deleted file mode 100644 index 4ff46857e..000000000 --- a/internal/builtinshader/shader.go +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright 2022 The Ebitengine Authors -// -// 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 builtinshader - -import ( - "bytes" - "fmt" - "sync" - "text/template" - - "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver" -) - -const ( - UniformColorMBody = "ColorMBody" - UniformColorMTranslation = "ColorMTranslation" -) - -type key struct { - Filter graphicsdriver.Filter - Address graphicsdriver.Address - UseColorM bool -} - -var ( - shaders = map[key][]byte{} - shadersM sync.Mutex -) - -var tmpl = template.Must(template.New("tmpl").Parse(`package main - -{{if .UseColorM}} -var ColorMBody mat4 -var ColorMTranslation vec4 -{{end}} - -{{if eq .Address .AddressRepeat}} -func adjustTexelForAddressRepeat(p vec2) vec2 { - origin, size := imageSrcRegionOnTexture() - return mod(p - origin, size) + origin -} -{{end}} - -func Fragment(position vec4, texCoord vec2, color vec4) vec4 { -{{if eq .Filter .FilterNearest}} -{{if eq .Address .AddressUnsafe}} - clr := imageSrc0UnsafeAt(texCoord) -{{else if eq .Address .AddressClampToZero}} - clr := imageSrc0At(texCoord) -{{else if eq .Address .AddressRepeat}} - clr := imageSrc0At(adjustTexelForAddressRepeat(texCoord)) -{{end}} -{{else if eq .Filter .FilterLinear}} - sourceSize := imageSrcTextureSize() - texelSize := 1 / sourceSize - - // Shift 1/512 [texel] to avoid the tie-breaking issue (#1212). - // As all the vertex positions are aligned to 1/16 [pixel], this shiting should work in most cases. - p0 := texCoord - texelSize/2 + texelSize/512 - p1 := texCoord + texelSize/2 + texelSize/512 - -{{if eq .Address .AddressRpeat}} - p0 = adjustTexelForAddressRepeat(p0) - p1 = adjustTexelForAddressRepeat(p1) -{{end}} - -{{if eq .Address .AddressUnsafe}} - c0 := imageSrc0UnsafeAt(p0) - c1 := imageSrc0UnsafeAt(vec2(p1.x, p0.y)) - c2 := imageSrc0UnsafeAt(vec2(p0.x, p1.y)) - c3 := imageSrc0UnsafeAt(p1) -{{else}} - c0 := imageSrc0At(p0) - c1 := imageSrc0At(vec2(p1.x, p0.y)) - c2 := imageSrc0At(vec2(p0.x, p1.y)) - c3 := imageSrc0At(p1) -{{end}} - - rate := fract(p0 * sourceSize) - clr := mix(mix(c0, c1, rate.x), mix(c2, c3, rate.x), rate.y) -{{end}} - -{{if .UseColorM}} - // Un-premultiply alpha. - // When the alpha is 0, 1-sign(alpha) is 1.0, which means division does nothing. - clr.rgb /= clr.a + (1-sign(clr.a)) - // Apply the clr matrix or scale. - clr = (ColorMBody * clr) + ColorMTranslation - // Premultiply alpha - clr.rgb *= clr.a - // Do not apply the color scale assuming the scale is (1, 1, 1, 1). - // Clamp the output. - clr.rgb = min(clr.rgb, clr.a) -{{else}} - // Apply the color scale. - clr *= color -{{end}} - - return clr -} - -`)) - -// Shader returns the built-in shader based on the given parameters. -// -// The returned shader always uses a color matrix so far. -func Shader(filter graphicsdriver.Filter, address graphicsdriver.Address) []byte { - shadersM.Lock() - defer shadersM.Unlock() - - // Now UseColorM is always true. When UseColorM is true, the color scale in vertices is not used. - // In the built-in shaders, the color scale is modified at the vertex shader (#1996), - // and this modification cannot be represented in a Kage program. - // A custom vertex shader in Kage (#2209), or changing the interpretation of scales (#2365) would solve the issue. - const useColorM = true - - k := key{ - Filter: filter, - Address: address, - UseColorM: useColorM, - } - if s, ok := shaders[k]; ok { - return s - } - - var buf bytes.Buffer - if err := tmpl.Execute(&buf, map[string]interface{}{ - "Filter": filter, - "FilterNearest": graphicsdriver.FilterNearest, - "FilterLinear": graphicsdriver.FilterLinear, - "Address": address, - "AddressUnsafe": graphicsdriver.AddressUnsafe, - "AddressClampToZero": graphicsdriver.AddressClampToZero, - "AddressRepeat": graphicsdriver.AddressRepeat, - "UseColorM": useColorM, - }); err != nil { - panic(fmt.Sprintf("builtinshader: tmpl.Execute failed: %v", err)) - } - - b := buf.Bytes() - shaders[k] = b - return b -} diff --git a/shader.go b/shader.go index dcfd5956d..950d0f550 100644 --- a/shader.go +++ b/shader.go @@ -15,12 +15,7 @@ package ebiten import ( - "fmt" - "sync" - - "github.com/hajimehoshi/ebiten/v2/internal/builtinshader" "github.com/hajimehoshi/ebiten/v2/internal/graphics" - "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver" "github.com/hajimehoshi/ebiten/v2/internal/ui" ) @@ -56,34 +51,3 @@ func (s *Shader) Dispose() { func (s *Shader) convertUniforms(uniforms map[string]interface{}) [][]float32 { return s.shader.ConvertUniforms(uniforms) } - -type builtinShaderKey struct { - filter graphicsdriver.Filter - address graphicsdriver.Address -} - -var ( - builtinShaders = map[builtinShaderKey]*Shader{} - builtinShadersM sync.Mutex -) - -func builtinShader(filter graphicsdriver.Filter, address graphicsdriver.Address) *Shader { - builtinShadersM.Lock() - defer builtinShadersM.Unlock() - - key := builtinShaderKey{ - filter: filter, - address: address, - } - if s, ok := builtinShaders[key]; ok { - return s - } - - src := builtinshader.Shader(filter, address) - s, err := NewShader(src) - if err != nil { - panic(fmt.Sprintf("ebiten: NewShader for a built-in shader failed: %v", err)) - } - builtinShaders[key] = s - return s -}