Tải bản đầy đủ - 0 (trang)
1 3D—a natural way of interacting with information

1 3D—a natural way of interacting with information

Tải bản đầy đủ - 0trang

3D—a natural way of interacting with information


The customer really wanted 3D (they actually asked for it), so they could quickly zip

around the model of the car, drawing cracks and chips. But the technology available to

us at the time and, quite frankly, our lack of knowledge, kept us from being able to

deliver on that. Instead, we opted for a flattened 2D version they could draw on. It was

nice, but it lacked that extra bit that could have put this application over the top.

The WPF 3D Closet Configurator. Shortly after I joined Microsoft in fall 2009, I

attended the Professional Developers Conference (PDC). While there, I talked to a

developer from Europe and a local designer who had together created a cool sit-down

in-store closet configurator application in WPF.2 European homes tend to be smaller

than American homes, so storage space is taken seriously. Configuring a closet for the

maximum use of that space can be a somewhat lengthy process.

The application they built was used in-store (like an upscale European version of a

big-box home store) and run by sales clerks with customers sitting next to them. The

clerk positioned 3D items on the screen: drawers, shelves, hangers, etc. to optimize the

use of space. While that was happening, the application built a list of all the pieces

needed. When complete, customers had 2D and 3D drawings of the final closet, a complete bill of materials, and an exact price for everything they needed. This approach

was both more enjoyable and more efficient than looking in catalogs or typing codes

into a computer.

It may not have had 300 text boxes on a battleship-gray forum, but there’s no

doubt in my mind that that was a business application, and a well-executed one at

that. There are many more examples of enhancing the experience using 3D for visualization or input. Once you have the skills and knowledge, you’ll find many other

opportunities where 3D can make your application that much more usable or help it

stand out in the crowd.

Now, to get back to the Amiga. The Amiga didn’t start it all, but it certainly popularized 3D. It was also one of the first consumer machines used in the production of

3D graphics on television (such as Babylon 5) and film. So, in tribute to the little Amiga

my friend had, and to the Amiga 1000 that started it all,3 and to show off what Silverlight is capable of, I decided to take inspiration from the Boing ball demo for the sample you’ll start in this chapter and complete in the next. In these two chapters, you’ll

build a simple animated bouncing ball demo, minus the physics simulation, to showcase the 3D capabilities of Silverlight.

This chapter isn’t intended to be a full primer on XNA and 3D, but more a practical one on how to use those technologies inside Silverlight. If you want to learn more

about these technologies, most of the things you’ll learn about XNA 4 on the web

apply to the version that’s in Silverlight. Plus, in general, 3D concepts such as matrices

and vertices are universal.



You can see my video interview showing the application here: http://bit.ly/WPF3dCloset.

Want to see some mid-1980s hardware demos that blew PCs and the Mac out of the water? See these two videos

on YouTube. First is the Boing ball that’s the inspiration for the 3D in this chapter: http://bit.ly/AmigaBoing.

Second is an iPhone-like shape/shadow real-time 3D demo: http://bit.ly/AmigaRT3D.




Introduction to 3D

26.2 The Silverlight/XNA 3D API

3D in Silverlight is based on a subset of the XNA Game Studio 4.0 3D core libraries,

which themselves are a .NET layer over the Windows-only DirectX technology. DirectX

is a C/C++ API for very low-level graphics programming, a driver specification, and also

a ton of helper functionality for creating graphics applications and games. It was

designed primarily to make games a reality on Windows but has since ended up just

about everywhere, including as the underlying technology for Windows Vista and Windows 7/8 desktop rendering.

NOTE XNA is not a high-level 3D engine with lighting and physics and what-

not, but rather the building blocks you or others can use to build a 3D rendering engine for specific application needs. A great example of a 3D engine with

all of that in place is the Babylon 3D Toolkit for Silverlight. This is freely available on CodePlex, so be sure to take a look at it there.

Silverlight supports what’s known as the XNA “Reach” profile. That means that it

works on Windows XP and above on Shader Model 2.0 or above DirectX 9–compatible

video card. The video card is a hard requirement; there’s no software fallback rendering. Not to worry, though, most PCs and laptops created in the past few years support

these levels. You’ll only run into problems if you try to repurpose that old Windows 3.1


26.2.1 Rendering pipeline

Silverlight supports Shader Model 2, not 3. This is important if you code your own

custom shaders or try to use shaders created by other people. The difference between

the two models has to do with what support they require on the video card as well

as differences in the shader programming language, number of available registers,

and more.

Unlike 2D shaders, 3D shaders are code that run directly on the GPU, outside the

Silverlight sandbox. Because of that hardware-level access, they can potentially be

used as a way to gain access to your computer for malicious purposes. Windows XP systems are especially vulnerable to this because the old driver model is nowhere nearly

as protected as the newer model. Silverlight 5 addresses this security issue by requiring

either elevated trust or end-user confirmation when you want to use the 3D system.

In addition, you must have the Silverlight EnableGPUAcceleration setting turned

on in order to use 3D rendering. Unlike WPF, Silverlight has no fallback to software

rendering when the hardware isn’t up to snuff.

In a nutshell, the rendering architecture of 3D rendering in Silverlight looks like

figure 26.1.

The rendering system takes vertices and primitives, which I’ll cover shortly, processes them, then moves them to the pixel-processing step. Pixel processing takes textures (images applied to the surface of 3D geometry) and combines them with the

geometry to produce the final on-screen pixels.


The Silverlight/XNA 3D API

Figure 26.1


The Silverlight 3D rendering pipeline. Source: MSDN Silverlight 3D Overview.

The XNA libraries are split across the Silverlight runtime, the Silverlight SDK, and the

Silverlight toolkit. The team split the assemblies this way to minimize the runtime

footprint of applications that don’t use 3D—the majority of Silverlight applications

out there. Conveniently, the 3D project templates take care of adding all the appropriate references for you.

26.2.2 Project templates

The Silverlight toolkit comes with several 3D project templates. You can get pretty far

without using the templates, but once you try to do something like load content,

you’ll wish you started with them. It’s also difficult to add a content project to an existing solution, so it’s best to start with the full project template.

The first step is to download and install the Silverlight 5 toolkit from http://

silverlight.codeplex.com. The Silverlight 5 version of the toolkit (I’m using the September 2011 build to code against, but a newer version should be out by the time you

read this) includes the Silverlight 3D Project templates as well as a number of helper


Next, you need to install XNA Studio 4 in order to use the 3D project templates

included with the toolkit. This free download is also linked to from the toolkit site.

Finally, if you plan to modify or compile any custom shaders in your project (the

default template, as of this writing, uses one named CustomEffect.slfx), you’ll need to

also install the latest DirectX SDK for Windows. It’s a big download, so budget some

time and bandwidth to get it.

Once you have the toolkit and other bits installed, create a new Silverlight 3D

Application project. I creatively named mine Silverlight3DExample. Figure 26.2 shows

the correct project template selected in the New Project dialog.

When the solution loads, you’ll see four different projects. The Silverlight project

and web project are ones you should be familiar with by now. The two content projects

are for loading assets like models, sounds, and images. They have a special relationship




Figure 26.2

Introduction to 3D

The New Project dialog showing the selected Silverlight 3D Application template

with the Silverlight application which (as of this writing) isn’t represented in the solution. If you crack open the Silverlight application’s project file, though, and search for

the word “content,” you’ll see how the two are linked.

The Silverlight application includes a basic Scene class as well as a custom vertex

type and a cube object. I’ll talk about vertices later. The cube is some prebuild geometry. That’s no fun, though! Ignore it. Delete it. Do whatever you need to do to pretend

it doesn’t exist. You’ll implement your own geometry so you’ll need to delete it later


Open the project properties for the Silverlight 3D application and make it an outof-browser application. Don’t make it elevated permissions for now; I’ll get to that

shortly. You want it left as is so you can do a little sleuthing in the next section.

26.3 Detecting capabilities with the GraphicsDeviceManager

Before you can use 3D, you should check to see if it’s available on the current system.

The user may have declined to permit it, the graphics card may not support it, or

something else may be wrong. Rather than simply show blank UI, it’s better to tell the

user what’s going on.

The GraphicsDeviceManager will be the primary mechanism for detecting the capabilities. But you’ll need to do a little work in XAML to make sure you have something



Detecting capabilities with the GraphicsDeviceManager

meaningful to show in either case. One thing I like to do for this and other similar

situations in Silverlight is to have the UI split into two different grids. The first grid is

shown when the feature can’t be used. The second grid is shown when the feature usage

checks out.

Listing 26.1 shows an example of this using two grids: Overlay3DNotAvailable

and MainContent.

Listing 26.1 The XAML UI with information overlay






d:DesignHeight="300" d:DesignWidth="400">






TextWrapping="Wrap" />






TextWrapping="Wrap" />


3D goes here

When you pasted in this code, you got rid of the “myDrawingSurface” from XAML.

That’s okay—you’ll replace it later. I’m not a fan of the “my” naming convention in

any case. But to be able to compile, you’ll need to comment out the offending lines

that reference it in the code-behind. I’ll address that shortly so don’t worry about it

for the moment.

When the application first starts up, both grids are collapsed and therefore invisible. It will be up to your code to decide which grid should be displayed.

Next you need to add a little code to make use of the two different parts of the UI.

For this you’ll use the GraphicsDeviceManager class. This is a singleton class that

exposes an instance of itself through the Current property. The instance exposes two




Introduction to 3D

properties and an event that are useful when checking for the availability of 3D graphics. Table 26.1 lists them.

Table 26.1 GraphicsDeviceManager members used when checking for the availability of 3D graphics



RenderMode property

Gets the status of 3D rendering capabilities. In Silverlight, because

there’s no software rendering, it’s either Unavailable or Hardware.

RenderModeReason property

An enumeration of possible reasons for the RenderMode value.

Using this, you can determine if the cause is a failure to set GPU

acceleration, blocked by security, you have an incompatible card, or

3D is temporarily unavailable for some other system reason, such as

a Windows XP lock screen.

RenderModeChanged event

This event is raised whenever the RenderMode property changes.

The passed-in event args include all the information you’d need about

the current and previous render modes.

By using the GraphicsDeviceManager’s properties, you can quickly and easily tell if

you’ll be able to use 3D features in Silverlight. In addition, by ensuring you pay attention to changes in the render mode by using the RenderModeChanged event, you can

build a more robust application capable of reacting properly to system changes.

Listing 26.2 shows how to use the GraphicsDeviceManager to enable the correct

portions of the UI and inform the user of any changes to the render capabilities.

Listing 26.2 Checking for 3D availability using the GraphicsDeviceManager class

public partial class MainPage : UserControl


public MainPage()



Loaded += new RoutedEventHandler(MainPage_Loaded);


void MainPage_Loaded(object sender, RoutedEventArgs e)


GraphicsDeviceManager.Current.RenderModeChanged +=



if (GraphicsDeviceManager.Current.RenderMode ==








void OnRenderModeChanged(object sender, RenderModeChangedEventArgs e)



Detecting capabilities with the GraphicsDeviceManager


if (e.RenderMode == RenderMode.Unavailable)





private void Disable3dUI(RenderModeReason reason)


string message = "3d Not Available. Reason: " + reason.ToString();

Overlay3DNotAvailable.Visibility = Visibility.Visible;

MainContent.Visibility = Visibility.Collapsed;

Error UI




private void Enable3dUI()


Overlay3DNotAvailable.Visibility = Visibility.Collapsed;

MainContent.Visibility = Visibility.Visible;




Now you can run the application. You should see a MessageBox informing you that 3D

isn’t available. You’ll also see the “3D is not available” overlay UI once you dismiss the

message box.

Now, enable GPU acceleration. On a web page, you do so by using the object tag


For this project, though, I’d like to simply make it an elevated trust out-of-browser

application. This isn’t a requirement, but for the reasons mentioned in the overview

of this chapter, it makes security easier when you go to run the application outside of

the development environment.

If you haven’t already, open the project properties and select the option to enable

running out-of-browser, as covered in chapter 5. Next, click the out-of-browser settings

button, and check both Use GPU Acceleration and “Require elevated trust when running outside the browser.”

Now, run the application again. You shouldn’t see the MessageBox this time

around but instead should see the placeholder for 3D content. If you see the placeholder, you’re ready to proceed to the rest of the chapter. If you see a message about

not having 3D capabilities on your system, you may want to first update your graphics

driver from the vendor’s website.4 If you still see that message, you may be on a very

old or unsupported piece of hardware. There aren’t a lot of those out there, especially


All the cool kids know that you don’t get your graphics drivers from Windows Update if you’re using a discrete

graphics card. Instead, go to the nVidia or AMD site and download the correct drivers directly.




Introduction to 3D

in developer hands, but it happens. In that case, I can recommend only that you beg,

borrow, and steal until you have a more modern machine with 3D capabilities.

So far, you’ve used the RenderModeChanged event simply to enable or disable some

UI. In a real application, this is the place you’ll want to refresh your data. For example, if the render mode changes from unavailable to available, you’ll have to rebuild

the objects you need to support 3D rendering in your application. Without 3D graphics available, you wouldn’t want to bother loading all that data in memory.

The GraphicsDeviceManager and GraphicsDevice together have a lot of additional features, which you’ll explore in many of the remaining examples in this chapter. Before you explore the types that make up shapes to render, let’s wire up the

drawing surface to provide you with somewhere to render to.

26.4 Using the DrawingSurface

The regular Silverlight graphics system is a retained mode system. That means that you

define the structures for rendering (like a rectangle or some text), and Silverlight

remembers it from frame to frame. Another type of rendering, often used in games and

in 3D,5 is called immediate mode rendering. In this type of rendering, you’re responsible for drawing the entire frame of graphics on-screen each time it’s rendered.

Because of this different approach in rendering, Silverlight requires a rectangle on

the screen where the 3D content can be placed, rather than just loosely intermingling

it like any other UI element or requiring an actual new Windows-recognized operating system window like many other desktop technologies do. This rectangle, defined

by the DrawingSurface element, is the virtual window in your application that will be

owned by XNA/DirectX.

Because the DrawingSurface is a FrameworkElement, you can use it in XAML just

like any other element, but much like the MediaElement, it’s a window into another

rendering system. Update the MainPage.xaml file MainContent grid so it looks like

the next listing. You can leave the original TextBlock if you wish, or comment it out as

done here.

Listing 26.3 The DrawingSurface element on a page







And good old GDI/GDI+ if you ever had the pain or pleasure of overriding WM_PAINT to do your drawing.



Project structure: the scene and objects


Listing 26.3 shows how to put the drawing surface on a page in a Silverlight application. I mentioned that the DrawingSurface is a FrameworkElement. Because of that, it

can participate in composition and properly work with z-ordering and other XAML

features. You can overlay XAML to partially obscure the DrawingSurface, for example.

This is something that business application designers will simply expect, but for game

designers, that’s the holy grail of 2D and 3D composition efficiency.

Antialiasing is the generic name for a number of algorithms that help remove the

staircase effect on lines. If we had a higher density of pixels on the screen than our

eyes could detect, this wouldn’t be necessary. The reality is, displays haven’t yet caught

up. If you want to support antialiasing for your own project, the PreferredMultiSampleCount property is what you need to use. I broke out the CompositionMode

property because this is something you can set only in XAML.6 The higher the number, the slower the rendering, so be careful of how much smoothness you ask for.

In the markup, I wired up the Draw event exposed by the DrawingSurface. The

Draw event is raised whenever the drawing surface is invalidated—meaning whenever

it needs to be drawn. If you follow the usual approach of drawing items inside the

event handler and then calling InvalidateSurface, it’ll be called for each frame to

be rendered to screen.

TIP If you’re looking for a place to put code to handle the screen resizing—

for example, to recalculate what you put in 3D space—the DrawingSurface

SizeChanged event is the recommended location.

If you run the application now (if you pasted the code rather than typing it by hand,

make sure you have the Draw event handler MainDrawingSurface_Draw:stubbed out),

you’ll get a blank 3D rendering space, most likely purple.7

You now have an application that’s capable of rendering 3D content. But you don’t

yet have anything in place to actually render. You’d be forgiven for assuming it’d be a

simple matter to throw a few shapes out there and they’d easily render. 3D rendering

is much more complex than that. For that reason, you’ll need to add structure and a

fair bit of code to the application before you’ll see results.

26.5 Project structure: the scene and objects

3D programming doesn’t start to make sense until you see an actual shape on-screen.

If there’s any one single chapter where I’d recommend you type in the code and

experiment a bit to see what happens, this would be that chapter.



This was true in the prerelease builds and is expected to remain true in the released product. Don’t just take

my word for it, though; try it out both in markup and in code.

As a reviewer from the Baltimore area pointed out, it’s a nice Ravens purple. Go Ravens!




Introduction to 3D

Figure 26.3

A high-level look at the

architecture of the

sample application

The problem is, 3D rendering systems show you absolutely nothing until you have all

the major pieces in place. If I added bits to the code as they were explained, you

wouldn’t see anything rendered on-screen until the last few sections in this chapter. I

don’t know about you, but when talking about something like 3D, I want to see pixels!

In this section, you’ll structure the project to make it easier to plug additional

pieces in later. There will be a number of things, like the camera, projections, shaders,

and more, that will be included in here in the barest possible way simply to make sure

you can render on-screen.

You can avoid these problems if you use a 3D toolkit like Babylon 3D. Although I’m

a big fan of that toolkit, I’d rather show you how Silverlight is working and let you

make toolkit decisions yourself with the underlying knowledge in place.

But in acknowledgement of the popularity and, quite frankly, necessity of toolkits,

I’ve structured this example application following patterns and APIs that are as close

to the Babylon approach without adding extra work. When you finish the example,

you’ll have a basic 3D application architecture that will help you understand 3D as well

as enable you to, relatively easily, port to a 3D toolkit later if you wish. Figure 26.3

shows the architecture.

In this section, you’ll build the skeleton of the application architecture. There will

be a fair bit of code in place you don’t yet understand, but by the end of the next

chapter, all will be revealed. The code you create here will provide the minimum

amount of structure necessary to avoid a constant refactoring, as well as provide the

support objects required to render 3D content.

26.5.1 The scene

When rendering in 3D, you typically need some sort of master object that defines all the

parameters for what you want to render. It includes the angles through which the user

will see the content, a list of the content itself, and other things like lights and effects.

The object responsible for managing all of that information is typically called a

scene or stage, taking inspiration from movie and theater, respectively. Scene is generally the more common name, and more appropriate for having multiple instances, so

you’ll use that here.

A 3D system could have multiple scenes. Consider for a moment the old 2D video

games where you had a “walking around in the wildness” mode, and then a special


Tài liệu bạn tìm kiếm đã sẵn sàng tải về

1 3D—a natural way of interacting with information

Tải bản đầy đủ ngay(0 tr)