God damnit.
Direct3D Is Not 'More Complicated' Than OpenGL
Unfortunately, there's this general feeling out there that Direct3D is more complicated than OpenGL, at least to start out with. I don't want to call it a myth, because I don't think it's spread by anyone, misinformed or otherwise. As far as I can tell, it's something that people believe because a whole lot of extremely poor writers have taken it upon themselves to publish shoddy tutorials, guaranteed to lose most beginners. (Say what you will about NeHe's code -- Jeff was incredibly effective at teaching and that's why his work entirely dominates). The reason for this is mainly that Direct3D tends to encourage good practices from the beginning, whereas OpenGL actively makes it more difficult than it should be to exercise good practice.
As a result of this encouragement, D3D tutorials typically go through a whole bunch of complexity, including setting up the window in some complicated way, setting up the device just so (and even enumerating in some cases!) and then going through the trouble of creating a vertex buffer to render from. The result is a pretty decent skeleton application. It's also misguided and makes for a terrible tutorial. The typical defense I see is that you should take the opportunity to show a beginner how to do things The Right Way (tm) right from the beginning, rather than retroactively killing off bad habits.
That's wrong. Very, very wrong.
As someone writing for beginners, your goal is not to teach them Right. Your goal is to introduce concepts to them -- one at a time -- and show them how to use each new concept without introducing arbitrary complexity. Actually, that's secondary. Your real, primary goal is to give them results as soon as possible. They should see successful results of their code, immediately, no matter how bad or wrong the code is. The best way to do that is to give them a minimum of code, so that there's very little chance of messing up the initial writing, and very little turnover time in getting it written. In short, the quality of an introductory tutorial can be directly judged by the amount of code it involves, and nothing more. All other criteria are totally irrelevant.
Given that claim, I now present what I think would be the correct accompanying code for a Direct3D Tutorial #2. (The first would be setting up the window, so just cut the D3D code out if you want to know what that looks like.)
#include #include HWND hWindow;IDirect3D9* D3D;IDirect3DDevice9* Device;struct Vertex{ float x, y, z, rhw; D3DCOLOR Color;};#define FVF_VERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)LRESULT WINAPI WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ){ switch( msg ) { case WM_CLOSE: PostQuitMessage( 0 ); return 0; case WM_PAINT: ValidateRect( hWnd, NULL ); return 0; } return DefWindowProc( hWnd, msg, wParam, lParam );}int main(){ HINSTANCE hInstance = GetModuleHandle( NULL ); //create a window WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0, 0, hInstance, NULL, NULL, NULL, NULL, "MiniD3D", NULL }; RegisterClassEx( &wc ); hWindow = CreateWindowEx( WS_EX_APPWINDOW | WS_EX_WINDOWEDGE, "MiniD3D", "MiniD3D", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, NULL, NULL, hInstance, NULL ); ShowWindow( hWindow, SW_SHOW ); UpdateWindow( hWindow ); //Set up d3d D3D = Direct3DCreate9( D3D_SDK_VERSION ); D3DPRESENT_PARAMETERS d3dpp = { 0 }; d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; D3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &Device ); //now create our triangle Vertex Triangle[3] = { { 150.0f, 50.0f, 0.5f, 1.0f, D3DCOLOR_XRGB( 255, 0, 0 ) }, { 250.0f, 250.0f, 0.5f, 1.0f, D3DCOLOR_XRGB( 0, 255, 0 ) }, { 50.0f, 250.0f, 0.5f, 1.0f, D3DCOLOR_XRGB( 0, 0, 255 ) } }; MSG msg; bool RunApp = true; while( RunApp ) { if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) { if( msg.message == WM_QUIT ) RunApp = false; TranslateMessage( &msg ); DispatchMessage( &msg ); } //render stuff Device->Clear( 0, 0, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0, 0, 0 ), 1.0f, 0 ); Device->BeginScene(); Device->SetFVF( FVF_VERTEX ); Device->DrawPrimitiveUP( D3DPT_TRIANGLELIST, 1, Triangle, sizeof(Vertex) ); Device->EndScene(); Device->Present( 0, 0, 0, 0 ); } Device->Release(); D3D->Release(); DestroyWindow( hWindow ); return 0;}
87 lines, including whitespace and comments, and even giving most braces their own lines.
The obvious question is of course, why don't I write a series of tutorials, if I'm so confident about what the correct way to do it is? The obvious answer is that I don't have time. I might do it for SlimDX though, since that's probably useful.