Tuesday, March 31, 2009

More GDC 2009 Links

Early release of some technical slides

Jon Peddie decks, including
GDC 2009 ( State of Visual Computing )
SIGGRAPH 2008 ( Directions for Ray Tracing )

Intel Content, except for Mike Abrash and Tom Forsyth ( should be RSN )

Early copy of Tom Forsyth's talk, with extra commentary ( needs translation )

Project Offset trailers, including the editor prefab and meteor trailers from GDC 2009

Mike and Toms' talks are now available here

Update 2:
Mikes DDJ paper is here

Maze Sample : Article 6 - D3D10Maze-Camera

Our next article is about improving the camera support in the Maze sample.

The main problem is I like features of both camera types in DXUT. I want to combine the behavior of CModelViewerCamera and CMazeFirstPersonCamera. The behavior of CMazeFirstPersonCamera is to enable standard keyboard control of the camera, while the behavior of CModelViewerCamera is to enable mouse rotation and mouse wheel control.

I want both. The least destructive way to do this is to add a new subclass of the DXUT classes, and mingle the code there without changing DXUT.

The Camera Project

Here is a screenshot of the updated project, with the added CMaze-Camera source/header file pair added

Solution Window

We’ll cover the changes in 3 sections: New Camera Class, Callback Changes, and Conclusion.

New Camera Class

Updating the camera controls amounts to merging the FrameMove method. I will perform a little information hiding and make integrating the camera a bit easier, but the basic idea is to take what both do and merge it.

With that in mind, I will start with the CFirstPersonCamera class and make a subclass:

class CMazeFirstPersonCamera : public CFirstPersonCamera
D3DXMATRIX mCameraRot;
D3DXMATRIX mCameraTrans;
void SetYaw(float fYaw) { m_fCameraYawAngle = fYaw; }
void SetEye(D3DXVECTOR3 vEye ) { m_vEye = vEye; }
void InternalFrameMove(FLOAT fElapsedTime);
virtual void FrameMove(FLOAT fElapsedTime);
D3DXMATRIX Render10(ID3D10Device* pd3dDevice);
D3DXMATRIX Render9(IDirect3DDevice9* pd3dDevice);


The FrameMove method invokes InternalFrameMove, which does the heavy lifting, and then prepares some matrices for later use.

void CMazeFirstPersonCamera::FrameMove(FLOAT fElapsedTime)

// Make a rotation matrix based on the camera's yaw & pitch
D3DXMatrixRotationYawPitchRoll( &mCameraRot, m_fCameraYawAngle, 0, 0 );

//make translation matrix based on eye pos
D3DXMatrixTranslation( &mCameraTrans,-m_vEye.x,-m_vEye.y,-m_vEye.z);

InternalFrameMove is the CFirstPersonCamera implementation with 2 changes.

1st I uncomment

//// Get the mouse movement (if any) if the mouse button are down
if((m_nActiveButtonMask & m_nCurrentButtonMask)m_bRotateWithoutButtonDown)
UpdateMouseDelta( );//fElapsedTime );

To get the mouse delta, and remove the parameter that is no longer needed.

2nd, after

// Move the eye position
m_vEye += vPosDeltaWorld;

I insert

//update by mousewheel
if( m_nMouseWheelDelta )//&& m_nZoomButtonMask == MOUSE_WHEEL )
float m_fRadius; // Distance from the camera to model

m_fRadius = 5.0f;

m_vVelocity.z = 10.0f*(m_nMouseWheelDelta*m_fRadius*0.1f/12.0f);

m_nMouseWheelDelta = 0;

// Simple euler method to calculate position delta
D3DXVECTOR3 vPosDelta = m_vVelocity * fElapsedTime;

// Transform vectors based on camera's rotation matrix
D3DXVECTOR3 vWorldUp, vWorldAhead;
D3DXVECTOR3 vLocalUp = D3DXVECTOR3( 0, 1, 0 );
D3DXVECTOR3 vLocalAhead = D3DXVECTOR3( 0, 0, 1 );
D3DXVec3TransformCoord( &vWorldUp, &vLocalUp, &mCameraRot );
D3DXVec3TransformCoord( &vWorldAhead, &vLocalAhead, &mCameraRot );

// Transform the position delta by the camera's rotation
D3DXVECTOR3 vPosDeltaWorld;
D3DXVec3TransformCoord( &vPosDeltaWorld, &vPosDelta, &mCameraRot );
m_vEye += vPosDeltaWorld;


if( m_bClipToBoundary )
ConstrainToBoundary( &m_vEye );

From CModelViewerCamera in order to take the mouse delta and convert it into camera movement.

Et voila. Now I have a camera that responds to both sets of controls, mouse and keyboard.

Callback changes

Since we know have a unified camera, we can define our camera variables to be of the same type:

CMazeFirstPersonCamera g_SkyCamera; // A FP camera
CMazeFirstPersonCamera g_SelfCamera; // A fp camera

The only callback changes are in the render code and the key handling code.

For OnD3D10FrameRender and D3D10, the code for each camera is now the same, since they are of the same type.

mProj = *g_SkyCamera.GetProjMatrix();
if ( g_bSelfCam )
mView = *g_SelfCamera.GetViewMatrix();
mViewSkybox = mView;

else if ( g_bSkyCam )
mView = *g_SkyCamera.GetViewMatrix();
mViewSkybox = mView;

For OnD3D9FrameRender and D3D9, the code for each camera is now also the same, since they are of the same type.

mProj = *g_SkyCamera.GetProjMatrix();
if ( g_bSelfCam )
mView = *g_SelfCamera.GetViewMatrix();
mViewSkybox = mView;

else if ( g_bSkyCam )
mView = *g_SkyCamera.GetViewMatrix();
mViewSkybox = mView;

Now we update the key handler to take input for the maze camera.
// Handle messages to the application
bool* pbNoFurtherProcessing, void* pUserContext )
// Pass messages to sky camera so it can respond to user input
g_SkyCamera.HandleMessages( hWnd, uMsg, wParam, lParam );

// Pass messages when paused to self camera so it can respond to input
if ( !g_bRunSim )
g_SelfCamera.HandleMessages( hWnd, uMsg, wParam, lParam );

return 0;

The 2nd part, sending input to g_SelfCamera, is the new part and is the part an alert reader brought up a few articles ago, so we have closed that loop. Note we only do this when paused, since the self camera is being modified by the solver when the sim is not paused. One writer per variable at a time is a good rule.

And that is it! Very simple yet effective. Now the mouse can be used to turn the camera, the mouse wheel can be used to move the position in-out, and the keyboard keys can be used to move the position.

No other callback changes are required. Sweet!


This builds on the previous article. Now we have a skybox rendering, a maze generating and rendering, a a simple solver for the maze, and camera controls.

For this article there is only a single screenshot showing a new camera position, this was a combination of mouse rotations, mouse wheel clicks, and keyboard keys.

Using the new camera class

Next up in the series are:
· an animated character rendered at the solver location,
· additional maze rendering features, and
· generating a new maze when the current one is full solved.

I am still working on the code for maze goals, the rendering I want to do for the goals has held me up a bit so when I get that complete I will add it to the series.

Friday, March 27, 2009

Post-GDC Update


Today is my birthday, happy birthday world!

Still working on the next maze article, sorry its taking so long. Code has been done, article is about 30% done. Maybe by Monday, that still keeps me inside March and roughly meeting my timetable.

GDC 2009

GDC was good.

I went down early and partied extra-hearty before the event so I could stay focused and not feel like I was missing anything.

End result - 3 days of meetings after meetings with developers about LRB1-E. Very productive!

3 days of meetings didnt leave much time for fun, but I still managed to see and hang out a bit with "rendering dudes" like Jay Patel(Blizzard), Wolfgang Engel(ShaderX), Brian Jacobsen(Valve), Jon Mavor(Uber), Tim Sweeney(Epic), Loren McQuade(NCSoft), Chas Boyd(Microsoft), and a few others. And saw a bunch of industry bizdev and evangelism folks I know, eg Chris Donahue, Phil Wright, Paul Trowe, Jeff Royle, Brian Bruning, Leslie P, and more.

I started going to GDC in 1994, and have only missed 2 or 3 in the last 15 years. The industry and event have both changed quite a bit over that time, but it is still one of the key events of the year and you can get a lot of good tech information from the sessions, network like hell with all the people you meet, get a good idea of what products are new/hot/cool by walking the expo floor, and get invited to cool parties every evening.

What else could a game developer want? Don Hopkins and his RV outside parked in the parking lot? More beer? Definitely more beer.

Larrabee at GDC

Slides arent up yet, but industry sites with new discussions are

The info on our 2 sessions:

Interestingly enough, the LRB prototype header file is already public at
This will let developers examine the new instruction set in detail, and once the slides to the Abrash and Forsyth talks are up will be a great complementary resource to allow people to fiddle.

Now if we can get Wolfgang to do a shader book about LRB...the only thing is he wants a new name. I think I got lucky last time, its not every time you can come up with such a good name. If this happens, I will have to mention Valve and their champagne party since that is where the idea took form.

More on Ray Tracing

Uber's Jon Mavor has an interesting blog post on ray tracing at:

Uber is definitely one to watch.

Interestingly enough, a while ago I noticed I had appeared again on Eric Haines' Ray Tracing Newsletter in Nov 2008

My first citation was Aug 1995
The two citations are almost 15 years apart, which is a both an indication of how long I have been hanging around in the industry and the fact that occasionally I make a real contribution.

You couldn't ask for much more. Ok, you could, but should you or would you jinx yourself? :-)

Random Programming Tip

check out


this is a great site to bookmark and the doc is chock full of great low-level programming tricks. I suspect some low-level optimizations like these will be important for LRB since the P54C core its based on is an in-order core and avoiding branch costs like some of these tricks show how to do is generally a good thing to get the fastest code.

Sunday, March 8, 2009

Windows 7 to scale to more Cores

So Microsoft has dodged the core scheduling issue inherent with SetThreadAffinityMask.

They did this for Win64, where SetThreadAffinityMask allows explicit scheduling of 64 threads ( as compared to 32 for Win32 ) with a clever hack to enable "thread groups". Each "thread group" is limited to 64 threads, but now there are 4 thread groups. Adding this "layer" gets round that limitation.

See Mark Russinovich on Channel 9

One way to access this functionality is via the CCR runtime

Good news is that the low-level access will still be available, see
at least for now.

Its pretty clear MS is trying to steer developers away from the low-level, however.

I'll have to play with threads and the default scheduler to see if that is realistic, and if the Windows 7 scheduler is better than previous schedulers. As I found when in Aces Studio, to get predictable performance games have to take the step of explicitly scheduling their own threads, at least prior to Windows 7.

Overall, this is good news for programmers trying to exploit parallelism, and IHVs who have hardware plans to provide silicon with more cores than that.

Oh, and no joy for Win32. The rub for Win32 is you can only schedule 32 threads explicitly so soon Win32 will not be able to cope with the number of cores available from an explicit scheduling standpoint. If thats not clear, there should be 4-way ( 4 socket ) mobo's soon if not already ( Apple is already shipping a box with dual 8-cores for 16 cores total ), and that means early in the lifetime of Windows 7 the hardware will be bumping up against this limit for Win32.

I hear that as the bell is tolling for Win32. Which is a good thing, since based on the overall pace of technology change over the last 28 years, Windows 7 should have been 64-bit only.