One way to represent a brush is as a simple bitmap. When the bitmap-brush is applied to draw a point, the bitmap is simply rendered at the specified location using an "over"-operator to merge the colors. This is seen below where a round and partially transparent red brush is applied to two points over a white and gray chessboard background.
Lines (and other curves) can be created by repeatedly painting the same brush over the background along the path. In the picture below the path between the two points is a simple line.
Notice that the repeated application of the same partially transparent brush to nearby points causes the transparent parts to become less transparent. This happens since the over-operator will merge the next (slightly offset) brush over a background which has already been affected by the previous brush stroke(s). In this way the effect of the brush is "amplified", and transparency lost. The results may be percieved as "unintuitive" by the user, since the intensity and transparency pattern of the resulting stroke actually looks quite different from that of the original brush.
For Pipedream I figured out the following algorithm as an alternative when rendering strokes with partially transparent brushes:
- Rather than painting directly over the image background (the chessboard here), I first render the stroke over a separate new, fully transparent background.
- During this rendering I only update the RGBA value of this new image if the alpha component A of the corresponding brush position is greater than the value already there. I.e. the stored pixel color will be the one corresponding to the largest A-value of the brush which has "touched" that pixel. In this sense the algorithm can be considered a color version of a "maximum value over-operator".
- Finally this separately rendered line stroke is merged with the original (chessboard) background, giving the result below.
Comparing this stroke to the original brush, the result may be closer to what the user expects.