{
if (use_texture) {
gl_FragColor = texture2D(texture0, gl_PointCoord) * v_color;
- if (gl_FragColor.a <= 0.01) discard;
} else {
gl_FragColor = v_color;
}
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
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
# 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
}
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
end
end
-# Texture with its own pixels
+# Texture with its own pixel data
class RootTexture
super Texture
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)
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
# 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