From: Alexis Laferrière Date: Mon, 26 Jun 2017 15:44:53 +0000 (-0400) Subject: gamnit: use premultiplied alpha X-Git-Url: http://nitlanguage.org gamnit: use premultiplied alpha Signed-off-by: Alexis Laferrière --- diff --git a/lib/gamnit/depth/particles.nit b/lib/gamnit/depth/particles.nit index 3c40ac1..bfe3392 100644 --- a/lib/gamnit/depth/particles.nit +++ b/lib/gamnit/depth/particles.nit @@ -258,7 +258,6 @@ class ParticleProgram { if (use_texture) { gl_FragColor = texture2D(texture0, gl_PointCoord) * v_color; - if (gl_FragColor.a <= 0.01) discard; } else { gl_FragColor = v_color; } @@ -301,7 +300,7 @@ class ExplosionProgram gl_Position = center * mvp; gl_PointSize = scale / gl_Position.z * pt; - if (pt > 0.8) v_color.a = (1.0-pt)/0.2; + if (pt > 0.8) v_color *= (1.0-pt)/0.2; """ end @@ -318,8 +317,8 @@ class SmokeProgram gl_PointSize = scale / gl_Position.z * (pt+0.1); if (pt < 0.1) - v_color.a = pt / 0.1; + v_color *= pt / 0.1; else - v_color.a = 1.0 - pt*0.9; + v_color *= 1.0 - pt*0.9; """ end diff --git a/lib/gamnit/display_android.nit b/lib/gamnit/display_android.nit index e9d1b4a..6d968f8 100644 --- a/lib/gamnit/display_android.nit +++ b/lib/gamnit/display_android.nit @@ -62,7 +62,7 @@ redef class TextureAsset return end - var buf = bmp.copy_pixels + var buf = bmp.copy_pixels(unmultiply=not premultiply_alpha) loaded = true width = bmp.width.to_f height = bmp.height.to_f diff --git a/lib/gamnit/flat.nit b/lib/gamnit/flat.nit index 56fd402..f3043c3 100644 --- a/lib/gamnit/flat.nit +++ b/lib/gamnit/flat.nit @@ -430,7 +430,7 @@ redef class App # Enable blending gl.capabilities.blend.enable - glBlendFunc(gl_SRC_ALPHA, gl_ONE_MINUS_SRC_ALPHA) + glBlendFunc(gl_ONE, gl_ONE_MINUS_SRC_ALPHA) # Enable depth test gl.capabilities.depth_test.enable @@ -695,7 +695,7 @@ private class Simple2dProgram } gl_Position = (vec4(c * scale, 1.0) * rotation() + translation)* mvp; - v_color = color; + v_color = vec4(color.rgb*color.a, color.a); } """ @ glsl_vertex_shader diff --git a/lib/gamnit/textures.nit b/lib/gamnit/textures.nit index 53e88a5..4fb98ac 100644 --- a/lib/gamnit/textures.nit +++ b/lib/gamnit/textures.nit @@ -208,7 +208,7 @@ class CustomTexture end end -# Texture with its own pixels +# Texture with its own pixel data class RootTexture super Texture @@ -221,6 +221,18 @@ class RootTexture init do all_root_textures.add self + # Should the pixels RGB values be premultiplied by their alpha value at loading? + # + # All gamnit textures must have premultiplied alpha, it provides a better + # alpha blending, avoids artifacts and allows for additive blending. + # + # When at `true`, the default, pixels RGB values are premultiplied + # at loading. Set to `false` if pixels RGB values are already + # premultiplied in the source data. + # + # This value must be set before calling `load`. + var premultiply_alpha = true is writable + private fun load_from_pixels(pixels: Pointer, width, height: Int, format: GLPixelFormat) do var max_texture_size = glGetIntegerv(gl_MAX_TEXTURE_SIZE, 0) @@ -229,6 +241,11 @@ class RootTexture return end + # Premultiply alpha? + if premultiply_alpha and format == gl_RGBA then + pixels.premultiply_alpha(width, height) + end + glPixelStorei(gl_UNPACK_ALIGNEMENT, 1) var tex = glGenTextures(1)[0] gl_texture = tex @@ -368,3 +385,20 @@ class TextureSet # Load all texture of this set fun load_all do for t in self do t.load end + +redef class Pointer + # Multiply RBG values by their alpha value + private fun premultiply_alpha(width, height: Int) `{ + uint8_t *bytes = (uint8_t *)self; + int x, y, i = 0; + for(y = 0; y < height; y ++) { + for(x = 0; x < width; x ++) { + int a = bytes[i+3]; + bytes[i ] = bytes[i ] * a / 255; + bytes[i+1] = bytes[i+1] * a / 255; + bytes[i+2] = bytes[i+2] * a / 255; + i += 4; + } + } + `} +end