October 2004 - Posts
In this post, I explain how to build one of the most basic 3D effect shapes, a gel ellipse. I also explain bell curve gradients.
The gel ellipse above consists of 3 parts: a glowing ellipse, a shine ellipse, and a shadow ellipse.
First we address the glowing ellipse. Open the Fill property for an Ellipse object, and modify as follows:
- Fill type: Path Gradient
- GradientType: TwoColorBell -- needed both for glows and solid surfaces; explained below.
- StartColor: darkest blue
- EndColor: light blue (you pick!)
- FocusPoint: (.5, .85). To move the center of the glow to the bottom. Why does this look better? If the glow is actually light reflected from inside a translucent material, the light is coming from above, and would focus like a lens toward the bottom of the hemisphere.
- Bounds: (-.1, -.1, 1.2, 1.2). This is optional. I made the bounds larger to make the effect a little weaker, so more of the blue color could appear at the bottom of the ellipse. Without this, the bottom is very dark.
- GammaCorrection: false. This is subjective, but I believe glows look better without gamma correction. This makes the area of the lighter color smaller. Leaving the Bounds at its default value, and leaving GammaCorrection on produce a similar effect.
Why is TwoColorBell so important? TwoColorBell specifies that the interpolation between the StartColor and EndColor is not linear -- it is not following a straight line. Instead, it follows a curve shaped like a bell. To illustrate more clearly, I show a LinearGradientFill, one using the TwoColorBell, and one using a linear interpolation. I set the BlendFocus to .5 to move the center of the bell curve to the center of the rectangle. For the linear interpolation, I set the GradientType to TwoColor and the Bounds to (0, 0, .5, .5) -- this makes the linear interpolation have the same center as the bell curve. Since the gradient is wrapped, we end up with a triangle shaped curve for the TwoColor gradient:
The upper left rectangle (bell, gamma corrected) produces the most realistic effect for curved shapes such as cylinders, pipes, tanks. And when used in the path gradient, it is the most realistic effect for spherical, rounded rectangles, and other rounded objects and edges. Interally either 256 or 511 individual gradient "stops" are created when displaying a bell curve. Imagine trying to define all those yourself, using SVG or Avalon, both of which lack bell gradients and path gradients.
Sometimes we may produce a 3D effect using two identical shapes. The back shape is filled with a solid color. The front shape is filled with a gradient, with either the start or end color transparent, and the other color being dark (for shadows) or light (for shines and highlights). This allows you to set a reference a Style containing a simple SolidFill for the back shape -- we did this with the VG.net in Internet Explorer sample.
In this case the GammaCorrection has no effect on the front shape, because it cannot work when one of the colors is transparent. While you can combine your translucent front shape with your back shape with gamma correction, by setting the CompositingMode on a RenderAppearance, performance suffers greatly this way, so it is best to avoid that with any animated objects.
Ok, back to the gel ellipse. Let's add the shine. Add an ellipse half the height of the first, but the same shape. Position it to cover the top half of the glow ellipse, and set its Fill:
- Fill type: Path Gradient
- GradientType: TwoColorBell
- StartOpacity: 0. The edge of the ellipse is transparent.
- EndColor: white
- FocusPoint: (.5, .4). The shine is reflecting from near the top of a curved surface, so the top part of the shine is at a greater angle relative to your eye than the bottom part -- the top part should appear shorter.
The size and positioning are subjective. GammaCorrection has no effect, since the StartColor is completely transparent. The shadow is another ellipse, a little larger. I will let you look at that yourself. Download the complete gel ellipse: GelEllipse.zip
What is it? Who knows, but Visual Studio .NET never looked like that before. We are working on some basic 3D effect Shapes for VG.net users. I will be posting some tips on gel ellipses, gel rectangles, solid ellipses, and solid rectangles soon.... all vector graphics, of course.
We have a file you can download to display the members of custom data types in VG.net without having to expand in the watch window. Not only is the watch window easier to use, you will be able to hold the mouse over a variable and see a tooltip displaying the contents.
We were only able to create this for C# users. Navigate to this folder on your development machine:
Program Files\Microsoft Visual Studio .NET 2003\Common7\Packages\Debugger
Open the file mcee_cs.dat in notepad. Add to the bottom the contents of this file
Now debugging is much easier!
As promised, I explain how to build these vector graphics raindrops with VG.net.
The raindrops are Splines. Any rounded Shape will do. It is best not to make them very convex.
A path gradient fill on each raindrop gives it a glowing, translucent effect. The idea is that the light is coming from the upper right, and refracted to focus on the lower left of each drop. Here are the Fill properties:
- Path Gradient fill type
- GradientType: TwoColorBell. This is very important, and one reason similar effects are difficult to acheive in SVG or Avalon (lack of path gradients is another reason). This creates a bell curve interpolation between the two colors; I will explain more in another blog entry.
- StartColor: darkest blue
- EndColor: white
- FocusPoint: here you have to use your eyeball a bit. I used (.7, .7) for the left drop and (.6, .6) for the right. You can also drag the green adornement in the sample box with the mouse, until it looks good.
- Bounds: (-.1, -.1, 1.2, 1.2). I decided to make the gradient bounds a bit bigger than the Spline, to reduce the intensity of the StartColor. I could have gotten the same effect by reducing the luminosity and saturation of the StartColor.
- GammaCorrection: false. To get a "glow" or interior lighting effect, gamma correction must be set to false. Gamma correction is necessary when trying to simulate rounded surfaces. You may remember we complained about the lack of gamma correction in the .NET PathGradientBrush. This is still a problem. However, we did find a slightly expensive way to simulate this with two GradientTypes: TwoColorBell and TwoColorTriangular. Since GammaCorrection defaults to true, you must set it to false here. If you do not see the combo box, download a new version of VG.net. The Gamma Correction combo box was added in the 2.2.1022 build.
The shine on the upper left corner of each drop was created by first drawing a Spline. The Spline was converted to a Path, and the control points were moved to make it look like the bent reflection of a rectangular light source:
The Fill property on the shine has these settings:
- Linear Gradient fill type
- GradientType: TwoColorBell. The bell curve is great for rounded surfaces using a linear gradient.
- StartOpacity: 0 (completely transparent)
- EndColor: white
- BlendFocus: .79. This pushes the most intense white to the upper-left, in the direction of Angle
- Angle: 235
- Bounds: (0, 0, .8, .8). I made the bounds smaller than the Shape because the Shape is nearly diagonal. This gives a tighter fit to the gradient.
The shadow for each raindrop in the original picture is an ellipse, with a PathGradientFill, the center a translucent black color, and the edge completely transparent. TwoColorBell must be used as a GradientType to get nice shadows. Later I changed from an ellipse to a copy of the Spline shape. Either shape looks great.
To see the details of the shadows, and to examine the Picture for yourself, download the raindrop sample code. You will need the 2.2.1022 VG.net build, or later, to view in the designer.
Our popular analog vector graphics clock for VG.net has been reworked to use PathGradientFills. The difference is stunning. Click the previous link to download and run the clock. Source code is included in the VG.net Lite release.
Version 2.2 of the VG.net vector graphics system is released. New features in this release include path gradients, path movement, and path tracking. Please read the Readme file in the VG.net download for more information.
The image above is the new PathMove sample. To download and run the sample, click on the image. Source code for the sample is included in the Lite download.
On the left hand side, the new PathMove method on Element moves the markers along the Polyline and Spline. PathMove also rotates the markers to match the tangent as they move. On the right hand side, we use the PathInterpolator property on Element to determine the closest point and tangent on a Spline relative to the mouse point.
The new PathGradientFill is used in several places in this sample. The markers use it to provide a translucent interior, with opaque edges. The Start/Stop button uses a path gradient to create a glowing gel button. Each large blue rounded rectangle serving as a background has a "glow" produced by a PathGradientFill. The glossy white shines at the top of each rectangle are also PathGradientFills. We will be posting more 3D tips using path gradients in later blog entries.
We have succeeded in optimizing path gradient fills. Now we have only a few more tweaks and the VG.net vector graphics system version 2.2 will be released.
PathGradientFill now has a Quality property you can use to determine the best trade-off between memory usage and drawing speed. Before we did the optimization, path gradient fills were essentially useless when you zoomed in a great deal. The screen became so slow you could not easily perform precise point editing. Now the fills are speedy! Look at the image above. All those fills are drawn using the lowest Quality setting -- it is difficult to see any difference for smaller objects. VG.net is the first and only GDI+ based vector graphics system with optimized gradients.
The PathGradientFill makes it possible to add drop-shadows to shapes. It may be a nice enhancement to just say ShadowVisible = true, and a shadow is drawn, instead of forcing people to create them explicitly. What do you think? Something for version 2.3?