Direct3D Is Not 'More Complicated' Than OpenGL

Published April 09, 2008
Advertisement
I don't like surprises. I especially dislike it when those surprises are in the form of obscure bugs in code I own due to a wacky decision some other library made. In this case, I discovered that SlimDX wasn't writing char data correctly (that's Unicode characters, not bytes), because Marshal.SizeOf(typeof(char)) is 1, even though sizeof(char) is 2.

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.
0 likes 8 comments

Comments

Saruman
Great post, I've always felt the exact same way about the DX tutorials.
April 09, 2008 10:30 PM
dmail
I did not know "sizeof(char) is 2." in C# I would have thought it was the same as C and C++ in which it is guaranteed to be one.
April 10, 2008 05:31 AM
Evil Steve
I've actually been thinking about writing some D3D tutorials, although time is rather limited.

As you said, I don't like how a lot of tutorials enforce The Right Way of doing things, particularly since I see a lot of tutorials doing horrible things like if(hr != D3D_OK) instead of using the SUCCEEDED and FAILED macros, never mentioning the debug runtimes, etc etc.

IMO, a good set of tutorials would be something like:
  • Basic window class set up, maybe just provided to the user even
  • Overview of D3D, how to set up the debug runtimes, checking return values, etc
  • A basic device class for rendering transformed verts via DrawPrimitiveUP (No vertex buffer), and minimal setup code (Could assume a 32-bit fullscreen device)
  • Proper device setup code (Enumeration of backbuffer / depthstencil / texture formats)
  • Rendering in 3D - Still no VB, just covering transformations and maybe a camera class
  • Vertex and index buffers
  • Textures
  • Lighting and materials
  • Vertex shaders
  • Pixel shaders
  • Any other "boring" stuff like resetting the device, optimisations, creating a device wrapper for managing render states, etc.

    Or something along those lines anyway.
  • April 10, 2008 06:15 AM
    Train
    Promit,
    If you could recomend to me a good set of D3D tutorials to start with (I have been debating with myself which of the many sets out there to use) I will begin to port them to SlimDX.

    I want to do this for several reasons:
    1. To get more practice with SlimDX
    2. To encourage more people to use SlimDX (the more people use it the safer I feel about using it myself as there will be more peer support)
    3. I forgot my 3rd reason.

    I was previously a MDX programmer who has been lost for a while, not wanting to use XNA because it was very limited considering the things I do, and the managed OpenGL options I found were very outdated and stale.
    April 10, 2008 06:58 PM
    Train
    oh, and the reason sizeof comes back 2 is because the char is UNICODE in CLR

    IIRC, unicode is 2 bytes.

    edit:

    http://msdn2.microsoft.com/en-us/library/eahchzkf(VS.80).aspx
    April 10, 2008 07:06 PM
    Promit
    Quote:Original post by Train
    oh, and the reason sizeof comes back 2 is because the char is UNICODE in CLR
    That part is fine. It's the detail that it's marshaled as ASCII which is bullshit.
    April 11, 2008 09:37 AM
    Gage64
    Quote:Original post by Promit
    Say what you will about NeHe's code -- Jeff was incredibly effective at teaching


    I disagree completely. I remember when I wanted to learn about 3D graphics, and those tutorials were the first thing I found. I already knew how to program (to some extent) but I knew nothing about 3D math or computer graphics. I started reading the tutorials and was literally amazed at how much was missing.

    The tutorials just threw a bunch of code at you and provided minimal explanations on what it did. I worked through the first several tutorials and felt like I had no idea how any of this stuff worked, why was the code structured the way it was, what was the logic behind it, etc. When I got to the more advanced tutorials, they relied heavily on knowledge "gained" in the previous tutorials, so at that point I just stopped and looked for another resource.

    I also think that many tutorials follow the model of NeHe's tutorials, where they show a bunch of code, say a couple of words on each line, and that's it. No high level overview and no discussions of concepts, just "immediate results" as you put it. I think this is very unfortunate and it doesn't look like it's gonna change, probably because those tutorials are being written by people who aren't experts, and true experts usually have better things to do than write tutorials.

    Everyone will have a different opinion and I know NeHe's tutorials are very popular, but I really hope new tutorial writers will take a different approach and focus more on true understanding and not on how to put pretty pictures on the screen as fast as possible.
    April 21, 2008 10:41 AM
    epsylon
    NeHe's tutorials are more recipes than real tutorials : just a few samples which go quickly (and effectively) straight to the point, assuming previous knowledge.
    April 22, 2008 04:16 AM
    You must log in to join the conversation.
    Don't have a GameDev.net account? Sign up!
    Advertisement