Tutorial 2c : Transparency effects
 
Introduction

One of the main uses of alpha values is to create transparency and blending effects. When we use the word "transparency" in terms of a Glide program, we're referring to any rendering operation that allows the background to show through to some extent, instead of being replaced.

In this tutorial we're going to learn about another new function, grAlphaBlendFunction. Whereas all of the colour / alpha functions that we've seen so far allow us to control how the source values are determined and modified, this function allows us to control the way that the computed colour of a new pixel is modified by the colour of the pixel that already exists in the rendering buffer.

The steps we follow to render a semi-transparent shape are:

  • Specify the colour source.
  • Tell Glide to use transparency.
  • Tell Glide how transparent the shape should be.
  • Draw the shape.
Specify the colour source

We can use any of Glide's available colour sources, but for now let's just consider the two that we've seen in the previous tutorials. We specify them in exactly the same way as we did before.

Note: using transparency doesn't change the way that the colour source is determined.

For instance, to use the constant colour:

  grColorCombine(
    GR_COMBINE_FUNCTION_LOCAL,
    GR_COMBINE_FACTOR_NONE,
    GR_COMBINE_LOCAL_CONSTANT,
    GR_COMBINE_OTHER_NONE,
    FXFALSE );
Or to use iterated colour:
  grColorCombine(
    GR_COMBINE_FUNCTION_LOCAL,
    GR_COMBINE_FACTOR_NONE,
    GR_COMBINE_LOCAL_ITERATED,
    GR_COMBINE_OTHER_NONE,
    FXFALSE );
Tell Glide to use transparency

As humans who live in a real environment with real objects, we think of a transparent object as one that allows a certain amount of light to pass through it. Glide doesn't actually understand the concept of transparency, but it does allow the programmer to determine how a new pixel should be blended with an existing pixel, which we can use to simulate transparency.

Let's imagine a real-world scenario and then see how it could be simulated in Glide:

Suppose we're looking at a picture hanging on the wall. We can see all of its colours exactly how they should be - blue is blue, green is green, etc. Then, we hold a sheet of semi-transparent red plastic in front of the picture. Because of the way the plastic affects light passing through it, the picture loses most of its blue and green qualities, and every colour becomes tinted red.

To do the same thing in Glide, we would first draw the picture, and we would then draw a red rectangle on top of it. However, before drawing the red rectangle we tell Glide that new pixels should be a combination of the source pixel (part of the red rectangle) and the destination pixel (part of the picture that is already there).

The call to grAlphaBlendFunction would be:

  grAlphaBlendFunction(
    GR_BLEND_SRC_ALPHA,
    GR_BLEND_ONE_MINUS_SRC_ALPHA,
    GR_BLEND_ONE,
    GR_BLEND_ZERO );
That may look horrendously complicated at first sight, but it is actually very simple - it just uses a few terms that we're not familiar with yet.

The first and second parameters passed to the grAlphaBlendFunction function specify the scaling factors for the source and destination colours. The third and fourth parameters specify the scaling factors for the source and destination alpha values.

For the purposes of this example, let's suppose we're using an opacity value of 75%, meaning that the final colour of a new pixel should be 75% of the source colour and 25% of the pixel that already exists in the rendering buffer. The opacity value would be set by specifying a value of 191 for the constant alpha.

Note: transparency and opacity are inversely proportional - the more transparent something is, the less opaque it is. A window is very transparent; a brick wall is 100% opaque.

The first parameter passed to the grAlphaBlendFunction function, GR_BLEND_SRC_ALPHA, tells Glide to scale the source colour by the source alpha, which in this case is the constant alpha. For example, if the source colour was bright red, it would be scaled to approximately 75% red.

The second parameter, GR_BLEND_ONE_MINUS_SRC_ALPHA, tells Glide to scale the destination colour by the source alpha, but to invert the source alpha before doing so. For example, if the destination colour was bright blue, it would be scaled to approximately 25% blue.

Note: before Glide scales a colour using an alpha value, which will be in the range 0 - 255, it first divides it by 255, bringing it within the range 0 - 1 (with 0 being minimum alpha and 1 being maximum alpha). The GR_BLEND_ONE_MINUS_SRC_ALPHA function tells Glide that an additional step should be performed, with the converted alpha value being subtracted from 1, so a value of 1 would become 0, a value of 0 would become 1, and a value of 0.75 would become 0.25, etc.

The third parameter, GR_BLEND_ONE, means that the source alpha should be unmodified. This is the value that is being used to determine the transparency / blending factor.

The fourth parameter, GR_BLEND_ZERO, means that the destination alpha should be set to zero. The algorithm we're creating doesn't need to know what the destination alpha value is, so we'd might as well set it to zero.

To help us picture how everything comes together to create the illusion of transparency, let's look at the system we've just created as a flowchart:

The top row is the source colour, going through both the grColorCombine and grAlphaBlendFunction modifiers, while the bottom row is the destination colour, which is only modified by grAlphaBlendFunction.

The two source colours, red and a non-existant colour, are combined to produce red, which is then scaled by the constant alpha value to produce 75% red. It then remains unchanged.

The destination colour, blue, is scaled by the inverted constant alpha value to produce 25% blue, which also remains unchanged.

Finally, the two calculated colours are combined to produce a final colour that is 75% red and 25% blue, which is magenta. That is the colour that is written to the rendering buffer.

Tell Glide how transparent the shape should be

The alpha value that we want to use for the transparency factor can be taken from any of the available sources, but for the moment let's just use the constant alpha value.

As always, we set the constant colour / alpha value using the grConstantColorValue function, with the only parameter being the return value from our own colour_ARGB function.

If the semi-transparent shape we're going to draw uses the constant colour, then we can set the colour at the same time. For instance, to set the colour to yellow, with an alpha value of 191 (to create a 75% transparency effect), the code would be:

  grConstantColorValue( colour_ARGB( 191, 255, 255, 0 ) );
If we're using a different colour source, we can specify zero for each of the three constant colour components, but we still use the same function to set the constant alpha value, ie:
  grConstantColorValue( colour_ARGB( 191, 0, 0, 0 ) );
Draw the shape

We draw the semi-transparent shape in exactly the same way as we would draw any other shape. For instance, to draw a triangle:

  GrVertex v1, v2, v3;

  [ ... define vertices ... ]

  grDrawTriangle( &v1, &v3, &v2 );
Or, to draw a rectangle:
  GrVertex vertices[ 4 ];

  [ ... define vertices ... ]

  grDrawPolygonVertexList( 4, vertices );
Working example


Figure 3 : Simulating transparency of constant and iterated colours.
Download the tutor_2c example code to see a working example that demonstrates transparency effects using constant and iterated colours, as shown in Figure 3.

Notice how the program is structured:

  1. After the grSstWinOpen function, we call grColorCombine to specify that the constant colour should be used.

  2. In the draw_triangle_top_left function we set the constant colour to green and then draw the first triangle.

  3. In the draw_triangle_top_right function we call grAlphaBlendFunction to enable transparency based on the constant alpha value, set the constant colour to blue with an alpha value of 127 and then draw the second triangle.

  4. In the draw_triangle_bottom_left function we disable transparency with another call to grAlphaBlendFunction, set the constant colour to red and then draw the third triangle.

  5. In the draw_triangle_bottom_right function we call grAlphaBlendFunction to enable transparency based on the constant alpha value and call grColorCombine to specify that iterated colours should be used. We then set the constant alpha value to 127, set each of the three vertices to a different colour and draw the fourth triangle.
Next Tutorial | Main Page

 
This tutorial is ©1998 by Andrew Smith. No part of this tutorial may be reproduced without permission. If you want to reproduce any of this tutorial for non-commercial purposes then I'm not likely to try and stop you, but please ask me first.