Tutorial Manual | FAQ

Bling is a C#-based library for easily programming images, animations, interactions, and visualizations on Microsoft's WPF/.NET. Bling is oriented towards design technologists, i.e., designers who sometimes program, to aid in the rapid prototyping of rich UI design ideas. Students, artists, researchers, and hobbyists will also find Bling useful as a tool for quickly expressing ideas or visualizations. Bling's APIs and constructs are optimized for the fast programming of throw away code as opposed to the careful programming of production code.

Bling as the following features that aid in the rapid prototyping of rich UIs:
  • Declarative constraints that maintain dynamic relationships in the UI without the need for complex event handling. For example, button.Width = 100 - slider.Value causes button to shrink as the slider thumb is moved to the right, or grow as it is moved to the left. Constraints have many benefits: they allow rich custom layouts to be expressed with very little code, they are easy animate, and they support UIs with lots of dynamic behavior.
  • Simplified animation with one line of code. For example, button.Left.Animate().Duration(500).To = label.Right will cause button to move to the right of label in 500 milliseconds.
  • High-level functional programming constructs for graphics programming including abstractions for textures, pixel effects, transitions, curves, surfaces, height fields, normal maps, and 3D/2.5D lighting.
  • Experimental support for Direct3D 10 surfaces that are defined by pixel, vertex, and geometry shaders.
  • Pixel shader effects without the need to write HLSL code or boilerplate code! For example, canvas.Effect.Custom = (input, uv) => new ColorBl(1d - input[uv].ScRGB, input[uv].ScA); defines and installs a pixel shader on a canvas that inverts the canvas's colors. Pixel shading in Bling takes advantage of your graphics card to create rich, pixel-level effects.
  • An experimental UI physics engine for integrating physics into user interfaces! The physics supported by Bling is flexible, controllable, and easy to program.
  • A rich library of geometry routines; e.g., finding where two lines intersect, the base of a triangle, the area of triangle, or a point on Bezier curve. These routines are compatible with all of Bling's features; e.g., they can be used in express constraints, pixel shaders, or physical constraints. Bling also provides a rich API for manipulating angles in both degrees and radians.
  • And many smaller things; e.g., a frame-based background animation manager and slide presentation system.
  • As a lightweight wrapper around WPF, Bling code is completely compatible with conventional WPF code written in C#, XAML, or other .NET languages.


Bling is an open source project created by Sean McDirmid and friends to aid in design rapid prototyping. We used Bling to enhance our productivity and would like to share it with other WPF UI design prototypers.

Getting Started

Requirments: Visual Studio 2008 full or Express, .NET 3.5 and .NET 3.5 SP1, Visual Studio 2008 SP1 (may not be necessary, comes with VS 2008 Express). To support WPF pixel shaders, the DirectX August 2008 runtime is sometimes required, although this is often already installed on your machine.

As of Bling 3, DirectX 10 is also supported for Windows Vista and Windows 7 (sorry XP users!). If you want to use DirectX 10, you'll have to install the latest redistrutable; e.g., the web installer. Bling also depends on the Windows API Code Pack and the DLR, but both DLLs are included in the distribution.

Download the source release from the web page. An example comes with the release. To include in your own project for WPF development, simply add the Bling.Core and Bling.WPF projects to your solution, and then add a reference to the Bling project from your own project. For DirectX 10 development, add and refer to the Bling.Core, Bling.WPF, and Bling.D3D10 projects.

Example

The code used in this getting started example is located in the GettingStarted.cs file of the GettingStarted project in the release. We start of this example by creating a thumb and label on a canvas:

ThumbBl thumb = new ThumbBl(canvas) {
  Background = Brushes.Red,
  CanDrag = true,
  CenterPosition = canvas.Size - new PointBl(20,20),
  ZIndex = 1,
};
LabelBl label = new LabelBl(canvas) {
  Content = "Hello World: ".Bl() + thumb.CenterPosition.ToStringBl(),
  Font = { Weight = FontWeights.SemiBold, Size = 80, },
  CenterPosition = canvas.CenterSize,
};

The first statement creates a red thumb that can be dragged (CanDrag = true). The initial location of the thumb is in the right hand bottom corner of the canvas,
while its Z index is set to one. The second statement creates a label whose content is bound to "Hello World" prepended to the current location of the thumb. By default,
assignments to properties in Bling are contraints where the bound to property will change as the bound-to expression changes. In our example, the label's content will change
to always reflect the location of the thumb, which you can experience this by moving the thumb. Likewise, the center position of the label is bound to the center of its containing canvas. As the window that contains the canvas is resized, the label is repositioned so that it always remains in the center.

Constraints are ubiquitous and incredibly expressive in Bling. Consider another constraint:

label.RenderTransform.Rotate = 
  (thumb.CenterPosition - label.CenterPosition).Angle.ToDegrees();

This code rotates the label according to the position of the thumb with respect to the center of the label. A vector from the center of the label is first computed using subtraction, where the vector is then converted into a radian angle (via Angle), which itself is turned into a degree angle (ToDegrees). The result is that the label rotates as the thumb is moved in a circle around its center. This example demonstrates the power of Bling constraints: properties can be bound to many kinds of expressions including those that operate over angles.

The next piece of code demonstrates how a UI widget can easily undergo custom pixel shading:

ThumbBl thumbB = new ThumbBl(canvas) {
  Background = Brushes.Blue, LeftTop = new PointBl(0,0), CanDrag = true 
};
label.Effect.Custom = (input, uv) => {
  /*L1*/ PointBl p = label.RenderTransform.Inverse.
   Transform(thumbB.CenterPosition - label.LeftTop);
  /*L2*/ PointBl q = uv * label.Size;
  /*L3*/ DoubleBl d = (p - q).Length;
  /*L4*/ d = 1 - (d / 500).Min(1);
  /*L5*/ ColorBl clr = (d).Lerp(Colors.Black, Colors.Blue);
  /*L6*/ return ColorBl.FromScRgb
    ((input[uv].ScA).Min((1 - (d * d)).Max(.4)), clr.ScRGB);
};

We want to shade the label with respect to the position of thumbB. However, pixel shader effects are applied before render transforms, so we have to transform the position of thumbB with respect to label's inverse transform, which happens on the first line of the shader (below (input,uv) => {). Since transforms are relative to the widgets they are applied, we also subtract label's left top position from thumbB's center position. uv identifies the position of the pixel being shaded in term of a percentage rather than in pixels. So that we can compare uv to the position of thumbB, we multiple it by the size of the label (line two) and then we can find the distance between the two points (line three). Line four specifies that the circle we care about is 500 pixels in radius, which we then invert so that closer distances are higher in value. Line five uses the result d to interpolate between black and blue colors, which is then used on line six to create the color of the pixel with some modifications to its alpha.

The resulting pixel shader executes on the GPU with performance similar to a DirectX pixel shader, and in fact, it is a DirectX pixel shader. Pixel shaders can refer to many UI objects and properties directly, such as positions, although there are limitations. For example, a pixel shader can refer to a point property but not an enum property, and can refer to an image brush but not a solid color brush (due to limitations enforced by WPF).

Last edited Oct 26, 2009 at 7:22 AM by mcdirmid, version 53