1. Trang chủ
  2. » Công Nghệ Thông Tin

Microsoft XNA Game Studio Creator’s Guide- P14 potx

30 224 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Lighting
Trường học Microsoft
Chuyên ngành Game Development
Thể loại Guide
Năm xuất bản Unknown
Thành phố Redmond
Định dạng
Số trang 30
Dung lượng 336,17 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

float3 unitDirection = normalizelightDirection; // L // N.L - dot product of surface normal and light direction float cosine = dotunitNormal, unitDirection; Diffuse Color * Diffuse Inten

Trang 1

float3 unitDirection = normalize(lightDirection); // L

// (N.L) - dot product of surface normal and light direction

float cosine = dot(unitNormal, unitDirection);

Diffuse Color * Diffuse Intensity * N.L

To make the light fade from the center even more dramatic, the light intensity isscaled with afallOffvariable.fallOffis the inverted exponent of the scaled dis-

tance, d, between the light and pixel exp(d) equals e d

where e is approximately

2.718281828

Because N.L = cos α, as the angle between the surface normal and light vector creases, cos α approaches 1 and diffuse light increases Shining a light directly at asurface normal generates a brighter reflection than a light shone at an angle awayfrom the normal vector.PointLightDiffuse()calculates the color added by thediffuse light:

de-float4 PointLightDiffuse(VStoPS IN){

// unit direction of light vector L

float3 lightDirection

= normalize(lightPosition - IN.transformedPosition); // brightest angle between L and N = 0

float diffuseLevel = dot(lightDirection, IN.normal);

// get distance from light to pixel

float distance = distance(lightPosition, IN.transformedPosition);

Trang 2

// compute a falloff for the lighting

float scale = 0.2f;

float fallOff = clamp(1.0f / exp(distance * scale), 0, 1);

// adjust the light intensity based on the falloff

lightIntensity *= fallOff;

// point light diffuse*intensity and color

return diffuseLevel * lightIntensity * color;

}

The point light vertex shader receives the vertex position, texture, and normal

data The position in the window is generated by multiplying the position by the

WVP matrix so that each vertex can be seen properly by the camera

transformedPositionis calculated by normalizing the product of the position

and World matrix, so this unit vector can be used in the specular and diffuse lighting

calculations The normal vector is also transformed with the World matrix and is

then normalized for the specular and diffuse calculations Ambient light is uniform

across the entire surface, so this calculation is performed in the vertex shader to save

a little processing time:

void VertexShader(in VSinput IN, out VStoPS OUT){

OUT.position = mul(IN.position, wvpMatrix);

The pixel shader combines the different lights together and blends them with the

texture for each pixel The sum of the ambient, specular, and diffuse light component

vectors is equivalent to the combination of different lighting components in Phong’s

reflection model

void PixelShader(in VStoPS IN, out PSoutput OUT){

float4 diffuseColor = PointLightDiffuse(IN);

float4 specularColor = SpecularLight(IN);

Trang 3

It is amazing that such a small amount of shader code can generate such a greatlighting effect

Point Light Example: The XNA Code

All of the shader code just described can be found in the PointLightPS.fx file in theShaders folder on this book’s website Be sure to add this file to your project in theShaders folder

To assist in setting the matrices for the shader, and to provide position data for thelighting calculations, the effect parameters l i g h t E f f e c t W o r l d,

lightEffectWVP, andlightEffectPositionare declared A texture ter,lightEffectTexture, allows you to set the image applied in the shader fromthe C# code The parameterlightEffectIntensitylets you set the intensity ofthe diffuse point light at run time from the application, andlightEffectColor

parame-allows you to set the color of the light Add these declarations to the game class ule level so you can set these shader variables from your C# code:

mod-private Effect lightEffect; // point light shader

private EffectParameter lightEffectWorld; // world matrix

private EffectParameter lightEffectWVP; // wvp matrix

private EffectParameter lightEffectPosition; // light position

private EffectParameter lightEffectIntensity; // point light strength private EffectParameter lightEffectTexture; // texture

private EffectParameter lightEffectColor; // color of point light

To be able to use your shader, you must load and compile it when the programstarts Add code to set up the shader inInitialize():

lightEffect = Content.Load<Effect>("Shaders\\PointLightPS");

To set the data in the shader variables at run time, you must initialize the effect rameters to reference the correct shader variables when the program begins To make

Trang 4

The LightingShader() method is needed in the game class to apply the

PointLightPS.fx shader while drawing with vertices while using an index buffer:

private void LightingShader(PrimitiveType primitiveType){

// avoid drawing back face for large amounts of vertices

// draw grid one row at a time

for (int Z = 0; Z < NUM_ROWS - 1; Z++){

graphics.GraphicsDevice.DrawIndexedPrimitives(

primitiveType, // primitive

Z * NUM_COLS, // start point in vertex

0, // vertex buffer offset

NUM_COLS * NUM_ROWS, // total verts in vertex buffer

0, // start point in index buffer

2 * (NUM_COLS - 1)); // end point in index buffer

Trang 5

Most of the code used to draw the primitive surface has been explained in previouschapters This includes transforming the object and drawing the vertices using an in-dex buffer reference Also, the shader’s effect parameters are used here to move thepoint light with the camera, to set the diffuse light intensity, and to set the texturevalue In step 4 of the code, the global variables in the shader are assigned values forthe WVP matrix and the World matrix This combination allows you to generatelight in the view space and then to render the objects based on the World matrix Re-place the existing version ofDrawIndexedGrid()with the following code to drawthe surfaces with the point light shader:

private void DrawIndexedGrid(string surfaceName){

// 3: build cumulative world matrix using I.S.R.O.T sequence

// identity, scale, rotate, orbit(translate & rotate), translate

world = scale * rotateX * rotateY * translate;

// 4: pass parameters to shader

lightEffectWVP.SetValue(world*cam.viewMatrix*cam.projectionMatrix); lightEffectWorld.SetValue(world);

Trang 6

If you compile and run the project, you will see the point light traveling with the

camera Move closer to the wall, and the light reflected back will become brighter

be-cause the point light is closer to the wall surface

Figure 22-4 shows the point light positioned above the center of the ground The

light is brightest directly beneath the light—hopefully this will help you see the point

of point light!

Point Light in the Vertex Shader Example

You won’t always be able to afford pixel-based lighting, because it is expensive for

the processor Moving specular and diffuse lighting calculations into the vertex

shader will drastically reduce the number of times these calculations need to be made

each frame The ambient, diffuse, and specular light can be combined in one color

variable in the vertex shader, which can then be sent to the pixel shader so that the

pixel shader doesn’t have to generate it When this color data is sent to the pixel

shader, it is automatically interpolated between vertices Using more vertices

pro-vides more definition and smoother shading; so for this method to be effective, an

index buffer is recommended for primitive surfaces

This example begins with the solution from the previous example You could

fol-low the steps here to modify the shader to implement vertex shader–based point

Trang 7

struct VStoPS2{

float4 position : POSITION0;

float4 color : COLOR;

float2 UV : TEXCOORD0;

};

The revised version of the vertex shader uses the new struct to define the output.Note that the calculations for all lights are now performed in the vertex shader Thecolor variable that is sent to the pixel shader stores the sum of the ambient, diffuse,and specular lights Replace the existing vertex shader with this revised version toprocess the lighting calculations before sending the output to the pixel shader:

void VertexShader(in VSinput IN, out VStoPS2 OUT){

VStoPS vsData; // original output values used for color calculation vsData.transformedPosition = mul(IN.position, worldMatrix);

vsData.normal = normalize(mul(IN.normal, (float3x3)worldMatrix)); vsData.position = mul(IN.position, wvpMatrix);

vsData.UV = IN.UV;

OUT.position = vsData.position; // position output OUT.UV = vsData.UV; // uv output

vsData.ambientColor = AmbientLight(); // color output

float4 diffuseColor = PointLightDiffuse(vsData);

float4 specularColor = SpecularLight(vsData);

OUT.color = (vsData.ambientColor + specularColor + diffuseColor);

}

A slight change is made in the pixel shader to receive the new vertex shader output,which already includes the combined ambient, diffuse, and specular light:

void PixelShader(in VStoPS2 IN, out PSoutput OUT){

OUT.color = tex2D(textureSampler, IN.UV)*(IN.color);

}

Trang 8

To view a stationary point light, in your XNA code, set the position of the light to

a constant value (Or you could continue to move the light with your camera if you

prefer.) You can make the position of the point light stationary by replacing the

in-struction that moves the light with the camera inDrawIndexedGrid():

lightEffectPosition.SetValue(new Vector4(0.0f, 0.0f, 0.0f, 1.0f));

When you run this version of the code, you will still see the point light It will not

be defined as much as the pixel shader point light, but you may notice a performance

boost when running it

A simple lighting system, such as a lone directional light or the sun, can add depth

to your game and reveal the details in your environment Point light can add

intrigu-ing details for night-time or indoor settintrigu-ings As you can see, the effect is quite

bril-liant

C HAPTER 22 REVIEW EXERCISES

To get the most from this chapter, try out these chapter review exercises

1. Complete the step-by-step examples presented in this chapter, if you have

not already done so

2. After completing the directional light demonstration using theBasicEffect

object, try reducing the number of vertices that are stored in the vertex

buffer by lowering the number of rows and columns to two each Run the

demo again (after this change has been made) and notice how the specular

detail diminishes Then, increase the total number of vertices for rows and

columns to 50 each Notice how the specular lighting’s effect improves

with more vertices

3. Using the directional light example, change the Y value of the normal

in the vertex buffer from +1 to –1 Notice how everything turns black

Explain why this happens

4. What is a useful intensity level for ambient light during daytime settings in

the directional light demo? What is a useful intensity level for ambient light

during evening settings in the directional light demo?

C H A P T E R 2 2

Trang 9

This page intentionally left blank

Trang 10

CHAPTER 23

Input Devices

Trang 11

Nowa-days, this means that you need to support the keyboard, mouse, Xbox 360 gamecontroller, Zune controls, and possibly even a wireless racing wheel The XNAFramework greatly simplifies this task Specifically, theMicrosoft.Xna.Frame-work.Input namespace enables the capture of button press and release events,mouse click events, keyboard presses and game controller button, thumbstick, DPad,and trigger events You can even use the Input library to send rumbles to users’ con-trollers to let them know when they have exploded

This chapter focuses primarily on the input handling library for the Xbox 360 and

PC Zune input handling is performed with a subset of this library A discussion ofZune input handling and an example are included at the end of this chapter

H ANDLING KEYBOARD INPUT

The Input library handles press and release events for all common keyboard keys To

view a full listing of key identifiers, type Keys in the Game Studio code window This

will open a drop-down menu that displays all identifiers available These are theidentifiers for common keyboard keys, as listed in Table 23-1

Help

Common keyboard keys

T A B L E 2 3 - 1

Trang 12

D0 to D9 refer to the numbers at the top of the keyboard, whereas keys onthe number pad use NumPad0 to NumPad9

You will capture key events using aKeyboardStateobject At each frame, this

object is updated by polling the keyboard with theGetState()method:

KeyboardState keyboardState = Keyboard.GetState();

Individual key events are distinguished with theIsKeyDown()method using a

Keysidentifier as a parameter:

bool KeyboardState.IsKeyDown(Keys Keys.Identifier);

H ANDLING MOUSE INPUT

In many PC versions of major game titles, and even for the 3D graphics engine used in

this book, the mouse can be used to control the player’s direction The Input

namespace enables handling of mouse-based events Mouse movements and click

events are detected with aMouseStateobject Every frame, the state of the mouse is

refreshed with theGetState()method, which retrieves information about the

cur-sor’s position and the press state of the mouse buttons:

MouseState mouseState = Mouse.GetState();

With these continuous updates, the MouseState object’s X and Y properties

track the cursor’s position in the game window:

int MouseState.X

int MouseState.Y

Press and release states of each mouse button are retrieved from the

B u t t o n S t a t e property of each button Most mice have a

MouseState.LeftButton and MouseState.RightButton property, and

some have aMouseState.MiddleButtonproperty TheButtonState

attrib-ute stores either aPressedvalue, if the button is pressed, or aReleasedvalue, if it

is not

H ANDLING CONTROLLER INPUT

In addition to the keyboard and mouse, theInputnamespace also handles events

for the game controller The game controller itself provides several options to obtain

C H A P T E R 2 3

Trang 13

user input through presses and shifts of the thumbstick, as well as presses to theDPad, buttons, left and right bumpers, and triggers Figure 23-1 shows the name ofeach control.

Game Pad States

TheGamePadStateobject for the controller allows you to check the state of eachcontrol on each game controller at every frame Because it is possible to have up tofour game controllers connected to your Xbox 360, theGamePadStateobject is of-ten declared as an array with a size of four:

private GamePadState[] gamePadState = new GamePadState[4];

Although the array has room for up to four controllers, if only one controller

is connected, this controller will use the first object in the array; it isreferenced with zero as the index

Right Shoulder Right Trigger B

A Right Stick

DPad Left Stick

Start X Y

Trang 14

At every frame, the states for each game pad are retrieved with theGetState()

method andPlayerIndexattribute to identify the controller:

gamePadState[0] = GamePad.GetState(PlayerIndex.One);

gamePadState[1] = GamePad.GetState(PlayerIndex.Two);

gamePadState[2] = GamePad.GetState(PlayerIndex.Three);

gamePadState[3] = GamePad.GetState(PlayerIndex.Four);

Handling Pressed and Released States

Most of the controls on the game controller use aButtonState.Pressedand a

ButtonState.Released attribute to indicate whether or not the control is

pressed Table 23-2 is a complete listing of controls that store either aPressedor

Releasedproperty

Thumbsticks

Another way to enable user control is to use thumbsticks They can be pushed up,

down, and sideways to help with tasks such as controlling the player’s view or

guid-ing the direction of game characters Each thumbstick stores a float to measure the

deviation from its central resting position The X and Y values range from -1 to +1,

where 0 is the center position These are the four possible thumbstick properties:

Buttons.A Buttons.Right Shoulder DPad.Down

Buttons.B Buttons.RightStick DPad.Left

Buttons.Back Buttons.Start DPad.Right

Buttons.LeftShoulder Buttons.X DPad.Up

Buttons.LeftStick Buttons.Y

Game pad controls

T A B L E 2 3 - 2

Trang 15

You can enable intuitive features such as acceleration or rapid firing with the Xbox

360 controller triggers On every controller there is one left and one right trigger.Each trigger returns a float that ranges from 0 (for released) to 1 (for fully pressed)

float GamePadState.Triggers.Right

float GamePadState.Triggers.Left

Adjusting the Input Device Responsiveness

The responsiveness needed for input controls can vary depending on the purpose ofthe control The IsKeyDown() method andButtonState.Pressedpropertycan be used to check whether a key, mouse button, or controller’s DPad, button, orthumbstick is pressed Similarly, theLeftandRightproperties of a trigger and the

X and Y properties of a thumbstick will return nonzero values when moved awayfrom their default positions Most of the time, an immediate response at every frame

is useful for events such as rapid fire or speed control In other situations, press eventsmight be used to toggle through a list of properties to choose a game character, select

a map, change weapons, or even enter a name through an input device When gling states, tens or even hundreds of true IsKeyDown() events or

tog-ButtonState.Pressedstates are registered between the time that the user firstpresses the control and releases it For cases like these, it is helpful to compare the cur-rent key or button state with the previous one The following code snippet showshow current and previous states are used to allow a player to alter the display valuesbetween “On” and “Off”:

if (kbstate.IsKeyDown(Keys.T) && kbstatePrevious.IsKeyUp(Keys.T))

if (keyT == "On") // alternate On or Off status

keyT = "Off"; // for keydown events else

keyT = "On";

Adding a Rumble

The ability to make a controller rumble is a popular feature among gamers Whetherthe player has crashed into a wall or is checked into the boards, sending a rumblethrough their controller will add to the effect A rumble can be sent to the left andright sides of the game controller with the methodSetVibration() The vibrationtakes three parameters to identify the control and to set the strength of the rumble.The rumble strength is measured with a float that ranges from 0 to 1

GamePad.SetVibration(int controllerNumber, float LRumble, float RRumble);

382

Ngày đăng: 02/07/2014, 06:20

TỪ KHÓA LIÊN QUAN