شاهد كورس كامل سيلفرلايت 5 مجانا هنا.
This content is based on Beta release, expect many changes in the final release.
Read What’s New in Silverlight 5 series here.
Introduction
In this article, we’ll have a brief discussion of the new features in graphics stack in Silverlight 5.
Overview
Silverlight 5 has undergone few changes in the graphics stack:
- Improved Performance and Rendering:
Performance has been improved dramatically by using lessons learned from Windows Phone 7. More comes later in this article. - Hardware Acceleration:
Silverlight 5 now depends more on GPU for graphics processing. This frees CPU from much work, and as a result, improves performance. - New 3D API:
The most exciting feature yet. Silverlight 5 now supports native 3D API. More comes later. - Vector Printing:
Very useful for certain cases, not available in the Beta. - Print Preview:
The long-waited printing feature. Silverlight 5 now allows you to show the user a preview of what he is going to print. Yet not available in the Beta.
Now let’s look at the currently available features in details.
Performance Improvements
To improve rendering performance, Silverlight 5 uses the composition model available in Windows Phone 7. This model implies using a separate, dedicated thread for graphics rendering instead of using the UI thread. This helps freeing the UI thread from graphics work, and thus improves the performance of rendering UI elements and reduces flickers and glitchy animations happen when UI thread was interrupted.
In addition, moving the graphics rendering to another thread adds support for independent animations and helps with immediate-mode rendering on the GPU (in which graphics are sent directly and being rendered on the display.)
3D API
Silverlight 5 now supports natively a 3D API. This API is based on the XNA API; you have the same classes and the same code, however, the 3D API is Silverlight is not game-loop based.
While it’s so amazing to have a 3D API natively supported in Silverlight, things are not as good as they seem. The 3D API of Silverlight 5 is very low-level, means that you have access to the GPU, vertex shaders, and other 3D primitives. It’s not as easy as it should be; it requires that you have a solid understanding of low-level graphics and game development to be able to interact with this API. However, the good news is that community will likely wrap this low-level API into simpler components.
Technically, to draw graphics on the screen you need to use the new control DrawingSurface where all the rendering and graphics go on. This control offers a Draw event that you can use to supply your drawing calls. The calls are carried to a GraphicsDevice object and then be processed and carried to the display.
Because of the complexities in this low-level API, and because we assume that you are a business developer, we won’t discuss the 3D API. Instead, we’ll have a brief look at two of the great samples of this API.
Cube Sample
The cube sample (download from http://bit.ly/sl5-cubesample, colored, non-textured) demonstrates how to create and rotate a 3D cube in Silverlight 5. Here’s a screenshot of this sample:
Looking at the Solution Explorer at project files, we can see that the project contains some pixel shader (PS) and vertex shader (VS) files. Those files besides the HLSL files contain the code (in the HLSL language) for the effects required to render the cube.
Moving to MainPage.xaml you can see the DrawingSurface object used to display the graphics and drawings.
<DrawingSurface Draw="OnDraw" SizeChanged="OnSizeChanged" />
Looking at the code behind at the Draw event handler, we can see that the sample has encapsulated all the code required for drawing the cube and rotating it into a new class called Scene. The Draw event passes the GraphicsDevice object to the Scene to have it draw the cube and other graphics into the device:
// init the 3D scene Scene scene = new Scene(); public MainPage() { InitializeComponent(); } void OnDraw(object sender, DrawEventArgs args) { // draw 3D scene scene.Draw(args.GraphicsDevice, args.TotalTime); // invalidate to get a callback next frame args.InvalidateSurface(); }
Moving to the Scene class, we can see that it creates another class that handles drawing the Cube, and has configured the view and camera position and completes the drawing in the Draw() function by clearing the screen and calling the Draw() function of the cube.
public class Scene { Matrix view; // The view or camera transform Matrix projection; // The single Cube at the root of the scene Cube Cube = new Cube(); public Scene() { // the camera's position Vector3 cameraPosition = new Vector3(0, 0, 5.0f); // the place the camera is looking (towards world origin) Vector3 cameraTarget = Vector3.Zero; // the transform representing a camera at a position looking at a target view = Matrix.CreateLookAt(cameraPosition, cameraTarget, Vector3.Up); } ... public void Draw(GraphicsDevice graphicsDevice, TimeSpan totalTime) { // clear the existing render target graphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Transparent, 1.0f, 0); // draw the Cube Cube.Draw(graphicsDevice, totalTime, view * projection); } }
Finally, the Cube class completes all the drawing by loading the vertex and pixel shaders in its constructor, configuring cube surfaces and surface colors in the CreateCube() function, and then performs the drawing and handling the animation in the Draw() function.
public class Cube { // the device to use when creating resources static readonly GraphicsDevice resourceDevice = GraphicsDeviceManager.Current.GraphicsDevice; // resources VertexShader vertexShader; PixelShader pixelShader; public Cube() { // Initialize resources required to draw the Cube vertexBuffer = CreateCube(); Stream shaderStream = Application.GetResourceStream( new Uri(@"CubeSample;component/Cube.vs", UriKind.Relative)).Stream; vertexShader = VertexShader.FromStream(resourceDevice, shaderStream); shaderStream = Application.GetResourceStream(...); ,,, } VertexBuffer CreateCube() { // cube vertices var cube = new VertexPositionColor[36]; // face coordinates Vector3 topLeftFront = new Vector3(-1.0f, 1.0f, 1.0f); Vector3 bottomLeftFront = new Vector3(-1.0f, -1.0f, 1.0f); ... return vb; } public void Draw(GraphicsDevice graphicsDevice, ...) { // update cube transform Matrix position = Matrix.Identity; // origin Matrix scale = Matrix.CreateScale(1.0f); // no scale modifier ... // setup pixel pipeline graphicsDevice.SetPixelShader(pixelShader); // draw using the configured pipeline graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 12); } }
Lengthy, isn’t it? Now, let’s have a look at another example.
Solar Wind
The Solar Wind 3D sample (download from http://bit.ly/sl5-solarwind) uses the new 3D features of Silverlight 5 to draw the Earth with day and night transitions, atmosphere layers, and population density overlays. It demonstrates advanced concepts and it’s very cool that you’ll like to run and play with it.
Babylon3D
The most amazing sample yet (download from http://bit.ly/sl5-babylon3d), it shows a full 3D realtime engine with some advanced features and an integrated collisions system.
Summary
Silverlight 5 has got few improvements in the graphics stack:
- Improved performance:
Uses the composition model of Windows Phone 7; a separate, dedicated thread for graphics and drawing. - Hardware Acceleration:
Depending more on GPU for graphics processing. Frees CPU from much work, and as a result, improves performance. - New 3D API:
A low-level 3D API based on XNA Framework. Difficult to work with. Community will likely wrap to simplify use. - Vector Printing:
Very useful for certain cases, not available in the Beta. - Print Preview:
Allows for print previews. Not in Beta.
Now, check out other What’s New in Silverlight 5? articles.