Вы находитесь на странице: 1из 265

......................................................................................................................................................

4
........................................................................................................ 4
....................................................................................................................... 4
....................................................................................................................................... 5
............................................................... 5
........................................................................................................................ 5
......................................................................................................................................... 5
1. XNA Framework .......................................................................................................... 6
OpenGL .................................................................................................................................................... 6
DirectX .................................................................................................................................................. 7
Managed DirectX ....................................................................................................................................... 8
XNA Framework ........................................................................................................................................ 9
1.1. , XNA Framework. ...................................11
1.2. . ..................................................................................................18
1.2.1. DirectX . ........................................................20
1.2.2. Visual Studio 2005 ................................................................24
1.2.3. .....................................................................................................27
1.2.4. . ........................32
................................................................................................................................................33
2. . ........................................................................................................35
2.1. . ................................................................................................35
2.2. . .............................................................................................36
2.3. HLSL ..............................................................................................................................37
2.3.1. ............................................................................................................38
2.3.2. HLSL ..................................................................................................................................40
2.3.3. XNA Framework..........................................................................47
2.4. (PrimitiveType.PointList). ......................................................................................................52
2.4.1. . .................................................58
2.4.2. . .................................................................................................60
2.4.3. ....................................................................................................62
2.4.4. HLSL. ........................................................................66
2.5. ........................................................................................................................................71
2.5.1. (PrimitiveType.LineList). .....................................................................71

2.5.2. (PrimitiveType.LineStrip). ........................................................................74


2.6. ..............................................................................................................................81
2.6.1. (PrimitiveType.TriangleList) .......................................................81
2.6.2. (PrimitiveType.TriangleFan) ...................................................................91
2.6.3. (PrimitiveType.TriangleStrip) .......................................93
..............................................................................................................................................109
3. . ...............................................................................110
3.1. .NET XNA Framework. ........................................110
3.2. . ...............................................................................................................117
3.2.1. . ...................................................................................121
3.2.2. . ...................................................................123
3.2.3. . ............................................................................125
3.3. . .....................................................................................................................................139
3.3.1. Idle.................................................................................................144
3.3.2. Stopwatch. ..........................................................145
3.3.3 ........................................................................147
3.3.4. foreach for. ..............................................................................................149
3.3.5. . .........153
3.4. . ............................................................................154
3.4.1. . .............................................................................................................155
3.4.2. . .......157
3.4.3. . .............................................................................159
..........................................................................................................................................162
4. .....................................................................................................................163
4.1. . .............................................................................................164
4.2. . ...........................................................................................................................168
4.3. . ..................................................................173
4.4. . ...........................................................................................177
4.5. . .................................................................179
4.5.1. Display Properties. ...............................183
4.6. .................................................................185
4.7. . ..............................................................................................................190
4.7.1. Custom Actions ............................................................................................192
4.7.2. .NET Framework 2.0 XNA Framework 1.0 .............................194
..........................................................................................................................................196

5. ...............................................................................................................197
5.1. HLSL ..........................................................................................197
5.1.1. .................................................................................................197
5.1.2. ........................................................................................197
5.1.3. ....................................................................................................198
5.1.4. - ...........................................................................................................199
5.2. NVIDIA FX Composer 2.0 ................................................................................................................202
5.2.1. COLLADA 1.4.1...........................................................................................................203
5.2.2. FX Composer 2.0 ......................................................................205
5.2.3. .....................................................................................................207
5.2.4. . ................................................................................211
5.3. Vertex Shader .................................................................................................214
5.3.1. .................................................................................................................................215
5.3.2. . ................................................................................................................................220
5.3.3. .......................................................................................225
5.4. ..................................................................................................227
5.4.1. XNA Framework ...........................................................230
5.5. ...............................................................................................................232
5.5.1. ........................................................................................233
5.5.2. if HLSL .........................................................................................................243
5.5.3. ......................................................................................................................................247
5.5.4. ..........................................................................263
..........................................................................................................................................264
..............................................................................................................................................265


.NET
. API OpenGL DirectX,
.NET ,
C++. .NET :
API OpenGL DirectX C++
, unsafe-
, , .NET API
.
, C++/CLI
API, : C++/CLI
, .
Microsoft XNA
.NET,
. XNA XNA Framework
.NET ,
. Windows XNA
Framework DirectX, .NET COM- DirectX.
, , ,
.NET, XNA Framework
. , XNA Framework
: ,
, , .. .. XNA Framework
Windows, ,
.NET Framework.
XNA ,
, :
, , CAD- .. ,
XNA:
XNA Framework. XNA Framework
Windows Forms ,
XNA Framework XNA
Framework.


,
. , C#
.NET.



Managed DirectX 2.0.
, Managed DirectX,
. ,
Managed DirectX. , ,
Managed DirectX, .
, , ,
: Managed DirectX 2.0 ,
Managed DirectX 2.0 XNA Framework. .
: XNA Framework. XNA Framework
, Managed DirectX,
, - Visual C++ .NET, .NET
.
, XNA Framework, , , -
5 ,
. , ,
, - ,

XNA Framework
.


, . XNA Framework.
XNA Framework Visual Studio,
.
XNA Framework. XNA
,
. :
, .

, XNA
Framework.
, .
,
; HLSL, - Vertex Shader 1.1
FX Composer 2.0,
.


Visual Studio 2005 Pro SP1,
Visual C# 2005 Express SP1. XNA Framework
,
1.1. ,
Intel GMA 9xx.


, , :
DOC , .
Examples , .
NVIDIA IDE NVIDIA FX Composer 2.0.
Tools
o Debug View .
o .NET Reflector .NET.
o RightMark 3D .
Visual C# 2005 Express XNA Game Studio 1.0 Express.
Visual C# 2005 Express SP1 Visual C# 2005 Express.
XNA Game Studio Express 1.0 XNA, .
XNA Game Studio 2.0 XNA Game Studio.
Visual C# 2005 Express, Visual C# 2005 Express
SP1 XNA Game Studio Express 1.0, Examples ,
read only.

,
. : (Codemasters Software),
(BHV), (NVIDIA), (Microsoft),
(Microsoft), , (NVIDIA), (NVIDIA),
(XNA Dev), , (Intel) (
Intel, ). (AMD),
(NVIDIA) (SolarWind), .

1. XNA Framework
Windows
GDI,

, . GDI

, GDI
. .
, ,

. ,

.
, GDI .
,
, , , , NVIDIA GeForce 5900 Ultra
Canon Laser Shot LBP-1120
. ,

. ,

. (,
,

3D
),

, GDI .

DOS Windows,
Windows.

OpenGL

,
Microsoft
Windows NT 3.5, Windows 95 OSR2
OpenGL
API
. OpenGL
.
, :
OpenGL ,
Windows.

MCI1.
: ,
.
OpenGL API,
. -
, ..,
API.

,
Windows.
OpenGL API, .
OpenGL
(ARB), , Intel,
Microsoft, AMD, NVIDIA, SGI, 3D Labs, Evans & Sutherland ..
,
.. , .
1

Media Control Interface .


,
. MCI , , [.4].

, API, ,
, ,
Microsoft.
, OpenGL
Windows, Microsoft API
.

DirectX
API, Microsoft, , WinG [.1].
API
Windows 3.1
Windows 95. 256 .
WinG ,
GDI. , DOS OpenGL 1.1 .
WinG , Microsoft
API
.
RenderMorfics Reality Lab
Windows. Game SDK, DirectX.
- Microsoft Reality Lab API
, DirectX,
DirectX
( 1.1). , DirectX,
,
. 2002- 9- DirectX.
DirectX ,
Microsoft DirectX, ,
.

, DirectX OpenGL 1.1
( DirectX) 7- . , 9- OpenGL
DirectX , OpenGL DirectX.

1.1. DirectX
DirectX

DirectX 1.0

1995

DirectX 2.0

1996

DirectX 3.0 / 3.0a

1996

DirectX 5.0 / 5.1 / 5.2

1997-1998

DirectX 6.0 / 6.1

1998-1999

DirectX 7.0 / 7.0a / 7.1

1999

DirectX 8.0 / 8.1

2000-2001

DirectX 9.0 / 9.0a / 9.0b / 9.0c +


Updates

2002-2006

DirectX?
,
- . DirectX COM2-,
. Microsoft
, Intel, ATI, NVIDIA,
2

Component Object Model . API


, . COM
, ,
. , COM,
[.9] MSDN.

Creative .. DirectX
,
Win32, GDI MCI.
DirectX 9 3 ( 1.1):
DirectX Graphics, .
DirectInput, : , ,
..
DirectSound, : ,
, MIDI- ..

1.1. DirectX

Managed DirectX
.NET Framework
, C#. , COM-
DirectX C++,
C++, , . ,
C# COM-, DirectX C#
: C#
.NET, unsafe-,
. , COM-
.NET
.
.NET, Microsoft 9-
DirectX COM- DirectX: Managed DirectX. 2005
Managed DirectX,
.NET 2.0, , Managed DirectX
(Generic) .
Managed DirectX 2.0 DirectX, Microsoft.DirectX.dll.
Microsoft.DirectX.dll .NET 2.0
.
.NET- Microsoft Visual Basic, Microsoft Visual C#,
Microsoft Visual J#, Iron Python .. DirectX, Managed DirectX
: Direct3D Graphics, DirectInput DirectSound.
( 1.2), .
3

DirectX : DirectDraw (
), DirectMusic ( ), DirectPlay ( ) DirectShow
( ). ,
DirectX.

DirectX COM-
DirectX. , COM- IDirect3D9 -
Microsoft.DirectX.Direct3D.Device, IDirect3DTexture9 Microsoft.DirectX.Direct3D.Texture
. , Managed DirectX
C++ 4.
1.2. Managed DirectX 2.0


DirectX

Microsoft.DirectX


DirectX

,

:
, ,
..

Microsoft.DirectX.Generic


DirectX

Microsoft.DirectX.Direct3D

DirectX Graphics

3D

Microsoft.DirectX.Direct3D.CustomVertex

DirectX Graphics

Microsoft.DirectX.DirectInput

DirectInput

Microsoft.DirectX.XInput

DirectInput


XBOX

Microsoft.DirectX.DirectSound

DirectSound

,
.

Beta Managed DirectX 2.0 Release,


XNA Framework.

XNA Framework
2005- Microsoft XBOX 360.
Microsoft x86
PowerPC, x86.
, Windows.
, Microsoft : Windows
XBOX 360. ,

, .
Microsoft,

, Windows, XBOX 360.
.NET: , .NET-
IL,
. , .NET-, -, ,
.
:
1. .NET Framework ,
, web-, web-. , ,
, . , .NET Framework
Windows ( System.Windows.Forms,
System.Drawings), Windows .
2. Managed DirectX, DirectX. DirectX
Windows, Managed DirectX API,
Windows. , Managed DirectX
System.Windows.Forms System.Drawing.
4

, DirectX
.

XBOX .NET Framework,


.NET Compact Framework. XNA Framework
API
Windows XBOX 360.
XNA Framework 4 ( 1.2):
Platform () , - API,
DirectX.
, . ,
Platform ,
: , Microsoft XNA Framework
.
Core Framework ( ) - XNA,
. Microsoft.Xna.Framework.dll 5
: Graphics ( ), Audio ( ), Input (
-), Math ( ), Storage ( ).
( 1.3).
Windows (Graphics, Audio, Input) DirectX,
Storage .NET Framework .
, .
Extended Framework ( ) ,
, : ,
, . Extended
Framework (Game Engine) .
Microsoft.Xna.Framework.Game.dll.
Game , . , XNA
(Starter Kits),
.

Games

Extended Framework
(Microsoft.Xna.Framework.Game.dll)

: Application Model, Content Pipeline

Core Framework
(Microsoft.Xna.Framework.dll)

: Graphics, Audio, Input, Math, Storage

Platform
: Direct3D, XACT, XINPUT, XContent ..
1.2. XNA Framework

1.3. Microsoft.Xna.Framework.dll

XNA

Microsoft.Xna.Framework

Math

: ,

.. Managed DirectX
( )


D3DX, DirectX. XNA
Framework

,


COM.
Microsoft.Xna.Framework.Graphics

Graphics

Microsoft.Xna.Framework.Graphics.PackedVector

Graphics

.
32 ,

Microsoft.Xna.Framework.Audio

Audio

Microsoft.Xna.Framework.Input

Input

(,
, ).

Microsoft.Xna.Framework.Storage

Storage


:
, (Save
Games) ..

, .
XNA Framework .
Microsoft.Xna.Framework.Graphics,
.

1.1. , XNA
Framework.
,
. . , XNA Framework,
( 1.3). GUI5-
Windows Forms, .NET.

1.3. (Ex01), XNA.

Graphic User Interface

Microsoft Visual Studio 2005 GUI


Windows (File | New | Project...). Visual C#
| Windows | Windows Application,
,
Create directory for Solution Ok6. Form1.cs
7
MainForm.cs .
Microsoft.Xna.Framework.dll, Core
Framework, Graphics.
Reference Solution Explorer Add
Reference... ( 1.4). Microsoft.Xna.Framework
Ok ( 1.5).

1.4. Solution Explorer

6
7

.
MainForm.cs.

1.5. Add Reference

.
, View Code
( View Code Solution Explorer).
Microsoft.Xna.Framework.Graphics,
:
using Microsoft.Xna.Framework.Graphics;

XNA Framework
GraphicsDevice, ( ).
GraphicsDevice :
public
GraphicsDevice(GraphicsAdapter
adapter,
DeviceType
deviceType,
IntPtr
renderWindowHandle, CreateOptions creationOptions, params PresentationParameters[]
presentationParameters);

adapter GraphicsAdapter, (
).

GraphicsAdapter.DefaultAdapter.
deviceType , DeviceType (
1.4). DeviceType.Hardware.
renderWindowHandle ,
.
creationOptions CreateOptions,
( 1.5).
CreateOptions.SoftwareVertexProcessing CreateOptions.SingleThreaded.
PresentationParameters PresentationParameters,

PresentationParameters.

, PresentationParameters. 1.6
PresentationParameters.
, .
, ,
CreateOptions.HardwareVertexProcessing ,
. Intel GMA 900 Intel GMA950,
i915G i945G . HardwareVertexProcessing
,
,
.
SoftwareVertexProcessing.
1.4. DeviceType

Hardware

Reference

DirectX SDK.
,
(,
8 GeForce2). ,

,
.

NullReference

-,
( NUL MS-DOS
Windows).

1.5. CreateFlags

HardwareVertexProcessing

GPU9

SoftwareVertexProcessing

CPU.

MixedVertexProcessing

.

. , ,
2.0
GeForce3,
1.1.
1.1 ,
2.0 .

NoWindowChanges


..
.
.

SingleThreaded

.

.

SinglePrecision


.
, double,
7 .

8
9

2.3.
Graphic Processor Unit , .

1.6. PresentationParameters

bool IsFullScreen


false.
,
true.

int BackBufferCount

,

.

,
.
.
,

, .

.

,
BackBufferCount 1.

int BackBufferWidth

.
0, Device
,
10.

int BackBufferHeight

.
0, Device
,
.

Direct3D.SwapEffect SwapEffect

,
.

SwapEffect.Discard
,
.

x86
(FPU) x8611 80-
, . ,
80-
, extended double.
(, float), 80- ,
32- float.
,
(CW) (PC), .
, , 7-, 16- 19-
. . 80-
,
.
PC CW (thread) , ,
. , CreateOptions.SinglePrecision
GraphicsDevice CW ,
7 . ,
, double, 7- .
: , , PC CW ,

10

, .
, ..
11
i486DX ,
(8087, 80287, 80387).

, , ,
.
, , , -, .
, CreateOptions.SinglePrecision ,

.
. ,
- , ,
double. ,
.
,
GraphicsDevice:
GraphicsDevice device=null;

Load
12
GraphicsDevice c ( 1.1) .
1.1
private void MainForm_Load(object sender, EventArgs e)
{
// presentParams
PresentationParameters presentParams = new PresentationParameters();
// ,
presentParams.IsFullScreen = false;
//
presentParams.BackBufferCount = 1;
//
presentParams.SwapEffect = SwapEffect.Discard;
// . 0 (
// ), GraphivsDevice
// presentParams. ,
// , .
presentParams.BackBufferWidth = ClientSize.Width;
presentParams.BackBufferHeight = ClientSize.Height;
//
//
//
//
//
//
//

, :
-
-
-
GPU
- presentParams (. )

device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware, Handle,
CreateOptions.SoftwareVertexProcessing | CreateOptions.SingleThreaded,
presentParams);
}

, .
Clear13 GraphicsDevice,
:
public void Clear(ClearOptions options, Color color, float depth, int stencil);

12

MainForm.
XNA Framework, GraphicsDevice,
(override) ( ) .

.
13

options , .

ClearOptions.Target.

ClearOptions.DepthBuffer ClearOptions.Stencil,

, .

color , .
Microsoft.Xna.Framework.Graphics.Color,
System.Drawing.Color. - XNA

Framework Windows.

depth , .

stencil , .

Clear Paint,
:
private void MainForm _Paint(object sender, PaintEventArgs e)
{
device.Clear(ClearOptions.Target, Microsoft.Xna.Framework.Graphics.Color.CornflowerBlue,
0.0f, 0);
}

Microsoft.Xna.Framework.Graphics.Color . ,
System.Drawing.

GraphicsDevice (override) ,
:
public void Clear(Color color);

color , .

:
private void MainForm_Paint(object sender, PaintEventArgs e)
{
device.Clear(Microsoft.Xna.Framework.Graphics.Color.CornflowerBlue);
}

Dispose.
FormClosed ( 1.2).
1.2.
private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
{
//
if (device != null)
{
// ()
device.Dispose();
// null
device = null;
}
}

, .NET Dispose
GraphicsDevice ( ,
Finalize, Dispose).
. , Finalize
, Windows Direct3D
, . , GraphicsDevice,
, Direct3D.
.
CreateOptions.SingleThreaded,
.

. ( F5).
, Clear ( ,
F9) ,
. , ?
, ,
.
.
Present GraphicsDevice:
void Present()

Paint
, , .
CD Ch01\Ex01.

1.2. .
GraphicsDevice.Clear ,
:
public void Clear(ClearOptions
Rectangle[] regions);

options,

Color

color,

float

depth,

int

stencil,

rect Microsoft.Xna.Framework.Rectangle,

, .
. Microsoft.Xna.Framework.Rectangle
System.Drawing,
XNA Framework Windows.

Rectangle Microsoft.Xna.Framework,

XNA Framework,
Microsoft.Xna.Framework.Graphics.
,
( 1.6):
1.3.
//
device.Clear(Microsoft.Xna.Framework.Graphics.Color.CornflowerBlue);
// , .
//
Microsoft.Xna.Framework.Rectangle[] rect = new Microsoft.Xna.Framework.Rectangle[1];
// , 25%
//
rect[0] = new Microsoft.Xna.Framework.Rectangle(ClientSize.Width/4,
ClientSize.Height/4, ClientSize.Width/2, ClientSize.Height/2);
//
device.Clear(ClearOptions.Target, Microsoft.Xna.Framework.Graphics.Color.Green, 0.0f,
0, rect);

1.6. , Clear.

Clear
. , ( 1.7).
, ,
, ( 1.4).

1.7. , Clear

1.4.
// Examples\Ch01\Ex02
private void MainForm_Paint(object sender, PaintEventArgs e)
{
//
device.Clear(Microsoft.Xna.Framework.Graphics.Color.WhiteSmoke);
// ,
Microsoft.Xna.Framework.Rectangle[] rects = new Microsoft.Xna.Framework.Rectangle[32];
int k = 0;
//
for (int j = 0; j < 8; j++)
for (int i = j % 2; i < 8; i += 2)
{
//
rects[k] = new Microsoft.Xna.Framework.Rectangle(i * ClientSize.Width / 8,
j * ClientSize.Height / 8, ClientSize.Width / 8, ClientSize.Height / 8);
k++;

}
// rects
device.Clear(ClearOptions.Target, Microsoft.Xna.Framework.Graphics.Color.Brown, 0.0f, 0,
rects);
device.Present();
}

1.2.1. DirectX .
, Windows XNA Framework
DirectX. , Windows
XNA Framework DirectX.
. ,
.
DirectX DirectX, Start |
All Programs | Microsoft DirectX SDK | DirectX Utilities | DirectX Control Panel.
1.8. ,
, DirectX.
.

1.8. DirectX. Direct3D.

Direct3D Direct3D Graphics. ,


Direct3D
Use Debug Version of Direct3D Use Retail Version of Direct3D

( Debug/Retail D3D Runtime).

Direct3D
Graphics

Direct3D Graphics
.
(, Visual Studio 2005).
Direct3D
Graphics. Debug Output Level,
,
. ,
.
Debugging : Maximum Validation (
, Direct3D Graphics), Enable Shader Debugging
( ) Break on Memory Leaks ( ).
.
(Debug) DirectX Graphics (Retail) .
DirectX .
.
, Use Retail Version of
DirectX Debug Output Level
Direct3D Graphics.

Debug View
Visual Studio 2005 Pro DirectX,
Visual C# 2005 Express .
CD Debug View,
\Tools\DebugView.
DebugView.exe. ( 1.9).
,
, .
Debug View,
.

1.9. Debug View

DirectX, DirectX.
, ( Ch01\Ex02), ,
. Debug Info :
// Direct3D
Direct3D9: :====> ENTER: DLLMAIN(041dd6e0): Process Attach: 0000041c, tid=000016a8
Direct3D9: :====> EXIT: DLLMAIN(041dd6e0): Process Attach: 0000041c
// Direct3D
Direct3D9: (INFO) :Direct3D9 Debug Runtime selected.

// Direct3D (
// DirectX-, C++)
D3D9 Helper: Enhanced
D3D_DEBUG_INFO

D3DDebugging

disabled;

Application

was

not

compiled

with

// INFO
// . ,
// Software Vertex Processing ( ).
// ,
// CreateOptions.SoftwareVertexProcessing.
Direct3D9: (INFO) :======================= Hal SWVP device selected
Direct3D9: (INFO) :HalDevice Driver Style 9
Direct3D9: :DoneExclusiveMode
Direct3D9: :====> ENTER: DLLMAIN(041dd6e0): Process Detach 0000041c, tid=0000022c
// Direct3D
Direct3D9: (INFO) :MemFini!
// Direct3D
Direct3D9: :====> EXIT: DLLMAIN(041dd6e0): Process Detach 0000041c


Time , .

, .. 0.0 .

, - .
device.Dispose() Close() .
:
Direct3D9: :====> ENTER: DLLMAIN(042dd6e0): Process Attach: 00000298, tid=00000910
Direct3D9: :====> EXIT: DLLMAIN(042dd6e0): Process Attach: 00000298
Direct3D9: (INFO) :Direct3D9 Debug Runtime selected.
D3D9 Helper: Enhanced
D3D_DEBUG_INFO

D3DDebugging

disabled;

Application

was

not

compiled

with

Direct3D9: (INFO) :======================= Hal SWVP device selected


Direct3D9: (INFO) :HalDevice Driver Style 9
Direct3D9: :DoneExclusiveMode
// . , (
// GraphicsDevice CreateOptions.SingleThreaded)
// .
Direct3D9: (WARN) :Device that was created without D3DCREATE_MULTITHREADED is being
used by a thread other than the creation thread.
// ! ,
Direct3D9: (ERROR) :Final Release for a device can only be called from the thread that
the device was created from.
Direct3D9: (WARN) :Device that was created without D3DCREATE_MULTITHREADED is being
used by a thread other than the creation thread.

Direct3D9: (WARN) :Device that was created without D3DCREATE_MULTITHREADED is being


used by a thread other than the creation thread.
Direct3D9: (WARN) :Device that was created without D3DCREATE_MULTITHREADED is being
used by a thread other than the creation thread.
Direct3D9: (WARN) :Device that was created without D3DCREATE_MULTITHREADED is being
used by a thread other than the creation thread.
Direct3D9: :====> ENTER: DLLMAIN(042dd6e0): Process Detach 00000298, tid=00000520
Direct3D9: (INFO) :MemFini!
Direct3D9: :====> EXIT: DLLMAIN(042dd6e0): Process Detach 00000298

, ,
,
Finalize ,
Direct3D , . , DirectX
.
Direct3D XNA Framework. ,
Direct3D ,
D3DCREATE_MULTITHREADED. GraphicsDevice,
, ,
CreateOptions.SingleThreaded.
, Direct3D .NET Framework ,
- GraphicsDevice
. ,
Direct3D, .
XNA Framework c DirectX.
, XNA Framework .NET DirectX.
?
XNA Framework
Direct3D.Device.Present, .NET Reflector,
CD Tools\NET Reflector14:
public unsafe void Present()
{
// , Dispose
// GraphicsDevice. Dispose ,
// ObjectDisposedException
InternalHelper.CheckDisposed(this, (void*) this.pComPtr);
// COM IDirect3DDevice9,
// GraphicsDevice.
IDirect3DDevice9* devicePtr1 = this.pComPtr;
// COM- IDirect3DDevice9::Present,
// . , .NET Reflector ,
// , .
int num1 = **(((int*) devicePtr1))[0x44](devicePtr1, 0, 0, 0, 0);
// IDirect3DDevice9::Present ,
// ( COM
// ).
if (num1 < 0)
{
// -2005530520 ( )
if (num1 == -2005530520)
{
// DeviceLost ( )
// . 1.2.4.
EventArgs args1 = EventArgs.Empty;
14

, C#-, .NET Reflector, . ,


IL-.

EventHandler handler1 = this.<backing_store>DeviceLost;


if (handler1 != null)
{
handler1(this, args1);
}
}
// .
// , Com- IDirect3DDevice9::Present
throw ExceptionHelper.GetExceptionFromResult(num1);
}
}

, GraphicsDevice.Present COM-
IDirect3DDevice9::Present COM.
, Windows GraphicsDevice.Present
. ,
.

1.2.2. Visual Studio 2005


Visual Studio 2005
, XNA Framework. Visual
Studio, .
, Visual Studio 2005 (Solution),
XML .sln.
: ,
( .exe .dll). ,
C#, .csproj. C#-
.cs, .resx ..
Solution Explorer ( 1.4).


. , 4 :
, , .
.

,
. Visual Studio 2005 :
Debug Release.
Debug .
, .exe
.
,
, .. , ,
,
.
Release .
: ,
, ..
( ), ,
.

Visual Studio ( 1.10). , Debug Release
. ,
Debug, Release
. ,
Release Shareware Version, Release Full Version ..

1.10.


Debug Release ,
, Debug Release-.
.

Release C#
. , Debug.
. Debug .
Properties Solution, 15. ( 1.11).

1.11.

Debug Enable unmanaged code debugging.


, . ?
XNA Framework COM-
DirectX16. Visual Studio 2005
COM- DirectX , ,
Output (. 1.1).

15
16

, , (*.cjproj ..)
, Windows.

Ch01\Ex02 ( )
Output DirectX ( 1.12).
.

1.12. Output.

, Output Enable unmanaged code Debugging


Debug View (. 1.1.1),
Visual C# 2005 Express.

Release, Visual Studio F5 (Start with Debugging)
.NET- , .
Ctrl + F5
(Start without debugging).


, Check for arithmetic overflow/underflow,
Advanced Build Setting, Advanced Build Setting Build
( 1.13). :
,
System.OverflowException.
, :
// 16- 32767
short a = 32767;
// 5. a -32764, 32752 !!!
a = (short) (a + 5);
// WriteLine -32764
Console.WriteLine(a);

1.13. Advanced Build Setting

,
Release. ,
, checked. :

checked
{
a = (short) (a + 5);
}

C#
. [.7], [.8] [.9].

1.2.3.
, (Ex02)
. , , - .
, -
( 1.13).
( 1.14).
, .
.
, Windows Forms Paint
. ,
Resize17 Invalidate, Paint.

1.13. .

1.14.

: ResizeRedraw,
Paint.
Load :
SetStyle(ControlStyles.ResizeRedraw, true);

. ?
, ,
.
( BackColor) .
.

17

Resize

, Paint Form
OnPaintBackground, BackColor.
, GDI+, ,
. ,
-
Paint. , OnPaintBackground
protected override void OnPaintBackground(PaintEventArgs pevent)
{
//
}

, , .
ControlStyles.Opaque, ,
:
SetStyle(ControlStyles.Opaque, true);

Load - .
, , ,
.
,
, Paint.
!
, ,
, . , .

Load. ,
,
, .
,
. XNA Framework Reset
GraphicsDevice:
public void Reset(params PresentationParameters[] presentationParameters);

presentationParameters

PresentationParameters,
.

PresentationParameters.

, PresentationParameters presentParams
Load ( MainForm) Resize
presentParams
Device.Reset ( 1.5).
1.5.
private void MainForm_Resize(object sender, EventArgs e)
{
//
presentParams.BackBufferWidth = ClientSize.Width;
presentParams.BackBufferHeight = ClientSize.Height;
//
device.Reset(presentParams);
}


.
Paint, .

- . ?
, . .
.
, Output DirectX,
:

Direct3D9: (ERROR) :Failed to create driver surface


Direct3D9: (ERROR) :Reset failed and Reset/TestCooperativeLevel/Release are the only legal
APIs to be called subsequently
A first chance exception of type 'Microsoft.DirectX.Direct3D.DriverInternalErrorException'
occurred in Microsoft.DirectX.Direct3D.dll

Direct3D ,
, , .
, ,
.
MinimumSize, .
Properties , ,
: , ..
Load
SizeFromClientSize, :
// 1x1 .
// MinimumSize
MinimumSize = SizeFromClientSize(new Size(1, 1));

. , ,
, Windows, .
- . ,
. ,
Resize
0 0 . ,
Windows . ,
Resize ,
:
1.6.
private void MainForm_Resize(object sender, EventArgs e)
{
// ,
if (WindowState != FormWindowState.Minimized)
{
presentParams.BackBufferWidth = ClientSize.Width;
presentParams.BackBufferHeight = ClientSize.Height;
device.Reset(presentParams);
}
}

18.
1.7 (Ex03).
1.7.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Xna = Microsoft.Xna.Framework;
using XnaGraphics = Microsoft.Xna.Framework.Graphics;
18

, (1.2.4).

namespace GSP.XNA.Book.Ch01.Ex03
{
public partial class MainForm : Form
{
GraphicsDevice device=null;
PresentationParameters presentParams;
public MainForm()
{
InitializeComponent();
}
private void MainForm_Load(object sender, EventArgs e)
{
SetStyle(ControlStyles.Opaque | ControlStyles.ResizeRedraw, true);
MinimumSize = SizeFromClientSize(new Size(1, 1));
presentParams = new PresentationParameters();
presentParams.IsFullScreen = false;
presentParams.BackBufferCount = 1;
presentParams.SwapEffect = SwapEffect.Discard;
presentParams.BackBufferWidth = ClientSize.Width;
presentParams.BackBufferHeight = ClientSize.Height;
device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware,
this.Handle, CreateOptions.SoftwareVertexProcessing | CreateOptions.SingleThreaded,
presentParams);
}
private void MainForm_Paint(object sender, PaintEventArgs e)
{
device.Clear(ClearOptions.Target, XnaGraphics.Color.WhiteSmoke, 0.0f, 0);
Xna.Rectangle[] rects = new Xna.Rectangle[32];
int k = 0;
for (int j = 0; j < 8; j++)
for (int i = j % 2; i < 8; i += 2)
{
rects[k] = new Xna.Rectangle(i * ClientSize.Width / 8,
j * ClientSize.Height / 8, ClientSize.Width / 8, ClientSize.Height / 8);
k++;
}
device.Clear(ClearOptions.Target, XnaGraphics.Color.Brown, 0.0f, 0, rects);
device.Present();
}
private void MainForm_Resize(object sender, EventArgs e)
{

if (WindowState != FormWindowState.Minimized)
{
presentParams.BackBufferWidth = ClientSize.Width;
presentParams.BackBufferHeight = ClientSize.Height;
device.Reset(presentParams);
}
}
private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
{
if (device != null)
{
device.Dispose();
device = null;
}
}
}
}

Microsoft.Xna.Framework
Microsoft.Xna.Framework.Graphics,

Microsoft.Xna.Framework.Color
Microsoft.Xna.Framework.Graphics.Rectangle.
using C# -
System.Drawing.

1.1.
, 10 ( 1.15).
, .
, .
.

public Color(byte r, byte g, byte
b), Color , .
0255 (0 , 255 ).

1.14. 1.1.

,
, CD Ch01\Ex04.

1.2.4.
.
Windows ,
XNA
. . , -
, ,
, .
GraphicsDevice
. XNA Framework DirectX
(Device Lost).
, ,
. , 19
ALT
+ Enter. , :
1. , DirectX.
2. . FAR, ,
(Start | All Programs | Accessories | Command
Prompt)
3. ( Alt + Enter).
Ex03 ,
- Microsoft.Xna.Framework.Graphics.DeviceLostException,
.
GraphicsDevice
GraphicsDeviceStatus:
public GraphicsDeviceStatus GraphicsDeviceStatus { get; }

GraphicsDeviceStatus,
:
Normal
NotReset , Reset
GraphicsDevice.

Lost .
NotReset, ,
GraphicsDevice.Reset, , .
Lost,
Paint .
,
Paint, . XNA Framework
Direct3D.DeviceNotResetException Direct3D.DeviceLostException.
Direct3D.DeviceNotResetException,
GraphicsDevice.Reset()
Form.Invalidate(), Paint.

. Paint 1.8.
1.8.
// Examples\Ch01\Ex05
private void MainForm_Paint(object sender, PaintEventArgs e)
{
try
{
// , DeviceLostException (
// catch)
19

, .

if (device.GraphicsDeviceStatus == GraphicsDeviceStatus.Lost)
throw new DeviceLostException();
// ,
if (device.GraphicsDeviceStatus == GraphicsDeviceStatus.NotReset)
device.Reset();
//
device.Clear(XnaGraphics.Color.WhiteSmoke);
Xna.Rectangle[] rects = new Xna.Rectangle[32];
int k = 0;
for (int j = 0; j < 8; j++)
for (int i = j % 2; i < 8; i += 2)
{
rects[k] = new Xna.Rectangle(i * ClientSize.Width / 8,
j * ClientSize.Height / 8, ClientSize.Width / 8, ClientSize.Height / 8);
k++;
}
device.Clear(ClearOptions.Target, XnaGraphics.Color.Brown, 0.0f, 0, rects);

//
//

//
//

device.Present();
}
DeviceNotResetException, .
Paint
catch (DeviceNotResetException)
{
Invalidate();
}
DeviceLostException,

catch (DeviceLostException)
{
}

1.2
, 1.1,
.

XNA Framework ,
,
-. XNA Framework
Microsoft DirectX .NET. DirectX,
Microsoft.Xna.Framework.dll
Microsoft.Xna.Framework.Game.dll
.NET 2.0 .
.NET-
Microsoft Visual Basic, Microsoft Visual C# , Microsoft Visual J# Iron Python. , XNA
Framework - ,
, , XBOX 360.
XNA Framework : Platform, Core
Framework, Extended Framework Game. Graphics (
Core Framework),
.
,

. , ,

2. .
XNA Framework ,
GDI/GDI+. XNA Framework
, . XNA
Framework : , .
,
. , NVIDIA GeForce 8800 GTX
400 20 [.7].
: ,
, . XNA Framework
x, y z.
, X , Y
, Z ( 2.1).
(-1, -1, 0), (+1, +1, 0).
(-1, 1, 0)

(1, 1, 0)
+Y

(0, 0, 0)

(-1, -1, 0)

+X

(1, -1, 0)

2.1. XNA Framework.

2.1. .
Microsoft.Xna.Framework.Graphics
. VertexPositionColor,
.
:
public VertexPositionColor(Vector3 position, Color color);

position ;

color .


Position Color VertexPositionColor:
public Color Color;
public Vector3 Position;

Microsoft.XNA.Framework.Vector3,
. Vector3 XNA Framework
Vector2 Vector4, , ,
20

.
,
. ,
. , TGV-A
513 / [15], 350 /.

. Vector2, Vector3, Vector4 XNA


Framework ,
. ,
. ,
Vector2, Vector3 Vector4
System.Drawing.PointF.
. :
//
VertexPositionColor[] vertices;

, , . ,
(GPU
Graphics Processor Unit), , ,
.
. XNA Framework
VertexDeclaration, :
public VertexDeclaration(GraphicsDevice graphicsDevice, VertexElement[] elements);

graphicsDevice ,

elements ( VertexElement) c .

elements,
. , elements
. elements? :
4. ( ).
5. (, , 21).
6. , ( , ,
22 ..).
7. .
, , .
, XNA Framework VertexPositionColor (
) ,
:
public static readonly VertexElement[] VertexElements;

,
VertexDeclaration.

2.2. .
,
VertexPositionColor.
, VertexTransformedPositionColor:
VertexDeclaration decl;

decl = new VertexDeclaration(device, VertexTransformedPositionColor.vertexElements);

, , -
Load .
Paint. ,
, ,
VertexDeclaration Device ,
Load.
DrawUserPrimitives:
DrawUserPrimitives<T>(PrimitiveType
primitiveCount);
21

primitiveType,

T[]

vertexData,

int

vertexOffset,

32- ,
, .
22
5.X.

int

primitiveType , PrimitiveType.

1.2.1, 1.2.2 1.2.3.


, XNA Framework :
(PrimitiveType.PointList),

(PrimitiveType.LineList),

(PrimitiveType.LineStrip), (PrimitiveType.TriangleList),

(PrimitiveType.TriangleStrip)

(PrimitiveType.TriangleFan).

vertexData .

vertexOffset . .

,
(, ).

primitiveCount , .

.
:
1.

2.

.
, , Load.

3.

Paint

GraphicsDevice.Clear.

4.

(
, Load).

5.

, GraphicsDevice. VertexDeclaration
, .

6.

GraphicsDevice.DrawUserPrimitives.

7.

, Device.Present.

, . , GPU
, .
,
. ,
DrawUserPrimitives 23.
.

2.3. HLSL
High Level Shader Language (
), HLSL. HLSL
.
, .
8- DirectX. DirectX 8
- , 9-
DirectX ,
. DirectX24,
- HLSL, DirectX 9. XNA Framework
HLSL, XNA Framework Windows
DirectX.
HLSL ,
.

23

DrawUserPrimitives
System.InvalidOperationException Both a valid vertex
shader and pixel shader (or valid effect) must be set on the device before draw
operations may be performed.
24

, NVIDIA Cg [.16], [.3]

2.3.1.
2.2 XNA Framework.
( GraphicsDevice.DrawUserPrimitives)
. . ,
GraphicsDevice.DrawUserPrimitives
XNA Framework, (
), ( 2.2).
:

,
,


( )


( )

2.2.

8. ,
.
() . : ,
25 .
, clip space.
: (x, y, z, w).
w:

x y z
( , , ).
w w w

, (1, 2, 3, 4)

1 2 3
( , , ) (0.25,0.5,0.75)
4 4 4

, 3D .
w 1.
(-1, -1, 0, 1),
(1, 1, 0, 1),
(0, 0, 0, 1).
25

5.x.

9.
. -
, .
.

DirectX . ,
Device.DrawUserPrimitives ,
. Managed DirectX XNA Framework Beta 1
, XNA Framework Beta 2 - .
, XNA Framework -.

10. . .
GraphicsDevice.DrawUserPrimitives.
PrimitiveType.TriangleStrip ,
() .
.
2.6.3.
11.
. (, )
.
,
.
12. ,
.
(, ..),
. ,
.

,
. NV40
NVIDIA, GeForce 6800, 6 16
, , 6- 16- . [.8]

13. .
.
, DirectX
. , NVIDIA GeForce 8800 GTX,
GPU G80, 8 , ,
[.7].
, ,
. HLSL
, .

. ,
, :
(),
.
AMD Athlon .
. ,
.
AMD 400 .
400 .
, . ,
400 . ,
400 2400 .
400 .
, 7-
(400/60). , . .

;
. ,
,
. , ,
.


. , 0.017
( 60 ), 28 0.44 ,
100 - 1.33 .. -,
( 2.3).
, .
.

GraphicsDevice.DrawUserPrimitives, .

2.3. .
, .

2.3.2. HLSL
XXI 3dfx GPU Rampage,
. Microsoft
3dfx - ,
DirectX 8. Vertex Shader 1.0 (VS
1.0), Pixel Shader 1.0 (PS 1.0) [.4].
, , ,
26. , Rampage
: 3dfx NVIDIA,
Rampage .

, 27 GPU NV10 (1999 ).
Microsoft DirectX. ,
DirectX-, NV10 - .
NV10 API OpenGL [.17], [.18].

26

(shader)
(shade) .
27
Pixel Shader 0.5

GPU NV20 (NVIDIA


GeForce3), 2001 . NV20
Microsoft NVIDIA Vertex Shader 1.1 Pixel Shader 1.1,
Vertex Shader 1.0 Pixel Shader 1.0. NV20 NV25
(GeForce4), .
Pixel Shader 1.1 1.328. GPU R200
(Radeon 8500) ATI Pixel Shader 1.4, R300 (Radeon 9700 Pro) Vertex Shader 2.0
Pixel Shader 2.0 (. 1).
2002-
. Microsoft , Vertex
Shader Pixel Shader .
Vertex/Pixel Shader
, .
GPU. ,
Vertex Shader Pixel Shader IL .NET.
Vertex Shader Pixel Shader
GPU , .
, GPU R200 ATI Pixel Shader 1.4 Pixel Shader 1.0,
Pixel Shader 1.1, Pixel Shader 1.2 Pixel Shader 1.3.
. , . , R200
Pixel Shader 2.0, ,
R200.
GPU
. , Pixel Shader 1.1 16
, Pixel Shader 2.0
.
- . ,
.
2002 Microsoft High Level Shader
Language (HLSL). HLSL ,
() . HLSL C-
C++ C#. HLSL
, . ,
HLSL, - DirectX. ,
HLSL C#- (IL),
( 2.4).


HLSL


(Vertex/Pixel
Shader)

2.4. HLSL-.

HLSL (Effect),
.fx. , 3DS MAX.
(technique). .
,
: High High End, Medium
, Low 29.
,
.

28

NV25 (GeForce4) Pixel


Shader 1.2. NV25 , ,
. Pixel Shader 1.2 ,
1.3.
29
.


,
. . ,
(aqua). , Fill.
, . : .

, .
(w), 1 ( 2.1).
2.1.
float4 MainVS(float3 pos)
{
return float4(pos, 1.0);
}

, , HLSL, C-:
MainVS, float3,
float4. float3 float4, C, C++,
C#? HLSL.

.
HLSL : .
C ( 1.1).
1.1.

bool

, true
false

int

32-

half

16-

float

32-

double

64-

, ,
. , ,
30. ,
31
double float, half - .

. int,
int,
. , :
// a 5
int a = 5;
// b 1
int b = a / 3;
// c 2
int c = b * 2;

? .
int, , float:
// a 5.0
float a = 5.0;
30

, .
, GPU NV3x (GeForce FX) half float 12-
-2 2. GPU ATI R3xx/R4xx 24-
. , GPU
ATI, NVIDIA Intel, 5.
31

// b 1.66667
float b = a / 3.0;
// c 3.33334
float c = b * 2.0;

, , . HLSL
int float:
// a 5.0
float a = 5.0;
// b
float b;
//
float fd = a / 3.0;
//
float ff = frac(fd);
//
b = fd - ff;
// , 0, .
// , frac(2.3) = 0.3, frac(-2.3) = 0.7
if ((fd < 0) && (ff > 0))
b = b + 1;
// c 2.0
float c = b * 2.0;

,
.
- , ,
HLSL.
32. , , int
.

.
, , ,
4. ,
, ( -) .
, GPU ,
( ).
HLSL 2- 4-. N
type ,
(Generic) C#:
vector<type, size>

type : bool, int, half, float double;

size , 1, 2, 3 4.

v, float.
vector<float, 4> v;

:
{type}{N}

type

N .

, v :
float4 v;
32

Vertex Shader Pixel Shader .

HLSL .
C. ,
v

(0.2, 0.4, 0.6, 0.8) .

float4 v={0.2, 0.4, 0.6, 0.8};

v:
float4 v=float4(0.2, 0.4, 0.6, 0.8);

N ,
, .. :
N.
:
// (0.1, 0.2)
float2 a={0.1, 0.2};
// (0.3, 0.4)
float2 b=float2(0.3, 0.4);
// . b
// 1.0. c (0.3, 0.4, 1.0)
float3 c=float3(b, 1.0);
// .
// d (0.7, 0.3. 0.4, 1.0)
float4 d=float4(0.7, c);
// . d
// (0.1, 0.2. 0.3, 0.4)
float4 e=float4(a, b);

, HLSL
2.1. , , ,
. DirectX ,
.
, Pos ,
. HLSL
(semantics), ,
. 2.2
. HLSL 3.

, ..
.
0. .

2.2.

POSITION[n]

COLOR[n]

PSIZE[n]

( )

,
. , pos
MainVS POSITION ( 2.2).
2.2.
float4 MainVS(float3 pos:POSITION)
{
return float4(pos, 1.0);
}

, MainVS .
HLSL . ,
,
POSITION ( 2.3).
2.3.
float4 MainVS(float3 pos:POSITION):POSITION
{
return float4(pos, 1.0);
}

- .
.
(aqua) ( 2.4).
2.4.
float4 MainPS() : COLOR
{
return float4(0.0, 1.0, 1.0, 1.0);
}


HLSL 0.0, 1.0.

,
. COLOR DirectX,
MainPS .

,
,
. (technique),
. Fill,
MainVS MainPS ( 2.5).
2.5.
technique Fill
{
pass p0
{
VertexShader = compile vs_1_1 MainVS();
PixelShader = compile ps_1_1 MainPS();
}
}

, technique.
, pass.
. Fill
p0.

,
.

(pass) :
VertexShader = compile { } { };

:
PixelShader = compile { } { };

(shader profile) - ,
. ,
,
. .
, Vertex Shader 1.1 vs_1_1; Pixel Shader 1.4 ps_1_4, Pixel
Shader 2.0 ps_2_0 . Pixel Shader 2.x
: ps_2_a ps_2_b, Pixel Shader 2.x,
NV3x, R4xx. 2.3 2.4
.
2.3.

vs_1_0

1.0

vs_1_1

1.1

vs_2_0

2.0

vs_2_a

2.x

vs_3_0

3.0

2.4.

ps_1_0

1.0

ps_1_1

1.1

ps_1_2

1.2

ps_1_3

1.3

ps_1_4

1.4

ps_2_0

2.0

ps_2_a

2.x ( NV3x)

ps_2_b

2.x ( R4xx)

ps_3_0

3.0

(.
2).
.
.
, , ATI Radeon 9500
(R3xx) , NVIDIA GeForce FX 5200 (NV3x) , Intel GMA 900 .
2, , , ,
vs_1_0, vs_1_1, vs_2_0 ps_1_0, ps_1_1, ps_1_2,
ps_1_3, ps_1_4 ps_2_0. , vs_2_0 ps_2_0
. (technique)
High End, vs_3_0 ps_3_0.

GPU NV3x
ps_2_0 ps_2_a ([.5], [.6]).
GPU, ps_1_4
ps_2_0. NV3x,
ps_1_4.

,
. , , Fill
vs_1_1 ps_1_1:
GeForce3 (NV20).

, , Fill, .
*.fx, ,
SimpleEffect.fx ( 2.6).
2.6.
// . (x, y, z).
// (x, y, z, 1.0)
float4 MainVS(float3 pos:POSITION):POSITION
{
return float4(pos, 1.0);
}
// . .
float4 MainPS():COLOR
{
return float4(0.0, 1.0, 1.0, 1.0);
}
// Fill
technique Fill
{
//
pass p0
{
// . vs_1_1
VertexShader = compile vs_1_1 MainVS();
// . ps_1_1
PixelShader = compile ps_1_1 MainPS();
}
}

C#-.

2.3.3. XNA Framework


XNA Framework, ,
Effect. Effect , ,
( 2.5). , HLSL
, .
. , Effect
Techniques EffectTechnique, . ,
Passes EffectPass .
Effect

Techniques
(EffectTechnique)

Passes
(EffectPass)
2.5. Effect.

.
*.fx
Effect.CompiledEffect:
public static CompiledEffect CompileEffectFromFile(string effectFile, CompilerMacro[]
preprocessorDefines, CompilerIncludeHandler includeHandler, CompilerOptions options,
TargetPlatform platform);

effectFile .

preprocessorDefines ( #define C#),


. null.

includeHandler , #include fx-.


#include, null.

options HLSL,
CompilerOptions ( 2.5.). CompilerOptions ,
|. , ,
CompilerOptions.None.

platform TargetPlatform, ,

XNA

Framework

1.0

TargetPlatform.Windows TargetPlatform.Xbox360, .
TargetPlatform.Windows.

2.5. CompilerOptions.

None

Debug

NotCloneable(*)

( )
Clone.
,
,
.
50%.

ForceVertexShaderSoftwareNoOptimizations


Pixel
Shader ( 3.0),
.

ForcePixelShaderSoftwareNoOptimizations


Pixel
Shader ( 3.0),
.

PartialPrecision

,
.
, double
float half.

SkipOptimization

SkipValidation


(
..)

. ,

- ,

.

(*) CompileEffectFromFile.
Effect.CompileEffectFromFile fx- (, - ),
System.IO.IOException
System.IO.FileNotFoundException System.IO.DirectoryNotFoundException.

CompileEffectFromFile

CompiledEffect,

, ( -
..).
public struct CompiledEffect
{

// ,
public string ErrorsAndWarnings { get; }
//
public bool Success { get; }
// Success true,
public byte[] GetEffectCode();
...
}

, GetEffectCode - ,
exe- .NET. ,
. , , -
.

- - ,
-. , Visual C# 2005
Express33 , Content Pipeline, fx nvb. ,
, Content Pipeline, fx-.

-
.
Effect:
public Effect(GraphicsDevice graphicsDevice, byte[] effectCode, CompilerOptions options,
EffectPool pool);

graphicsDevice Direct3D,

byte[] effectCode
CompileEffectFromFile.

options , CompilerOptions

2.5.).

CompilerOptions.NotCloneable,

pool EffectPool,

. fx-,
null.
Effect - .
.
Techniques :
public EffectTechniqueCollection Techniques { get; }

XNA- . ,
Effect
CurrentTechnique.
public EffectTechnique CurrentTechnique { get; set; }

, ,
CurrentTechnique,
EffectTechnique, .
EffectTechnique:
public sealed class EffectTechnique
{
//
public string Name { get; }
//
public EffectPassCollection Passes { get; }
//
public bool Validate();
33

Visual Studio 2005 Pro .

...
}

.
GPU, ( ) .
(technique) GPU (,
ps_1_4 NV2x), XNA Framework .
, , 34.

. EffectTechnique
Validate. , Validate
true, false. ,

.
, ,
, :
GraphicsDevice device;
// , true -
// Load
closing = false;
...
// Load.
CompiledEffect compiledEffect;
try
{
//
compiledEffect = Effect.CompileEffectFromFile(effectFileName, null, null,
CompilerOptions.None, TargetPlatform.Windows);
}
//
catch (IOException ex)
{
//
MessageBox.Show(ex.Message, " ", MessageBoxButtons.OK,
MessageBoxIcon.Error);
// . Close()
// Load, (
// Application.Idle, Close ,
// closing true).
closing = true;
Application.Idle += new EventHandler(Application_Idle);
return;
}
//
if (!compiledEffect.Success)
{
//
MessageBox.Show(String.Format(" : \r\n{0}",
compiledEffect.ErrorsAndWarnings), " ", MessageBoxButtons.OK,
34

, .

MessageBoxIcon.Error);
closing = true;
Application.Idle += new EventHandler(Application_Idle);
return;
}
// - .
effect = new Effect(device, compiledEffect.GetEffectCode(),
CompilerOptions.NotCloneable, null);
// .
if (!effect.CurrentTechnique.Validate())
{
//
MessageBox.Show(String.Format("
\"{1}\"\n\r" +

\"{0}\"

" , GPU",
effect.CurrentTechnique.Name,
MessageBoxButtons.OK,

effectFileName),

"

",

MessageBoxIcon.Error);
closing = true;
Application.Idle += new EventHandler(Application_Idle);
return;
}

, .
, , Effect.Begin:
public void Begin();


(CurrentTechnique) :

passes)

14. Pass .
15. GraphicsDevice.DrawUserPrimitives.
16. End .
Effect.End.
:
Effect effect;
...
// Paint
...
// effect.
effect.Begin();
//
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
//
effect.Begin();
//
device.DrawUserPrimitives(...);
...
device.DrawUserPrimitives(...);
//
effect.End();
}
//

effect.End();

, , ,
.

, foreach,

(effect.CurrentTechnique.Passes),
for.
. 3.3.4.

2.4. (PrimitiveType.PointList).
, , .
XNA Framework .
,
( 2.7).
2.7.
// Examples\Ch02\Ex01
// C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
// , ,
// System.IO
using System.IO;
// XNA Framework
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using XnaGraphics = Microsoft.Xna.Framework.Graphics;
namespace GSP.XNA.Book.Ch02.Ex01
{
public partial class MainForm : Form
{
// XNA Framework
GraphicsDevice device = null;
//
PresentationParameters presentParams;
// ( )
VertexPositionColor[] vertices = null;
//
VertexDeclaration decl = null;
// ,
Effect effect = null;
// , true
bool closing = false;
public MainForm()
{
InitializeComponent();

}
private void MainForm_Load(object sender, EventArgs e)
{
//
SetStyle(ControlStyles.Opaque | ControlStyles.ResizeRedraw, true);
MinimumSize = SizeFromClientSize(new Size(1, 1));
presentParams = new PresentationParameters();
presentParams.IsFullScreen = false;
presentParams.BackBufferCount = 1;
presentParams.SwapEffect = SwapEffect.Discard;
presentParams.BackBufferWidth = ClientSize.Width;
presentParams.BackBufferHeight = ClientSize.Height;
device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware,
this.Handle, CreateOptions.SoftwareVertexProcessing | CreateOptions.SingleThreaded,
presentParams);
// ,
vertices = new VertexPositionColor[1];
//
decl = new VertexDeclaration(device, VertexPositionColor.VertexElements);
// () , .
// ,
// ,
vertices[0] = new VertexPositionColor(new Vector3(0.0f, 0.0f, 0.0f),
XnaGraphics.Color.Aqua);

//
CompiledEffect compiledEffect;
try
{
// -
compiledEffect = Effect.CompileEffectFromFile(effectFileName, null, null,
CompilerOptions.None, TargetPlatform.Windows);
}
//
catch (IOException ex)
{
//
MessageBox.Show(ex.Message, " ", MessageBoxButtons.OK,
MessageBoxIcon.Error);
closing = true;
Application.Idle += new EventHandler(Application_Idle);
return;
}
//
if (!compiledEffect.Success)
{
// ErrorsAndWarnings
//
MessageBox.Show(String.Format(" : \r\n{0}",
compiledEffect.ErrorsAndWarnings), " ", MessageBoxButtons.OK,
MessageBoxIcon.Error);
closing = true;

Application.Idle += new EventHandler(Application_Idle);


return;
}
// -.
// CompilerOptions.NotCloneable,
// ,
effect = new Effect(device, compiledEffect.GetEffectCode(),
CompilerOptions.NotCloneable, null);
// (,
// GPU)
if (!effect.CurrentTechnique.Validate())
{
// GPU ,
MessageBox.Show(String.Format(" \"{0}\"
\"{1}\"\n\r" + " , GPU",
effect.CurrentTechnique.Name, effectFileName), " ", MessageBoxButtons.OK,
MessageBoxIcon.Error);
closing = true;
Application.Idle += new EventHandler(Application_Idle);
return;
}
}
private void MainForm_Paint(object sender, PaintEventArgs e)
{
// - Load,
// Paint ( effect ,
// )
if (closing)
return;
try
{
// ,
if (device.GraphicsDeviceStatus == GraphicsDeviceStatus.Lost)
throw new DeviceLostException();
if (device.GraphicsDeviceStatus == GraphicsDeviceStatus.NotReset)
device.Reset(presentParams);
//
device.Clear(XnaGraphics.Color.CornflowerBlue);
//
device.VertexDeclaration = decl;
// .
effect.Begin();
//
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
//
pass.Begin();
//
device.DrawUserPrimitives(PrimitiveType.PointList, vertices, 0,
vertices.Length);
//

pass.End();
}
//
effect.End();
//
//
device.Present();
}
//
catch (DeviceNotResetException)
{
Invalidate();
}
catch (DeviceLostException)
{
}
}
// Idle. .
void Application_Idle(object sender, EventArgs e)
{
Close();
}
//
private void MainForm_Resize(object sender, EventArgs e)
{
if (WindowState != FormWindowState.Minimized)
{
presentParams.BackBufferWidth = ClientSize.Width;
presentParams.BackBufferHeight = ClientSize.Height;
device.Reset(presentParams);
}
}
//
private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
{
if (device != null)
{
device.Dispose();
device = null;
}
}
}
}

.
( ) ,
:
VertexPositionColor[] vertices = null;
VertexDeclaration decl = null;

, :
Effect effect = null;

Load .
, Load
:
vertices = new VertexPositionColor[1];
vertices[0] = new VertexPositionColor(new Vector3(0.0f, 0.0f, 0.0f), XnaGraphics.Color.Aqua);
// VertexPositionColor
decl = new VertexDeclaration(device, VertexPositionColor.VertexElements);

Load fx-, -
:
// .
// ,
// .
// 2.7.
CompiledEffect compiledEffect;
// fx-
compiledEffect = Effect.CompileEffectFromFile(effectFileName, null, null,
CompilerOptions.None, TargetPlatform.Windows);
// - .
effect = new Effect(device, compiledEffect.GetEffectCode(), CompilerOptions.NotCloneable,
null);


Close , , MSDN,
. Idle,
Close. : Idle
, Paint. , ,
Idle ,
. Paint
, : ,
Paint .
Paint, .
, .
VertexDeclaration ,
Load:
device.VertexDeclaration = decl;

Load.
,
Reset. ,
.
, , : :
effect.Begin();
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Begin();
device.DrawUserPrimitives(PrimitiveType.PointList, vertices, 0, vertices.Length);
pass.End();
}
effect.End();

, , . ,
.
Visual Studio 2005. Visual Studio
2005,

Windows
Forms

Microsoft.Xna.Framework.dll. Solution Explorer


Add | New Folder, Data,

( 2.6). Data
SimpleEffect.fx ( 2.7), , Add | New
Item... . SimpleEffect.fx 2.6.

2.6. .

2.7. SimpleEffect.fx.

Data,
SimpleEffect.fx. , Debug Visual Studio exe- bin\Debug,
Release bin\Release. , ,
,
. , :
Solution Explorer SimpleEffect.fx Properties
Copy to Output Directory Copy if newer ( 2.8).
Visual Studio bin\Debug bin\Release
bin\Debug\Data bin\Release\Data SimpleEffect.fx.

2.7.
CD Ch02\Ex01.

2.8. SimpleEffect.fx.

2.4.1. .
, ,
CreateOptions.SoftwareVertexProcessing,
(CPU). ,
,

GPU.

CreateOptions.HardwareVertexProcessing ,
(, Intel
GMA 900 Intel GMA 950).
? GPU.
GPU ,
CreateOptions.HardwareVertexProcessing,
CreateOptions.SoftwareVertexProcessing.
, GPU. XNA Framework

GraphicsDeviceCapabilities,

. ,
(),
GraphicsDeviceCapabilities :
// GraphicsDeviceCapabilities
public sealed class GraphicsDeviceCapabilities : IDisposable
{
// ,
public GraphicsDeviceCapabilities.PrimitiveCaps PrimitiveCapabilities { get; }
//
public GraphicsDeviceCapabilities.DeclarationTypeCaps DeclarationTypeCapabilities {
get; }
//
public GraphicsDeviceCapabilities.VertexShaderCaps VertexShaderCapabilities { get; }
//
public GraphicsDeviceCapabilities.PixelShaderCaps PixelShaderCapabilities { get; }
//
public GraphicsDeviceCapabilities.DriverCaps DriverCapabilities { get; }
// ,
//

public GraphicsDeviceCapabilities.DeviceCaps DeviceCapabilities { get; }3


...
// :
// Vertex Shader,
public Version VertexShaderVersion { get; }
// Pixel Shader,
public Version PixelShaderVersion { get; }
// ,
public float MaxPointSize { get; }
// ,
// DrawUserPrimitives
public int MaxPrimitiveCount { get; }
//
...
}

, ,
GraphicsDeviceCapabilities.DeviceCaps DeviceCapabilities:
// DeviceCaps
public struct DeviceCaps
{
// DrawUserPrimitives
public bool SupportsDrawPrimitives2Ex { get; }
// (
//
// )
public bool SupportsHardwareRasterization { get; }
//
public bool SupportsHardwareTransformAndLight { get; }
...
}

,
SupportsHardwareTransformAndLight. ,

GraphicsDeviceCapabilities.DeviceCapabilities.SupportsHardwareTransformAndLight.

true,
CreateOptions.HardwareVertexProcessing,
CreateOptions.SoftwareVertexProcessing.
XNA Framework
GraphicsDeviceCapabilities.
GraphicsDeviceCapabilities :
public GraphicsDeviceCapabilities GraphicsDeviceCapabilities { get; }

:
GraphicsDeviceCapabilities .
: , ,
. , - :
// .
device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware, this.Handle,
CreateOptions.SoftwareVertexProcessing | CreateOptions.SingleThreaded, presentParams);
// GPU
if (device.GraphicsDeviceCapabilities.DeviceCapabilities.SupportsHardwareTransformAndLight)
{
//
device.Dispose();
// ,
device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware,
this.Handle,

CreateOptions.HardwareVertexProcessing | CreateOptions.SingleThreaded,
presentParams);
}

, .
XNA Framework
GraphicsDeviceCapabilities . ,
GraphicsDevice GraphicsAdapter,
. , XNA Framework
GetCapabilities, GraphicsDeviceCapabilities,
:
public GraphicsDeviceCapabilities GetCapabilities(DeviceType deviceType);

deviceType , DeviceType (
1.4).

deviceType? , GetCapabilities ,
(DeviceType.Hardware, DeviceType.Reference
DeviceType.NullReference),
. , deviceType
GetCapabilities, deviceType
(GraphicsDevice).
,
:
GraphicsDeviceCapabilities caps =
GraphicsAdapter.DefaultAdapter.GetCapabilities(DeviceType.Hardware);
CreateOptions options = CreateOptions.SingleThreaded;
if (caps.DeviceCapabilities.SupportsHardwareTransformAndLight)
options |= CreateOptions.HardwareVertexProcessing;
else
options |= CreateOptions.SoftwareVertexProcessing;
device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware, this.Handle,
options, presentParams);

CD Examples\Ch02\Ex02.

2.4.2. .
, (Ex02), ,
. ,
. GraphivsDevice RenderState,
:
public RenderState RenderState {get; }

RenderState, ,
. , RenderState.PointSize :
// 1.0f
float PointSize { get; set; }

, PointSize 10, 10x10


( 2.9):
// Paint
device.RenderState.PointSize = 10.0f;

2.9 10x10 .

GraphicsDevice.RenderState.PointSize
. ,
, 10x10.
, ,
:
.
2.4.1 , XNA Framework GraphicsDeviceCapabilities
. , PointSize
, :
public float MaxPointSize { get; }



D3D RightMark, CD RightMark D3D.
D3D RightMark, D3D RightMark |
Direct3D 9.0 Information ( Available Tests)
. 2.10 , ATI Radeon 9800
XT 256x256 .
D3D RightMark
100%. D3D RightMark, ;
.

2.10. D3D RightMark

, ,
10x10 (Ex02). Load
new GraphicsDevice :
// 10x10
if (device.GraphicsDeviceCapabilities.MaxPointSize < 10)
{
//
MessageBox.Show(" 10 ",
" ", MessageBoxButtons.OK, MessageBoxIcon.Error);
//
closing = true;
// Idle, ( Close
// Load )
Application.Idle += new EventHandler(Application_Idle);
// Load

return;
}

2.6 MaxPointSize
. ,
64- . , XNA Framework
, , XNA Framework
64- .
.
2.6. GPU.
GPU

( )

NV20 (NVIDIA GeForce3)

64

NV25 (NVIDIA GeForce4)

8192

NV3x (NVIDIA GeForce FX)

8192

R2xx R5xx (ATI Radeon)

256

GMA 900 (Intel 915G)

256

GMA 950 (Intel 945G)

256

2.4.3. .
,
.
MouseDown,
. , ,
Paint. 2.8 (Ex04).
2.8.
public partial class MainForm : Form
{
...
//
VertexPositionColor[] vertices = null;
//
int pointCount = 0;
...
private void MainForm_Load(object sender, EventArgs e)
{
...
// ,
// DrawUserPrimitives
maxVertexCount = Math.Min(device.GraphicsDeviceCapabilities.MaxPrimitiveCount,
device.GraphicsDeviceCapabilities.MaxVertexIndex);
// , 16-
vertices = new VertexTransformedPositionColor[16];
}
private void MainForm_Paint(object sender, PaintEventArgs e)
{
...
//
device.Clear(XnaGraphics.Color.CornflowerBlue);
// ( DrawUserPrimitives
// )
if (pointCount > 0)

{
device.VertexDeclaration = decl;
device.RenderState.PointSize = 10.0f;
//
effect.Begin();
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Begin();
device.DrawUserPrimitives(PrimitiveType.PointList, vertices, 0,
pointCount);
pass.End();
}
effect.End();
}
device.Present();
...
}
private void MainForm_MouseDown(object sender, MouseEventArgs e)
{
//
if (e.Button == MouseButtons.Left)
{
//
if (pointCount == maxVertexCount)
{
//
MessageBox.Show(String.Format(" +
GPU: {0}.", maxVertexCount), "", MessageBoxButtons.OK,
MessageBoxIcon.Warning);
return;
}
//
if (pointCount == vertices.Length)
{
// ( )
int newSize = vertices.Length * 2;
//
if (newSize > maxVertexCount)
newSize = maxVertexCount;
//
VertexPositionColor[] newVertices = new VertexPositionColor[newSize];
//
vertices.CopyTo(newVertices, 0);
// vertices
vertices = newVertices;
}
// ,
// . XNA
// Framework MouseToLogicalCoords.
vertices[pointCount] = new VertexPositionColor(
Helper.MouseToLogicalCoords(e.Location, ClientSize), XnaGraphics.Color.Aqua);
//

pointCount++;
//
Invalidate();
}
}
}

. , .NET Framework
,
,
. ,
, ,
. :
( ,
),
.

, , Genetic list<>. . ,
DrawUserPrimitives System.Array,
ToArray(),
. , list<>
, , ,
.

,
GraphicsDevice.DrawUserPrimitives. , GraphicsDevice.DrawUserPrimitives

,
. ,
, ,
CPU GPU.
DrawUserPrimitives ,
. ,
, .
GraphicsDeviceCapabilities:
// ,
public int MaxPrimitiveCount { get; }
// , .
public int MaxVertexIndex { get; }

2.7 2.8
. , Intel GMA 900 65535
65534 .
(65534). ATI
. ,
, ,
MaxPrimitiveCount, MaxVertexIndex:
maxVertexCount = Math.Min(device.GraphicsDeviceCapabilities.MaxVertexIndex,
device.GraphicsDeviceCapabilities.MaxPrimitiveCount)

2.7. MaxPrimitiveCount GPU


GPU

NVIDIA NV2x - NV3x

1.048.575

ATI R2xx - R5xx

1.048.575

Intel GMA 9xx

65.535

65.535 1.048.57535

Intel GMA 3000

2.8. MaxVertexIndex GPU


GPU

ATI R2xx - R5xx

16.777.215

NVIDIA NV2x - NV3x

1.048.575

Intel GMA 9xx

65.534

Intel GMA 3000

65.534 16.777.21536

!
,
(blue screen of
death). XNA Framework
XNA- .

, ,
65534 . ? ,
, 18 Intel GMA 900.
, , .
:
, . , 37.
,
. , DrawUserPrimitives
System.IndexOutOfRangeException.
, .

XNA Framework,
-1 .. +1. , , Windows
Y , XNA Framework .
,
Helper, Helper.cs ( 2.9).
, XNA Framework.
2.9.
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace GSP.XNA
{
class Helper
{
//
. .
public static Vector3 MouseToLogicalCoords(System.Drawing.Point location,
System.Drawing.Size clientSize)
35

.
.
37

MaxPrimitiveCount.
, .
36

{
Vector3 v;
// [-1, +1]. 0
// Math.Max, 1.
v.X = (float)location.X / (float)Math.Max(clientSize.Width - 1, 1) * 2.0f - 1.0f;
v.Y = 1.0f - (float)location.Y / (float)Math.Max(clientSize.Height - 1, 1)*2.0f;
v.Z = 0.0f;
return v;
}
}
}

2.4.4. HLSL.
, , ,
. , , :

(aqua), ( SimpleEffect.fx)
C#-. ,
vertices[pointCount] = new VertexPositionColor(
Helper.MouseToLogicalCoords(e.Location, ClientSize), XnaGraphics.Color.Aqua);

vertices[pointCount] = new VertexPositionColor(


Helper.MouseToLogicalCoords(e.Location, ClientSize), XnaGraphics.Color.Red);

, .
fx- ,
.

HLSL
.
: (iPos) (iColor).
(oPos) (oColor).
iColor COLOR ( 2.10).
COLOR oColor ,
.
2.10.
void MainVS(in float3 iPos:POSITION, in float4 iColor:COLOR,
out float4 oColor:COLOR)
{
oPos = float4(iPos, 1);

out float4 oPos:POSITION,

// Color .
oColor = iColor;
}

: in out. in
, . out ,
: out-
. ,
inout. , iColor oColor
Color, ( 2.11).
2.11.
// ( color)
void MainVS(in float3 iPos:POSITION, inout float4 color:COLOR, out float4 oPos:POSITION)

{
oPos = float4(iPos, 1);
}

(in, out inout), HLSL (in).


, in . ,
.

, 38,
.
HLSL C ( 2.12).
2.12.
// .
//
struct VertexInput
{
float3 pos : POSITION;
float4 color : COLOR;
};
//
struct VertexOutput
{
float4 pos : POSITION;
float4 color : COLOR;
};
void MainVS(in VertexInput input, out VertexOutput output)
{
output.pos = float4(input.pos, 1.0f);
output.color = input.color;
}

, :
,
VertexInput. MainVS
(output). , MainVS ,
( 2.13).
2.13.
VertexOutput MainVS(VertexInput input)
{
// output
VertexOutput output;
output.pos = float4(input.pos, 1.0f);
output.color = input.color;
//
return output;
}

.
,
( ). ,
, . ,
. ,
38

(
).
( 2.14).
2.14.
float4 MainPS(float4 color:COLOR):COLOR
{
return color;
}


COLOR. ,

39.
. , COLOR
TEXCOORD ( 2.14). ,

.

ps_1_x ,
ps_2_0.
2.6.
2.14.
struct VertexInput
{
float3 pos : POSITION;
float4 color : COLOR;
};
struct VertexOutput
{
float4 pos : POSITION;
// ,
float4 color : TEXCOORD;
};

VertexOutput MainVS(VertexInput input)


{
VertexOutput output;
output.pos = float4(input.pos, 1.0f);
output.color = input.color;
return output;
}
//
float4 MainPS(float4 color:TEXCOORD):COLOR
{
return color;
}
technique Fill
{
pass p0
39

ps_3_0
. 4.x.

{
VertexShader = compile vs_2_0 MainVS();
PixelShader = compile ps_2_0 MainPS();
}
}

C#-
, , C#-
:
.
MouseDown ( 2.15).
2.15.
private void MainForm_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
// ,
if (pointCount == maxVertexCount)
{
MessageBox.Show(String.Format(" +
GPU: {0}.", maxVertexCount), "", MessageBoxButtons.OK,
MessageBoxIcon.Warning);
return;
}
// .
if (pointCount == vertices.Length)
{
int newSize = vertices.Length * 2;
if (newSize > maxVertexCount)
newSize = maxVertexCount;
VertexPositionColor[] newVertices = new VertexPositionColor[newSize];
vertices.CopyTo(newVertices, 0);
vertices = newVertices;
}
XnaGraphics.Color color;
double delta;
do
{
// R, G, B
byte[] bytes = new byte[3];
rnd.NextBytes(bytes);
//
color = new XnaGraphics.Color(bytes[0], bytes[1], bytes[2]);
//
delta = Math.Pow((color.R - XnaGraphics.Color.CornflowerBlue.R), 2) +
Math.Pow((color.G - XnaGraphics.Color.CornflowerBlue.G), 2) +
Math.Pow((color.B - XnaGraphics.Color.CornflowerBlue.B), 2);
}
// , .
while(delta < 1000);
//
vertices[pointCount] = new VertexPositionColor(Helper.MouseToLogicalCoords(

e.Location, ClientSize), color);


pointCount++;
}
Invalidate();
}

,
. ,
( 2.11).
,
:

r (c1r c2r ) 2 (c1g c2 g ) 2 (c1b c2b ) 2

(2.1)

r .

c1r , c1g , c1b , ;

c2 r , c2 g , c2b , .

,
, .
CD Ch02\Ex05.

Color1

Color2

B
2.11. .

2.1
, y=cos(x), x
0720 ( 2.12). ,
CD (Ch02\Ex06).

2.12. y=f(x), .

2.5.
XNA Framework : (PrimitiveType.LineList)
(PrimitiveType.LineStrip).
Device.DrawUserPrimitives .
,
, .. ( 2.13).
. (PrimitiveType.LineStrip) ,
. ,
.. ( 2.14).
v1

v5
v4

v0
v2

v3
2.13. (Direct3D.PrimitiveType.LineList)

v1

v5
v4

v0
v2

v3
2.14. (Direct3D.PrimitiveType.LineStrip)

2.5.1. (PrimitiveType.LineList).
PrimitiveType.LineList
Ex04. ,
. , Paint
, ,
, . 2.16
(Ex07):
2.16
public partial class MainForm : Form
{
...

//
VertexPositionColor[] vertices = null;
//
int lineCount = 0;
// ,
// DrawUserPrimitives
int maxLineCount;
// , , (
// , )
bool AddingLine = false;
...
private void MainForm_Load(object sender, EventArgs e)
{
...
// ,
// DrawUserPrimitives
maxLineCount = Math.Min(device.GraphicsDeviceCapabilities.MaxPrimitiveCount,
device.GraphicsDeviceCapabilities.MaxVertexIndex / 2);
// ,
vertices = new VertexPositionColor[16];
}
private void MainForm_Paint(object sender, PaintEventArgs e)
{
...
//
device.Clear(XnaGraphics.Color.CornflowerBlue);
//
if (lineCount > 0)
{
device.VertexDeclaration = decl;
//
effect.Begin();
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Begin();
device.DrawUserPrimitives(PrimitiveType.LineList, vertices, 0,
lineCount);
pass.End();
}
effect.End();
}
device.Present();
...
}
...
private void MainForm_MouseDown(object sender, MouseEventArgs e)
{
//
if (e.Button == MouseButtons.Left)
{
// ,
if (lineCount == maxLineCount)

{
MessageBox.Show(String.Format(" +
GPU: {0}.", maxLineCount), "", MessageBoxButtons.OK,
MessageBoxIcon.Warning);
return;
}
//
AddingLine = true;
// ,
// .
if (lineCount * 2 >= vertices.Length)
{
int newLineCount = lineCount * 2;
//
if (newLineCount > maxLineCount)
newLineCount = maxLineCount;
VertexPositionColor[] newVertices = new VertexPositionColor[newLineCount*2];
vertices.CopyTo(newVertices, 0);
vertices = newVertices;
}
// .
// [-1, +1] MouseToLogicalCoords,
// 2.4.3.
vertices[lineCount * 2] =
new VertexPositionColor(Helper.MouseToLogicalCoords(e.Location, ClientSize),
XnaGraphics.Color.Aqua);
vertices[lineCount * 2 + 1] = vertices[lineCount * 2];
// 1
lineCount++;
//
Invalidate();
}
}
private void MainForm_MouseMove(object sender, MouseEventArgs e)
{
//
if (AddingLine == true)
{
//
vertices[lineCount * 2 - 1].Position = Helper.MouseToLogicalCoords(e.Location,
ClientSize);
//
Invalidate();
}
}
private void MainForm_MouseUp(object sender, MouseEventArgs e)
{
//
if (e.Button==MouseButtons.Left)
//
AddingLine = false;
}
}

, ,
DrawUserPrimitives. 2.4.3,
,
,

GraphicsDeviceCapabilities.MaxPrimitiveCount

GraphicsDeviceCapabilities.MaxVertexIndex.

PrimitiveType.LineList , ,
,
GraphicsDeviceCapabilities.MaxVertexIndex 2.
,
Ctrl+Z,
.. , ,
2.17.
( 2.15).
2.17.
private void MainForm_KeyDown(object sender, KeyEventArgs e)
{
if ((e.KeyCode==Keys.Z) && (e.Control==true))
if (AddingLine == false)
{
if (lineCount > 0)
lineCount--;
Invalidate();
}
}

2.15. , (Ex07)

2.5.2. (PrimitiveType.LineStrip).
PrimitiveType.LineStrip. ,
,
.
PrimitiveType.LineStrip , ,
0.8 (Ex08). ,
. ,
( 2.16).
:

0..360
x x0 r sin( )
y y0 r cos( )

x y

x0 y0

, 0 360.

2.18.

2.16. , Direct3D.PrimitiveType.LineStrip.

2.18.
public partial class MainForm : Form
{
GraphicsDevice device = null;
PresentParameters presentParams;
VertexDeclaration decl;
VertexPositionColor[] vertices = null;
// , .
const int LineStripCount = 32;
...
private void MainForm_Load(object sender, EventArgs e)
{
...
decl = new VertexDeclaration(device, VertexPositionColor.VertexElements);
// ,
vertices = new VertexPositionColor[LineStripCount + 1];
}
private void MainForm_Paint(object sender, PaintEventArgs e)
{
...
//
device.Clear(XnaGraphics.Color.CornflowerBlue);
device.VertexDeclaration = decl;

(2.2)

//
for (int i = 0; i <= LineStripCount; i++)
{
// 2.2
float angle = (float)i / (float)LineStripCount * 2.0f * (float)Math.PI;
// 0.8
float x = 0.8f * (float)Math.Sin(angle);
float y = 0.8f * (float)Math.Cos(angle);
//
int red=(int) (255 * Math.Abs(Math.Sin(angle * 3)));
int green = (int)(255 * Math.Abs(Math.Cos(angle * 2)));
//
vertices[i] = new VertexPositionColor(new Vector3(x, y, 1.0f),
new XnaGraphics.Color(red, green, 0));
};
// , . vertices.Length - 1
// .
effect.Begin();
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Begin();
device.DrawUserPrimitives(PrimitiveType.LineStrip, vertices, 0,
vertices.Length - 1);
pass.End();
}
effect.End();
device.Present();
}
...
}

: Load 2.2
, , .
Paint.
,
;
, GDI+, .
.

.
,
, ( 2.17).
:
17. ,
.
18. ,
.

2.17. .

:
,
. :
19.

:
, 40. 2.3.1 2.2
. ,
, [-1, +1].

. Viewport GraphicsDevice:
public Viewport Viewport { get; set; }

Viewport, ,
:
public struct Viewport
{
// ,
public int Width { get; set; }
// ,
public int Height { get; set; }
// X
public int X { get; set; }
// Y
public int Y { get; set; }
...
}

, Viewport ,
. XNA
Framework X Y , Width Height
. ,
.

100100, ( 2.19).
2.19.
40

// Examples\Ch02\Ex09
private void MainForm_Load(object sender, EventArgs e)
{
// ! ,
//
// System.InvalidOperationException
MinimumSize = SizeFromClientSize(new Size(100, 100));
...
}
private void MainForm_Paint(object sender, PaintEventArgs e)
{
if (closing)
return;
try
{
if (device.GraphicsDeviceStatus == GraphicsDeviceStatus.Lost)
throw new DeviceLostException();
if (device.GraphicsDeviceStatus == GraphicsDeviceStatus.NotReset)
device.Reset();
// .
Viewport viewport = new Viewport();
viewport.Width = 100;
viewport.Height = 100;
// Viewport
device.Viewport = viewport;
//
device.Clear(XnaGraphics.Color.CornflowerBlue);
//
...
}
}

2.18. ?
20. . ,
.
21. .
,
.

2.18. 100100, .


DirectX
, , .

Ex08:

, . ,
, Clear
. , ,
Helper.cs
( 2.20).
2.20.
// ,
class Helper
{
...
// .
// , .
public static Viewport SquareViewport(System.Drawing.Size clientSize)
{
Viewport viewport = new Viewport();
viewport.Width = Math.Min(clientSize.Width, clientSize.Height);
viewport.Height = viewport.Width;
viewport.X = (clientSize.Width- viewport.Width) / 2;
viewport.Y = (clientSize.Height - viewport.Height) / 2;
return viewport;
}
// .
//
public static Viewport FullScreenViewport(System.Drawing.Size clientSize)
{
Viewport viewport = new Viewport();
viewport.Width = clientSize.Width;
viewport.Height = clientSize.Height;
return viewport;

}
}

, Helper,
2.21.
2.21.
// Ch02\Ex10
private void MainForm_Paint(object sender, PaintEventArgs e)
{
if (closing)
return;
try
{
if (device.GraphicsDeviceStatus == GraphicsDeviceStatus.Lost)
throw new DeviceLostException();
if (device.GraphicsDeviceStatus == GraphicsDeviceStatus.NotReset)
device.Reset();
//
device.Viewport = Helper.FullScreenViewport(ClientSize);
//
device.Clear(XnaGraphics.Color.CornflowerBlue);
//
device.Viewport = Helper.SquareViewport(ClientSize);
...
}
}

2.19.
, , .

2.19. , , .

2.2.
, 2.1,
PrimitiveType.PointList PrimitiveType.LineStrip.
: 1, ,
-1 . ( 2.20).
:

red (0.5 0.5 cos )0.3 255

(2.3)

green (0.5 0.5 cos )0.3 255

red
green

,
y 0, .

2.20.

CD Examples\Ch02\Ex11.

2.6.
XNA Framework
:
PrimitiveType.TriangleList,
PrimitiveType.TriangleFan

PrimitiveType.TriangleStrip. , PrimitiveType.TriangleList.

2.6.1. (PrimitiveType.TriangleList)
:
0-, 1- 2- , 3-, 4- 5- ,
6-, 7- 8- .. ( 2.21).
v1

v5

v4

v7

v0
v2
v3

v6

v8

2.21. , PrimitiveType.TriangleList.

XNA Framework ,
. , ,
2.21 (v0, v1, v2) (v6, v7, v8).
(v3, v4, v5) , .
XNA Framework
.

, . XNA Framework
GraphicsDevice.RenderState.CullMode,
:
public CullMode CullMode { get; set; }

CullMode:
CullMode.None
CullMode.Clockwise ,

CullMode.CounterClockwise ,
.

GraphicsDevice.RenderState.CullMode

CullMode.CounterClockwise, ,
.
CullMode.None.
2.22 (Ex12),
( 2.22).

2.22.

2.22
public partial class MainForm : Form
{
const string effectFileName = "Data\\ColorFill.fx";
GraphicsDevice device = null;
PresentationParameters presentParams;
Effect effect = null;
VertexDeclaration decl = null;
VertexPositionColor[] vertices = null;

FillMode fillMode=FillMode.Solid;
bool closing = false;
...
private void MainForm_Load(object sender, EventArgs e)
{
...
//
vertices = new GraphicsBuffer<TransformedColored>(3);
//
vertices[0] = new VertexPositionColor(new Vector3(0.0f, 0.4f, 0.0f),
XnaGraphics.Color.Coral);
vertices[1] = new VertexPositionColor(new Vector3(0.4f, -0.4f, 0.0f),
XnaGraphics.Color.LightGreen);
vertices[2] = new VertexPositionColor(new Vector3(-0.4f, -0.4f, 0.0f),
XnaGraphics.Color.Yellow);
}
private void MainForm_Paint(object sender, PaintEventArgs e)
{
...
device.Clear(XnaGraphics.Color.CornflowerBlue);
//
device.RenderState.CullMode = Cull.None;
device.VertexDeclaration = decl;
//
effect.Begin();
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Begin();
device.DrawUserPrimitives(PrimitiveType.TriangleList, vertices, 0,
vertices.Length / 3);
pass.End();
}
effect.End();
device.Present();
...
}
...

, .

PrimitiveType.TriangleList.


, 3D 3ds Max Maya
(Wireframe).
, , . XNA Framework
,
.
RenderState.FillMode GraphicsDevice:
FillMode FillMode { get; set; }

FillMode:

FillMode.Point , .
XNA Framework: ,
device.RenderState.PointSize.
FillMode.WireFrame ,
TrianglePrimitive.LineList TrianglePrimitive.LineStrip.
FillMode.Solid .
RenderState.FillMode FillMode.Solid,
.
FillMode (Ex12)

( 2.23).
2.23
public partial class MainForm : Form
{
//
FillMode fillMode=FillMode.Solid;
...
private void MainForm_Paint(object sender, PaintEventArgs e)
{
...
//
device.RenderState.CullMode = Cull.None;
//
device.RenderState.FillMode = fillMode;
//
device.RenderState.PointSize = 3.0f;
...
//
effect.Begin();
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Begin();
device.DrawUserPrimitives(PrimitiveType.TriangleList, vertices, 0,
verteces.Length / 3);
pass.End();
}
effect.End();
...
}
private void MainForm_KeyDown(object sender, KeyEventArgs e)
{
//
if (e.KeyCode == Keys.Space)
{
//
switch (fillMode)
{
case FillMode.Point:
fillMode = FillMode.WireFrame;
break;
case FillMode.WireFrame:
fillMode = FillMode.Solid;
break;
case FillMode.Solid:
fillMode = FillMode.Point;

break;
}
//
Invalidate();
}
}
}

.
. 41
, .
( 2.23).
,
( 2.24). 4
. ,
, ( 2.25).
( 2.26),
27 . ,
( 2.27), ,
, .

2.23. . .

41

, , [16]

2.24. . .

2.25. . .

2.26. . .

2.27. , 11 .

,
DrawUserPrimitives.
,
n .
.
. , 1
. 1 + 1 = 2.
1 + 1 + 3 = 5, 1 + 1 + 3 + 9 = 14. ,
n :
n1

tc 1 1 3 9 ... 3n1 1 3i

(2.4)

i 0

tc , n .

, , .
[.20] :
n

xi
i 0

1 x n1
1 x

(2.5)

, 2.4 n :
n1

tc 1 3i 1
i 0

1 3( n1)1 3n 1

1 3
2

(2.6)

, ?
, , .
, (n) 11,

311 1
88574 88574 3 = 265722.
2


. ?
.
(n),
tc. (2.6)

3n 2 tc 1

(2.7)

3:

n floor (log 3 (2 tc 1))

(2.8)

floor(x) , , x ( Math.Floor C#).



2.8 Intel GMA 900 9- ,
NVIDIA NV2x-3x 12- , ATI R2xxR5xx 13- .

.
:
1.

2.

DrawUserPrimitives.

DrawTriangle

. ,
,
1. ,
0.
2.24.
2.24.
// Examples\Ch02\Ex13
public partial class MainForm : Form
{
// .
// ,
//
const int n = 15;
const string effectFileName = "Data\\ColorFill.fx";
GraphicsDevice device = null;
PresentParameters presentParams;
Effect effect = null;
VertexDeclaration decl = null;
//
VertexPositionColor[] vertices = null;
// ( ,
// )
int currentVertex;
// , vertices .
//
a, b, c
//
pass
void DrawTriangle(Vector2 a, Vector2 b, Vector2 c, int pass)
{
// ,
if (pass <= 0)
return;
//
pass -= 1;
//
vertices[currentVertex] = new VertexPositionColor(new Vector3(ab.X, ab.Y, 0.0f),
XnaGraphics.Color.Black);
vertices[currentVertex + 1] = new VertexPositionColor(new Vector3(ac.X, ac.Y, 0.0f),
XnaGraphics.Color.Black);
vertices[currentVertex + 2] = new VertexPositionColor(new Vector3(bc.X, bc.Y, 0.0f),
XnaGraphics.Color.Black);

//
currentVertex += 3;
//
Vector2 ab = new Vector2((a.X +
Vector2 ac = new Vector2((a.X +
Vector2 bc = new Vector2((b.X +

b.X) / 2.0f, (a.Y + b.Y) / 2.0f);


c.X) / 2.0f, (a.Y + c.Y) / 2.0f);
c.X) / 2.0f, (b.Y + c.Y) / 2.0f);

// ,
//
DrawTriangle(a, ab, ac, pass);
DrawTriangle(b, ab, bc, pass);
DrawTriangle(c, ac, bc, pass);
}
private void MainForm_Load(object sender, EventArgs e)
{
...
// ,
//
int maxTriangleCount = Math.Min(device.GraphicsDeviceCapabilities.MaxPrimitiveCount,
device.GraphicsDeviceCapabilities.MaxVertexIndex / 3);
// 2.8 ,
//
int maxPass = (int) Math.Floor(Math.Log(2 * maxTriangleCount - 1, 3));
// , n
int passes = Math.Min(n, maxPass);
// 2.6 , .
int triangleCount = ((int)Math.Pow(3, passes) + 1) / 2;
//
vertices = new VertexPositionColor[3 * triangleCount];
Text += " : " + passes.ToString();
//
Vector2 a = new Vector2(0.0f, 0.9f);
Vector2 b = new Vector2(-0.9f, -0.9f);
Vector2 c = new Vector2(0.9f, -0.9f);
//
currentVertex = 0;
//
vertices[currentVertex] = new VertexPositionColor(new Vector3(a.X, a.Y, 0.0f),
XnaGraphics.Color.Black);
vertices[currentVertex + 1] = new VertexPositionColor(new Vector3(b.X, b.Y, 0.0f),
XnaGraphics.Color.Black);
vertices[currentVertex + 2] = new VertexPositionColor(new Vector3(c.X, c.Y, 0.0f),
XnaGraphics.Color.Black);
currentVertex += 3;
// pass
CreateTriangle(a, b, c, passes);
}
private void MainForm_Paint(object sender, PaintEventArgs e)
{
...

//
device.Clear(ClearFlags.Target, Color.White, 0.0f, 0);
device.BeginScene();
//
device.RenderState.CullMode = Cull.None;
//
device.RenderState.FillMode = FillMode.WireFrame;
device.VertexFormat = TransformedColored.Format;
//
device.DrawUserPrimitives(PrimitiveType.TriangleList, verteces.NumberElements/3,
verteces);
device.EndScene();
device.Present();
}
...
}
}

2.3.
, ,
( 2.28). CD Ch02\Ex14.

2.28.

2.6.2. (PrimitiveType.TriangleFan)
, PrimitiveType.TriangleFan,
. (0-, 1- 2-) .
0-, 2- 3- , 0-, 3- 4- .. ( 2.29).
, ,
.
v3
v2
v4

v0
v1

v5

2.29. , PrimitiveType.TriangleFan

, Ex09,
( 1.31).
Load Paint:
22. .
23.
24. LineList TriangleFan

(Space). ,
, ( 2.31).

2.30. , 64- (PrimitiveType.TriangleFan)

2.31. ( 18- ), .

(Ex15) 2.25.
2.25.
//
const int slices = 64;
//
FillMode fillMode = FillMode.Solid;
private void MainForm_Load(object sender, EventArgs e)
{
...
//
vertices = new VertexPositionColor[slices + 2];
// ,
vertices[0] = new VertexPositionColor(new Vector3(0.0f, 0.0f, 0.0f),
XnaGraphics.Color.White);
//
for (int i = 0; i <= slices; i++)
{
//
float angle = (float)i / (float)slices * 2.0f * (float)Math.PI;
float x = 0.7f * (float)Math.Sin(angle);
float y = 0.7f * (float)Math.Cos(angle);
//
byte red = (byte)(255 * Math.Abs(Math.Sin(angle * 3)));
byte green = (byte)(255 * Math.Abs(Math.Cos(angle * 2)));
//
vertices[i + 1] = new VertexPositionColor(new Vector3(x, y, 0.0f),
new XnaGraphics.Color(red, green, 0));
};
...
}
private void MainForm_Paint(object sender, PaintEventArgs e)
{
...

// .
// FullScreenViewport Helper
device.Viewport = Helper.FullScreenViewport(ClientSize);
//
device.Clear(XnaGraphics.Color.CornflowerBlue);
//
device.Viewport = Helper.SquareViewport(ClientSize);
// (. )
device.RenderState.CullMode = CullMode.None;
//
device.RenderState.FillMode = fillMode;
device.VertexDeclaration = decl;;
//
effect.Begin();
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Begin();
device.DrawUserPrimitives(PrimitiveType.TriangleFan, vertices, 0, vertices.Length
- 2);
pass.End();
}
effect.End();
//
device.Present();
}
//
private void MainForm_KeyDown(object sender, KeyEventArgs e)
{
//
if (e.KeyCode == Keys.Space)
{
//
if (fillMode == FillMode.Solid)
fillMode = FillMode.WireFrame;
else
fillMode = FillMode.Solid;
//
Invalidate();
}
}

2.6.3. (PrimitiveType.TriangleStrip)
, PrimitiveType.TriangleStrip,
. 0-, 1- 2- ,
3-, 2- 1- , 2-, 3- 4- ,
5-, 4- 3-, . ( 2.32).
:
, ,
.
RenderState.CullMode (. x.x).

v5

v3
v1

v9

v11

v8

v10

V7

v4
v0

v6

v2

2.32.


, PrimitiveType.LineStrip.
, 2.32 ,
.

y=cos(x)

PrimitiveType.TriangleStrip, ,

0720 (04 ) 10 .
2.1 2.2,
.
.
, ,
( 2.33).

2.33. , ( ,
).

.
2.30 p0, p1, p2 .. p0
, , 0.05 , v0 v1,
10 . ,
(v2v3, v4v5, v6v7, , v2nv2n+1), 0.1 . , ,
, v0, v1, v2, v3,
0.1 , ( 2.34).

2.34.

,
. ,
y=cos(x), ,
y=cos(x) X Y:

y 0.6 cos(2 x)

(2.9)

cos

x , [-1, +1]. x ,
, -1 +1.
0 4 (0...720).

y y , [-0.7, +0.7].

x -1 +1 (2.9),
p0, p1, , pn ( 2.34). ,
v0, v1, , v2n, v2n+1 p0
pn 0.05 .
, : ,
v0v1, v2v3, , v2nv2n+1 p0, p1, , pn.
, Y , :
v0 = p0 - 0.05
v1 = p0 + 0.05
..
(Ex16) 2.26.
2.26.
public partial class MainForm : Form
{
// ,
const int QuadStrips = 100;
//
const int TriStrips = QuadStrips * 2;
...
//
VertexPositionColor[] vertices = null;
//
FillMode fillMode = FillMode.Solid;
...

(2.10)

private void MainForm_Load(object sender, EventArgs e)


{
...
//
vertices = new VertexPositionColor[TriStrips+2];
//
for (int i = 0; i <= QuadStrips; i++)
{
// x
float x = -1.0f + 2.0f * (float) i / (float) QuadStrips;
// , x
float angle = 2.0f * (float)Math.PI * x;
float cos = (float)Math.Cos(angle);
// y 2.9
float y = 0.6f * cos;
// 2.3 (.
// 2.2)
byte green = (byte)(Math.Pow(0.5f + cos * 0.5f, 0.3f) * 255.0f);
byte red = (byte)(Math.Pow(0.5f - cos * 0.5f, 0.3f) * 255.0f);
// v[i*2] (. 2.10)
vertices[i * 2] = new VertexPositionColor(new Vector3(x, y - 0.05f, 0.0f),
new XnaGraphics.Color(red, green, 0));
// v[i*2+1]
vertices[i * 2 + 1] = new VertexPositionColor(new Vector3(x, y + 0.05f, 0.0f),
new XnaGraphics.Color(red, green, 0));
};
...
}
private void MainForm_Paint(object sender, PaintEventArgs e)
{
...
device.Clear(XnaGraphics.Color.DarkSlateGray);
//
device.RenderState.CullMode = CullMode.None;
//
device.RenderState.FillMode = fillMode;
device.VertexDeclaration = decl;
// ,
effect.Begin();
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Begin();
device.DrawUserPrimitives(PrimitiveType.TriangleStrip, vertices, 0,
vertices.Length - 2);
pass.End();
}
effect.End();
device.Present();
}
}

. ,
y=cos(x), ,
, cos(x) -1 1. (
2.35).

,
, 2.6.3.

2.35. y=cos(x)

y=cos(x)
, v0v1, , v2nv2n+1 Y .
, , .
v0v1, , v2nv2n+1, , 45 ( 2.36):
// v[2*i+1] p[n]
float nx = (float) (5.0 / Math.Sqrt(2.0));
float ny = nx;
// 5 (-1, -1) (+1, +1)
vertices[i * 2] = new VertexPositionColor(new Vector3(x - nx, y - ny, 0.0f),
new XnaGraphics.Color(red, green, 0));
vertices[i * 2 + 1] = new VertexPositionColor(new Vector3(x + nx, y + ny, 0.0f),
new XnaGraphics.Color(red, green, 0));

2.36. y=cos(x) . (-1, -1) (+1, +1).

, ,
, v2iv2i+1 . ,
0.1 , v2iv2i+1
.
v2iv2i+1 0.1 , pi,
:
25. ,

s pi.
26. , n , s .
27. v2i v2i+1 pi

n n .

. , ,
, :

s (

df ( x, y) df ( x, y )
,
)
dx
dy

(2.11)

s ,

f ( x, y) , (f(x, y)=0)

df ( x, y ) df ( x, y )
,
x y
dx
dy

s (2.9), f(x, y)=0:

y 0.6 cos(2 x) 0
,

(2.12)

s:

s (sx , s y )
sx

d ( y 0.6 cos(2 x))


1.2 sin(2 x )
dx

(2.13)

sy

d ( y 0.6 cos(2 x))


1
dy

MathCAD
, .
, , MathCAD.
MatCAD
, .
(Ctrl + .) Enter,
( 2.37). MathCAD , , [.22].

2.37. MathCAD.

n a

s n , s :

s
s

(2.14)

n , s a
a ( 0.05)

s s

v2i v2i+1 :

v2i pi n
v2i1 pi n

(2.15)

2.13, 2.14 2.15 Ex16 (


)
Paint ( 2.27).
2.27.
// CD Ex02\Ex17.
for (int i = 0; i <= QuadStrips; i++)
{
float x = -1.0f + 2.0f * (float) i / (float) QuadStrips;
float angle = 2.0f * (float)Math.PI * x;
float cos = (float)Math.Cos(angle);
float y = 0.6f * cos;
byte green = (byte)(Math.Pow(0.5f + cos * 0.5f, 0.3f) * 255.0f);
byte red = (byte)(Math.Pow(0.5f - cos * 0.5f, 0.3f) * 255.0f);
// s
float sx = (float)(1.2 * Math.PI * Math.Sin(2.0 * Math.PI * x));
float sy = 1.0f;
// s
float length = (float)Math.Sqrt(sx * sx + sy * sy);
// nx
float nx = sx / length * 0.05f;
float ny = sy / length * 0.05f;
// v[i*2] v[i*2+1] (
// 2.15)
vertices[i * 2] = new VertexPositionColor(new Vector3(x - nx, y - ny, 0.0f),
new XnaGraphics.Color(red, green, 0));
vertices[i * 2 + 1] = new VertexPositionColor(new Vector3(x + nx, y + ny, 0.0f),
new XnaGraphics.Color(red, green, 0));
};

Paint
. , , ,
. 2.38.

2.38. y=cos(x)

CD-

, PrimitiveType.TriangleStrip
. 2.28
, CD ( 2.39).

2.39. CD-, 200

2.28
public partial class MainForm : Form
{
// fx-
const string effectFileName = "Data\\ColorFill.fx";
//
const int slices = 100;
// CD-
const float innerRadius = 0.2f;
// CD-
const float outerRadius = 0.7f;
//
FillMode fillMode = FillMode.Solid;
...
private void MainForm_Load(object sender, EventArgs e)
{
...
//
vertices = new VertexPositionColor[slices * 2 + 2];
// CD
for (int i = 0; i <= slices; i++)
{
//
float angle = (float)i / (float)slices * 2.0f * (float)Math.PI;
//
float sin = (float)Math.Sin(angle);
float cos = (float)Math.Cos(angle);

// CD
float x = innerRadius * sin;
float y = innerRadius * cos;
//
vertices[i * 2] = new VertexPositionColor(new Vector3(x, y, 0.0f),
XnaGraphics.Color.White);
// CD
x = outerRadius * sin;
y = outerRadius * cos;
//
byte red = (byte)(255 * Math.Abs(Math.Sin(angle * 3)));
byte green = (byte)(255 * Math.Abs(Math.Cos(angle * 2)));
//
vertices[i * 2 + 1] = new VertexPositionColor(new Vector3(x, y, 0.0f),
new XnaGraphics.Color(red, green, 0));
};
}
private void MainForm_Paint(object sender, PaintEventArgs e)
{
...
device.Viewport = Helper.FullScreenViewport(ClientSize);
device.Clear(ClearFlags.Target, Color.CornflowerBlue, 0.0f, 0);
device.Viewport = Helper.SquareViewport(ClientSize);
device.RenderState.CullMode = CullMode.None;
device.RenderState.FillMode = fillMode;
device.VertexDeclaration = decl;
// CD
effect.Begin();
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Begin();
device.DrawUserPrimitives(PrimitiveType.TriangleStrip, vertices, 0,
vertices.Length - 2);
pass.End();
}
effect.End();
device.Present();
}
...
}
// , Space
// ()
private void MainForm_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Space)
{
if (fillMode == FillMode.Solid)
fillMode = FillMode.WireFrame;
else
fillMode = FillMode.Solid;

Invalidate();
}
}
}

, Ex18 Ex09 2.5.2


(, ). CD-
, 0.1 ,
0.7 ( 2.40) ,
2.2 ( 2.5.2).

2.40. CD-, 18- (36 ), .


(Ex19) : ,
( 2.41).
Ex18.

2.41. .

:
, .
. , 45 X Y,
:

x x0 r sin 2 sign(sin )

(2.16)

y y0 r cos 2 sign(cos )

x y .

x0 y0 .

, 0 360 (02).

r .
sign Math.Sign .NET.

, 45 ,
, Ex19,
CD ( 2.39).
2.39.
for (int i = 0; i <= slices; i++)
{
float angle = (float)i / (float)slices * 2.0f * (float)Math.PI;
float sin = (float)Math.Sin(angle);
float cos = (float)Math.Cos(angle);
// ,
//
float sin2 = sin * sin * Math.Sign(sin);
float cos2 = cos * cos * Math.Sign(cos);
//
float x = innerRadius * sin;
float y = innerRadius * cos;
vertices[i * 2] = new VertexPositionColor(new Vector3(x, y, 0.0f),
XnaGraphics.Color.White);
// 2.16.
x = outerRadius * sin2;
y = outerRadius * cos2;
//
byte red = (byte)(255 * Math.Abs(Math.Sin(angle * 3)));
byte green = (byte)(255 * Math.Abs(Math.Cos(angle * 2)));
//
vertices[i * 2 + 1] = new VertexPositionColor(new Vector3(x, y, 0.0f),
new XnaGraphics.Color(red, green, 0));
};

2.42. 45 , .
40- .

Ex21 2.42. ,
45 .
, x0, y0,
:

x x0 ( x x0. ) cos ( y y0 ) sin

(2.17)

y y0 ( x x0. ) sin ( y y0 ) cos

x0 , y0 ,
x , y

x y 2.16,
, :

x x0

r
(cos 2 sign(cos ) sin 2 sign(cos ))
2

y y0

r
(cos 2 sign(cos ) sin 2 sign(cos ))
2

45,

(2.18)

Ex19,
2.18, . :
45 . ( 2.39)
, ,
, . 45
2.17 2.2:

x x0

r
(cos sin )
2

y y0

r
(cos sin )
2

(2.19)

2.39. , . .

2.19 -
( 2.37 2.40). 2.18 2.19 2.40 (Ex20):

2.44. , .

2.40.
//
const float innerRadius = 0.285f;
const float outerRadius = 1.0f;
// ,
readonly float sqrt2 = (float)Math.Sqrt(2.0);
...
for (int i = 0; i <= slices; i++)
{
float angle = (float)i / (float)slices * 2.0f * (float)Math.PI;
float sin = (float)Math.Sin(angle);

float cos = (float)Math.Cos(angle);


float sin2 = sin * sin * Math.Sign(sin);
float cos2 = cos * cos * Math.Sign(cos);
float x = innerRadius /sqrt2 * (cos + sin);
float y = innerRadius / sqrt2 * (cos - sin);
vertices[i * 2] = new VertexPositionColor(new Vector3(x, y, 0.0f),
XnaGraphics.Color.White);
x = outerRadius * outerRadius/sqrt2 * (cos2 + sin2);
y = outerRadius * outerRadius / sqrt2 * (cos2 - sin2);
byte red = (byte)(255 * Math.Abs(Math.Sin(angle * 3)));
byte green = (byte)(255 * Math.Abs(Math.Cos(angle * 2)));
vertices[i * 2 + 1] = new VertexPositionColor(new Vector3(x, y, 0.0f),
new XnaGraphics.Color(red, green, 0));
};

2.4
2.18 2.19 ,
42:

r
n
n
( cos sign(cos ) sin sign(cos ))
2
r
n
n
y y0
( cos sign(cos ) sin sign(cos ))
2

x x0

(2.20)

x , y .

x0 , y0 .

r .
n

, 0 360.

n=1, ( 2.19), n=2


( 2.18). n .
[.23].
, , , n
2.5.
1.3 ( 2.45).

42

, 2.20 , 45

2.45. , . 2.5,
1.3.

CD \Examples\Ch02\Ex21.

2.5
, ,
:

x sin(2 )

(2.21)

y cos(3 )

x , y

, 0 360 (02)

10 (
2.46).

2.46.

, ,
.
, , 2.21
:

x 0.85 sin(2 )

(2.22)

y 0.85 cos(3 )
x, y

k (k x , k y )
kx

d (0.85 sin(2 ))
1.7 cos(2 )
d

ky

d (0.85 cos(3 ))
2.55 sin(3 )
d

(2.23)

k x , k y
, , :

s ( k y , k x )
sx k y 2.55 sin(3 )

(2.24)

s y k x 1.7 cos(2 )
( s ),
( ).
CD \Examples\Ch02\Ex22.

GDI, XNA Framework



: , .
, ,
. ,
(
).

. ,
. DirectX XNA Framework
- Vertex Shader Pixel Shader.
GPU. , Pixel Shader 1.3
NV25 (GeForce4).
, -
GPU; , Vertex Shader Pixel Shader
IL .NET.

. HLSL (High Level Shader Language) C-
, .
, HLSL, -
,
. , ps_2_a , Pixel Shader 2.x
GPU NV3x (GeForce FX). , ,
,
GPU (. 2).

3. .
:
?
?
?
?
. .

3.1. .NET XNA


Framework.

. .NET,
. ,
,
, 43.
, , ( ,
Panel). XNA Framework
,
Windows Forms.
,
Windows Forms . ,
44 [.24].
,
Control. , Windows Forms
Handle, Width, Height, SetWidth, Show, Hide, Paint, Click, Resize
45.

Control ,
Panel .

, Control protected.
Form,
(protected) .
, Visual Studio,
. , SetStyle,
ControlStyles.Opaque.
, XNA- (
1.2.3).
Control
, SetStyle protected public. Visual Studio
XnaPanel (File | New Project | Class Library,
Name XnaPanel OK). Create directory for
solution, ,
. System.Windows.Forms 3.1.
3.1.
using
using
using
using
43

System;
System.Collections.Generic;
System.Text;
System.Windows.Forms;

, , (Activity Editor) Microsoft


Train Simulator.
44
Visual Studio
45
Control MSDN.

namespace GSP.XNA
{
// ( ) XnaPanel, Control
public class XnaPanel : Control
{
//
public XnaPanel()
{
// ,
BackColor = Color.CornflowerBlue;
// 1x1
MinimumSize = new Size(1, 1);
}
// SetStyle Control public
public new void SetStyle(ControlStyles flag, bool value)
{
// Control
base.SetStyle(flag, value);
}
}
}


xnaPanel
, MinimumSize Size(1, 1).
, ,
(. 1.2.3).

Visual Studio Toolbox XnaPanel


Components ( 3.1).

3.1. Toolbox XnaPanel

, .
,
( 3.2).

Solution Explorer Add | New Project ( 3.3).
Windows Application, Name
(, Test) Ok. ,
XNA Framework using.

3.2. , XnaPanel

3.3. (Solution)

SplitContainer,
Dock Fill , FixedPanel
Panel2. SplitContainer (Group)
Dock. (Label)
: 1, 2, 3.
(Panel) vertex1Panel, vertex2Panel
vertex3Panel. , BorderStyle
FixedSingle. SplitContainer XnaPanel,
xnaPanel , Dock Fill.
, ColorDialog.
.
Load FormClosed ( 3.2).
3.2.
//
GraphicsDevice device = null;
PresentationParameters presentParams;
Effect effect = null;
VertexDeclaration decl = null;
VertexPositionColor[] vertices = null;
bool closing = false;
private void MainForm_Load(object sender, EventArgs e)
{
// xnaPanel
xnaPanel.SetStyle(ControlStyles.Opaque | ControlStyles.ResizeRedraw, true);

// presentParams
presentParams = new PresentationParameters();
presentParams.IsFullScreen = false;
presentParams.BackBufferCount = 1;
presentParams.BackBufferWidth = xnaPanel.ClientSize.Width;
presentParams.BackBufferHeight = xnaPanel.ClientSize.Height;
presentParams.SwapEffect = SwapEffect.Discard;
//
GraphicsDeviceCapabilities caps =
GraphicsAdapter.DefaultAdapter.GetCapabilities(DeviceType.Hardware);
CreateOptions options = CreateOptions.SingleThreaded;
if (caps.DeviceCapabilities.SupportsHardwareTransformAndLight)
options |= CreateOptions.HardwareVertexProcessing;
else
options |= CreateOptions.SoftwareVertexProcessing;
// . (IntPtr renderWindowHandle)
// xnaPanel
device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware,
xnaPanel.Handle, options, presentParams);
//
vertices = new VertexPositionColor[3];
//
...
}
private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
{
//
if (device != null)
{
device.Dispose();
device = null;
}
}

, Load
. this xnaPanel.
Paint Resize xnaPanel ( 3.3).
3.3.
private void xnaPanel_Paint(object sender, PaintEventArgs e)
{
// ,
if (closing)
return;
try
{
// ,
if (device.GraphicsDeviceStatus == GraphicsDeviceStatus.Lost)
throw new DeviceLostException();
// ,
if (device.GraphicsDeviceStatus == GraphicsDeviceStatus.NotReset)
device.Reset(presentParams);
// xnaPanel

device.Viewport = Helper.FullScreenViewport(xnaPanel.ClientSize);
//
device.Clear(XnaGraphics.Color.CornflowerBlue);
//
device.Viewport = Helper.SquareViewport(xnaPanel.ClientSize);
//
device.RenderState.CullMode = CullMode.None;
//
device.VertexDeclaration = decl;
// .
// Microsoft.Xna.Framework.Graphics.Color System.Drawing.Color,
// .
vertices[0] = new VertexPositionColor(new Vector3(0.0f, 0.4f, 0.0f),
new XnaGraphics.Color(vertex1Panel.BackColor.R, vertex1Panel.BackColor.G,
vertex1Panel.BackColor.B));
vertices[1] = new VertexPositionColor(new Vector3(0.4f, -0.4f, 0.0f),
new XnaGraphics.Color(vertex2Panel.BackColor.R, vertex2Panel.BackColor.G,
vertex2Panel.BackColor.B));
vertices[2] = new VertexPositionColor(new Vector3(-0.4f, -0.4f, 0.0f),
new XnaGraphics.Color(vertex3Panel.BackColor.R, vertex3Panel.BackColor.G,
vertex3Panel.BackColor.B));
//
effect.Begin();
foreach(EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Begin();
device.DrawUserPrimitives(PrimitiveType.TriangleList, vertices, 0,
vertices.Length / 3);
pass.End();
}
effect.End();
//
device.Present();
}
//
catch (DeviceNotResetException)
{
Invalidate();
}
catch (DeviceLostException)
{
}
}
private void xnaPanel_Resize(object sender, EventArgs e)
{
//
if (WindowState != FormWindowState.Minimized)
{
//
presentParams.BackBufferWidth = xnaPanel.ClientSize.Width;

presentParams.BackBufferHeight = xnaPanel.ClientSize.Height;
//
device.Reset(presentParams);
}
}

:
Windows ,
, , xnaPanel
. vertex1Panel
Click:
private void vertex1Panel_Click(object sender, EventArgs e)
{
// sender Panel
Panel panel = (Panel)sender;
//
colorDialog1.Color = panel.BackColor;
//
if (colorDialog1.ShowDialog() == DialogResult.OK)
{
// ,
panel.BackColor = colorDialog1.Color;
// xnaPanel
panelDX.Invalidate();
}
}

, sender,
vertex2Panel vertex3Panel:
Click vertex1Panel_Click.
.
CD Examples\Ch03\Ex01.

Visual Studio 46 :
Solution Explorer Set as
StartUp Project ( 3.4).

46

, F5

3.4.

3.1.
, .
, : ,
, (, ) ( 3.5).

3.5. 3.1.

XNA Framework XnaPanel


Ch03\Ex02. XnaPanel Toolbox:
28. XnaPanel Ch03\Ex01. Solution Explorer
(Solution)
Add | Existing Project .
PanelDX (Examples\Ch03\Ex01 - XnaPanel\XnaPanel\XnaPanel.csproj) Ok.
(Ctrl + Shift + B) Xna Panel
Toolbox.
29. ToolBox Ex01.
ToolBox Choose Items .
Choose Toolbox Items . Browse
PanelDX (Examples\Ch03\Ex01 - XnaPanel\XnaPanel\bin\Release\XnaPanel.dll).
, Ok, Toolbox XnaPanel.
, .

3.2. .
, .
:
30. ,
Windows (Taskbar).
31. (back)
: XNA
Framework , .
32.
.

Windows Forms,
.

(GraphicsDevice) PresentationParameters.
, IsFullScreen true:
presentParams = new PresentationParameters();
presentParams.IsFullScreen = true;

, , :

33. .
34. ( ..).
35. .
47 (back) BackBufferWidth
BackBufferHeight PresentationParameters. :
// 640 480
presentParams.BackBufferWidth = 640;
presentParams.BackBufferHeight = 480;

,
. ,
.
BackBufferFormat PresentationParameters:
public SurfaceFormat BackBufferFormat { get; set; }

SurfaceFormat , ( 3.1).

,
. , SurfaceFormat.Color,
SurfaceFormat.Bgr32. ,
- ;
, (
3.2.2).
3.1. ,
SurfaceFormat

Unknown
Rgba1010102

Color

32

10

10

10

32

Bgr32

32

Bgr565

16

16

Bgra5551

SurfaceFormat SurfaceFormat.Unknown.
,
. , Windows 32- ,
SurfaceFormat.Bgr32.
.
SurfaceFormat.Unknown
System.InvalidOperationException.
, ,
. , ,
SurfaceFormat.Bgr32, , XNA Framework:
presentParams.BackBufferFormat = SurfaceFormat.Bgr32;


, , SurfaceFormat.Bgr32 32 ,
24 ( , 8 ).
, 8, 16, 32
64 . , 24- 8, 16 32-
, , ,
, . , 24-
47

32 , 24 , 32-
.

, , .
- 85 ,
. LCD
, LCD-
60 .
FullScreenRefreshRateInHz PresentationParameters:
public int FullScreenRefreshRateInHz { get; set; }

,
, , .
FullScreenRefreshRateInHz, ,
Windows /.

System.InvalidOperationException,
.
, 3.4.
3.4.
presentParams = new PresentationParameters();
presentParams.BackBufferCount = 1;
presentParams.SwapEffect = SwapEffect.Discard;
// 640480, 32 ,
//
presentParams.IsFullScreen = true;
presentParams.BackBufferWidth = 640;
presentParams.BackBufferHeight = 480;
presentParams.BackBufferFormat = SurfaceFormat.Bgr32;
presentParams.FullScreenRefreshRateInHz = 0;

GraphicsDeviceCapabilities caps =
GraphicsAdapter.DefaultAdapter.GetCapabilities(DeviceType.Hardware);
CreateOptions options = CreateOptions.SingleThreaded;
if (caps.DeviceCapabilities.SupportsHardwareTransformAndLight)
options |= CreateOptions.HardwareVertexProcessing;
else
options |= CreateOptions.SoftwareVertexProcessing;
device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware, this.Handle,
options, presentParams);

Resize. ,
(
ALT + TAB) Windows , ,
, Resize.
, ( back)
:
3.5.
private void MainForm_Resize(object sender, EventArgs e)
{
// ,
//
if ((!presentParams.IsFullScreen) && (WindowState != FormWindowState.Minimized))
{
presentParams.BackBufferWidth = ClientSize.Width;

presentParams.BackBufferHeight = ClientSize.Height;
device.Reset(presentParams);
}
}

:
3.6.
private void MainForm_Paint(object sender, PaintEventArgs e)
{
if (closing)
return;
try
{
if (device.GraphicsDeviceStatus == GraphicsDeviceStatus.Lost)
throw new DeviceLostException();
if (device.GraphicsDeviceStatus == GraphicsDeviceStatus.NotReset)
device.Reset(presentParams);
//
device.Viewport = Helper.FullScreenViewport presentParams);
//
device.Clear(XnaGraphics.Color.CornflowerBlue);
// (
// )
device.Viewport = Helper.SquareViewport(presentParams);
// CD- (. 2.6.3)
...
}
catch (DeviceNotResetException)
{
Invalidate();
}
catch (DeviceLostException)
{
}
}

,
,
PresentationParameters presentParams.
:
3.7.
//
public static Viewport SquareViewport(PresentationParameters presentParams)
{
return SquareViewport(new System.Drawing.Size(presentParams.BackBufferWidth,
presentParams.BackBufferHeight));
}
//
public static Viewport FullScreenViewport(PresentationParameters presentParams)
{
return FullScreenViewport(new System.Drawing.Size(presentParams.BackBufferWidth,
presentParams.BackBufferHeight));

, CD- ( 3.6),
Examples\Ch03\Ex03.

3.6. CD-, (64048032bpp)

3.2.1. .
Ch03\Ex03 ( 3.4) ,
64048032bpp48. ,
System.InvalidOperationException.

. ,
,
:
presentParams = new PresentationParameters();
presentParams.BackBufferCount = 1;
presentParams.SwapEffect = SwapEffect.Discard;
presentParams.IsFullScreen = true;
// 640480, 32 , 60
presentParams.BackBufferWidth = 640;
presentParams.BackBufferHeight = 480;
presentParams.BackBufferFormat = SurfaceFormat.Bgr32;
presentParams.FullScreenRefreshRateInHz = 60;
try
{
device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware,
this.Handle,
options, presentParams);
}
catch(InvalidOperationException)
{
// ,
//
presentParams.IsFullScreen = false;
presentParams.BackBufferWidth = 0;
presentParams.BackBufferHeight = 0;
presentParams.BackBufferFormat = SurfaceFormat.Unknown;
presentParams.FullScreenRefreshRateInHz = 0;

48

BPP Bit Per Pixel ( )

// :
// , , ..
device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware,
this.Handle, options, presentParams);
}

, :
- XNA Framework
. XNA Framework
, , , 49.
, ,
.
,
? , ,
, .
LCD-, - (
, 1024768 12801024).
CurrentDisplayMode GraphicsAdapter:
public DisplayMode CurrentDisplayMode { get; }

DisplayMode:
public struct DisplayMode
{
//
public int Width { get; }
//
public int Height { get; }
//
public SurfaceFormat Format { get; }
//
public int RefreshRate { get; }
...
}

, :
3.8.
//
DisplayMode displayMode = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode;
presentParams = new PresentationParameters();
presentParams.IsFullScreen = true;
presentParams.BackBufferCount = 1;
presentParams.SwapEffect = SwapEffect.Discard;
// ,
presentParams.BackBufferWidth = displayMode.Width;
presentParams.BackBufferHeight = displayMode.Height;
presentParams.BackBufferFormat = displayMode.Format;
presentParams.FullScreenRefreshRateInHz = displayMode.RefreshRate;
GraphicsDeviceCapabilities caps =
GraphicsAdapter.DefaultAdapter.GetCapabilities(DeviceType.Hardware);
CreateOptions options = CreateOptions.SingleThreaded;
if (caps.DeviceCapabilities.SupportsHardwareTransformAndLight)
options |= CreateOptions.HardwareVertexProcessing;
else
options |= CreateOptions.SoftwareVertexProcessing;
49

-, XNA Framework, DirectX,


XNA Framework.

device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware, this.Handle,


options, presentParams);

3.2.2. .
,
. ,
,

640480 800600.
.
,
, ,
( 3.7). ,
XNA Framework GraphicsAdapter SupportedDisplayModes,
DisplayMode ,
.

3.7. .

, Windows Forms .
3.2. ListBox
displayModeListBox. , Ok
DialogResult OK.
3.2.

Name

DisplayModeForm

Text

FormBorderStyle

FixedDialog

MaximizeBox

False

MinimizeBox

False

, : SelectedDisplayMode,
( 3.9).
3.9.

public partial class DisplayModeForm : Form


{
// . ,
// .
public DisplayModeForm(GraphicsAdapter adapter)
{
InitializeComponent();
// ,
// displayModeListBox
foreach (DisplayMode diplayMode in adapter.SupportedDisplayModes)
displayModeListBox.Items.Add(diplayMode);
//
displayModeListBox.SelectedIndex = 0;
}
// ,
public DisplayMode SelectedDisplayMode
{
get
{
return (DisplayMode)displayModeListBox.SelectedItem;
}
}
}

, Load
:
3.10.
private void MainForm_Load(object sender, EventArgs e)
{
SetStyle(ControlStyles.Opaque | ControlStyles.ResizeRedraw, true);
MinimumSize = SizeFromClientSize(new Size(1, 1));
presentParams = new PresentationParameters();
presentParams.IsFullScreen = true;
presentParams.BackBufferCount = 1;
presentParams.SwapEffect = SwapEffect.Discard;
//
using (DisplayModeForm displayModeForm = new
DisplayModeForm(GraphicsAdapter.DefaultAdapter))
{
//
displayModeForm.ShowDialog();
// ,
DisplayMode mode = displayModeForm.SelectedDisplayMode;
//
presentParams.BackBufferWidth = mode.Width;
presentParams.BackBufferHeight = mode.Height;
presentParams.BackBufferFormat = mode.Format;
presentParams.FullScreenRefreshRateInHz = mode.RefreshRate;
}
...
//
device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware,
this.Handle, options, presentParams);

- ,
. Examples\Ch03\Ex05.

. :
/ .
,

. , NEC MultiSync FE991SB 4:3 = 1.33,


320240, 640480, 800600, 1024768, 1280960, 16001200, 17921344
. 12801024 ( 5:4=1.25)
Y, 1360768 ( 16:9=1.77)
X . ,
16:9 1088612, 1280768, 1360768 1600900 (..
16:9) .

3.8. , 1360768,
4:3.

?
. ,
, :
.
,
.

.
, SupportedDisplayModes ,
- (. 3.1 3.2).
-
- . ,
SurfaceFormat.Bgr32, 99.9% SurfaceFormat.Color. ,
, -.

3.2.3. .
Ch03\Ex05 ,
, :
36. ,
.
.
37. , .
:
, ( ),
.
38. ,
. ,
17921344 ,

4:3, 5:4 16:9,


50.
39.
, (,
).
, ,
( 3.9). Visual Studio 2005 Windows Application.
, .
7 :
3.3. .

Width

int

Height

int

Format

SurfaceFormat

SurfaceFormat.Unknown

RefreshRate

int

FullScreen

bool


(false , true )

true

Init

bool

true,

false

ShowSettingForm

bool

true

,
Visual Studio. Solution Explorer
Properties, Setting.settings,
51.
3.3 3.10.

3.9. .

50

, ,

( , , Half-Life 2).
51
Settings
Properties.

3.10.

.
, 3.9
3.4.
3.4. .

Form
( )

Name

SettingsForm

Text

FormatBorderStyle

FixedDialog

MinimizeBox

false

MaximizeBox

false

Name

inWindowCheckBox

Text

GroupBox

Text

Label

Text

ComboBox
(
)

Name

aspectRatioComboBox

DropDownStyle

DropDownList

Label

Text

ComboBox
( )

Name

resolutionComboBox

DropDownStyle

DropDownList

Label

Text

ComboBox
( )

Name

colorDepthComboBox

DropDownStyle

DropDownList

Label

Text

CheckBox

ComboBox
( )

Name

refreshRateComboBox

DropDownStyle

DropDownList

Button

Name

okButton

Text

Ok

Text

Cancel

DialogResult

Cancel

Button

, , ,
( ) .
,
Bgr32 Bgr565. ,
: ,
. (
), .
3.11.
3.11.
//
public struct AspectItem
{
//
public float aspect;
public AspectItem(float aspect)
{
this.aspect = aspect;
}
// (ResolutionItem)
// . true, - false
public bool Compare(float aspect)
{
// (
// ), true
if (this.aspect == 0)
return true;

//
//
//
//

, .
,
. , 1360 x 768 85/48=1.771,
16/9=1.778.
if (Math.Abs(this.aspect - aspect) < this.aspect * 0.01f)
return true;
else
return false;
}

//
public override string ToString()
{
if (aspect == 0)
return "";
if (Compare(4.0f / 3.0f))
return "4 : 3";

if (Compare(5.0f / 4.0f))
return "5 : 4";
if (Compare(16.0f / 9.0f))
return "16 : 9";
return aspect.ToString();
}
}
//
public struct ResolutionItem : IComparable<ResolutionItem>
{
//
public int width;
public int height;
public ResolutionItem(int width, int height)
{
this.width = width;
this.height = height;
}
// X Y
public float Aspect
{
get
{
return (float)width / (float)height;
}
}
//
public override string ToString()
{
return width.ToString() + " x " + height.ToString();
}
// IComparable<ResolutionItem>,
//
public int CompareTo(ResolutionItem other)
{
//
if (width > other.width)
return 1;
if (width < other.width)
return -1;
// , .
// , .
if (height > other.height)
return 1;
if (height < other.height)
return -1;
return 0;

}
}
//
public struct ColorDepthItem : IComparable<ColorDepthItem>
{
//
public SurfaceFormat value;
public ColorDepthItem(SurfaceFormat value)
{
this.value = value;
}
//
public override string ToString()
{
string str;
switch (value)
{
case SurfaceFormat.Bgr32:
str = "32 ({0})";
break;
case SurfaceFormat.Bgr565:
str = "16 ({0})";
break;
case SurfaceFormat.Rgba1010102:
str = "32 ({0})";
break;
case SurfaceFormat.Bgr555:
str = "16 {0}";
break;
default:
str = "{0}";
break;
}
return string.Format(str, value);
}
// IComparable<ColorDepthItem>,
//
public int CompareTo(ColorDepthItem other)
{
if (value > other.value)
return -1;
if (value < other.value)
return 1;
return 0;
}
}
//
public struct RefreshRateItem : IComparable<RefreshRateItem>
{

//
public int value;
public RefreshRateItem(int value)
{
this.value = value;
}
//
public override string ToString()
{
return value.ToString() + " ";
}
// IComparable< RefreshRateItem>,
//
public int CompareTo(RefreshRateItem other)
{
if (value > other.value)
return 1;
if (value < other.value)
return -1;
return 0;
}
}

,
, ( 3.12).
3.12.
public partial class SettingsForm : Form
{
//
SortedDictionary<ResolutionItem, SortedDictionary<ColorDepthItem,
SortedDictionary<RefreshRateItem, bool>>> modeCollection;
// . Properties.Settings
// ( 3.10).
Properties.Settings settings;
//
internal SettingsForm(Properties.Settings settings, GraphicsAdapter adapter)
{
InitializeComponent();
//
this.settings = settings;
// ,
//
if (!settings.Init)
{
settings.Width = adapter.CurrentDisplayMode.Width;
settings.Height = adapter.CurrentDisplayMode.Height;
settings.Format = adapter.CurrentDisplayMode.Format;
settings.RefreshRate = adapter.CurrentDisplayMode.RefreshRate;
settings.FullScreen = true;

}
modeCollection = new SortedDictionary<ResolutionItem,
SortedDictionary<ColorDepthItem, SortedDictionary<RefreshRateItem, bool>>>();
// ,
// modeCollection
foreach (DisplayMode mode in adapter.SupportedDisplayModes)
{
ResolutionItem res = new ResolutionItem(mode.Width, mode.Height);
if (!modeCollection.ContainsKey(res))
modeCollection.Add(res, new SortedDictionary<ColorDepthItem,
SortedDictionary<RefreshRateItem, bool>>());
ColorDepthItem depth = new ColorDepthItem(mode.Format);
if (!modeCollection[res].ContainsKey(depth))
modeCollection[res].Add(depth, new SortedDictionary<RefreshRateItem,
bool>());
RefreshRateItem refresh = new RefreshRateItem(mode.RefreshRate);
if (!modeCollection[res][depth].ContainsKey(refresh))
modeCollection[res][depth].Add(refresh, true);
}
// .
inWindowCheckBox.Checked = !settings.FullScreen;
//
aspectRatioComboBox.Items.Add(new AspectItem());
aspectRatioComboBox.Items.Add(new AspectItem(4.0f / 3.0f));
aspectRatioComboBox.Items.Add(new AspectItem(5.0f / 4.0f));
aspectRatioComboBox.Items.Add(new AspectItem(16.0f / 9.0f));
// ()
aspectRatioComboBox.SelectedIndex = 0;
}
...
}

, ,
. ,
1024x768x32bpp:@85Hz
modeCollection[1024x768][ SurfaceFormat.Brg32][85]52.
, SelectedIndexChanged,
3.13.
3.13.
//
//
private void aspectRatioComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
//

52

: modeCollection[new
ResolutionItem(1024, 768)][new ColorDepthItem(SurfaceFormat.Bgr32)][new
RefreshRateItem(85)]. , ,
,
.

AspectItem aspect = (AspectItem)aspectRatioComboBox.SelectedItem;


//
ResolutionItem currentResolution;
// .
// ,
if (resolutionComboBox.SelectedIndex != -1)
currentResolution = (ResolutionItem)resolutionComboBox.SelectedItem;
else
currentResolution = new ResolutionItem(settings.Width, settings.Height);
//
resolutionComboBox.Items.Clear();
//
foreach (ResolutionItem res in modeCollection.Keys)
//
if (aspect.Compare(res.Aspect))
//
resolutionComboBox.Items.Add(res);
// ,
//
if (resolutionComboBox.Items.Count != 0)
{
//
resolutionComboBox.SelectedItem = currentResolution;
// ,
if (resolutionComboBox.SelectedIndex == -1)
resolutionComboBox.SelectedIndex = 0;
}
// ,
// /
// Ok
inWindowCheckBox_CheckedChanged(inWindowCheckBox, null);
}
// CheckedChange ,
private void inWindowCheckBox_CheckedChanged(object sender, EventArgs e)
{
//
if (inWindowCheckBox.Checked)
{
// ,
aspectRatioComboBox.Enabled = false;
resolutionComboBox.Enabled = false;
colorDepthComboBox.Enabled = false;
refreshRateComboBox.Enabled = false;
okButton.Enabled = true;
}
else
{
//
aspectRatioComboBox.Enabled = true;
//
if (resolutionComboBox.Items.Count > 0)
{
// Ok
resolutionComboBox.Enabled = true;

colorDepthComboBox.Enabled = true;
refreshRateComboBox.Enabled = true;
okButton.Enabled = true;
}
else
{
//
resolutionComboBox.Enabled = false;
colorDepthComboBox.Enabled = false;
refreshRateComboBox.Enabled = false;
okButton.Enabled = false;
}
}
}

,
SelectedIndexChanged ( 3.14).
3.14.
private void resolutionComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
//
ResolutionItem res = (ResolutionItem) resolutionComboBox.SelectedItem;
//
ColorDepthItem currentColorDepth;
// .
// ,
if (colorDepthComboBox.SelectedIndex != -1)
currentColorDepth = (ColorDepthItem)colorDepthComboBox.SelectedItem;
else
currentColorDepth = new ColorDepthItem(settings.Format);
//
colorDepthComboBox.Items.Clear();
//
//
foreach (ColorDepthItem colorDepth in modeCollection[res].Keys)
colorDepthComboBox.Items.Add(colorDepth);
// ,
colorDepthComboBox.SelectedItem = currentColorDepth;
//
if (colorDepthComboBox.SelectedIndex == -1)
colorDepthComboBox.SelectedIndex = 0;
}

, ,

,
,

SelectedIndexChanged ( 3.15).
3.15.
private void colorDepthComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
// ( )
ResolutionItem res = (ResolutionItem)resolutionComboBox.SelectedItem;
ColorDepthItem colorDepth = (ColorDepthItem)colorDepthComboBox.SelectedItem;
//

RefreshRateItem currentRefreshRate;
// .
// ,
if (refreshRateComboBox.SelectedIndex != -1)
currentRefreshRate = (RefreshRateItem)refreshRateComboBox.SelectedItem;
else
currentRefreshRate = new RefreshRateItem(settings.RefreshRate);
//
refreshRateComboBox.Items.Clear();
// ,
//
foreach (RefreshRateItem refreshRate in modeCollection[res][colorDepth].Keys)
refreshRateComboBox.Items.Add(refreshRate);
//
refreshRateComboBox.SelectedItem = currentRefreshRate;
// ,
if (refreshRateComboBox.SelectedIndex == -1)
refreshRateComboBox.SelectedIndex = 0;
}

, Ok:
3.16.
private void okButton_Click(object sender, EventArgs e)
{
//
//
settings.FullScreen = !inWindowCheckBox.Checked;
if (!inWindowCheckBox.Checked)
{
settings.Width = ((ResolutionItem)resolutionComboBox.SelectedItem).width;
settings.Height = ((ResolutionItem)resolutionComboBox.SelectedItem).height;
settings.Format = ((ColorDepthItem)colorDepthComboBox.SelectedItem).value;
settings.RefreshRate = ((RefreshRateItem)refreshRateComboBox.SelectedItem).value;
}
// .
//
settings.Init = true;
// . .
settings.ShowSettingForm = false;
DialogResult = DialogResult.OK;
}

.
,
.
. , ,
:
40. , , .
Init Settings true.
41. ,
,
. ?
ShowSettingForm

true . ,
ShowSettingForm true, .
42. , ,
. Load
/config . ,

, /config.
, , ,
,
Load ( 3.17).
3.17.
using System.Diagnostics;
void InitGraphivsDevice()
{
SetStyle(ControlStyles.Opaque | ControlStyles.ResizeRedraw, true);
MinimumSize = SizeFromClientSize(new Size(1, 1));
//
settings = new Properties.Settings();
// , /config
string[] args = Environment.GetCommandLineArgs();
bool configParam = false;
if ((args.Length == 2) && (args[1].ToUpper() == "/CONFIG"))
configParam = true;
//
if ((configParam) || (settings.ShowSettingForm) || (!settings.Init))
{
//
using (SettingsForm settingsForm = new SettingsForm(settings,
GraphicsAdapter.DefaultAdapter))
{
//
settingsForm.ShowDialog();
// /config
if (configParam)
{
//
closing = true;
Application.Idle += new EventHandler(Application_Idle);
return;
}
}
}
presentParams = new PresentationParameters();
presentParams.BackBufferCount = 1;
presentParams.SwapEffect = SwapEffect.Discard;
//
presentParams.IsFullScreen = settings.FullScreen;
if (settings.FullScreen)
{

presentParams.BackBufferWidth = settings.Width;
presentParams.BackBufferHeight = settings.Height;
presentParams.BackBufferFormat = settings.Format;
presentParams.FullScreenRefreshRateInHz = settings.RefreshRate;
}
else
{
presentParams.BackBufferWidth = 0;
presentParams.BackBufferHeight = 0;
presentParams.BackBufferFormat = SurfaceFormat.Unknown;
presentParams.FullScreenRefreshRateInHz = 0;
}
//
GraphicsDeviceCapabilities caps = GraphicsAdapter.DefaultAdapter.GetCapabilities(
DeviceType.Hardware);
CreateOptions options = CreateOptions.SingleThreaded;
if (caps.DeviceCapabilities.SupportsHardwareTransformAndLight)
options |= CreateOptions.HardwareVertexProcessing;
else
options |= CreateOptions.SoftwareVertexProcessing;
try
{
//
device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware,
this.Handle,
options, presentParams);
}
catch (InvalidOperationException)
{
//
closing = true;
Application.Idle += new EventHandler(Application_Idle);
//
if (MessageBox.Show(" . +
" ( ..)?", "", MessageBoxButtons.YesNo,
MessageBoxIcon.Error) == DialogResult.Yes)
{
// ShowSettingForm true,
//
settings.ShowSettingForm = true;
//
settings.Save();
//
Process.Start(Application.ExecutablePath);
}
return;
}
}
private void MainForm_Load(object sender, EventArgs e)
{
//
InitGraphivsDevice();
// , Load
if (closing)
return;

// ( , ,
// ..
...
}

- ,
. CD-
Examples\Ch03\Ex03.

.
.NET Framework 2.0 XML user.config,
:
<Profile Directory>\<Company Name>\<App Name>_<Evidence Type>_<Evidence
Hash>\<Version>\user.config

Profile Directory ,
c:\Documents and Settings\< >\Local Settings\Application Data
Company Name , ,
AssemblyCompany Properties\AssemblyInfo.cs.
App Name , ,
AssemblyProduct Properties\AssemblyInfo.cs.
Evidence Type, Evidence Hash .
Version , , AssemblyVersion
Properties\AssemblyInfo.cs
, h03\Ex06
C:\Documents and Settings\Administrator\Local Settings\Application
Data\GSP_Inc\Ex06__Fullscreen_Dialog._Url_31gvfqvzegievbxah0w1qmgu2s2siyo3\1.0.0.0\user.config.

:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<userSettings>
<GSP.XNA.Book.Ch03.Ex06.Properties.Settings>
<setting name="Width" serializeAs="String">
<value>1280</value>
</setting>
<setting name="Height" serializeAs="String">
<value>960</value>
</setting>
<setting name="Format" serializeAs="String">
<value>Bgr32</value>
</setting>
<setting name="RefreshRate" serializeAs="String">
<value>85</value>
</setting>
<setting name="FullScreen" serializeAs="String">
<value>True</value>
</setting>
<setting name="Init" serializeAs="String">
<value>True</value>
</setting>
<setting name="ShowSettingForm" serializeAs="String">
<value>False</value>
</setting>
</GSP.XNA.Book.Ch03.Ex06.Properties.Settings>
</userSettings>
</configuration>

,
. ,
.

3.3. .
, XNA Framework
.
? ,
().
,
25- FPS53.
,
25 .
( ), ( 3.11).
( Timer), 40 (
25 ).
. ,
.
,
. 3.18.

3.11. .

3.18.
// CD Examples\Ch03\Ex07
public partial class MainForm : Form
{
// ,
const string effectFileName = "Data\\ColorFill.fx";
// ()
const float diskMinSpeed = 0.5f;
53

FPS Frames Per Second ( )

//
const float diskMaxSpeed = 1.3f;
//
const int diskSlices = 32;
//
const float diskRadius = 0.1f;
//
readonly static XnaGraphics.Color diskInnerColor = XnaGraphics.Color.White;
//
readonly static XnaGraphics.Color diskOuterColor = XnaGraphics.Color.Green;
//
const float borderSize = 0.1f;
//
readonly static XnaGraphics.Color borderInnerColor = XnaGraphics.Color.DarkBlue;
//
readonly static XnaGraphics.Color borderOuterColor = XnaGraphics.Color.CornflowerBlue;
GraphicsDevice device = null;
PresentationParameters presentParams;
Effect effect = null;
VertexDeclaration decl = null;
//
VertexPositionColor[] borderVerts = null;
//
VertexPositionColor[] baseDiskVerts = null;
// ,
VertexPositionColor[] diskVerts = null;
FillMode fillMode = FillMode.Solid;
// X
float speedX;
// Y
float speedY;
// X
float posX = 0;
// Y
float posY = 0;
//
Random rnd = new Random();
// ( ..)
Properties.Settings settings;
bool closing = false;
// , diskMinSpeed .. diskMaxSpeed
float RndSpeed()
{
return diskMinSpeed + (float)rnd.NextDouble() * (diskMaxSpeed - diskMinSpeed);
}
// Load
private void MainForm_Load(object sender, EventArgs e)
{
//
InitGraphivsDevice();

if (closing)
return;
//
decl = new VertexDeclaration(device, VertexPositionColor.VertexElements);
// ,
// (PrimitiveType.TriangleStrip)
borderVerts = new VertexPositionColor[10];
borderVerts[0] = new VertexPositionColor(new Vector3(-1.0f, -1.0f, 0.0f),
borderOuterColor);
borderVerts[1] = new VertexPositionColor(new Vector3(-1.0f + borderSize, -1.0f +
borderSize, 0.0f),
borderInnerColor);
borderVerts[2] = new VertexPositionColor(new Vector3(-1.0f, 1.0f, 0.0f),
borderOuterColor);
borderVerts[3] = new VertexPositionColor(new Vector3(-1.0f + borderSize, 1.0f borderSize, 0.0f),
borderInnerColor);
borderVerts[4] = new VertexPositionColor(new Vector3(1.0f, 1.0f, 0.0f),
borderOuterColor);
borderVerts[5] = new VertexPositionColor(new Vector3(1.0f - borderSize, 1.0f borderSize, 0.0f),
borderInnerColor);

borderVerts[6] = new VertexPositionColor(new Vector3(1.0f, -1.0f, 0.0f),


borderOuterColor);
borderVerts[7] = new VertexPositionColor(new Vector3(1.0f - borderSize, -1.0f +
borderSize, 0.0f),
borderInnerColor);
borderVerts[8] = new VertexPositionColor(new Vector3(-1.0f, -1.0f, 0.0f),
borderOuterColor);
borderVerts[9] = new VertexPositionColor(new Vector3(-1.0f + borderSize, -1.0f +
borderSize, 0.0f),
borderInnerColor);
// .
// (PrimitiveType.TriangleFan)
baseDiskVerts = new VertexPositionColor[diskSlices + 2];
baseDiskVerts[0] = new VertexPositionColor(new Vector3(0.0f, 0.0f, 0.0f),
XnaGraphics.Color.White);
for (int i = 0; i <= diskSlices; i++)
{
float angle = (float)i / (float)diskSlices * 2.0f * (float)Math.PI;
float x = diskRadius * (float)Math.Sin(angle);
float y = diskRadius * (float)Math.Cos(angle);
baseDiskVerts[i + 1] = new VertexPositionColor(new Vector3(x, y, 0.0f),
diskOuterColor);
};
// . ,
// .
diskVerts = (VertexPositionColor[]) baseDiskVerts.Clone();

// X Y
speedX = RndSpeed();
speedY = RndSpeed();
}
// Paint
private void MainForm_Paint(object sender, PaintEventArgs e)
{
...
//
effect.Begin();
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Begin();
device.DrawUserPrimitives(PrimitiveType.TriangleStrip, borderVerts, 0,
borderVerts.Length - 2);
device.DrawUserPrimitives(PrimitiveType.TriangleFan, diskVerts, 0,
diskVerts.Length - 2);
pass.End();
}
effect.End();
device.Present();
...
}
// Tick , Interval 40
private void timer_Tick(object sender, EventArgs e)
{
// ,
//
posX += speedX * (float)timer.Interval * 0.001f;
posY += speedY * (float)timer.Interval * 0.001f;
//
if (posX >= 1 - diskRadius - borderSize)
{
//
posX = 1 - diskRadius - borderSize;
// .
speedX = -Math.Sign(speedX) * RndSpeed();
}
//
if (posY >= 1 - diskRadius - borderSize)
{
posY = 1 - diskRadius - borderSize;
speedY = -Math.Sign(speedY) * RndSpeed();
}
//
if (posX <= -1 + diskRadius + borderSize)
{
posX = -1 + diskRadius + borderSize;
speedX = -Math.Sign(speedX) * RndSpeed();
}

//
if (posY <= -1 + diskRadius + borderSize)
{
posY = -1 + diskRadius + borderSize;
speedY = -Math.Sign(speedY) * RndSpeed();
}
//
// .
for (int i = 0; i < baseDiskVerts.Length; i++)
{
diskVerts[i].Position.X = baseDiskVerts[i].Position.X + posX;
diskVerts[i].Position.Y = baseDiskVerts[i].Position.Y + posY;
}
//
Invalidate();
}
}

, ,
, .

, baseDiskVerts.

.
. .
! 25 fps .
? .
54.
, . , 25 FPS
25 FPS FPS. ,
25-30 FPS
. ,
, 60 FPS.

,
300 /, 60 FPS . ,
FPS
( ) 60-100 Hz.
Motion Blur55,
.

, . , 64 , .. 0.015 .
Interval 15 .
, : ,
.
?
Windows MSDN. 15 ,
55 . , ,
, .
.
, ,
WM_TIMER, WM_KEYDOWN, WM_CHAR WM_KEYUP
WM_TIMER. , WM_TIMER
,

54
55

, - .

56. ,
, , ,
.
WM_TIMER,

Timer . ,
, ,

.

3.3.1. Idle.
, Timer -
Windows. ,
. , ,
, ,
. ,
. ,
, .
?
, ,
Idle Invalidate.
Idle
System.Enviroment.TickCount, ,
. 3.19.
3.19.
// Examples\Ch03\Ex08
public partial class MainForm : Form
{
// System.Enviroment.TickCount
// Idle.
int lastTick;
private void MainForm_Load(object sender, EventArgs e)
{
...
// System.Enviroment.TickCount
lastTick = Environment.TickCount;
Application.Idle += new EventHandler(Application_Idle);
}
void Application_Idle(object sender, EventArgs e)
{
// , .
if (closing)
{
Close();
return;
}
int currentTick = Environment.TickCount;
// ( ), Idle
float delta = (float)(currentTick - lastTick) * 0.001f;
//
posX += speedX * delta;
posY += speedY * delta;

56

Windows [.28].

//
...
//
lastTick = currentTick;
//
Invalidate();
}
...
}

Ch03\Ex08 , ,
. Idle
Trace.WriteLine(delta), , Visual Studio
Output. , :
delta
delta
delta
delta
delta
delta
delta
delta
delta
delta
delta

=
=
=
=
=
=
=
=
=
=
=

0,078
0
0
0,016
0,015
0
0,016
0,015
0,016
0
0,016

delta,
, .
Idle 15-16 ,
. , -
. MSDN.
Environment.TickCount Win32 GeTickCount, 10
. , 10
Environment.TickCount , .

3.3.2. Stopwatch.
Environment.TickCount
, Microsoft .NET Framework 2.0
System.Diagnostics.Stopwatch, .
.
Stopwatch Start.
ElapsedMilliseconds ,
. , Stop.
Stopwatch Frequency,
,
Stopwatch
, 1 . Frequency
1.870.000.0000, 1/18700000000 = 510-10 .
ElapsedMilliseconds 1
, Stopwatch ElapsedTicks,
. ElapsedTicks
Stopwatch.Frequency. ,
, , ,
, ..,
Stopwatch .

, Stopwatch 3.20.
3.20.
// Examples\Ch03\Ex09
public partial class MainForm : Form
{
//
Stopwatch stopwatch;
// ,
// Idle
long lastTime;
private void MainForm_Load(object sender, EventArgs e)
{
...
//
stopwatch = new Stopwatch();
stopwatch.Start();
lastTime = 0;
// Output
Trace.WriteLine("Accuracy = " + 1.0 / Stopwatch.Frequency + " sec");
Application.Idle += new EventHandler(Application_Idle);
}
void Application_Idle(object sender, EventArgs e)
{
// , .
if (closing)
{
Close();
return;
}
// ,
double currentTime = (double)stopwatch.ElapsedTicks / (double)Stopwatch.Frequency;
// ( ), Idle
float delta = (float)(currentTick - lastTick);
//
posX += speedX * delta;
posY += speedY * delta;
//
...
//
lastTime = currentTime;
//
Invalidate();
}
...
}

, , Output .
Output :
Accuracy = 5,3475935828877E-10 sec

delta
delta
delta
delta
delta
delta
delta
delta
delta
delta
delta

=
=
=
=
=
=
=
=
=
=
=

0,035
0,006
0,003
0,002
0,011
0,012
0,012
0,012
0,011
0,013
0,011


,
JIT- Paint.

- - . ,
:
Accuracy = 5,3475935828877E-10 sec
delta = 0,035
delta = 0,022
delta = 0,013
delta = 0,032
delta = 0,015
delta = 0,032
delta = 0,014
delta = 0,032
delta = 0,016
delta = 0,032
delta = 0,014
delta = 0,016
delta = 0,019

, .

3.3.3 .
, CRT- ,
, .
57,
.
, , .
, ,
, ,
. ,
.
XNA Framework

.
PresentationInterval PresentationParameters:
public PresentInterval PresentationInterval { get; set; }

PresentationInterval
PresentInterval:

PresentInterval.Default , PresentInterval.One.

PresentInterval.One
.

57

1 . [.13].

PresentInterval.Immediate , .

PresentInterval.Default PresentInterval.One -,
. PresentInterval.Default
Windows, , ,
. - Windows
, ,
( 3.3.2). , ,
.
PresentInterval.Default, PresentInterval.One ,
. ,
:
, ,
.
, .
,
-
.
, ,
.
( 3.2.3)
(vsynchCheckBox), PresentInterval.One,
PresentInterval.Immediate ( 3.12).

PresentationInterval

Microsoft.Xna.Framework.Graphics.PresentInterval,
( 3.21).

3.12. .

3.21.
// CD- Examples\Ch03\Ex10
//
public partial class MainForm : Form
{
void InitGraphivsDevice()
{
...
presentParams = new PresentationParameters();
presentParams.BackBufferCount = 1;
presentParams.SwapEffect = SwapEffect.Discard;
presentParams.IsFullScreen = settings.FullScreen;

//
presentParams.PresentationInterval = settings.PresentationInterval;
...
}
...
}
//
public partial class SettingsForm : Form
{
//
internal SettingsForm(Properties.Settings settings, GraphicsAdapter adapter)
{
...
//
if (settings.PresentationInterval == PresentInterval.One)
vsynchCheckBox.Checked = true;
else
vsynchCheckBox.Checked = false;
}
// Ok
private void okButton_Click(object sender, EventArgs e)
{
...
//
if (vsynchCheckBox.Checked)
settings.PresentationInterval = PresentInterval.One;
else
settings.PresentationInterval = PresentInterval.Immediate;
...
}
}

,
Output.
1.0/{ }.

1 , 1000 fps.
.

3.3.4. foreach for.


(Passes) foreach.
foreach
.
foreach , Enumerator.
,
List<int> numbers = new List<int>(3);
...
int s = 0;
foreach (int v in numbers)
s += v;

:
List<int> numbers = new List<int>(3);
...

int s = 0;
// enumerator
IEnumerator enumerator = numbers.GetEnumerator();
//
while (enumerator.MoveNext())
//
s += (int)enumerator.Current;

, . . , GetEnumerator :
public class List<T> : IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection,
IEnumerable
{
public Enumerator<T> GetEnumerator()
{
return new Enumerator<T>((List<T>) this);
}
...
public struct Enumerator : IEnumerator<T>, IDisposable, IEnumerator
{
private List<T> list;
private int index;
private int version;
private T current;
internal Enumerator(List<T> list);
public void Dispose();
public bool MoveNext();
public T Current { get; }
object IEnumerator.Current { get; }
void IEnumerator.Reset();
}
}

, GetEnumerator
. -, C# MoveNext
Current Enumerator IEnumerator,
(boxing) Enumerator . , ,
(inline) MoveNext Current ,
. List
foreach for ,
.
. ,
GetEnumerator , .
:
43. foreach
enumerator, , , ,
.
44. MoveNext ,
, .
, ,
enumerator, foreach.
Passes Effect.
EffectPassCollection, :

public sealed class EffectPassCollection : IEnumerable<EffectPass>


{
//
private List<EffectPass> pPass;
// ( ),
// IEnumerator<EffectPass>
public IEnumerator<EffectPass> GetEnumerator()
{
return (IEnumerator<EffectPass>) this.pPass.GetEnumerator();
}
}

. EffectPassCollection
List. this.pPass.GetEnumerator
Enumerator List, .
, - IEnumerator
IEnumerator<EffectPass>,
. ,
Paint , 10.000.000 for
foreach ( 3.22).
3.22.
// Examples\Ch03\Ex11
#define TEST
#if TEST
bool testing = true;
#endif
private void MainForm_Paint(object sender, PaintEventArgs e)
{
// TEST
#if TEST
//
if (testing)
{
//
const int n = 10000000;
int sum;
// ,
Trace.WriteLine("Gen 0 collection count: " + GC.CollectionCount(0));
Stopwatch timer = new Stopwatch();
//
timer.Start();
// passes
sum = 0;
EffectPassCollection passes = effect.CurrentTechnique.Passes;
// n
for (int i = 0; i < n; i++)
// passes for
for (int j = 0; j < passes.Count; j++)
sum += (int)passes[j].Name[0];
// ,
double time1 = (double)timer.ElapsedTicks / (double)Stopwatch.Frequency;

//
Trace.WriteLine("-----------for------------");
Trace.WriteLine("Sum : " + sum.ToString());
Trace.WriteLine("Gen 0 collection count: " + GC.CollectionCount(0));
Trace.WriteLine("Time1 : " + time1);
Trace.WriteLine("");
//
timer.Reset();
timer.Start();
sum = 0;
// , foreach
for (int i = 0; i < n; i++)
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
sum += (int)pass.Name[0];
// ,
double time2 = (double)timer.ElapsedTicks / (double)Stopwatch.Frequency;
//
Trace.WriteLine("---------foreach----------");
Trace.WriteLine("Sum : " + sum.ToString());
Trace.WriteLine("Gen 0 collection count: " + GC.CollectionCount(0));
Trace.WriteLine("Time2 : " + time2);
//
Trace.WriteLine("Time2 / Time1 = " + time2 / time1);
Trace.WriteLine("");
testing = false;
}
#endif
}

Intel Pentium-4 2.8C


:
Accuracy = 3,5730747380043E-10 sec
Gen 0 collection count: 3
-----------for-----------Sum : 1120000000
Gen 0 collection count: 3
Time1 : 0,554915015846586
---------foreach---------Sum : 1120000000
Gen 0 collection count: 915
Time2 : 1,84470303389776
Time2 / Time1 = 3,32429828211344
, foreach 915 58,
for foreach . ,
58

, , .
Intel Core2 Due E6300 foreach
229 . ,

foreach Paint, ,
. ,
,
.

Microsoft ,
0 1 . , foreach,
, (1.84
0.55) / 915 = 0.0014 . ,
,
. [.27], [.14] [.15].

foreach,

Examples\Ch03\Ex11.

3.3.5.
.
, - . ,
. , ,
, , -
, -
.
,
.
. , ,
.
, ,
.
, ,
.
(
..). ,
.

.
. :
, , 0.005 .
Idle ( 3.23).
3.23.
// ( ),
const float timeStep = 0.005f;
// Idle ( )
const float maxDelta = 5.0f;
void Application_Idle(object sender, EventArgs e)
{
...
//
double currentTime = (double)stopwatch.ElapsedTicks / (double)Stopwatch.Frequency;
// Idle maxDelta, lastTime
// Idle
if (currentTime - lastTime > maxDelta)
lastTime = currentTime - maxDelta;

CPU. , Intel Core2 Due E6300 (2MB)


, Pentium-4 2.8C (512KB). , Intel Core2 Due
E6300 4 Pentium-4 2.8C (915/229 = 3.996).

// timeStep
while (lastTime + timeStep < currentTime)
{
posX += speedX * timeStep;
posY += speedY * timeStep;
...
lastTime += timeStep;
}
Invalidate();
}


.
,
5 ( maxDelta).
,
.


,
.
maxDelta 0.2 - 0.5 .

3.4. .

, , .. , ,
() .
,
( , ).
,
. , .
, ,
, , , . ,
0.2,
20% 80% .
, .
:

c cs cd (1 )

(3.1)

cs

cd

, 0 , 1 .

XNA Framework. , XNA


Framework ,
(. 2.3.1). ,
, . ,
, . ,
, ( ).
, ,
3.1.

3.4.1. .
.
, ,
, .
,
ROP59,
( 3.13).

ROP

3.13. ROP.


ROP . ,
G70 24 16 ROP.

, ROP
.

ROP
. ROP
:

d op(b s, c d )

(3.2)

d [d r , d g , db , d a ]
op (. 3.5)
s

[ sr , sg , sb , sa ]

[d r , d g , d b , d a ]

b, [br , bg , bb , ba ]

[cr , cg , cb , ca ]


ROP
,
(FSAA Full Scene Anti Aliasing) ..

RenderState
GraphicsDevice. true
AlphaBlendEnable.
public bool AlphaBlendEnable { get; set; }

,
BlendFunction ( 3.5)
RenderState.BlendFunction.
public BlendFunction BlendFunction { get; set; }

3.5. BlendFunction.

Add ( )

Subtract

(
) ( ).

ReverseSubtract

(
) ( ).

59

Raster OPeration Unit .

Max

Min

,
Blend ( 3.6). b
RenderState.SourceBlend, c RenderState.DestinationBlend:
public Blend SourceBlend { get; set; }
public Blend DestinationBlend { get; set; }

3.6. Blend.

BlendFactor

RenderState.BlendFactor.

InverseBlendFactor

(1,
1,
1,
1)

RenderState.BlendFactor.

Zero

(0, 0, 0, 0).

One

(1, 1, 1, 1).

SourceColor

[ sr , sg , sb , sa ] .
InverseSourceColor

[1 sr ,1 sg ,1 sb ,1 sa ] .
SourceAlpha

InverseSourceAlpha

[sa , sa , sa , sa ] .

[1 sa ,1 sa ,1 sa ,1 sa ] .
DestinationColor

InverseDestinationColor

[d r , d g , d b , d a ] .

[1 d r ,1 d g ,1 db ,1 d a ] .
DestinationAlpha

InverseDestinationAlpha

[d a , d a , d a , d a ] .

[1 d a ,1 d a ,1 d a ,1 d a ] .
SourceAlphaSaturation

[ f , f , f ,1] ,

f min( sa , d a ) .
, .
,
:

d r (1 sr ) sr sa d r
d g (1 sg ) sg sa d g

db (1 sb ) sb sa db

(3.3)

,
. , SurfaceFormat.Bgr565 SurfaceFormat.Bgr32
.
,
. sr , s g , sb ,

d r , d g , db ,

BlendFunction.Subtract.
.

sr , s g , sb 3.6

, Blend.InverseSourceColor.

d r , d g , db

sa , Blend.SourceAlpha.

, ROP 3.3
:
device.RenderState.AlphaBlendEnable = true;
device.RenderState.BlendFunction = BlendFunction.Subtract;
device.RenderState.SourceBlend = Blend.InverseSourceColor
device.RenderState.DestinationBlend = Blend.SourceAlpha;


XNA Framework
, RGB Alpha
.
RenderState.SeparateAlphaBlendEnabled true,
RenderState.BlendFunction, RenderState.SourceBlend RenderState.DestinationBlend
R, G B . -
: RenderState.AlphaBlendOperation, RenderState.AlphaSourceBlend,
RenderState.AlphaDestinationBlend. ,
.

3.4.2.
.
, 3.1
ROP XNA Framework. ,
,
RenderState.BlendFactor.
.
3.1 ,
XNA Framework:
// (0 , 255 ).
// RenderState.BlendFactor
// 0..1 255.
const byte opacity = 50;
//
device.RenderState.AlphaBlendEnable = true;
//
device.RenderState.BlendFunction = BlendFunction.Add;
// opacity ( opacity / 255)
device.RenderState.BlendFactor = new XnaGraphics.Color(opacity, opacity, opacity, 0);
// , , opacity / 255
device.RenderState.SourceBlend = Blend.BlendFactor;
// , , 1 - opacity / 255
device.RenderState.DestinationBlend = Blend.InverseBlendFactor;


3.1 (Examples\Ch03\Ex02) ( 3.14).
(TrackBar) ,
3.7.

3.14. , .

3.7. .

TrackBar

Name

opacityTrackBar

Minimum

Maximum

255

TickFrequency

Label

Name

opacityLabel

Label

Text

Scroll
Paint ( 3.24). CD
Examples\Ch03\Ex13.
3.24.
private void opacityTrackBar_Scroll(object sender, EventArgs e)
{
//
opacityLabel.Text = ((float)opacityTrackBar.Value / 255.0f).ToString("0.00");
// xnaPanel
xnaPanel.Invalidate();
}

private void xnaPanel_Paint(object sender, PaintEventArgs e)


{
...
// ( Ch01\Ex03
// (. 1.2).
...
device.RenderState.CullMode = CullMode.None;
device.RenderState.PointSize = 3;
device.RenderState.AlphaBlendEnable = true;
device.RenderState.BlendFunction = BlendFunction.Add;
// BlendFactor
device.RenderState.BlendFactor = new XnaGraphics.Color((byte)opacityTrackBar.Value,
(byte)opacityTrackBar.Value, (byte)opacityTrackBar.Value, 0);
device.RenderState.SourceBlend = Blend.BlendFactor;
device.RenderState.DestinationBlend = Blend.InverseBlendFactor;
//
...
}

3.4.3. .
, ,

x sin(2 )
y cos(3 )

x , y

, 0 360 (02)

.
, :
, 0, 360. ,
( 3.15).
,
RenderState.BlendFactor .
- ,
:
device.RenderState.AlphaBlendEnable = true;
device.RenderState.BlendFunction = BlendFunction.Add;
device.RenderState.SourceBlend = Blend.SourceAlpha;
device.RenderState.DestinationBlend = Blend.InverseSourceAlpha;


2.5. Idle
Load Paint ( 3.25).

3.15. .

3.25.
// Examples\Ch03\Ex14
public partial class MainForm : Form
{
//
const int QuadStrips = 200;
//
const int TriStrips = QuadStrips * 2;
...
//
VertexPositionColor[] vertices = null;
//
Stopwatch stopwatch = null;
...
private void MainForm_Load(object sender, EventArgs e)
{
...
//
vertices = new VertexPositionColor[TriStrips + 2];
//
for (int i = 0; i <= QuadStrips; i++)
{
//
float angle = 2.0f * (float)Math.PI * (float)i / (float)QuadStrips;
//
float cos = (float)Math.Cos(angle);
float x = 0.85f * (float)Math.Sin(2 * angle);

float y = 0.85f * (float)Math.Cos(3 * angle);


//
byte green = (byte)(Math.Pow(0.5f + cos * 0.5f, 0.3f) * 255.0f);
byte red = (byte)(Math.Pow(0.5f - cos * 0.5f, 0.3f) * 255.0f);
/// , 0.015
float sx = -2.55f * (float)Math.Sin(3 * angle);
float sy = -1.7f * (float)Math.Cos(2 * angle);
float length = (float)Math.Sqrt(sx * sx + sy * sy);
float nx = sx / length * 0.015f;
float ny = sy / length * 0.015f;
// , 0.015
// , . ,
// 0.03 .
vertices[i * 2] = new VertexPositionColor(new Vector3(x - nx, y - ny, 0.0f),
new XnaGraphics.Color(red, green, 0));
vertices[i * 2 + 1] = new VertexPositionColor(new Vector3(x + nx, y + ny, 0.0f),
new XnaGraphics.Color(red, green, 0));
};
...
//
stopwatch = new Stopwatch();
stopwatch.Start();
// Idle,
Application.Idle+=new EventHandler(Application_Idle);
//
Application_Idle(this, null);
}
//
void Application_Idle(object sender, EventArgs e)
{
if (closing)
Close();
//
float currentTime = (float)stopwatch.ElapsedTicks / (float)Stopwatch.Frequency;
//
for (int i = 0; i <= QuadStrips; i++)
{
//
byte opacity = (byte)Math.Max(Math.Min((currentTime - 15.0f *
(float)i / (float)QuadStrips) * 255.0f, 255f), 0.0f);
// . , Color
// ,
// .
vertices[i * 2].Color = new XnaGraphics.Color(vertices[i * 2].Color.R,
vertices[i * 2].Color.G, vertices[i * 2].Color.B, opacity);
vertices[i * 2 + 1].Color = new XnaGraphics.Color(vertices[i * 2 + 1].Color.R,
vertices[i * 2 + 1].Color.G, vertices[i * 2 + 1].Color.B, opacity);
};
// ( 16 )
if (currentTime > 16.0f)
{

// ,
// .
Application.Idle -= new EventHandler(Application_Idle);
//
stopwatch.Stop();
}
//
Invalidate();
}
private void MainForm_Paint(object sender, PaintEventArgs e)
{
...
device.RenderState.CullMode = CullMode.None;
device.RenderState.FillMode = fillMode;
//
device.RenderState.AlphaBlendEnable = true;
device.RenderState.BlendFunction = BlendFunction.Add;
device.RenderState.SourceBlend = Blend.SourceAlpha;
device.RenderState.DestinationBlend = Blend.InverseSourceAlpha;
device.VertexDeclaration = decl;
//
effect.Begin();
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Begin();
device.DrawUserPrimitives(PrimitiveType.TriangleStrip, vertices, 0,
vertices.Length - 2);
pass.End();
}
effect.End();
device.Present();
}
}

Windows Forms,
, Win32.

.

4.
,
XNA
(ScreenSaver), :
, ( 4.1).
? , Windows
.
:
,
, , 60.
,
.

4.1. .

exe- .scr.
, Windows ,
4.1. C++
Scrnsave.lib ( Scrnsavw.lib),
, ..
WM_PAINT
.

, Win32 API
.

60

, Norton Commander
.

4.1.

/s

/c{:n}

. n
Display Properties.

/p {n}


n.

.NET Framework 2.0 Scrnsave.lib,


. ,
, . !

Visual Studio 2005 Pro Screen Saver Starter Kit,
. , , Screen Saver Starter Kit 61
, .

4.1. .
, .
. Windows Forms,
New Project Create directory for solution (
). ,
,
. Firework (Project | Add Class).
Firework (,
). , Firework,
, Firework

FireworkException .
4.1.
class FireworkException : Exception
{
public FireworkException(string message) : base(message) { }
}

Firework .
? .scr,
fx- . Visual Studio
fx- exe-.
ColorFill.fx, , Build Action
Embedded Resource ( 4.2).

61

,
.

4.2. fx- .

Firework 4.2.
4.2.
// CD Examples\Ch04\Ex01
class Firework : IDisposable
{
//
const string effectFileName = "GSP.XNA.Book.Ch04.Ex01.Data.ColorFill.fx";
//
const int slices = 64;
// ( )
public const float diskSpeed = 3.0f;
//
public const float diskRadius = 0.015f;
//
float diskAngle = 0;
// ,
...
//
//
//
//

. :
hWnd .
scintillaSize ( )
scintillaInterval ( )
public Firework(IntPtr hWnd, float scintillaSize, float scintillaInterval)
{
//
this.hWnd = hWnd;
presentParams = new PresentationParameters();
presentParams.BackBufferCount = 1;

presentParams.SwapEffect = SwapEffect.Discard;
presentParams.PresentationInterval = PresentInterval.One;
try
{
GraphicsDeviceCapabilities caps =
GraphicsAdapter.DefaultAdapter.GetCapabilities(DeviceType.Hardware);
CreateOptions options = CreateOptions.SingleThreaded;
if (caps.DeviceCapabilities.SupportsHardwareTransformAndLight)
options |= CreateOptions.HardwareVertexProcessing;
else
options |= CreateOptions.SoftwareVertexProcessing;
device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware,
hWnd, options, presentParams);
}
// Display
// Properties
catch (DeviceNotSupportedException)
{
//
//
throw new FireworkException(" Direct3D");
}

decl = new VertexDeclaration(device, VertexPositionColor.VertexElements);


diskVertices = new VertexPositionColor[slices + 2];
//
Stream effectStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(
effectFileName);
//
CompiledEffect compiledEffect = Effect.CompileEffectFromFile(effectStream, null,
null, CompilerOptions.None, TargetPlatform.Windows);
if (!compiledEffect.Success)
throw new FireworkException(String.Format(
" : \r\n{0}", compiledEffect.ErrorsAndWarnings));
effect = new Effect(device, compiledEffect.GetEffectCode(),
CompilerOptions.NotCloneable, null);
if (!effect.CurrentTechnique.Validate())
throw new FireworkException(String.Format(" \"{0}\""+
\"{1}\"\n\r , GPU",
effect.CurrentTechnique.Name, effectFileName));
stopwatch = new Stopwatch();
stopwatch.Start();
}
// ,
// .
public void Update()
{
// , currentTime
// . ,
// double

double currentTime = (float)stopwatch.ElapsedTicks / (float)Stopwatch.Frequency;


// delta ,
// float
float delta = (float)(currentTime - lastTime);
//
diskAngle += diskSpeed * delta;
//
diskVertices[0] = new VertexPositionColor(new Vector3(0.0f, 0.0f, 0.0f),
XnaGraphics.Color.LightGray);
for (int i = 0; i <= slices; i++)
{
float angle = (float)i / (float)slices * 2.0f * (float)Math.PI;
float x = diskRadius * (float)Math.Sin(diskAngle + angle);
float y = diskRadius * (float)Math.Cos(diskAngle + angle);
byte red = (byte)(255 * Math.Abs(Math.Sin(angle * 3)));
byte green = (byte)(255 * Math.Abs(Math.Cos(angle * 2)));
diskVertices[i + 1] = new VertexPositionColor(new Vector3(x, y, 0.0f),
new XnaGraphics.Color(red, green, 128));
};
lastTime = currentTime;
}
//
public void Paint()
{
...
}
//
public void Dispose()
{
if (stopwatch != null)
stopwatch.Stop();
if (device != null)
{
device.Dispose();
device = null;
}
}
}

, , Firework (
4.3).
4.3.
public partial class FullscreenForm : Form
{
Firework firework = null;
public FullscreenForm()
{
InitializeComponent();
}

private void FullscreenForm_Load(object sender, EventArgs e)


{
SetStyle(ControlStyles.Opaque | ControlStyles.ResizeRedraw, true);
MinimumSize = SizeFromClientSize(new Size(1, 1));
try
{
firework = new Firework(Handle, 0.0f, 0.0f);
}
catch (FireworkException ex)
{
MessageBox.Show(ex.Message, " ", MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
Application.Idle += new EventHandler(Application_Idle);
}
void Application_Idle(object sender, EventArgs e)
{
if (firework == null)
{
Close();
return;
}
firework.Update();
Invalidate();
}
private void FullscreenForm_FormClosed(object sender, FormClosedEventArgs e)
{
if (firework != null)
{
firework.Dispose();
firework = null;
}
}
private void FullscreenForm_Paint(object sender, PaintEventArgs e)
{
if (firework == null)
return;
firework.Paint();
}
}

.
FormBorderStyle None, WindowState Maximized.
,
.

4.2. .
, .
, ,

.

.
,
, .
, Firework ( 4.4).
4.4.
class Scintilla
{
//
const float StartTime = 6.0f;
//
const float MinSpeed = 0.3f;
const float MaxSpeed = 0.45f;
//
const float tSlowing = 0.105f;
//
const float rSlowing = 0.25f;
//
public Color color;
// (..
// )
public float angle;
public float distance;
//
public float time;
//
public float tSpeed;
//
public float rSpeed;
//
public VertexPositionColor Vertex
{
get
{
VertexPositionColor vertex;
//
vertex.Position.X = distance * (float)Math.Sin(angle);
vertex.Position.Y = distance * (float)Math.Cos(angle);
vertex.Position.Z = 0;
//
vertex.Color = new Color(color.R, color.G, color.B, (byte)(255f * time /
StartTime));
return vertex;
}
}
// . diskAngle ,
//
public void Init(float diskAngle)
{
// (
// ). rnd Firework
distance = (float)rnd.NextDouble() * Firework.diskRadius;
//
angle = (float)Firework.rnd.NextDouble() * 2.0f * (float)Math.PI;

//
tSpeed = MinSpeed + (float)Firework.rnd.NextDouble() * (MaxSpeed - MinSpeed);
// 4
rSpeed = Firework.diskSpeed / 4.0f;
// ( )
byte red = (byte)(255 * Math.Abs(Math.Sin((angle - diskAngle) * 3)));
byte green = (byte)(255 * Math.Abs(Math.Cos((angle - diskAngle) * 2)));
color = new Color(red, green, 128, 255);
//
time = StartTime;
}
// . delta ,
// Update
public void Update(float delta)
{
//
if (time > 0.0f)
{
//
time = time - delta;
//
tSpeed = Math.Max(tSpeed - tSlowing * delta, 0.0f);
rSpeed = Math.Max(rSpeed - rSlowing * delta, 0.0f);
//
distance += tSpeed * delta;
angle += rSpeed * delta;
}
}
}

:
.
, 5 ( ,
).
, .
, List :
45. .
46. DrawUserPrimitives .
List ToArray() ,
, ,
.
.
,
, .
,
. 4.5
Firework .
4.5.
class Firework : IDisposable
{
...
// ,
const float timeStep = 0.005f;

// Update 1 .
//
const float maxDelta = 1.0f;
// , (5
// )
int maxScintillaCount;
//
const float scintillaProbability = 0.3f;
//
float scintillaSize;
...
// ,
double lastTime = 0;
//
List<Scintilla> scintillas;
//
VertexPositionColor[] scintillasVertices = null;
// ,
int scintillasVertexount = 0;
// , Firework Scintilla
public static Random rnd = new Random();
//
public Firework(IntPtr hWnd, float scintillaSize, float scintillaInterval)
{
this.hWnd = hWnd;
//
this.scintillaSize = scintillaSize;
this.maxScintillaCount = maxScintillaCount;
...
//
scintillas = new List<Scintilla>(16);
//
scintillasVertices = new VertexPositionColor[16];
...
}
//
public void Update()
{
double currentTime = (float)stopwatch.ElapsedTicks / (float)Stopwatch.Frequency;
// maxDelta
if (currentTime - lastTime > maxDelta)
lastTime = currentTime - maxDelta;
// timeStep,
int stepCount = (int)Math.Floor((currentTime - lastTime) / timeStep);
// Update,
float delta = stepCount * timeStep;
//
diskAngle += diskSpeed * delta;
//
...

//
for (int i = 0; i < stepCount; i++)
{
lastTime += timeStep;
//
scintillasVertexount = 0;
// ,
int scintillaCount = rnd.Next(maxScintillaCount + 1);
//
for (int j = 0; j < scintillas.Count; j++)
{
//
scintillas[j].Update(delta);
//
if (scintillas[j].time > 0)
{
//
scintillasVertexount++;
}
else
//
{
//
while (scintillaCount > 0)
{
// ,
scintillaCount--;
// scintillaProbability
if ((Firework.rnd.NextDouble() < scintillaProbability))
{
//
scintillas[j].Init(diskAngle);
//
scintillasVertexount++;
break;
}
}
}
}
//
while (scintillaCount > 0)
{
scintillaCount--;
if ((Firework.rnd.NextDouble() < scintillaProbability))
{
//
scintillas.Add(new Scintilla());
scintillas[scintillas.Count - 1].Init(diskAngle);
scintillasVertexount++;
}
}
}
//
if (scintillasVertexount > scintillasVertices.Length)
{
// . ,

// ( )
scintillasVertices = new VertexPositionColor[Math.Max(scintillasVertexount,
scintillasVertices.Length * 2)];
}
//
int k = 0;
for (int i = 0; i < scintillas.Count; i++)
//
if (scintillas[i].time > 0)
{
scintillasVertices[k] = scintillas[i].Vertex;
k++;
}
}
//
public void Paint()
{
...
device.RenderState.CullMode = CullMode.None;
//
device.RenderState.AlphaBlendEnable = true;
device.RenderState.BlendFunction = BlendFunction.Add;
device.RenderState.SourceBlend = Blend.SourceAlpha;
device.RenderState.DestinationBlend = Blend.InverseSourceAlpha;
// ()
device.RenderState.PointSize = scintillaSize;
...
//
if (scintillasVertexount > 0)
{
device.DrawUserPrimitives(PrimitiveType.PointList, scintillasVertices,
0, scintillasVertexount);
}
//
device.DrawUserPrimitives(PrimitiveType.TriangleFan, diskVertices, 0,
diskVertices.Length - 2);
...
}

Load :
private void FullscreenForm_Load(object sender, EventArgs e)
{
...
// , 5
firework = new Firework(Handle, 3.0f, 10f);
...
}

CD Examples\Ch04\Ex02.

4.3. .
, . ,
.


( 4.6).
4.6.
private void FullscreenForm_KeyDown(object sender, KeyEventArgs e)
{
Close();
}


. . ,
-
.
,
10 ( 4.7).
4.7.
public partial class FullscreenForm : Form
{
// , true MouseMove
bool isMouseActive = false;
// MouseMove
System.Drawing.Point mouseLocation;
...
// MouseDown,
private void FullscreenForm_MouseDown(object sender, MouseEventArgs e)
{
Close();
}
// MouseMove
private void FullscreenForm_MouseMove(object sender, MouseEventArgs e)
{
// MouseMove
if (!isMouseActive)
{
isMouseActive = true;
//
mouseLocation = e.Location;
}
else
{
// X Y
// , 10
if ((Math.Abs(e.Location.X - mouseLocation.X) > 10) ||
(Math.Abs(e.Location.Y - mouseLocation.Y) > 10))
{
//
Close();
}
}
}
}


(, Internet Explorer ).
, . ,

, , , ,

( 4.8).
4.8.
// Deactivate ,
//
private void FullscreenForm_Deactivate(object sender, EventArgs e)
{
Close();
}

,
Hide Cursor:
4.9.
private void FullscreenForm_Load(object sender, EventArgs e)
{
Cursor.Hide();
...
}

,
/s. ,
Main Program ( 4.10).

Visual Studio /s, Command line
arguments Debug .
4.10.
static class Program
{
[STAThread]
static void Main()
{
//
string[] args = Environment.GetCommandLineArgs();
// "/S"
if ((args.Length == 2) && (args[1].ToUpper() == "/S"))
{
//
Application.Run(new FullscreenForm());
return;
}
// "/S",
return;
}
}

.scr.
,
. Build Events Post-build event
command line ( 4.3):
copy "$(TargetFileName)" "*.scr"

copy, exe .scr. exe-


$(TargetFileName), copy
exe-.

4.3. Build Events.

.scr-
( 4.4). ,
:
Test /s.
Configure () .
Install () Screen Saver Display Properties
.
, . ,
,
( ) Display Properties
. ,
. , .

4.4. .

4.4. .
,

. , .
.
, ,
.
Main.
AllScreens Screen.
( 4.11).
4.11.
static void Main()
{
string[] args = Environment.GetCommandLineArgs();
if ((args.Length == 2) && (args[1].ToUpper() == "/S"))
{
//
foreach (Screen screen in Screen.AllScreens)
{
//
FullscreenForm form = new FullscreenForm(screen);
//

form.Show();
}
// .
// Idle, .
Application.Run();
return;
}
return;
}

, , ,
, .
Load ( 4.12).
4.12.
Screen screen = null;
public FullscreenForm(Screen screen)
{
this.screen = screen;
InitializeComponent();
}
private void FullscreenForm_Load(object sender, EventArgs e)
{
//
// ! Bounds ,
// (.. WindowsState Maximized)
Bounds = screen.Bounds;
...
}

.
, Close
. , Close .
Application.Exit.
Application.Exit
FormClosed.
FormClosing, Application.Exit.
Deactivate: ,
- (
).
Deactivate.
4.13.
4.13.
// FormClosing
private void FullscreenForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (firework != null)
{
firework.Dispose();
firework = null;
}
}
private void FullscreenForm_Deactivate(object sender, EventArgs e)

{
// , Deactivate
if (Application.MessageLoop)
Application.Exit();
}
private void FullscreenForm_MouseDown(object sender, MouseEventArgs e)
{
// Application.Exit (
// Form.Close)
Application.Exit();
}
...

CD Examples\Ch04\Ex04.

4.5. .
.
: ,
, 5 .
,
. :
, 0 ( )
9 ( ), , 5 ,
.
, (Properties
( 4.5):

scintillaSize . 2
scintillaDensity . 5.

4.5. .

Setting)

Load ,
( 4.14).

4.14.
public partial class FullscreenForm : Form
{
Properties.Settings settings;
private void FullscreenForm_Load(object sender, EventArgs e)
{
...
// (
// )
settings = new Properties.Settings();
try
{
// , 5 ,
firework = new Firework(Handle, (float)settings.scintillaSize,
(settings.scintillaDensity + 1) * 5);
}
...
}

4.6 4.2.

4.6. .

4.2. .

SettingsForm
( )

Name

SettingsForm

Text

ShowInTaskbar

false

TopMost

true

MinimizeBox

false

MaximizeBox

false

GroupBox

Text

Label

Text

TrackBar

Name

scintillaSizeTrackBar

Minimum

Maximum

Label

Text

TrackBar

Name

scintillaDensityTrackBar

Minimum

Maximum

Name

okButton

Text

Ok

Name

cancelButton

Text

Button

Button

scintillaSizeTrackBar scintillaDensityTrackBar
scintillaSize scintillaDensity .
Application Settings | Value ( 4.7).

4.7. scintillaSizeTrackBar scintillaSize .

(
4.15).
4.15.
public partial class SettingsForm : Form
{
public SettingsForm()
{
InitializeComponent();
}
// Ok
private void okButton_Click(object sender, EventArgs e)
{
Properties.Settings settings = new Properties.Settings();
//
settings.scintillaSize = scintillaSizeTrackBar.Value;

settings.scintillaDensity = scintillaDensityTrackBar.Value;
//
settings.Save();
//
Close();
}
//
private void cancelButton_Click(object sender, EventArgs e)
{
// ,
Close();
}
}

, 3-
:
.
/C.
/C:n, n Display
Properties. , /C:299792.
, Main Program
:
4.16.
static void Main()
{
// /C
if ((args.Length == 1) || ((args.Length == 2) &&
(args[1].Length >= 2) && (args[1].ToUpper().Substring(0, 3) == "/C")))
{
//
Application.Run(new SettingsForm());
return;
}
}

, , :
( )
Display Properties. , ,
, .

4.8. Display Properties.

4.5.1. Display Properties.


Display Properties
Display Properties . ,
Display Properties
. Win32 API ,
.
,
Display Properties ( 4.17).
4.17.
public partial class SettingsForm : Form
{
// Display Properties.
//
bool center = false;
// Display Properties
IntPtr parentHandle;
public SettingsForm(IntPtr parentHandle):this()
{
//
this.parentHandle = parentHandle;

//
center = true;
}
...
}

Main
/C:n ( 4.18).
4.18.
static void Main()
{
...
// ( , ,
// ) /C
if ((args.Length == 1) || ((args.Length >= 2) && args[1].ToUpper() == "/C"))
{
//
Application.Run(new SettingsForm());
return;
}
// /C:n
if ((args.Length == 2) && (args[1].Length > 3) && (args[1].ToUpper().Substring(0, 3) ==
"/C:"))
{
// IntPtr
IntPtr hWnd = (IntPtr)int.Parse(args[1].ToUpper().Substring(3, args[1].Length - 3));
// Display Properties
// hWnd
Application.Run(new SettingsForm(hWnd));
}
...
}

.
MSDN [.26] :
BOOL GetWindowRect(HWND hWnd, LPRECT lpRect);

hWnd ;

lpRect RECT,

.
.NET Framework 2.0 GetWindowRect,
RECT, .
.NET Framework, GetWindowRect RECT,
http://pinvoke.net. Win32 API ,
Win32 ( 4.19).
Win32,

(, x64 Xbox 360).
4.19.
// Win32 API, http://pinvoke.net
using System.Runtime.InteropServices;

public static class Win32


{
// RECT
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
// ,
public int Width { get { return right - left + 1; } }
public int Height { get { return bottom - top + 1; } }
}
//
[DllImport("user32.dll")]
public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);}

, , Load
Display Properties ( 4.20).
4.20.
private void SettingsForm_Load(object sender, EventArgs e)
{
if (center)
{
// RECT
Win32.RECT rect = new Win32.RECT();
// Display Properties
Win32.GetWindowRect(parentHandle, out rect);
// Display Properties
int centerX = (rect.right + rect.left) / 2;
int centerY = (rect.bottom + rect.top) / 2;
// Display Properties
Left = centerX - Width / 2;
Top = centerY - Height / 2;
}
}

CD Examples\Ch04\Ex05.

4.6. .

.
( Screen Saver
Display Properties) .
Display Properties WM_PAINT,
, Display
Properties WM_CLOSE.
, .NET
Framework
Win32. , Win32 ( 4.21).

4.21.
public static class Win32
{
...
// .
public delegate IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
// WNDCLASSEX,
[StructLayout(LayoutKind.Sequential)]
public struct WNDCLASSEX
{
[MarshalAs(UnmanagedType.U4)]
public int cbSize;
[MarshalAs(UnmanagedType.U4)]
public uint style;
public WndProc lpfnWndProc;
public int cbClsExtra;
public int cbWndExtra;
public IntPtr hInstance;
public IntPtr hIcon;
public IntPtr hCursor;
public IntPtr hbrBackground;
public string lpszMenuName;
public string lpszClassName;
public IntPtr hIconSm;
}
//
[Flags]
public enum WindowStyles : uint
{
//
WS_CHILD = 0x40000000,
//
WS_VISIBLE = 0x10000000,
//
WS_DISABLED = 0x08000000,
...
}
//
[Flags]
public enum ClassStyles : uint
{
//
CS_PARENTDC = 0x0080,
...
}
// Windows
public enum WindowsMessages : uint
{
WM_CLOSE = 0x10,
WM_DESTROY = 0x2,
WM_PAINT = 0xF,
...
}

//
[DllImport("user32")]
public static extern short RegisterClassEx([In] ref WNDCLASSEX lpwcx);
//
[DllImport("user32.dll")]
public static extern IntPtr CreateWindowEx(uint dwExStyle, string lpClassName,
string lpWindowName, uint dwStyle, int x, int y, int nWidth, int nHeight,
IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, IntPtr lpParam);
//
[DllImport("user32.dll")]
public static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);
//
[DllImport("user32.dll")]
public static extern bool DestroyWindow(IntPtr hWnd);
// WM_QUIT,
[DllImport("user32.dll")]
public static extern void PostQuitMessage(int nExitCode);
//
[DllImport("user32.dll")]
public static extern IntPtr DefWindowProc(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr
lParam);
...
}

Main /P, :
47. .
48. .
49. .
50. Firework.
51. .
, , 4.22.
4.22.
static void Main()
{
...
// /P n
if ((args.Length == 3) && (args[1].ToUpper() == "/P"))
{
//
IntPtr parentHandle = (IntPtr)uint.Parse(args[2]);
//
Win32.RECT rect;
Win32.GetClientRect(parentHandle, out rect);
//
Win32.WNDCLASSEX wndClassEx = new Win32.WNDCLASSEX();
wndClassEx.cbSize = Marshal.SizeOf(wndClassEx);
wndClassEx.style = (uint)Win32.ClassStyles.CS_PARENTDC;
// (. 4.23).
wndClassEx.lpfnWndProc = new Win32.WndProc(WindowProc);

wndClassEx.cbClsExtra = 0;
wndClassEx.cbWndExtra = 0;
wndClassEx.hIcon = IntPtr.Zero;
wndClassEx.hIconSm = IntPtr.Zero;
wndClassEx.hCursor = IntPtr.Zero;
wndClassEx.hbrBackground = IntPtr.Zero;
wndClassEx.lpszMenuName = null;
wndClassEx.lpszClassName = "XNASCREENSAVER";
wndClassEx.hInstance = Marshal.GetHINSTANCE(typeof(Program).Module);
//
if (Win32.RegisterClassEx(ref wndClassEx) == 0)
return;
//
displayHandle = Win32.CreateWindowEx(0, "XNASCREENSAVER", "XNAScreenSaver",
(uint)(Win32.WindowStyles.WS_CHILD | Win32.WindowStyles.WS_VISIBLE |
Win32.WindowStyles.WS_DISABLED), 0, 0, rect.Width, rect.Height, parentHandle,
IntPtr.Zero, Marshal.GetHINSTANCE(typeof(Program).Module), IntPtr.Zero);
try
{
// Firework .
// ,
// .
firework = new Firework(displayHandle, 1.0f, 5);
}
catch (FireworkException ex)
{
MessageBox.Show(ex.Message, " ", MessageBoxButtons.OK,
MessageBoxIcon.Error);
return;
}
// .
Application.Run();
return;
}
return;
}
}

( 4.23):
WM_PAINT .
WM_CLOSE .
WM_DESTROY .
4.23.
//
public static IntPtr WindowProc(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam)
{
switch (uMsg)
{
// WM_PAINT
case (uint)Win32.WindowsMessages.WM_PAINT:
if (firework != null)
{

//
firework.Update();
//
firework.Paint();
}
return IntPtr.Zero;
// WM_CLOSE
case (uint)Win32.WindowsMessages.WM_CLOSE:
if (firework != null)
{
//
firework.Dispose();
firework = null;
}
//
Win32.DestroyWindow(displayHandle);
return IntPtr.Zero;
// WM_DESTROY
case (uint)Win32.WindowsMessages.WM_DESTROY:
//
Win32.PostQuitMessage(0);
return IntPtr.Zero;
default:
return Win32.DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}


. ,
( 4.9).

4.9. .

4.7. .
. ,
,
. ,
. , , Visual Studio 2005.
.
, ( Add | New Project | Other Project Types |
Setup and Deployment | Setup Project). ProductName Manufacture
, , ,
Add or Remove Programs.

4.10. .


, , Windows Installer
, Windows
2000 .
,
. ,
Windows Installer, ,
(, Nullsoft Scriptable Install System). Internet
500 .

Windows
.
, , Program
Files. Windows File System (Setup)
Application
Folder
Default
Location

[ProgramFilesFolder][Manufacturer]\[ProductName] [WindowsFolder] ( 4.11).


Application Folder *.scr ...\bin\Release (
Add | File
Application Folder). , Application Folder
Microsoft.Xna.Framework.dll, .

, , Exclude true,
,
.NET Framework 2.0 DirectX, Microsoft
XNA Framework.

4.11. , .

SCRNSAVE.EXE
HKEY_CURRENT_USER\Control Panel\Desktop. ,
.
Solution
View | Registry.
. HKEY_CURRENT_USER Control
Panel ( New | Key), Desktop. Desktop
SCRNSAVE.EXE ( New | String Value)
[TARGETDIR]mysaver.scr ( 4.12),

[TARGETDIR] , , (
\Windows).

mysaver.scr .

4.12. .

, SCRNSAVE.EXE
( Windows XP Service Pack 2). ,
, Windows 3.x, .
, 100%
. Windows
, .
desk.cpl,
Display Properties. ,
, Display
Properties. InstallScreenSaver .
rundll32:
rundll32.exe desk.cpl,InstallScreenSaver { }

, , Windows
rundll32, .

4.7.1. Custom Actions


Windows Installer, Visual Studio,
, .
Custom Actions.
, ,
rundll32.
SetupCustomActions ( Add | New Project | Visual C# | Class
Library). Solution
SetCurrentScrenSaver (Add | New Item | Installer Class). ,
Installer ( 4.24).
4.24.
using
using
using
using

System;
System.Collections.Generic;
System.ComponentModel;
System.Configuration.Install;

namespace SetupCustomActions
{
// RunInstaller, true, ,
//
[RunInstaller(true)]
public partial class SetCurrentScrenSaver : Installer
{
public SetCurrentScrenSaver()
{
InitializeComponent();
}
}
}

Installer , Custom Actions.


, ,
Install Installer ( 4.25).
4.25.
using System.Diagnostics;
public override void Install(System.Collections.IDictionary stateSaver)
{
// Installer
base.Install(stateSaver);

// rundll32
Process.Start("rundll32.exe", "desk.cpl,InstallScreenSaver " +
Context.Parameters["ScreenSaver"]);
}

Context.Parameters,
, (
).
.
. Solution
(Setup) View | Custom Actions.
Custom Actions, ,
, , .. Install (,
) Add Custom Action.
, ,
Custom Actions.
Application Folder (, ).
Add Output, Project ,
Custom Actions ( , SetupCustomActions). ,
Primary output (,
) Ok ( 4.13).

4.13. , Custom Actions.

Custom Actions Install


Primary output from SetupCustomActions (Active).
SetupCustomActions , Installer,
[RunInstaller(true)], .
, ,
ScreenSaver . CustomActionData
Primary output from SetupCustomActions (Active)
/ScreenSaver="[TARGETDIR]Firework XNA.scr" ( 4.14).

4.14. , .

4.7.2. .NET Framework 2.0 XNA Framework


1.0
,
.
52. .NET Framework 2.0
53. XNA Framework 1.0.
,
. , (
) . ,
,
.
Visual Studio 2005
. ,
.
.
( Properties), Prerequisite
, ( 4.15).

Specify the install location for prerequisites Download
prerequisites from the same location as my application.

4.15. .

, XNA Game Studio 1.0 Express


Prerequisite Visual Studio 2005. CD .
\Tools\XNA Game Studio Express 1.0\VS 2005 Prerequisite
install.bat, Prerequisite Microsoft XNA
Framework. install.bat Visual Studio,

XNAFramework

\Microsoft
Visual
Studio
8\SDK\v2.0\BootStrapper\Packages\.

XNAFramework :
xnafx_redist.msi XNA Framework XNA Game Studio Express 1.0 ( \XNA Game
Studio Express\v1.0\Redist\XNA FX Redist).
product.xml , xnafx_redist.msi.
\En\package.xml
Prerequisite XNA Framework [.12].
, ( Build),
\Setup\Release ,
XNA Framework ?.

4.16. .

4.17. .

,
, ,
,
.
Windows Installer
, , .NET Framework 2.0 XNA Framework 1.0.

5.

, -
. ,
.
HLSL
.
,
.

HLSL, 2.3.

5.1. HLSL
,
HLSL.

5.1.1.
HLSL C.
+, -, *, /, %, ++, --, +=, -=, *=, /= %=.
, . C.
:
float4 a = {1, 2, 3, 4};
float4 b = {5, 6, 7, 8};
// . {1+5, 2+6, 3+7, 4+8} = {6, 8, 10, 12}
float4 c = a+b;
// . d {1*5, 2*6, 3*7, 4*8} = {5, 12, 21, 32}
float4 d = a*b;

,
:
float4 a = {1, 2, 3, 4};
// b {1*2, 2*2, 3*2, 4*2} = {2, 4, 6, 8}
float4 b = a*2;

32-
62. , float4 half4 double4
63.

5.1.2.
DirectX . -,
. ,
[]. ,
:
float4 color = float4(0.2, 0.7, 0.5, 1.0);
// avg 1.6
float avg = (color[0] + color[1] + color[2] + color[3])/4;

,
DirectX
. x r, y g,
62

.
(. 7.x).
63
int4 , HLSL
32-
(. 2.3.2).

z b, w a. , x, y, z, w
, r, g, b, a :
float avg = (color.r + color.g + color.b + color.a)/4;

float avg = (color.x + color.y + color.z + color.w)/4;


.
, HLSL
. ,
.
() :
//
float4 a={1, 2, 3, 4};
// b a.
// b (1, 2)
float2 b=a.xy;
// c {1, 1, 2}
float3 c=a.xxy;
// x, y, z . a
// {3, 2, 1, 4}
a.xyz=a.zyx;


,
. . ,
HLSL a.rgzw,
, .

HLSL ,
. .
,
float a=3;
float4 v=float4(a, a, a, a);

:
float a=3;
//
float4 v=a.xxxx;


. HLSL :
=
. :
float a=3;
// v (3, 3, 3, 3)
float4 v=a;

5.1.3.
HLSL
: ,

. HLSL 4.
, .
HLSL . ,
, , 1 .
, . , b

1
a

b=1.0/sqrt(a), b=rsqrt(a).

GPU ( ), . ,
.

HLSL, , b=1.0/sqrt(a)
b=rsqrt(a). ,
.

5.1.4. -

, - :

l ( r g b) / 3
r l
g l
bl

(5.1)

r, g, b ,

. ,
- , -
. ,
PrimitiveType.TriangleStrip -
.
5.1 , -
. ,
56% 640x480, -
6404800.56=172000 . ,
172000/4=43000 (!), .
1280x960 .
,
.
- ( 5.1).
5.1.
struct VertexInput
{
float3 pos : POSITION;
float4 color : COLOR;
};
struct VertexOutput
{
float4 pos : POSITION;
float4 color : COLOR;
};

VertexOutput MainVS(VertexInput input)


{
VertexOutput output;
output.pos = float4(input.pos, 1.0f);
// -
float luminance = (input.color.r+input.color.g+input.color.b)/3.0;
output.color.r = luminance;
output.color.g = luminance;

output.color.b = luminance;
output.color.a = input.color.a;
return output;
}
float4 MainPS(float4 color:COLOR):COLOR
{
return color;
}
technique BlackAndWhiteFill
{
pass p0
{
VertexShader = compile vs_1_1 MainVS();
PixelShader = compile ps_1_1 MainPS();
}
}

5.1
, , .
,
( 5.2).
5.2.
VertexOutput MainVS(VertexInput input)
{
VertexOutput output;
output.pos = float4(input.pos, 1.0f);
// ,
output.color.rgb = (input.color.r+input.color.g+input.color.b)/3.0;
output.color.a = input.color.a;
return output;
}


, HLSL
5.1 r, g, b .
... ,
.

.
. (5.1):

1
1
1
l r g b
3
3
3

(5.2)

, ,
:

1 1 1
l ( , , ) ( r , g , b)
3 3 3

(5.3)

5.3
5.1.
. , 5.1 5.3
dot ( ),
( 5.3).

5.3.
VertexOutput MainVS(VertexInput input)
{
VertexOutput output;
output.pos = float4(input.pos, 1.0f);
// . dot
// (1/3.0, 1/3.0, 1/3.0)
output.color.rgb = dot(input.color.rgb, 1/3.0);
output.color.a = 1.0;
return output;
}


,
- ( 5.1).
, Load ( 5.4),
CD
Examples\Ch05\Ex01.

5.1. , - .

5.4.
public partial class MainForm : Form
{
// , -
const string effectFileName = "Data\\BlackAndWhiteFill.fx";
GraphicsDevice device = null;
PresentationParameters presentParams;
VertexDeclaration decl = null;
//
VertexPositionColor[] vertices = null;
Effect effect = null;
bool closing = false;

public MainForm()
{
InitializeComponent();
}
private void MainForm_Load(object sender, EventArgs e)
{
//
...
decl = new VertexDeclaration(device, VertexPositionColor.VertexElements);
vertices = new VertexPositionColor[4];
// .
// -
vertices[0] = new VertexPositionColor(new
XnaGraphics.Color.Green);
vertices[1] = new VertexPositionColor(new
XnaGraphics.Color.YellowGreen);
vertices[2] = new VertexPositionColor(new
XnaGraphics.Color.White);
vertices[3] = new VertexPositionColor(new
XnaGraphics.Color.GreenYellow);

,
Vector3(-0.75f, -0.75f, 0.0f),
Vector3(-0.75f, 0.75f, 0.0f),
Vector3(0.75f, -0.75f, 0.0f),
Vector3(0.75f, 0.75f, 0.0f),

//
...
}
// Paint, Resize, Closed ..
...
}

5.1
(5.1) , ,
. ,
, .
(NTSC) :

l 0.299 r 0.587 g 0.114 b

(5.4)

, - 5.4.
Ch05\Ex01.
CD Examples\Ch05\Ex02.

5.2. NVIDIA FX Composer 2.0


.fx . ,
. , .NET
.cs-
C# (csc.exe).
. , IDE Visual
Studio ,
IntelliSense, , .
XNA ,
. ,
: ATI
RenderMonkey 1.6 NVIDIA FX Composer 2.0. NVIDIA FX
Composer,
.NET Framework.


NVIDIA FX Composer 2.0 .NET. ,
FX Composer 2.0 .NET Reflector.

FX Composer 2.0? , Visual Studio


, HLSL, GLSL64 Cg65. , , FX
Composer Visual Studio 2005 :
, IntelliSense, . , FX Composer
. , ,
-, Visual Studio FX Composer. , NVIDIA FX Composer
, ,
.
FX Composer 2.0 COLLADA 1.4.1,

.

5.2.1. COLLADA 1.4.1


COLLADA (COLLAborative Design Activity) ,
(DCC66). COLLADA
XML XSD-. ,
:
.
.
.
.
.
.
.
.
.
.. ..
, COLLADA XML,
.
COLLADA :
<?xml version="1.0"?>
<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
<library_images>
<image id="my_color" name="my_color">
<init_from>data/default_color.dds</init_from>
</image>
</library_images>
<library_effects>
<effect id="BlinnEffect" name="Blinn Effect">
<profile_CG platform="PC-OGL">
<include sid="Blinn" url="Data/Blinn.cg"/>
</profile_CG>
<profile_CG platform="PS3">
<include sid="Blinn" url="Data/Blinn.cg"/>
</profile_CG>

64

OpenGL Shading Language (GLSL) , API OpenGL.


Cg , NVIDIA. API
DirectX, API OpenGL.
66
Digital Content Creation (DCC) .
65

<profile_GLSL>
<include sid="Blinn" url="Data/Blinn.glsl"/>
</profile_GLSL>
<extra type="import">
<technique profile="NV_import">
<import url="Data/Blinn.fx" compiler_options="" profile="fx"/>
</technique>
</extra>
</effect>
</library_effects>
<library_materials>
<material id="BlinnMaterial" name="Blinn Material">
<instance_effect url="#BlinnEffect">
<!-- -->
</instance_effect>
</material>
</library_materials>
</COLLADA>

, <COLLADA>:
<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
</COLLADA>

<COLLADA> , :
<library_images> ;
<library_effects> ;
<library_materials> ;
<library_cameras> ;
<library_lights> ;
<library_geometries> ;
..
<effect>, <library_effects>:
<library_effects>
<effect id="BlinnEffect" name="Blinn Effect">
</effect>
</library_effects>
id , name ,

FX Composer 2. COLLADA
API,
. :
API .
<profile_XXX>,
<effect>:
<profile_CG> Cg. platform
, : ,
"PC-OGL" , API OpenGL PC,
PS3 Playstation 3.
<profile_GLSL> GLSL.
<profile_GLES> API OpenGL ES67.
<profile_COMMON> - ,
(Standard Material) 3ds Max.
67

OpenGL ES API OpenGL, : ,


..

<profile> ,
: , ..
,
<profile> <code>.
,
HLSL. , (1.4.1) COLLADA
HLSL.

<extra>, FX Composer .fx :
<extra type="import">
<technique profile="NV_import">
<import url="Data/Blinn.fx" compiler_options="" profile="fx"/>
</technique>
</extra>

, fx.
COLLADA .
. ,
, .

68, , ,
, ..
, , , ,
. ,
.
<library_materials>
<material>.
<material>

<instance_effect>, url
<library_effects>,

<instance_effect>

.
<library_effects> <library_materials>
COLLADA, COLLADA FX. FX Composer
2 COLLADA FX,
COLLADA
. , FX Composer 2
COLLADA,
(
).
, .


COLLADA,

FX Composer 2.0.

5.2.2. FX Composer 2.0


. FX Composer 2.069 Start (Start |
All Programs |
NVIDIA Corporation | FX Composer 2 | FX Composer 2). 5.2
FX Composer 70.
.
FX Composer,
(Standard Toolbar) .
IDE .

68

5.4.
FX Composer 2.0 CD- \NVIDIA.
FX Composer http://developer.nvidia.com/ .
70
, ,
.
.
69


FX Composer 2 ,
User Guide Start Page, FX Composer.

: Start Page, Shader Library Editor.


Start Page, Visual Studio 2005:
(Recent), (Getting Started),
(Tasks) .
FX Composer ( User Guide Getting
Started).
Shader Library
NVIDIA.
Editor ,
.

1
3

6
5.2. FX Composer 2: 1 , 2 Start Page , 3 Materials, 4
Properties, 5 Render, 6 Animation.

: Materials, Assets Project.


Material, 3ds Max, ,
COLLADA.
Assets ,
COLLADA.
Project, , Solution
Explorer Visual Studio 2005.
Properties,
71.
Render, ,
71

5.4.

API OpenGL DirectX ( , COLLADA


API).
Animation Tasks.
Animation
.
Tasks , ..
Error List Visual Studio.
: ,
. , ,
, Visual Studio. 72
View ( 5.3).

5.3. FX Composer View.


View Layouts, FX
Composer. ( Artist, Authoring, Default,
Turning), .
- ,
View | Layouts | Reset Layout.

5.2.3.
FX Composer 2.0 .
FX Composer - . FX Composer.
, , File
| New | New Project. Assets ( 5.4). , ,
COLLADA, 5.2.1.
, Effects Assets <library_effects>, Materials
<library_materials> ..

72

5.4. Assets.

Effects
Add Effect... .
( 5.5). HLSL,
HLSL FX. Effect Name (, BlackAndWhite).
, ,
, .

5.5. .

Effect Wizard, Next.


, .
Empty, , , . Name
(, BlackAndWhite.fx), Location ,
. , Finish.

5.6. .

Effects. , Effects
BlackAndWhite, Collada,
BlackAndWhite.fx ( 5.7).

.fx ,
BlackAndWhite .cg .glsl.

5.7. Effects.


73
BlackAndWhite.fx. 5.1 .
73

, HLSL
.

HLSL, .
Ctrl + F7.
, Tasks ( 5.8),
.

, Output ( 5.9)
View | Output.

5.8. Task .

5.9. Output .

File | Save All.


, .
, :
Project.fxcproj FX Composer IDE
. XML.
Document1.dae COLLADA .
BlackAndWhite.fx .
Document1.dae, FX Composer 2.0 , :
<?xml version="1.0"?>
<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
<asset>
<contributor>
<author>Sergei Gaidukov</author>
<authoring_tool>NVIDIA FX Composer 2.0</authoring_tool>
<comments/>
<copyright/>
</contributor>
<created>2007-06-04T16:39:20</created>
<keywords>FXComposer, NVIDIA</keywords>
<modified>2007-06-04T16:39:21</modified>
<subject/>
<title/>
</asset>
<library_effects>
<effect id="Effect" name="BlackAndWhite">

<profile_COMMON>
<technique sid="__fxc2_default">
<constant/>
</technique>
</profile_COMMON>
<extra type="import">
<technique profile="NV_import">
<import url="BlackAndWhite.fx" compiler_options="" profile="fx"/>
</technique>
</extra>
</effect>
</library_effects>
</COLLADA>

, <COLLADA> : <asset> ,
, ; <library_effects>.
Effect BlackAndWhite,
: HLSL74 COMMON.

COLLADA ,
COMMON.

.fx-.
FX Composer 2.0,
File | Open | Open Project... .
, .fx-? FX
Composer 2.0 COLLADA,
.fx- File | Open | Open File...
.fx- , , .
, :
.fx-. Assets, Effects,
Add Effect From File... , .
, ,
.

5.2.4. .
,

, .
Shader Perfomance,
NVIDIA .

BlackAndWhite, 5.2.3. Assets
, ,
Analyze Performance, Shader Performance (
5.10), : Startup Form BlackAndWihite.fx. ,
, ,
Analyze Performance.

74

COLLADA HLSL,
<extra>, .

5.10. Shader Performance.

BlackAndWhite.fx
(Analyze a Pass)
(Compare Passes).
, .
75.
p0.
: . BlackAndWhite.fx,
return, - ,
. , BlackAndWhite.fx
Drivers GPU, ForceWare ,
.

. Run
. Table,
5.10. ,
NVIDIA GeForce 7800 GTX ForceWare 162.03
7 ,
491.000.000 . ,
,
. ,
, .

Precision Branches
.
: BlackAndWhite.fx ,
32-.

Graph .
.
Tools | Settings... Settings
FX Composer Enviroment |
ShaderPerf. ... DefaultSelectedGPUs
Selected Default GPUs
( 5.11). ,
GeForce 6 , GPU NV4x G7x.
.

75

Analyze a Pass , Compare Passes


.

5.11. Setting Select Default GPUs.

OK BlackAndWhite.fx Shader Perfomance ,


. GPU ,
, Graph .
(
5.12).

5.12. .

,
. , 100.000 . ,

,
GeForce6 (GeForce 6200) 150.000.000 / 100.000 = 1.500
.
GeForce6.

.

Shader
Performance
. ,
, .
, , .
HLSL
C++, . ,
,

.
, , ,
.

GeForce3 GeForce4,
-1 +1.
.

, HLSL,
ASM Editor BlackAndWhite_Asm.txt
:
################################################################
# Technique: BlackAndWhiteFill
# Pass: p0
################################################################
//
// Generated by Microsoft (R) D3DX9 Shader Compiler 9.12.589.0000
vs_1_1
def c0, 0.333333343, 1, 0, 0
dcl_position v0
dcl_color v1
add r0.w, v1.y, v1.x
add r0.w, r0.w, v1.z
mul oD0.xyz, r0.w, c0.x
mad oPos, v0.xyzx, c0.yyyz, c0.zzzy
mov oD0.w, v1.w
// approximately 5 instruction slots used

, Microsoft (R)
D3DX9 Shader Compiler 9.12.589.0000,
Vertex Shader 1.1. ,
Vertex Shader.
NVIDIA FX Composer 2.0 ,
.

5.3. Vertex Shader


Vertex Shader
, .

, ,

. , .
Vertex Shader IL,
.

5.3.1.
, SSE76
x86. ( )
, .
, 128- ,
, , 32- ( 5.13).
W
127

Z
95

Y
63

X
31

5.13. 128- (32 ).

, (
5.14):
, (
, ..).
, .
,
.

5.14. .

,
1.1.

Vertex Shader 1.1 Pixel Shader 1.1
GeForce3 (NV20).


( 5.15):
16 v0, v1 v15 , (Input Registers).
96- c0, c1 c95 ... cN ,
(Constant Float Registers).
, 4
. 128 , ..
32- .
GPU. , GPU
- ,
32- .
v0, v1 v15 77, :
, , , ..

dcl_xxx, 5.1. HLSL
76

128- SSE Intel Pentium-III,


, , [.6].
77
, , .

v0 ... v15, , dcl_xxx


. ,
, FX Composer 5.2.4,
:
dcl_position v0
dcl_color v1

,
:
struct VertexInput
{
float3 pos : POSITION;
float4 color : COLOR;
};

5.1. ,

HLSL

dcl_position

POSITION

dcl_color

COLOR

dcl_psize

PSIZE

78

dcl_texcoord

TEXCOORD

127

95

63

31

127

v0

c0

v1

c1

v2

c2

v3

c3

v4

c4

v5

c5

v6

c6

v7

c7

v8

c8

v9

c9

v10

c10

v11

c11

v12

c12

v13

c13

v14

c14

v15

c15

95

c16
...

63

31

...

c93
c94
c95
...

...

cN

5.15. .

, , .
def:
78

6.x.

def { }, { 0}, { 1}, { 2}, { 3}

,
c0 (0.333333343, 1, 0, 0).
def c0, 0.333333343, 1, 0, 0

- . ,
0.333333343

(input.color.r+input.color.g+input.color.b)/3.0.
, 1
:
output.pos = float4(input.pos, 1.0f);

, Vertex Shader 1.1


96 .

GraphicsDeviceCapabilities.MaxVertexShaderConstants GraphicsDevice. 5.2
.

,
GraphicsDeviceCapabilities.MaxVertexShaderConstants. , ,
, ,
DirectX.

5.2. GPU.
GPU

NV2x

96

NV3x

256

NV4x

256

G7x

256

R2xx

192

R3xx

256

R4xx

256
79

Intel GMA 9xx

8192

Intel GMA 3000

8192

, , ,
(. 5.4).


,
. Vertex Shader 1.1
( 5.16):
12 r0, r1 r11
(Temporary Registers).
a0,
(Address Register).

79

Intel GMA 9xx GMA 3000 CPU.

127

95

63

31

r0

a0

r1
r2
r3
r4
r5
r6
r7
r8
r9
r10
r11
5.16. .

SSE x86,
- . ,
. ,
2, c5
c7.
c[a0.x + 5].

, ,
HP-11C.



: ,
.


, Vertex Shader 1.1
( 5.17):
oPos (Position Register).
oD0 oD1 (Color Registers). ,
oD0 , oD1 .
oT0, oT1, oT2, oT3, oT4, oT5, oT6, oT7
(Texture Coordinate Register). ,
.
oPts (Point Size Register).
(PrimitiveType.PointList).
oFog, (Fog Register).

oPos

oPts

oD1

oFog

oD2

oT0
oT1
oT2
oT3
oT4
oT5
oT6
oT7
5.17. .

GPU Vertex Shader 1.1,


. ,

.
: GPU NV4x R5xx
,
.
, ,
HLSL . :
HLSL
( 5.3). , GPU

. , HLSL GPU
.
5.3. HLSL

oPos

POSITION

oD0

COLOR, COLOR0

oD1

COLOR1

oT0

TEXCOORD, TEXCOORD0

0T1

TEXCOORD1

oT2

TEXCOORD2

oT3

TEXCOORD3

oT4

TEXCOORD4

oT5

TEXCOORD5

oT6

TEXCOORD6

oT7

TEXCOORD7

oPts

PSIZE

oFog

FOG

, .
, .
,
HLSL, . ,
, .

5.3.2. .
, Vertex Shader 1.1.
x86,
Vertex Shader x86.
:
op dst, src0 [, src1] [, src2]

op .

dst , .

src0, src1, src2 - .

.
Vertex Shader 1.1
: 128. ,
,
.
,
.

MOV
,
x86:
mov dst, src

dst ;

src .

c2 r5:
mov r5, c2

Vertex Shader :
. ,
.
. ,
HLSL .
. , r5
c2 ,
:
mov r5.xyz, -c2.yxz

ADD
ADD :
add dst, src0, src1

dst , .

src0 .

src1 .

: dst = src0 + src1. ,


v0 c0 r0

add r0, v0, c0

SUB
:
sub dst, src0, src1

dst = src0 src1


, ,
.

, x y v2 z w v3
y z r1:
sub r1.yz, v2.xy, v3.zw

MUL
:
mul dst, src0, src1

dst = src0 src1

c0 x c1
r0:
mov r0, c0, c1.xxxx

MAD
:
mad dst, src0, src1, src2

dst = src0 src1 + src2


, mul
add. c0 v1
c1. r0:

mad r0, c0, v1, c1

DP3
x, y, z :
dp3 dst, src0, src1

dst.xyzw = src0.x src1.x + src0.y src1.y + src0.z src1.z

, r1
v0 r0:
dp3 r1, v0, r0

DP4
:
dp4 dst, src0, src1

dst.xyzw = src0.x src1.x + src0.y src1.y + src0.z src1.z + src0.w src1.w

r1
v0 r0:
dp4 r1.x, v0, r0

FRC {x}
:
frc dst, src0

dst = {src0}


, {2.3}=3, {- 2.3}=0.7

y xy - ( x
y ). xy r0
r1:
frc r0.xy, r1

frc , .
, .
,
Vertex Shader 1.1 frc
.
Vertex Shader 1.1,
frc,
.

RCP 1/x
:
rcp dst, src0

dst.xyzw=1/src0

src . src0 0, dst

, GPU ( 10 38).

GPU NVIDIA NV3x Floating-Point Specials: -Inf ( ),
+Inf ( ), NaN ( ) .. , NV3x
1.0/0.0 +Inf. Floating-Point Specials
[.16].

1/r1.w r0.w:
rcp r0.w, r1.w

EXPP 2x 2-3
2 2-3 :
expp dst, src0

dst , .
x , y
, z , w

src0 , 2. .

80:
dest.x
dest.y
dest.z
dest.w
80

=
=
=
=

2floor(src0)
src0 floor(src0)
2src
1

Vertex Shader 2.0 EXPP .


, , .

z 10 (2-3 ).
2r1.w r0.z.
.z.
rcp r0.z, r1.w

EXP 2x 6-7
2 21 (6-7 ):
expp dst, src0

dst.xyzw = 2src0

, 10 .
,
, expp.
2r1.x r0.y:
expp r0.y, r1.x

MIN
,
.
min dst, src0, src1

dst -, .

src0 src1 , .

:
dst = src0;
if (src0.x > src1.x)
dst.x=src1.x;
if (src0.y > src1.y)
dst.y=src1.y;
if (src0.z > src1.z)
dst.z=src1.z;
if (src0.w > src1.w)
dst.w=src1.w;

w r4 r0, x y
r3:
min r3.xy, r4.w, r0

MAX
,
.
max dst, src0, src1

dst -, .

src0 src1 , .

:
dst = src0;
if (src0.x > src1.x)
dst.x=src0.x;
if (src0.y > src1.y)
dst.y=src0.y;

if (src0.z > src1.z)


dst.z=src0.z;
if (src0.w > src1.w)
dst.w=src0.w;

r4 r2, r1:
max r1, r4, r2

SGE
1,
, 0 :
sge dst, src0, src1

dst , .

src0 src1 , .

:
dst.xyzw = 0;
if (src0.x >= src1.x)
dst.x = 1;
if (src0.y >= src1.y)
dst.y = 1;
if (src0.z >= src1.z)
dst.z = 1;
if (src0.w >= src1.w)
dst.w = 1;

SLT
1,
, 0 :
slt dst, src0, src1

dst , .

src0 src1 , .

:
dst.xyzw = 0;
if (src0.x< src1.x)
dst.x = 1;
if (src0.y < src1.y)
dst.y = 1;
if (src0.z < src1.z)
dst.z = 1;
if (src0.w < src1.w)
dst.w = 1;

,
.
DirectX.

Vertex Shader
DirectX (Start | All Programs | Microsoft DirectX SDK | DirectX Documentation | DirectX SDK
Documentation for C++) Index .
Vertex Shader Index
: vs_1_1, vs_2_0, vs_2_x vs_3_0.

5.3.3.
, .

BlackAndWhite.fx.
HLSL ,
, FX Composer 2.0. , :
struct VertexInput
{
float3 pos : POSITION;
float4 color : COLOR;
};
struct VertexOutput
{
float4 pos : POSITION;
float4 color : COLOR;
};

VertexOutput MainVS(VertexInput input)


{
VertexOutput output;
output.pos = float4(input.pos, 1.0f);
float luminance = (input.color.r+input.color.g+input.color.b)/3.0;
output.color.r = luminance;
output.color.g = luminance;
output.color.b = luminance;
output.color.a = input.color.a;
return output;
}
float4 MainPS(float4 color:COLOR):COLOR
{
return color;
}
technique BlackAndWhiteFill
{
pass p0
{
VertexShader = compile vs_1_1 MainVS();
PixelShader = compile ps_1_1 MainPS();
}
}

:
vs_1_1
def c0, 0.333333343, 1, 0, 0
dcl_position v0
dcl_color v1
add r0.w, v1.y, v1.x
add r0.w, r0.w, v1.z
mul oD0.xyz, r0.w, c0.x
mad oPos, v0.xyzx, c0.yyyz, c0.zzzy
mov oD0.w, v1.w

Vertex Shader, .
4 c ,
Vertex Shader: vs_1_1, vs_2_0, vs_2_x vs_3_0.
, 1.1.
def, c0 (0.333333343, 1,
0, 0), .

.
dcl_position dcl_color ,
v0, v1.
.
w r0.
x c0, 0.333333343,
3. x, y, z
oD0. ,
HLSL:
output.color.rgb = (input.color.r+input.color.g+input.color.b)/3.0;

, HLSL luminance,
r, g, b .
.
. mad
. , HLSL- ? ? . madd
v0 c0,
oPos, .
, mad
c0:
oPos = v0.xyzx * c0.yyyz + c0.zzzy = v0.xyzx * (1, 1, 1, 0) + (0, 0, 0, 1) = (v0.xyz, 0) +
(0, 0, 0, 1)

, mad HLSL-:
output.pos = float4(input.pos, 1.0f);

, HLSL-:

mov oPos.xyz, v0.xyz
mov oPos.w, c0.y

mad.
, mov - oD0 , ..
output.color.a = input.color.a


5 , 5.2.4, GPU
NV4x G7x 7 . ,
. :
1. HLSL 3
. ,
HLSL dot.
2. , , - (alpha
blending). , -. , ,
- .
, .
, , 5.5:
5.5.
VertexOutput MainVS(VertexInput input)
{

VertexOutput output;
output.pos = float4(input.pos, 1.0f);
// - , ,
// a
output.color.rgba = dot(input.color.rgba, 1.0/3.0);
return output;
}

, FX Composer 2.0, :
// Generated by Microsoft (R) D3DX9 Shader Compiler 9.12.589.0000
vs_1_1
def c0, 0.333333343, 1, 0, 0
dcl_position v0
dcl_color v1
dp4 oD0, v1, c0.x
mad oPos, v0.xyzx, c0.yyyz, c0.zzzy
// approximately 2 instruction slots used

, dp4, mov
- . ,
2.5
( 5 2 ). ( Run
Shader Perfomance) ,
7 3- , 2.3 . GeForce 7800 GTX
1 491.000.000 ,
1.146.000.000 .

5.4.
, ,
, .
, [0..1] ,
. 1,
, 0 , 0..1
.
:
cr = kr or
cg = kg og
cb = kb ob

cr, cg, cb ;

or, og, ob ;

kr, kg, kb .

:
VertexOutput MainVS(VertexInput input)
{
VertexOutput output;
output.pos = float4(input.pos, 1.0f);
//
const float4 filter = float4(0.2, 0.8, 0.5, 1.0);
// ,
output.color = input.color * filter;

(5.4)

return output;
}

. ,
? ,
, filter .
: GPU ,
. ,
.
HLSL
. :
uniform, ,
. , filter,
:
uniform float4 circleColor;

,
. :
uniform float4 circleColor = float4(0.5, 1.0, 0.8, 1.0);

, uniform ,
uniform-. uniform
static, . :
// circleColor
static float4 circleColor=float4(0.5, 1.0, 0.8, 1.0);


static .
, C# :
.

static .
, .
, , .

( 5.6).
5.6.
//
float4 filter;
struct VertexInput
{
float3 pos : POSITION;
float4 color : COLOR;
};
struct VertexOutput
{
float4 pos : POSITION;
float4 color : COLOR;
};

VertexOutput MainVS(VertexInput input)


{
VertexOutput output;
output.pos = float4(input.pos, 1.0f);
output.color = input.color * filter;

return output;
}
float4 MainPS(float4 color:COLOR):COLOR
{
return color;
}
technique FilterFill
{
pass p0
{
VertexShader = compile vs_1_1 MainVS();
PixelShader = compile ps_1_1 MainPS();
}
}

NVIDIA FX Composer 2.0 ,


Shader Perfomance:
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//

Generated by Microsoft (R) D3DX9 Shader Compiler 9.12.589.0000


Parameters:
float4 filter;

Registers:
Name
Reg
Size
------------ ----- ---filter
c0
1

Default values:
filter
c0
= { 0, 0, 0, 0 };

vs_1_1
def c1, 1, 0, 0, 0
dcl_position v0
dcl_color v1
mul oD0, v1, c0
mad oPos, v0.xyzx, c1.xxxy, c1.yyyx
// approximately 2 instruction slots used

, float4
filter c0. ,
,
(0, 0, 0, 0).
, filter
c0, .

, , ,
. , , ,
, ,
.

5.4.1. XNA Framework


XNA Framework Parameters Effect:
public EffectParameterCollection Parameters { get; }

,
. ,
, :
public EffectParameter this[string name] { get; }


, null.

EffectParameter,
SetValue
GetValueXXX. GetValueXXX.
// HLSL float
public float GetValueSingle();
// float: , float[10].
// count
public float[] GetValueSingleArray(int count);
// , (float2)
public Vector2 GetValueVector2();
// , (float2[])
public Vector2[] GetValueVector2Array(int count);
// , (float3)
public Vector3 GetValueVector3();
// , (float3[])
public Vector3[] GetValueVector3Array(int count);
// , (float4)
public Vector4 GetValueVector4();
// , (float4[])
public Vector4[] GetValueVector4Array(int count);

, XNA Framework HLSL


GPU, -
. , rgba ,
.

(,

HLSL,

System.InvalidCastException.

SetValueXXX , GetValueXXX
SetValue . , float
GetValueSingle() public void SetValue(float value).
XNA Framework, 5.7 ,
, ,
( 5.18). ,
.

5.18. .

5.7.
public partial class MainForm : Form
{
// , 5.4 ( 5.6)
const string effectFileName = "Data\\FilterFill.fx";
...
Effect effect = null;
// , filter ( )
EffectParameter filterParam;
private void MainForm_Load(object sender, EventArgs e)
{
...
//
CompiledEffect compiledEffect;
compiledEffect = Effect.CompileEffectFromFile(effectFileName, null, null,
CompilerOptions.None, TargetPlatform.Windows);
...
//
effect = new Effect(device, compiledEffect.GetEffectCode(), CompilerOptions.NotCloneable,
null);
...
// EffectParameter, filter
filterParam = effect.Parameters["filter"];
// filter ,
Debug.Assert(filterParam != null, effectFileName + " : filter");
}
// ,
private void filterPanel_Click(object sender, EventArgs e)
{

if (colorDialog.ShowDialog() == DialogResult.OK)
{
//
filterPanel.BackColor = colorDialog.Color;
xnaPanel.Invalidate();
}
}

private void xnaPanel_Paint(object sender, PaintEventArgs e)


{
...
// . Windows Form
// 0..255, XNA Framework 0..1,
// 255
filterParam.SetValue(new Vector4((float)filterPanel.BackColor.R / 255.0f,
(float)filterPanel.BackColor.G / 255.0f, (float)filterPanel.BackColor.B / 255.0f,
1.0f));
//
effect.Begin();
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Begin();
device.DrawUserPrimitives(PrimitiveType.TriangleStrip, vertices, 0,
vertices.Length - 2);
pass.End();
}
effect.End();
device.Present();
...
}

XNA Framework
:
effect.Parameters["filter"].SetValue(newColor);

, , : -,
, -, ,
XNA Framework
.
Load filter,
EffectParameter.

EffectParameter
Debug.Assert null
, -
.

5.5.
, HLSL Vertex Shader 1.1.
- . ,
, .
4-
: ,
. ,
,
GPU.
, ,
HLSL Vertex Shader 1.1.

5.5.1.
, :
, (
5.8).

5.8.
// ,
float delta = (float)(currentTime - lastTime);
//
diskAngle += diskSpeed * delta;
//
diskVertices[0] = new VertexPositionColor(new Vector3(0.0f, 0.0f, 0.0f),
XnaGraphics.Color.LightGray);
for (int i = 0; i <= slices; i++)
{
float angle = (float)i / (float)slices * 2.0f * (float)Math.PI;
float x = diskRadius * (float)Math.Sin(diskAngle + angle);
float y = diskRadius * (float)Math.Cos(diskAngle + angle);
byte red = (byte)(255 * Math.Abs(Math.Sin(angle * 3)));
byte green = (byte)(255 * Math.Abs(Math.Cos(angle * 2)));
diskVertices[i + 1] = new VertexPositionColor(new Vector3(x, y, 0.0f),
new XnaGraphics.Color(red, green, 128));
};

, .
, , ,
, ,
. :
angle .
angle
.
,
.
,
. Vertex Shader 1.1 ,
,
.
,
5.4.
, .

. , ,
5.3.1 , (, ..)
v0, v1 v15,
, .
5.4. ,


5.8

diskAngle

angle

diskRadius

Angle

red/green


, ,
. , ,
. C#
DiskEffect, ( 5.9).
, - ,

81.
5.9.
//
static class DiskEffect
{
//
public static float angle;
//
//
input
//
output
public static void VertexShader(VertexPositionColor[] input, VertexPositionColor[]
output)
{
// ( ,
//
for (int i = 0; i < input.Length; i++)
{
// .
// angle Y
float a = input[i].Position.Y + angle;
// . X
output[i].Position.X = input[i].Position.X * (float)Math.Sin(a);
output[i].Position.Y = input[i].Position.X * (float)Math.Cos(a);
output[i].Position.Z = 0;
//
output[i].Color = input[i].Color;
}
}
}

,
Ch04\Ex01 ( ).
5.10.

81

DirectX SDK PIX for Windows,


. .

5.10.
public partial class MainForm : Form
{
// .
// . -
const string effectFileName = "Data\\ColorFill.fx";
//
const int slices = 64;
//
public const float diskSpeed = 3.0f;
//
public const float diskRadius = 0.018f;
GraphicsDevice device;
PresentationParameters presentParams;
VertexDeclaration diskDeclaration;
//
VertexPositionColor[] diskVertices = null;
// , .
//
VertexPositionColor[] transformedDiskVertices = null;
Effect diskEffect = null;
Stopwatch stopwatch;
bool closing = false;
private void MainForm_Load(object sender, EventArgs e)
{
...
//
device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware,
this.Handle, options, presentParams);
//
diskDeclaration = new VertexDeclaration(device,
VertexPositionColor.VertexElements);
//
diskVertices = new VertexPositionColor[slices + 2];
// , (
// )
transformedDiskVertices = new VertexPositionColor[slices + 2];
// (,
// )
diskVertices[0] = new VertexPositionColor(new Vector3(0.0f, 0.0f, 0.0f),
XnaGraphics.Color.LightGray);
for (int i = 0; i <= slices; i++)
{
float angle = (float)i / (float)slices * 2.0f * (float)Math.PI;
byte red = (byte)(255 * Math.Abs(Math.Sin(angle * 3)));
byte green = (byte)(255 * Math.Abs(Math.Cos(angle * 2)));
//
diskVertices[i + 1] = new VertexPositionColor(new Vector3(diskRadius, angle,
0.0f), new XnaGraphics.Color(red, green, 128));
};

...
//
diskEffect = new Effect(device, compiledEffect.GetEffectCode(),
CompilerOptions.NotCloneable, null);
//
stopwatch = new Stopwatch();
stopwatch.Start();
}
private void MainForm_Paint(object sender, PaintEventArgs e)
{
...
//
float time = (float)stopwatch.ElapsedTicks / (float)Stopwatch.Frequency;
DiskEffect.angle = diskSpeed * time;
//
DiskEffect.VertexShader(diskVertices, transformedDiskVertices);
//
device.VertexDeclaration = diskDeclaration;
//
diskEffect.Begin();
for (int i = 0; i < diskEffect.CurrentTechnique.Passes.Count; i++)
{
EffectPass currentPass = diskEffect.CurrentTechnique.Passes[i];
currentPass.Begin();
//
device.DrawUserPrimitives(PrimitiveType.TriangleFan, transformedDiskVertices,
0, diskVertices.Length - 2);
currentPass.End();
}
diskEffect.End();
device.Present();
}
...
}

CD- Exampes\Ch05\Ex05.



HLSL. 5.9, .
HLSL
( 5.11).
5.11.
// Disk.fx
float angle;
struct VertexInput
{
float3 pos : POSITION;
float4 color : COLOR;
};

struct VertexOutput
{
float4 pos : POSITION;
float4 color : COLOR;
};

VertexOutput MainVS(VertexInput input)


{
VertexOutput output;
float a = input.pos.y + angle;
output.pos.xy = input.pos.xx * float2(sin(a), cos(a));
output.pos.zw = float2(0.0, 1.0);
output.color = input.color;
return output;
}
float4 MainPS(float4 color:COLOR):COLOR
{
return color;
}
technique Disk
{
pass p0
{
VertexShader = compile vs_1_1 MainVS();
PixelShader = compile ps_1_1 MainPS();
}
}

,
: DiskEffect
, (transformedDiskVertices).
angle.
5.12.
5.12.
public partial class MainForm : Form
{
//
const string effectFileName = "Data\\Disk.fx";
Effect diskEffect = null;
// EffectParameter, angle
EffectParameter angleParam = null;
private void MainForm_Load(object sender, EventArgs e)
{
...
// EffectParameter, angle
angleParam = diskEffect.Parameters["angle"];
Debug.Assert(angleParam != null, effectFileName + " : angle");
}
private void MainForm_Paint(object sender, PaintEventArgs e)

{
...
float time = (float)stopwatch.ElapsedTicks / (float)Stopwatch.Frequency;
// angle
angleParam.SetValue(diskSpeed * time);
//
device.VertexDeclaration = diskDeclaration;
diskEffect.Begin();
for (int i = 0; i < diskEffect.CurrentTechnique.Passes.Count; i++)
{
EffectPass currentPass = diskEffect.CurrentTechnique.Passes[i];
currentPass.Begin();
device.DrawUserPrimitives(PrimitiveType.TriangleFan, diskVertices, 0,
diskVertices.Length - 2);
currentPass.End();
}
diskEffect.End();
device.Present();
...
}
}

, Paint
.
- C#-.


,
82:
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//

Generated by Microsoft (R) D3DX9 Shader Compiler 9.12.589.0000


Parameters:
float angle;

Registers:
Name
Reg
Size
------------ ----- ---angle
c0
1

Default values:
angle
c0

= { 0, 0, 0, 0 };

vs_1_1
def c1, 0.159154937, 0.25, 0.5, -0.00138883968
def c2, 6.28318548, -3.14159274, -2.52398507e-007, 2.47609005e-005

82

, .

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.

def c3, 0.0416666418, -0.5, 1, 0


dcl_position v0
dcl_color v1
add r0.w, v0.y, c0.x
mad r1.xy, r0.w, c1.x, c1.yzzw
frc r0.xy, r1
mad r0.xy, r0, c2.x, c2.y
mul r0.xy, r0, r0
mad r1.xy, r0, c2.z, c2.w
mad r1.xy, r0, r1, c1.w
mad r1.xy, r0, r1, c3.x
mad r1.xy, r0, r1, c3.y
mad r0.xy, r0, r1, c3.z
mul oPos.xy, r0, v0.x
mov oPos.zw, c3.xywz
mov oD0, v1

// approximately 15 instruction slots used

? angle c0, c1, c2 c3 -


, 13
, 15
. - frc,
.
,
, , .

,
, Vertex Shader 1.1 128
.

a = input.pos.y + angle
w r0.
, . ,
- sin cos
( Vertex Shader 1.1 ). ,
,
:
r1.x = a 0.159154937 + 0.25
r1.y = a 0.159154937 + 0.5

0.159154937 , ,
:

1. =
+ 0.25
2

1. =
+ 0.5
2
r0:

0. =
+ 0.25
2

0. =
+ 0.5
2
r0 :

0. =
+ 0.25 6.28318548 3.14159274
2

0. =
+ 0.5 6.28318548 3.14159274
2
, 3.14159274 , 6.28318548 :


+ 0.25
2

0. = 2
+ 0.5
2
,
r0.y MathCad , 83:
0. = 2

a, r0.y [-, +)
cos(a) = cos(r0.y)
, , a [-,
+), . ? ,
,
.
cos(a) . , ,
, ,
.
C x r0 :
r0.x [-, +)
sin(a) = cos(r0.x)

, 2-4 sin = cos


( ) .
2
, HLSL ,
, .
, , , [-, +)
:

= 0. = 2
+ 0.25
2

= 0. = 2
+ 0.5
2
r0 ,
r1:
1. = 2.52398507 107 2 + 2.47609005 105
1. = 2.52398507 107 2 + 2.47609005 105
r1 ax2 -0.00138883968:
1. = 2.52398507 107 2 + 2.47609005 105 2 0.00138883968
1. = 2.52398507 107 2 + 2.47609005 105 2 0.00138883968
ax2
. r0
84:
0. =

2.523 107 2 + 2.476 105 2 0.001388 2 + 0.0416 2 0.5 2 + 1

0. =

2.523 107 2 + 2.476 105 2 0.001388 2 + 0.0416 2 0.5 2 + 1

ax ay
:
0. = 1 0.5 2 + 0.0416 4 0.001388 6 + 2.476 105 8 2.523 107 10
0. = 1 0.5 2 + 0.0416 4 0.001388 6 + 2.476 105 8 2.523 107 10
? , cos(x)
:
2 4 6 8 10
2
+ +
+ + (1)
2! 4! 6! 8! 10!
2 !
, . ,
y r0 , x
( sin(a) = cos(ax), cos(a) = cos(ay)).
cos = 1

83
84


, .

HLSL
.

cos(x)
cos
MathCad,
cos ( 5.19). ,
, 210-3.
, cos,
cos(x)=-cos(x).

5.19. Mathcad.

.
x y oPos.
z w 0 1. , ,
v1.
5.20 ,
HLSL . ,
,
.
. ,
,
R3xx R4xx 1-4

( , , ).

.

5.20. Vertex Shader 1.1 HLSL.

,
Vertex Shader 1.1. R2xx
,
Vertex Shader 1.1,
frc, . : R4xx
.. +,
.
, , Vertex
Shader 1.1 (
add mul dp4),
.
, FX Composer 2.0
Vertex Shader 1.1,
, . GeForce
7800 GTX 20 ,
172.000.000 .
,
, .
,
. ,
,
.

5.1
, ,
sin cos. , ,
, .
, ,
.

G8x R6xx ,
, . ,
, ,
.

.

. sin cos ,
. :
float a = input.pos.y + angle;

input.pos.y , angle
, . , sin(input.pos.y)
cos(input.pos.y) Load
, sin(angle) cos(angle)
. ,
,
:
sin(+)=sin()cos()+cos()sin()

(5.5)

cos(+)=cos()cos()-sin()sin()
: Ch05\Ex06,
5.5,
. NVIDIA FX Composer 2.0,
(, , ).

, 5.5
:
. ,
sin(angle).
HLSL, sin(angle), cos(angle), -sin(angle)
.

,
, \Examples\Ch05\Ex07.

5.5.2. if HLSL

, ,
if HLSL vs_1_1.
HLSL if:
if ( )
{
1
}
else
{
2
}

, , : Vertex Shader
1.1 ( , ..).
. C# if,
if,
85. HLSL
vs_1_1 , ,
. , HLSL
if .
,
if. , ,
,
( 5.13).
5.13.
85

,
, if
[.12].

// Examples\Ch05\Ex08
VertexOutput MainVS(VertexInput input)
{
VertexOutput output;
if (input.pos.x != 0)
{
// ,
float a = input.pos.y + angle;
output.pos.xy = input.pos.xx * float2(sin(a), cos(a));
}
else
// , (0.0, 0.0)
output.pos.xy = float2(0.0, 0.0);
output.pos.zw = float2(0.0, 1.0);
output.color = input.color;
return output;
}

FX Composer :
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//

Generated by Microsoft (R) D3DX9 Shader Compiler 9.12.589.0000


Parameters:
float angle;

Registers:
Name
Reg
Size
------------ ----- ---angle
c0
1

Default values:
angle
c0

= { 0, 0, 0, 0 };

vs_1_1
def c1, 0.159154937, 0.25, 0.5, -0.00138883968
def c2, 6.28318548, -3.14159274, -2.52398507e-007, 2.47609005e-005
def c3, 0.0416666418, -0.5, 1, 0
dcl_position v0
dcl_color v1
1. add r0.w, v0.y, c0.x
2. mad r1.xy, r0.w, c1.x, c1.yzzw
3. frc r0.xy, r1
4. mad r0.xy, r0, c2.x, c2.y
5. mul r0.xy, r0, r0
6. mad r1.xy, r0, c2.z, c2.w
7. mad r1.xy, r0, r1, c1.w
8. mad r1.xy, r0, r1, c3.x
9. mad r1.xy, r0, r1, c3.y
10. mad r0.xy, r0, r1, c3.z

11.
12.
13.
14.
15.
16.

mul
mul
slt
mul
mov
mov

r0.w, v0.x, v0.x


r0.xy, r0, v0.x
r0.w, -r0.w, r0.w
oPos.xy, r0, r0.w
oPos.zw, c3.xywz
oD0, v1

// approximately 18 instruction slots used

, 13 16, 15
18, 20 21 . , 3
. :
G7x VLIW-86 87:
(ADD, MUL, MADD ..) (RCP, SIN, COS
..). ,
G7x .
, NVIDIA
. , ,
G7x. ,
,
.
. 10
float a = input.pos.y + angle
. r0.x
sin(a), r0.y cos(a).
input.pos.x .

input.pos.x ,
input.pos.xx * float2(sin(a), cos(a)).
-input.pos.xinput.pos.x +input.pos.xinput.pos.x :
if (-input.pos.x* input.pos.x < input.pos.x* input.pos.x)
r0.w=1
else
r0.w=0

, r0.w 1, input.pos.x 0, 0
. , ,
r0.w = (input.pos.x!=0)

: Vertex Shader 1.1


, HLSL 0
mul slt.

Vertex Shader 1.1 ,
. , Vertex Shader 1.1
, :
.
- :
half/float/double
,
. ,

.
C#:
// Examples\Ch05\Ex09
class Program
86

Very Long Instruction Word (VLIW) ,


,
. VLIW- Intel Itanium
87
,
Vertex Shader 1.1 .

{
static void Main(string[] args)
{
float a = 1.2f;
float b = 1.4f;
float c = 1.68f;
float mul = a * b;
float delta = c - mul;
Console.WriteLine("a = "
Console.WriteLine("b = "
Console.WriteLine("c = "
Console.WriteLine("sum =
Console.WriteLine("delta
Console.ReadKey();

+
+
+
"
=

(double)a);
(double)b);
(double)c);
+ (double)mul);
" + (double)delta);

}
}

:
a = 1,20000004768372
b = 1,39999997615814
c = 1,67999994754791
sum = 1,6800000667572
delta = -1,19209289550781E-07

, 1.2 1.4 ,
1.68 1.21.4 , -1.1910-7. ,
1.681.21.4.
,
, ( ) .
,
88. a b 10,
1214 168:
a = 12
b = 14
c = 168
sum = 168
delta = 0


, G8x, ,
. ,
mul/slt .

x y
input.pos.x 0: input.pos.x!=0, , input.pos.x==0,
. ,
if (input.pos.x != 0)
{
...
}
else
output.pos.xy = float2(0.0, 0.0);

mul / slt / mul.


. HLSL if
, ,
( G7x ).

88

, .

5.5.3.

. .
timeStep.
, maxScintillaCount.
, .
StartTime,
: ,
.
. ,
, ,
.
, 89,

, .. ..
,
:
,
.
.
.
,
.
, , , ..,
( 5.21). ,
,
, , -
.

5.21. .

,
, ,
, .
90. ,
, :
currentTime = time vertexStartTime;
localTime = currentTime % timeLoop;

time , .

vertexStartTime , .

, .

% .

timeLoop , , .

89

()
. ,
.
90
, ,
, .

localTime .

5.22 currentTime time, Mathcad. ,


,
. time ,
timeLoop, .

5.22. .

, .
,

.
delta:
// .
//
tSpeed = Math.Max(tSpeed - tSlowing * delta, 0.0f);
//
rSpeed = Math.Max(rSpeed - rSlowing * delta, 0.0f);
//
distance += tSpeed * delta;
//
angle += rSpeed * delta;

,
,

, .
.
= 0

tSpeed ;

tSpeed0 ;

tSlowing ;

t (localtime).

, , (0
) , , . ,
=

(0 ) = 0

2
+
2

, t=0
0 :
02
+ =
2
, C
:
0 = 0 0

= 0 + 0

(5.6)

5.6 ,
0 ,
.
,
0:
= min(localtime,

= 0 + 0

(5.7)

2

, ,
.

, :
0
= min
(localtime,
)
(5.8)

= + 0 + 0

2
2

0 ( );

0 ( );

, ,
. :
, .
,
(.. ).

,
. ,
, C#. ,
, .


, , ,
. ,
( 5.5). ,
, .
,
91.
, , , HLSL
v0, v1 v15. , ,
5.14.
5.5. ,

time

time

timeLoop

timeLoop

diskSpeed

diskSpeed

vertexStartTime

distance0

angle0

tSpeed

rSpeed

5.14.
static class FireworkEffect
{
// .
const float tSlowing = 0.105f;
const float rSlowing = 0.25f;
//
const float liveTime = 4.0f;
//
public
public
public

time, timeLoop, diskSpeed


static float time;
static float timeLoop;
static float diskSpeed;

// .
91

//
//

//
//
//
//

//
//
//

input ,
output
public static void VertexShader(VertexPositionColorTexture[][] input,
VertexPositionColor[][] output)
{
( ).
,
GPU Intel GMA9xx,

for (int j = 0; j < input.Length; j++)


{
for (int i = 0; i < input[j].Length; i++)
{
,
float currentTime = time - input[j][i].Position.X;
, 0 timeLoop
float localTime = currentTime % timeLoop;
,
float remainTime = liveTime - localTime;

// ,
//
float td = Math.Min(localTime, input[j][i].TextureCoordinate.X / tSlowing);
//
float distance = input[j][i].Position.Y + td *
(input[j][i].TextureCoordinate.X - td * tSlowing / 2.0f);
// ,
//
float tr = Math.Min(localTime, input[j][i].TextureCoordinate.Y / rSlowing);
//
float angle = input[j][i].Position.Z + diskSpeed * (time - localTime) +
tr * (input[j][i].TextureCoordinate.Y - tr * rSlowing / 2.0f);
//
output[j][i].Position.X = distance * (float)Math.Sin(angle);
output[j][i].Position.Y = distance * (float)Math.Cos(angle);
output[j][i].Position.Z = 0.0f;
// ,
if ((currentTime >= 0) && (remainTime > 0))
{
Vector4 color = input[j][i].Color.ToVector4();
//
color.W = remainTime / liveTime;
output[j][i].Color = new XnaGraphics.Color(color);
}
else
{
output[j][i].Color = new XnaGraphics.Color(0, 0, 0, 0);
}
}
}
}
}

.
VertexPositionColorTexture, Position
Color TextureCoordinate, X Y .
5.7 5.8 ,

. ,
mad . if, ,
.

, HSLS sin cos .

Load,
( 5.15).
5.15.
public partial class MainForm : Form
{
//
const string effectFileName = "Data\\ColorFill.fx";
const int slices = 64;
const float diskSpeed = 3.0f;
const float diskRadius = 0.018f;
//
const int fireworkVerticesCount = 300000;
// 20
const float timeLoop = 20.0f;
//
const float minSpeed = 0.3f;
//
const float maxSpeed = 0.45f;
//
const float pointSize = 1.0f;
// .
//
VertexDeclaration decl;
//
VertexPositionColorTexture[][] fireworkVertices = null;
// ,
VertexPositionColor[][] transformedFireworkVertices = null;
// , ( )
Effect effect = null;
Random rnd = new Random();
Stopwatch stopwatch;
bool closing = false;
// FPS
// ,
float lastTime = 0;
// ,
int frameCount = 0;
private void MainForm_Load(object sender, EventArgs e)
{
// ,
int maxVerticesCount = Math.Min(device.GraphicsDeviceCapabilities.MaxVertexIndex,
device.GraphicsDeviceCapabilities.MaxPrimitiveCount);
// ,

// fireworkVerticesCount
int arrayCount = (int)Math.Ceiling((float)fireworkVerticesCount /
(float)maxVerticesCount);
//
fireworkVertices = new VertexPositionColorTexture[arrayCount][];
// ,
transformedFireworkVertices = new VertexPositionColor[arrayCount][];
//
for (int k = 0; k < fireworkVerticesCount; k++)
{
// ,
int j = k / maxVerticesCount;
//
int i = k % maxVerticesCount;
//
if (i == 0)
{
//
int remain = fireworkVerticesCount - j * maxVerticesCount;
// maxVerticesCount
remain = Math.Min(remain, maxVerticesCount);
//
fireworkVertices[j] = new VertexPositionColorTexture[remain];
transformedFireworkVertices[j] = new VertexPositionColor[remain];
}
//
fireworkVertices[j][i].Position.X = (float)rnd.NextDouble() * timeLoop;
//
fireworkVertices[j][i].Position.Y = (float)rnd.NextDouble() * diskRadius;
//
fireworkVertices[j][i].Position.Z = (float)rnd.NextDouble() * 2.0f *
(float)Math.PI;
//
fireworkVertices[j][i].TextureCoordinate.X = minSpeed + (float)rnd.NextDouble() *
(maxSpeed - minSpeed);
//
fireworkVertices[j][i].TextureCoordinate.Y = diskSpeed / 4.0f * (1.0f +
0.01f * (float)rnd.NextDouble());
//
byte red = (byte)(255 * Math.Abs(Math.Sin(fireworkVertices[j][i].Position.Z *
3)));
byte green = (byte)(255 * Math.Abs(Math.Cos(fireworkVertices[j][i].Position.Z *
2)));
fireworkVertices[j][i].Color = new XnaGraphics.Color(red, green, 128, 255);
}
}
}

CPU GPU,
300.000 . (, Intel GMA 9xx)
92,
, . , -

92

. 2.4.3.

,
.
, ,
( 5.16).
5.16.
private void MainForm_Paint(object sender, PaintEventArgs e)
{
// GPU
device.RenderState.CullMode = CullMode.None;
device.RenderState.AlphaBlendEnable = true;
device.RenderState.BlendFunction = BlendFunction.Add;
device.RenderState.SourceBlend = Blend.SourceAlpha;
device.RenderState.DestinationBlend = Blend.InverseSourceAlpha;
device.RenderState.PointSize = pointSize;
device.VertexDeclaration = decl;
// ,
float time = (float)stopwatch.ElapsedTicks / (float)Stopwatch.Frequency;
// ,
FireworkEffect.time = time;
FireworkEffect.timeLoop = timeLoop;
FireworkEffect.diskSpeed = diskSpeed;
//
FireworkEffect.VertexShader(fireworkVertices, transformedFireworkVertices);
effect.Begin();
for (int i = 0; i < effect.CurrentTechnique.Passes.Count; i++)
{
EffectPass currentPass = effect.CurrentTechnique.Passes[i];
currentPass.Begin();
//
for (int j = 0; j < transformedFireworkVertices.Length; j++)
{
//
device.DrawUserPrimitives(PrimitiveType.PointList,
transformedFireworkVertices[j], 0, transformedFireworkVertices[j].Length);
}
currentPass.End();
}
effect.End();
// -,
device.RenderState.AlphaBlendEnable = false;
float angle = diskSpeed * time;
//
DiskEffect.angle = angle;
DiskEffect.VertexShader(diskVertices, transformedDiskVertices);
//
...
//
device.Present();

//
frameCount++;
//
if (time - lastTime >= 1)
{
// FPS
Text = ((float)frameCount / (time - lastTime)).ToString();
//
lastTime = time;
frameCount = 0;
}
}

CD \Examples\Ch05\Ex10.
NVIDIA GeForce 7600GT Intel GMA 9xx 5.6.
,
,
. , 10 ,
. ,
, -
.
5.6. Ch05\Ex10 GPU

FPS

Intel Core2 Duo E6300, i945P, 2GB RAM, DDR2-667,


GeForce 7600GT 256MB, Windows Vista Ultimate x64,
ForceWare 158.24

10.7

Intel Pentium-4 3.4GHz, i915P, 512MB RAM, ATI Radeon


x700 Pro, Windows XP Pro SP2, ASUS Driver 8.05

6.3

Intel Core2 Duo E4300, i946GZ (GMA 3000), 2GB RAM


DDR2-667, Windows Vista Ultimate x64, GMA Driver
7.14.10.1283

9.9



PresentationParameters.PresentationInterval

PresentInterval.Immediate,
.


,
. :
. , ,
.
, .
. ,
, Helper (
5.17).
5.17.
class Helper
{
...
// ,

public class LoadAndCompileEffectException : Exception


{
public LoadAndCompileEffectException(string message) : base(message) { }
}
// .
// LoadEffectException.
public static Effect LoadAndCompileEffect(GraphicsDevice device, string filename)
{
CompiledEffect compiledEffect;
try
{
compiledEffect = Effect.CompileEffectFromFile(filename, null, null,
CompilerOptions.None,
TargetPlatform.Windows);
}
catch (IOException ex)
{
throw new LoadAndCompileEffectException(ex.Message);
}
if (!compiledEffect.Success)
{
throw new LoadAndCompileEffectException(String.Format("
: \r\n{0}",
compiledEffect.ErrorsAndWarnings));
}
Effect effect = new Effect(device, compiledEffect.GetEffectCode(),
CompilerOptions.NotCloneable, null);
if (!effect.CurrentTechnique.Validate())
{
throw new LoadAndCompileEffectException(String.Format(" " +
\"{0}\" \"{1}\"\n\r , " +
GPU", effect.CurrentTechnique.Name, filename));
}
return effect;
}
}


- , C#
HLSL, - ( 5.18).
, C#- HLSL -, HLSL
,
. , ,
.
5.18.
// Firework.fx
//
// tSlowing rSlowing ,
//
static float2 slowing = {0.105, 0.25};
static float liveTime = 4.0;
float diskSpeed;
float time;

float timeLoop;
struct VertexInput
{
float3 pos : POSITION;
float4 color : COLOR;
float2 texcoord : TEXCOORD;
};
struct VertexOutput
{
float4 pos : POSITION;
float4 color : COLOR;
};

VertexOutput MainVS(VertexInput input)


{
VertexOutput output;
float currentTime = time - input.pos.x;
float localTime = currentTime % timeLoop;
float remainTime = liveTime - localTime;
//
float2 t = min(localTime.xx, input.texcoord / slowing);
float2 sCoord = input.pos.yz + t * (input.texcoord t * slowing / 2.0f);
//
//
sCoord.y += diskSpeed * (time - localTime);
// sin cos (sin, cos)
output.pos.xy = sCoord.x * float2(sin(sCoord.y), cos(sCoord.y));
output.pos.zw = float2(0.0, 1.0);
output.color.rgb = input.color.rgb;
if ((remainTime > 0) && (currentTime >= 0))
{
output.color.a = remainTime / liveTime;
}
else
{
output.color.a = 0;
}
return output;
}
float4 MainPS(float4 color:COLOR):COLOR
{
return color;
}
technique Firework
{
pass p0

{
VertexShader = compile vs_1_1 MainVS();
PixelShader = compile ps_1_1 MainPS();
}
}

( 5.19).
5.19.
public partial class MainForm : Form
{
//
const string diskEffectFileName = "Data\\Disk.fx";
//
const string fireworkEffectFileName = "Data\\Firework.fx";
//
Effect diskEffect = null;
// , angle
EffectParameter angleParam = null;
//
Effect fireworkEffect = null;
// , : diskSpeed, time, timeLoopParam
EffectParameter diskSpeedParam = null;
EffectParameter timeParam = null;
EffectParameter timeLoopParam = null;

private void MainForm_Load(object sender, EventArgs e)


{
...
// ,
//
fireworkDeclaration = new VertexDeclaration(device,
VertexPositionColorTexture.VertexElements);
try
{
//
diskEffect = Helper.LoadAndCompileEffect(device, diskEffectFileName);
fireworkEffect = Helper.LoadAndCompileEffect(device, fireworkEffectFileName);
}
catch (Helper.LoadAndCompileEffectException ex)
{
//
closing = true;
MessageBox.Show(ex.Message, " ", MessageBoxButtons.OK,
MessageBoxIcon.Error);
Application.Idle += new EventHandler(Application_Idle);
return;
}
// , angle
angleParam = diskEffect.Parameters["angle"];
Debug.Assert(angleParam != null, diskEffectFileName + " : angle");
// , diskSpeed
diskSpeedParam = fireworkEffect.Parameters["diskSpeed"];

Debug.Assert(diskSpeedParam != null, fireworkEffectFileName + " :


diskSpeed");
// , time
timeParam = fireworkEffect.Parameters["time"];
Debug.Assert(timeParam != null, fireworkEffectFileName + " :
time");
// , timeLoop
timeLoopParam = fireworkEffect.Parameters["timeLoop"];
Debug.Assert(timeLoopParam != null, fireworkEffectFileName + " :
timeLoop");
}
private void MainForm_Paint(object sender, PaintEventArgs e)
{
...
float time = (float)stopwatch.ElapsedTicks / (float)Stopwatch.Frequency;
//
timeParam.SetValue(time);
timeLoopParam.SetValue(timeLoop);
diskSpeedParam.SetValue(diskSpeed);
//
//
//
//
//

. !
,
. ,
,
.
device.VertexDeclaration = fireworkDeclaration;

//
fireworkEffect.Begin();
for (int i = 0; i < fireworkEffect.CurrentTechnique.Passes.Count; i++)
{
EffectPass currentPass = fireworkEffect.CurrentTechnique.Passes[i];
currentPass.Begin();
for (int j = 0; j < fireworkVertices.Length; j++)
{
device.DrawUserPrimitives(PrimitiveType.PointList, fireworkVertices[j],
0, fireworkVertices[j].Length);
}
currentPass.End();
}
fireworkEffect.End();

//
device.RenderState.AlphaBlendEnable = false;
angleParam.SetValue(diskSpeed * time);
//
device.VertexDeclaration = diskDeclaration;
//
...
// FPS

...
}
}

CD Examples\Ch05\Ex11.


Vertex Shader 1.1,
. NVIDIA FX Composer
2.0 , ,
.
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//

Generated by Microsoft (R) D3DX9 Shader Compiler 9.12.589.0000


Parameters:
float diskSpeed;
float time;
float timeLoop;

Registers:
Name
-----------diskSpeed
time
timeLoop

Reg
Size
----- ---c0
1
c1
1
c2
1

Default values:
diskSpeed
c0
= { 0, 0, 0, 0 };
time
c1

= { 0, 0, 0, 0 };

timeLoop
c2
= { 0, 0, 0, 0 };

vs_1_1
def c3, 0.0416666418, -0.5, 1, 0
def c4, 4, 9.52380943, 0.104999997, 0.25
def c5, 0.5, 0.159154937, 0.25, -0.00138883968
def c6, 6.28318548, -3.14159274, -2.52398507e-007, 2.47609005e-005
dcl_position v0
dcl_color v1
dcl_texcoord v2
// float currentTime = time - input.pos.x;
1. add r2.w, -v0.x, c1.x
// float localTime = currentTime % timeLoop
2. mul r0.w, r2.w, c2.x
3. add r1.w, c2.x, c2.x
4. sge r0.w, r0.w, -r0.w
5. mad r0.w, r0.w, r1.w, -c2.x
6. rcp r1.w, r0.w
7. mul r3.w, r2.w, r1.w

8.
9.

expp r4.y, r3.w


mov r1.w, r4.y

// input.texcoord / slowing
// float2 t = min(localTime.xx, input.texcoord / slowing).
//
10. mul r0.xy, v2, c4.yxzw
// float localTime = currentTime % timeLoop
11. mul r3.w, r0.w, r1.w
// float2 t = min(localTime.xx, input.texcoord / slowing)
12. min r0.xy, r0, r3.w
// float2 sCoord =
13. mul r1.xy, r0,
14. mad r1.xy, r1,
15. mad r0.xy, r0,

input.pos.yz + t * (input.texcoord
c4.zwzw
-c5.x, v2
r1, v0.yzzw

- t * slowing / 2.0f)

// sCoord.y += diskSpeed * (time - localTime)


16. mad r3.w, r0.w, -r1.w, c1.x
17. mad r3.w, c0.x, r3.w, r0.y
// output.pos.xy = sCoord.x * float2(sin(sCoord.y), cos(sCoord.y))
18. mad r2.xy, r3.w, c5.y, c5.zxzw
19. frc r1.xy, r2
20. mad r1.xy, r1, c6.x, c6.y
21. mul r1.xy, r1, r1
22. mad r2.xy, r1, c6.z, c6.w
23. mad r2.xy, r1, r2, c5.w
// (currentTime >= 0) if
24. sge r2.w, r2.w, c3.w
// output.pos.xy = sCoord.x * float2(sin(sCoord.y), cos(sCoord.y))
25. mad r2.xy, r1, r2, c3.x
// float remainTime = liveTime - localTime
26. mad r1.w, r0.w, -r1.w, c4.x
// output.pos.xy = sCoord.x * float2(sin(sCoord.y), cos(sCoord.y))
27. mad r2.xy, r1, r2, c3.y
28. mad r1.xy, r1, r2, c3.z
// if: (remainTime > 0)
29. slt r0.w, c3.w, r1.w
// output.color.a = remainTime / liveTime
30. mul r1.w, r1.w, c4.w
// if:
// ((remainTime > 0) && (currentTime >= 0))
31. mul r0.w, r2.w, r0.w
//
// output.pos.xy = sCoord.x * float2(sin(sCoord.y), cos(sCoord.y))
// ( sCoord.x)
32. mul oPos.xy, r0.x, r1

// if. if true,
// , .
33. mul oD0.w, r1.w, r0.w
// output.pos.zw = float2(0.0, 1.0);
34. mov oPos.zw, c3.xywz
// output.color.rgb = input.color.rgb
35. mov oD0.xyz, v1
// approximately 37 instruction slots used

HLSL .
currentTime % timeLoop 8 ( 2- 9-).
, Vertex Shader 1.1 ,
.
C#:
// C#, a%b. ,
// HLSL
static float mod(float a, float b)
{
// (a/b) , (nb=-b)
float cmp;
if (a*b > -a*b)
cmp = 1;
else
cmp = 0;
float nb = cmp * (b + b) - b;
//
float div = a * (1.0f / nb);
//
float frac = div - (float)Math.Floor(div);
//
float result = frac * nb;
return result;
}

,
frc. ,
, frc. ,
, expp, 2n.
2n, , y
- (a floor(a)).
, , , % HLSL
, .
,
HLSL , .
: HLSL
, float remainTime = liveTime localTime,
, .
if,
Vertex Shader 1.1
, && .


, , float2 sCoord = input.pos.yz + t * (input.texcoord t
* slowing / 2.0f) ,

slowing / 2.0f, mul.


, HLSL ,
. , Vertex Shader 1.1
, .
, .
5.20.
5.20.
// CD Examples\Ch05\Ex12
static float2 slowing = {0.105, 0.25};
//
static float2 slowing2 = slowing / 2.0f;
...
VertexOutput MainVS(VertexInput input)
{
...
float2 sCoord = input.pos.yz + t * (input.texcoord
t * slowing2);
...
}

:
( 37 36),
5 ( 42 37)
.
NVIDIA GeForce 7800 GTX 76.000.000 86.000.000
, .. 13%.
,
,
HLSL- , .

5.5.4.
. 5.23
, Excel Ch05\Ex10
Ch05\Ex12 GPU.
90
80
70
60
50
Ex10 (CPU)
40

Ex12 (GPU)

30
20
10
0
GeForce7600GT

Radeon X700 Pro

i946GZ (GMA 3000)

5.23. Ch05\Ex10 Ch05\Ex12 GPU.

, GeForce 7600GT Radeon X700 Pro CPU GPU


10 . GPU i946GZ (GMA 3000)
( 3.5 ), : i946GZ
93, -
.
. , .NET

. ,
, . ,
Pentium-III SSE
, Vertex Shader.
C# IL ,
JIT- IL- exe- . ,
SSE-
.
. i946GZ GPU
DirectX
Processor Specific Geometry Pipeline (PSGP). PSGP
CPU,
100%. SSE,
CPU - .
C#, .
, .
, C# HLSL-,
.
, .
, ,
.

HLSL
: , ,
, if.
IDE NVIDIA FX Composer 2.0, ,
, . ,
, ,
.
, HLSL, Vertex Shader.
Vertex Shader 1.1 .

93

, Intel 946GZ GPU Intel GMA 3000,


. (7.14.10.1283)
, Intel 946GZ
CPU.


, . , ,
. email: gsaf@sura.ru.
, XNA. ,
, , 3D ,
XNA. ,
.
Internet-,
XNA :
http://xna.com/ XNA.
http://creators.xna.com/ , , XNA.

http://msdn2.microsoft.com/en-us/xna/default.aspx XNA MSDN.


http://forums.microsoft.com/msdn/ - , XNA.
http://abi.exdream.com/ - Benjamin Nitschke, Professional XNA Game
Programming Starter Kit-.
http://www.xnadev.ru/ , XNA.