Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Introduction to 3D Game Programming with DirectX.9.0 - F. D. Luna

.pdf
Скачиваний:
243
Добавлен:
24.05.2014
Размер:
6.94 Mб
Скачать

354Chapter 19

FogStart—Marks the starting depth at which objects will begin to be fogged

FogEnd—Marks the ending depth at which objects will stop being fogged

Note: FogStart and FogEnd essentially define the depth interval (from the viewpoint) that objects must be in to be fogged.

FogColor—A DWORD or D3DCOLOR value type that describes the fog’s color

FogEnable—Specify true to enable vertex fog or false to dis-

F M which ones don’t. ThisAis useful for only fogging certain areas. For

able vertex fog

Y

 

Any geometry that we render using the fog.txt effect will have fog

 

L

applied to it. In this way, we can control which objects get fogged and

example, generallyEif it is foggy outside, the insides of houses are not

foggy. On the same note, certain parts of a geographic region may be foggy, but otherTparts may not be. Figure 19.2 shows screen shots taken from this section’s sample program called Fog Effect.

Figure 19.2: Screen shots from the Fog Effect sample. In this sample we use a linear fog function, and the fog render states are specified inside an effect file.

Team-Fly®

The Effects Framework 355

19.9 Sample Application: Cartoon Effect

The two effect file samples that we have shown so far did not use shaders. Because shaders are typically an important part of special effects, we want to show at least one example of them together. The sample CartoonEffect implements the cartoon shader as discussed in Chapter 17, but this time using the effects framework. Following is an abridged version of the effect file:

//

//File: tooneffect.txt

//Desc: Cartoon shader in an effect file.

extern matrix WorldMatrix; extern matrix ViewMatrix; extern matrix ProjMatrix; extern vector Color;

extern vector LightDirection;

static vector Black = {0.0f, 0.0f, 0.0f, 0.0f}; extern texture ShadeTex;

struct VS_INPUT

{

vector position : POSITION; vector normal : NORMAL;

};

struct VS_OUTPUT

{

vector position : POSITION; float2 uvCoords : TEXCOORD;

vector diffuse : COLOR;

};

// Cartoon Shader Function: VS_OUTPUT Main(VS_INPUT input)

{

...[Implementation omitted for brevity.]

}

sampler ShadeSampler = sampler_state

{

Texture = (ShadeTex);

MinFilter = POINT; // no filtering for cartoon shading MagFilter = POINT;

MipFilter = NONE;

};

technique Toon

{

pass P0

{

// Set P0’s vertex shader. vertexShader = compile vs_1_1 Main();

P a r t I V

356 Chapter 19

// Hook up the sampler object to sampler stage 0. Sampler[0] = (ShadeSampler);

}

}

We note that the cartoon shader functions are defined inside the effect file, and we specify the shader to use for a particular pass using the syntax vertexShader = compile vs_1_1 Main(); in the pass block. Device states are set as usual in the effect file.

19.10 EffectEdit

Before we conclude this chapter, we want to mention the EffectEdit program that ships with the DirectX SDK. It can be found in the \DXSDK\Samples\C++\Direct3D\Bin folder. Figure 19.3 shows a screen shot.

Figure 19.3: A screen shot of the EffectEdit program that ships with the DirectX SDK

The EffectEdit program is useful for testing and writing effect files. We recommend that you spend some time exploring this tool.

19.11 Summary

Effect files encapsulate a complete effect, including possible hardware fallbacks for hardware with different capabilities and rendering passes. The effects framework is desirable because we can change effect files without recompiling source code and because it allows us to encapsulate an effect, making everything modular. Effect files can be used without shaders; that is, it is perfectly acceptable to make an effect file that uses the fixed function pipeline.

The Effects Framework 357

A technique is a particular implementation of a special effect. Typically, an effect file will consist of several techniques that all implement the same effect but in different ways. Each implementation will utilize the capabilities of a specific generation of hardware. Thus, the application can choose the technique that is most fitting for the target hardware. For example, to implement multitexturing, we might define two techniques—one that uses pixel shaders and one that uses the fixed function pipeline. In this way, users with a pixel shader-capable 3D card can use the pixel shader technique, and users with a 3D card that does not support pixel shaders can still execute the effect in the fixed function version.

A technique consists of one or more rendering passes. A rendering pass consists of the device states and shaders used to render the geometry for that particular pass. Multiple rendering passes are necessary because some special effects require the same geometry to be rendered several times, each time with different device states and/or shaders.

P a r t I V

This page intentionally left blank.

Appendix

An Introduction to Windows Programming

To use the Direct3D API (application programming interface), it is necessary to create a Windows (Win32) application with a main window, upon which we render our 3D scenes. This appendix serves as an introduction to writing Windows applications using the native Win32 API. Loosely, the Win32 API is a set of low-level functions and structures exposed to us in the C programming language that enables our application and the Windows operating system (OS) to communicate with each other. For example, to notify Windows to show a particular window, we use the Win32 API function ShowWindow.

Windows programming is a huge subject, and this appendix introduces only what is necessary for us to use Direct3D. For readers interested in learning more about Windows programming with the Win32 API, the book Programming Windows (now in its fifth edition) by Charles Petzold is the standard text on the subject. Another invaluable resource when working with Microsoft technologies is the MSDN library, which is usually included with Microsoft’s Visual Studio but can also be read online at www.msdn.microsoft.com. In general, if you come upon a Win32 function or structure that you would like to know more about, go to MSDN and search for that function or structure. Often in this appendix we direct you to look up a function or structure on MSDN for more elaborate details.

Objectives

To learn and understand the event-driven programming model used in Windows programming

To learn the minimal code necessary to create a Windows application that is necessary to use Direct3D

359

360 Appendix

Note: To avoid confusion, we use a capital W to refer to Windows the OS, and we use a lowercase w to refer to a particular window running in Windows.

Overview

As the name suggests, one of the primary themes of Windows programming is programming windows. Many of the components of a Windows application are windows, such as the main application window, menus, toolbars, scroll bars, buttons, and other dialog controls. Therefore, a Windows application typically consists of several windows. These next few subsections provide a concise overview of Windows programming concepts that we should be familiar with before beginning a more complete discussion.

Resources

In Windows, several applications can run concurrently. Therefore, hardware resources such as CPU cycles, memory, and even the monitor screen must be shared among multiple applications. In order to prevent chaos from ensuing due to several applications accessing/modifying resources without any organization, Windows applications do not have direct access to hardware. One of the main jobs of Windows is to manage the presently instantiated applications and handle the distribution of resources among them. Thus, in order for our application to do something that might affect another running application, it must go through Windows. For example, to display a window, you must call ShowWindow; you cannot write to video memory directly.

Events, the Message Queue, Messages, and the

Message Loop

A Windows application follows an event-driven programming model. Typically, a Windows application sits and waits (an application can perform idle processing—that is, perform a certain task when no events are occurring) for something to happen—an event. An event can be generated in a number of ways; some common examples are keypresses, mouse clicks, and when a window is created, resized, moved, closed, minimized, maximized, or becomes visible.

When an event occurs, Windows sends a message to the application for which the event occurred and adds the message to the application’s message queue, which is simply a priority queue that stores messages

An Introduction to Windows Programming

for an application. The application constantly checks the message queue for messages in a message loop, and when it receives one it dispatches it to the window procedure of the particular window that the message is for. (Remember that an application can contain several windows within it.) The window procedure is a special function that is associated with each window of the application. (Every window has a window procedure, but several windows can share the same window procedure. Therefore, we don’t necessarily have to write a window procedure for each window.) The window procedure is a function we implement that handles specific messages. For instance, we may want to destroy a window when the Escape key is pressed. In our window procedure we would write:

case WM_KEYDOWN:

if( wParam == VK_ESCAPE )

::DestroyWindow(MainWindowHandle); return 0;

The messages that a window doesn’t handle are usually forwarded to a default window procedure, which then handles the message.

To summarize, the user or an application does something to generate an event. The OS finds the application that the event was targeted toward, and it sends that application a message in response. The message is then added to the application’s message queue. The application is constantly checking its message queue for messages. When it receives a message, the application dispatches it to the window procedure associated with the window for which the message is targeted. Finally, the window procedure executes instructions in response to the message.

Figure 1 summarizes the event-driven programming model.

361

A p p e n d i x

362 Appendix

Figure 1: The event-driven programming model

GUI

Most Windows programs present a GUI (graphical user interface) that users can work from. A typical Windows application has one main window, a menu, a toolbar, and perhaps some other controls. Figure 2 shows and identifies some common GUI elements. For Direct3D game programming, we do not need a fancy GUI. In fact, all we need is a main window, where the client area is used to render our 3D worlds.

Figure 2: A typical Windows application GUI. The client area is the entire large white space of the application. Typically, this area is where the user views most of the program’s output. When we program our Direct3D applications, we render our 3D scenes into the client area of a window.

An Introduction to Windows Programming

Hello World Windows Application

Below is the code to a fully functional yet simple Windows program. Follow the code as best you can. The next section explains the code a bit at a time. It is recommended that you create a project with your development tool, type the code in by hand, compile it, and execute it as an exercise. Note that you must create a Win32 Application Project, not a Win32 Console Application Project.

/////////////////////////////////////////////////////////////////////

//

//File: hello.cpp

//Author: Frank D. Luna (C) All Rights Reserved

//System: AMD Athlon 1800+ XP, 512 DDR, Geforce 3, Windows XP,

//MSVC++ 7.0

//

//Desc: Demonstrates creating a Windows application.

/////////////////////////////////////////////////////////////////////

//Include the windows header file, this has all the

//Win32 API structures, types, and function declarations

//we need to program Windows.

#include <windows.h>

//The main window handle. This is used to identify

//the main window we are going to create.

HWND MainWindowHandle = 0;

//Wraps the code necessary to initialize a Windows

//application. Function returns true if initialization

//was successful, else it returns false.

bool InitWindowsApp(HINSTANCE instanceHandle, int show);

//Wraps the message loop code. int Run();

//The window procedure, handles events our window

//receives.

LRESULT CALLBACK WndProc(HWND hWnd,

UINT msg,

WPARAM wParam,

LPARAM lParam);

// Windows equivalant to main()

int WINAPI WinMain(HINSTANCE hInstance,

HINSTANCE

hPrevInstance,

PSTR

pCmdLine,

int

nShowCmd)

{

//First we create and initialize our Windows

//application. Notice we pass the application

//hInstance and the nShowCmd from WinMain as

363

A p p e n d i x