From a3b0831472601bacf2eb946a211968070c8015f6 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Mon, 22 Dec 2014 21:39:25 +0900 Subject: [PATCH] Change the texture pixel format to premultiplied alpha (#36) --- image.go | 2 +- internal/math.go | 10 +++++----- internal/opengl/internal/shader/shader.go | 17 ++++++++--------- internal/opengl/texture.go | 6 +++--- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/image.go b/image.go index 3a71a7093..3373af5db 100644 --- a/image.go +++ b/image.go @@ -101,7 +101,7 @@ type syncer interface { } // Image represents an image. -// The pixel format is non alpha-premultiplied. +// The pixel format is alpha-premultiplied. type Image struct { syncer syncer inner *innerImage diff --git a/internal/math.go b/internal/math.go index 8e59d7421..b37743a16 100644 --- a/internal/math.go +++ b/internal/math.go @@ -37,11 +37,11 @@ func NextPowerOf2Int(size int) int { } func RGBA(clr color.Color) (r, g, b, a float64) { - clr2 := color.NRGBA64Model.Convert(clr).(color.NRGBA64) + cr, cg, cb, ca := clr.RGBA() const max = math.MaxUint16 - r = float64(clr2.R) / max - g = float64(clr2.G) / max - b = float64(clr2.B) / max - a = float64(clr2.A) / max + r = float64(cr) / max + g = float64(cg) / max + b = float64(cb) / max + a = float64(ca) / max return } diff --git a/internal/opengl/internal/shader/shader.go b/internal/opengl/internal/shader/shader.go index 43574edb4..38f55382e 100644 --- a/internal/opengl/internal/shader/shader.go +++ b/internal/opengl/internal/shader/shader.go @@ -84,15 +84,15 @@ varying vec2 vertex_out_tex_coord1; void main(void) { vec4 color0 = texture2D(texture0, vertex_out_tex_coord0); vec4 color1 = texture2D(texture1, vertex_out_tex_coord1); + // Un-premultiply alpha + color0.rgb /= color0.a; + // Apply the color matrix color0 = (color_matrix * color0) + color_matrix_translation; + // Premultiply alpha + color0 = clamp(color0, 0.0, 1.0); + color0.rgb *= color0.a; - // Photoshop-like RGBA blending. - // - // NOTE: If the textures are alpha premultiplied, this calc would be much simpler, - // but the color matrix must be applied to the straight alpha colors. - // Thus, straight alpha colors are used in Ebiten. - gl_FragColor.a = color0.a + (1.0 - color0.a) * color1.a; - gl_FragColor.rgb = (color0.a * color0.rgb + (1.0 - color0.a) * color1.a * color1.rgb) / gl_FragColor.a; + gl_FragColor = color0 + (1.0 - color0.a) * color1; } `, }, @@ -104,8 +104,7 @@ varying vec2 vertex_out_tex_coord0; void main(void) { vec4 color0 = texture2D(texture0, vertex_out_tex_coord0); - gl_FragColor.rgb = color0.a * color0.rgb; - gl_FragColor.a = 1.0; + gl_FragColor = color0; } `, }, diff --git a/internal/opengl/texture.go b/internal/opengl/texture.go index 21300571d..96ffd076d 100644 --- a/internal/opengl/texture.go +++ b/internal/opengl/texture.go @@ -23,7 +23,7 @@ import ( "image/draw" ) -func adjustImageForTexture(img image.Image) *image.NRGBA { +func adjustImageForTexture(img image.Image) *image.RGBA { width, height := img.Bounds().Size().X, img.Bounds().Size().Y adjustedImageBounds := image.Rectangle{ image.ZP, @@ -32,11 +32,11 @@ func adjustImageForTexture(img image.Image) *image.NRGBA { internal.NextPowerOf2Int(height), }, } - if nrgba, ok := img.(*image.NRGBA); ok && img.Bounds() == adjustedImageBounds { + if nrgba, ok := img.(*image.RGBA); ok && img.Bounds() == adjustedImageBounds { return nrgba } - adjustedImage := image.NewNRGBA(adjustedImageBounds) + adjustedImage := image.NewRGBA(adjustedImageBounds) dstBounds := image.Rectangle{ image.ZP, img.Bounds().Size(),