D3D初始化介绍



介绍
本文通过个应用D3D屏幕保护提供了在编程时对DDrawD3D化过程个介绍相当不错 
本文作者:Jason Cwik, mail:[email protected]

源代码在此 

BTW: 本人E文实在是有点拙劣水平不足,但自我感觉勇气可嘉,) 纯属乱翻为提高本文可用性使用中英对照方式发布若想骂我敬请到留言簿处或mailme 


--------------------------------------------------------------------------------

有关法律责任
本文和所有本文相关部分版权归Jason Cwik所有授权Pigprince中文版版权所有授权您可以通过电子手段( 2进制形式)分发(e-mail、邮寄或存储)本文档全部或部分在没有对本文做任何改变情况下授权容许打印拷贝建议使用最新版本 所有信用和版权声明被保留如果您要在其它站点加个指向本文连接请通知 Jason Cwik(E文版)或Pigprince(中英文对照版)取得授权 

需要拥有其它发布形式权利如在公司、组织、商业产品如:书籍、报刊杂志、CD-ROM、应用软件Software等中发布请尊重作者权利(署名权取得报酬权等) 

本文没有任何明确或含蓄表达介绍说明本文是完全正确对于应用本文内容所产生任何结果本人概不负责如果您在开发较高预算工程请您不要只依赖于本文家的言 

所有名称商标版权等属于该名称商标版权等法定所有者 


--------------------------------------------------------------------------------
Probably the most complicated part of writing a DirectDraw or Direct3D program is the initalization of the drawing/rendering engine. Here I will present the initalization sequence of my screensaver in detail, poing out the steps as we go. Be aware that there is more than one method to initialize Direct3D. In my opinion, this method is more complex, but allows the most flexibility. 
也许在写个DirectDraw或者Direct3D时最麻烦、最复杂莫过于化部分了在这里我将详细介绍在我写屏幕保护化部分指出我们必需走几步需要注意是不是只有种思路方法来进行Direct3D我认为虽然DirectX化十分复杂但是却具有极大弹性 

The first step is to create the DirectDraw erface. We do this with a call to DirectDrawCreate. This call doesn't do much except for initalize the COM erface to DirectDraw. Also notice that throughout this example we are using C which allows us to remove the virtual table poer and the first parameter of the function (which is basically just a poer to this). 

步: 创建DirectDraw接口 

这个工作由DirectDrawCreate来完成这个只是化DirectDrawCOM接口还要注意在这个例子中我们使用是C可以很方便移动虚拟表头指针和个参数 (可以简单到只用个this指针)
  

LastResult = DirectDrawCreate(NULL, &lpDD1, NULL);
(FAILED(LastResult))
{
    Msg("Error creating DirectDraw\\n%s", D3DRMError(LastResult));
    goto exit_with_error;

DirectDraw version 2 has some features that are not present in DirectDraw, and some of our calls later require it, so we will query for DirectDraw2 from the DirectDraw erface. This call is a perfect example of where COM rears it's ugly head. With COM, all dferent versions of the API are available at once, depending on which one you are looking at. Also, all of the erfaces know about the other ones, so we can query for them. You will see code segments similar to this one throughout the code, whenever we need to get a related erface from an existing object. 
DirectDraw2有些特别它不是包含在DirectDraw中并且我们会还要用到它所以我们在directDraw接口中查询它这个依赖于COM接口COM接口使区别版本、区别性质API协同工作同样所有COM接口也是协同起来您可以在下面多处看到相似代码来实现已存在对象和相关接口关联 

LastResult = lpDD1->QueryInterface(IID_IDirectDraw2, (void **) &myglobs.lpDD2);
(FAILED(LastResult))
{
    Msg("Error querying DirectDraw2\\n%s", D3DRMError(LastResult));
    goto exit_with_error;

  
Since Direct3D is related to DirectDraw, we can query for our Direct3D (version 2) erface from the DirectDraw erface. 


既然Direct3D也同样可以关联于DirectDraw我们也可以在DirectDraw接口中查询Direct3D2接口
  

LastResult = myglobs.lpDD2->QueryInterface(IID_IDirect3D2, (void **) &myglobs.lpD3D2);
(FAILED(LastResult))
{
    Msg("Error querying Direct3D2\\n%s", D3DRMError(LastResult));
    goto exit_with_error;

The example program also uses the Retained Mode erface, so we create it with a call to Direct3DRMCreate. 
这个例子是基于Direct3D Retained-Mode接口我们将使用Direct3DRMCreate进行创建
  

// Create D3DRM
LastResult = Direct3DRMCreate(&lpD3DRM1);
(FAILED(LastResult))
{
    Msg("Error creating D3DRM\\n%s", D3DRMError(LastResult));
    goto exit_with_error;

Again, we want to use the er version of the erface, so we will query for it from the older erface. 
再者我们要使用接口新例子要在旧接口中查询

LastResult = lpD3DRM1->QueryInterface(IID_IDirect3DRM2, (void **) &myglobs.lpD3DRM2);
(FAILED(LastResult))
{
    Msg("Error querying D3DRM2\\n%s", D3DRMError(LastResult));
    goto exit_with_error;

Since we are done with the D3DRM (version 1) erface, we can now release it. The RELEASE macro just makes sure the poer isn't NULL, calls the release method of the erface and then s the poer to NULL . 
既然D3DRM接口我们已用完了现在应该释放它RELEASE宏判断指针为非空(!NULL) 后接口release思路方法将指针置空

RELEASE(lpD3DRM1);
The next step which isn't completely shown right here (Look for it later) enumerates the drivers available and the modes for each driver. Earlier in the program, we loaded s from the registry specying which driver and mode the user wanted to use. After enumeration, we search through the results to find their selection. If the driver/mode isn't found, we pop up the dialog prompting them to change the selection. 
第 2步:例举了已有驱动和每个驱动具体模式
但对这叙述并不完整在这个早期版本里我们从注册表中读取指明用户要使用驱动和模式在例子化以后我们通过搜索结果值来确定用户选择如果该驱动或驱动模式未被发现则弹出个对话框提示用户改变他们选择

(!EnumDrivers)
{
    Msg("Error enumerating D3D device drivers.\\n");
    goto exit_with_error;
}
(!EnumModes)
{
    Msg("Error enumerating DirectDraw display modes.\\n");
    goto exit_with_error;

// Find our driver and mode. If we can't find the driver / mode
// they want, run the configuration dialog.
(!SelectDriver(driver_buffer))
{
    Msg("Could not find requested D3D Driver: %s. Please choose a  one.\\n",  driver_buffer);
    theApp.DoConfig;
    goto exit_with_error;


(!SelectMode(mode_buffer))
{
    Msg("Could not find requested display mode: %s. Please choose a  one.\\n",  mode_buffer);
    theApp.DoConfig;
    goto exit_with_error;
}

The next section we must branch depending on whether we are doing a full screen mode or not (this is to facilitate debugging and for the little preview window in the screen saver dialog). Right before the , I have a line that I can uncomment  I want to force the program to run in a window instead of fullscreen for debugging. I am only going to present the fullscreen code here, since that's what most people are erested in. The windowed code is available here. 


下面我们要处理个满屏/非满屏分支非满屏窗口模式是为了更容易调式和处理在屏幕保护对话框中预览窗在IF语句的前注释处应是强迫运行于窗口代码这段代码在这里 

// For debugging purposes,  this to FALSE and the screensaver will
// run in a window instead of fullscreen.
//myglobs.bFullscreen = FALSE; 
(myglobs.bFullscreen)
{

The first part of ting the video mode involves ting the Cooperative Level. In this call, we tell DirectDraw that we want to go o fullscreen mode (DDSCL_FULLSCREEN), which in turn requires exclusive mode (DDSCL_EXCLUSIVE). As an added precaution, we also  the flag DDSCL_ALLOWREBOOT, which makes DirectDraw trap for alt-ctl-delete so it can switch back to windowed mode. 
显示模式设置部分包括“合作水平”(Cooperative Level)在下面我们告诉DirectDraw我们要进入排他模式(DDSCL_EXCLUSIVE)满屏模式(DDSCL_FULLSCREEN), 作为项附加防范还要置标志DDSCL_ALLOWREBOOT使DirctDraw接管Alt-Ctl-Del消息以便恢复为窗口模式
  

LastResult = myglobs.lpDD2->SetCooperativeLevel(myglobs.hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT);
(FAILED(LastResult))
{
    Msg("Error ting Exclusive mode\\n%s", D3DRMError(LastResult));
    goto exit_with_error;

Now that we've told DirectDraw to operate in exclusive mode, we must tell it what mode to use. This was read in earlier from the options stored in the registry. The last two arguments are the refresh rate and flags, neither of which are used here. Setting the refresh rate to zero assumes the default value, which should be fine for almost every application. After ting the mode, we make sure the global variables know about the size of the screen. The ClientOnPrimary field is used in windowed mode, because DirectDraw doesn't care about the client area of the window, coordinates are still specied in absolute screen coordinates. 
现在我们已经告诉了DirectDraw工作在排他模式记住定要对工作模式进行设定这是在先前从注册表中读取最后 2项内容是刷新率和标志这里没有用到这 2项将刷新率设为0来使用刷新率缺省值在绝大多数中都可以工作得很好在模式设置后要确信全局变量中包含了屏幕大小ClientOnPrimary部分用于窗口模式DirectDraw不管窗口客户区大小坐标系还是使用绝对屏幕坐标系 

LastResult = myglobs.lpDD2->SetDisplayMode(
   myglobs.Mode[myglobs.ModeSelected].w,
   myglobs.Mode[myglobs.ModeSelected].h,
   myglobs.Mode[myglobs.ModeSelected].bpp, 0, 0);
bIgnoreWM_SIZE = FALSE;
(FAILED(LastResult))
{
    Msg("Error ting video mode. Try running configuration again.\\n%s", D3DRMError(LastResult));
    goto exit_with_error;

myglobs.WindowWidth = myglobs.Mode[myglobs.ModeSelected].w;
myglobs.WindowHeight = myglobs.Mode[myglobs.ModeSelected].h;
myglobs.pClientOnPrimary.x = myglobs.pClientOnPrimary.y = 0;

Now that we have the mode  up, we need to create the drawing surfaces. To do good animation, we need to double-buffer, so we're going to  up the flags so that it creates one back buffer (you can make as many as you have VRAM for, but two should be sufficient unless you're doing stereo imaging... but that's a whole other topic). This call is similar to may DirectX calls that have lots of fields. You initlaize the structure to zero, then  flags in the dwFlags element speciing which fields you have filled in. 
现在我们已经进行完了模式设置我们还需要双缓冲来显示效果良好动画可以通过设置些标志来创建个后缓冲(你可以在你显示内存足够情况下创建任意多个但是般 2个应该足够了除非你要做立体图形实时绘演可那完全是另个问题了)这个可以应用于许多DirectX功能将这个结构化为0然后置dwFlags元件指明你要置位功能


  

// Create the front and back surfaces
mem(&ddsd, 0, (ddsd));
ddsd.dwSize = (ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_3DDEVICE | DDSCAPS_FLIP |
   DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX;
(myglobs.Driver[myglobs.DriverSelected].bIsHardware)
    ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
ddsd.dwBackBufferCount = 1; 
LastResult = CreateSurface(&ddsd, &myglobs.lpFrontBuffer);
(FAILED(LastResult))
{
    Msg("Error creating Buffers\\n%s", D3DRMError(LastResult));
    goto exit_with_error;
}

// Get a handle on the back buffer
ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
LastResult = myglobs.lpFrontBuffer->GetAttachedSurface(&ddsd.ddsCaps, &myglobs.lpBackBuffer);
(FAILED(LastResult))
{
    Msg("Error Getting Back Buffer\\n%s", D3DRMError(LastResult));
    goto exit_with_error;
}

If the hardware does Z-buffering (for 3D), we'll create another surface in video memory for it. We also need to check what depth Z buffer is needed (because dferent cards do dferent levels). After the surface is created, it is attached to the others. 

如果硬件支持3DZ-buffering,我们就要在显示内存中创建另个表面还需测试 Z-buffer 深度(区别显示卡支持深度区别)创建完表面隶属于其它表面
  

// Create a Z buffer  we need it.
(myglobs.Driver[myglobs.DriverSelected].bDoesZBuffer)
{
    mem(&ddsd, 0, (ddsd));
    ddsd.dwSize = (ddsd);
    ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS| DDSD_ZBUFFERBITDEPTH
    ddsd.dwWidth = myglobs.Mode[myglobs.ModeSelected].w;
    ddsd.dwHeight = myglobs.Mode[myglobs.ModeSelected].h;
    ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
    (myglobs.Driver[myglobs.DriverSelected].bIsHardware)
        ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
    
        ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; 
    devDepth = myglobs.Driver[myglobs.DriverSelected].Desc.dwDeviceZBufferBitDepth;
     (devDepth & DDBD_32)
        ddsd.dwZBufferBitDepth = 32;
      (devDepth & DDBD_24)
        ddsd.dwZBufferBitDepth = 24;
      (devDepth & DDBD_16)
        ddsd.dwZBufferBitDepth = 16;
      (devDepth & DDBD_8)
        ddsd.dwZBufferBitDepth = 8;
    
    {
        Msg("Unsupported Z-buffer depth requested by device.\\n");
        goto exit_with_error;
    }
    LastResult = CreateSurface(&ddsd, &myglobs.lpZBuffer);
    (FAILED(LastResult))
    {
        Msg("Error creating ZBuffer Surface.\\n%s", D3DRMError(LastResult));
        goto exit_with_error;
    }
    myglobs.lpBackBuffer->AddAttachedSurface(myglobs.lpZBuffer);
}

Now that the surfaces are created, we can create the rendering device (D3DDevice2). 现在表面创建完毕下面我们创建绘演设备(D3DDevice2)
  

// Create a D3DDevice2 from the surfaces.
LastResult = myglobs.lpD3D2->CreateDevice(myglobs.Driver[myglobs.DriverSelected].Guid,(LPDIRECTDRAWSURFACE) myglobs.lpBackBuffer, &myglobs.lpD3DDevice2);
(FAILED(LastResult))
{
    Msg("Error creating D3DDevice from surface\\n%s", D3DRMError(LastResult));
    goto exit_with_error;
}
}
//** Windowed mode initialization goes here ** 


All of the drivers are now initialized. If you are doing immediate mode, stop here. The rest of the code is for ting up retained mode. The first thing we do is to create the D3DRMDevice from the D3DDevice. 
所有驱动已化完毕如果您是工作在D3D Immediate-mode模式化就已完成下面代码是设置D3D Retained-mode模式首先要做是从D3DDevice中创建D3DRMDevice
  

// Create the RM from the IM
LastResult = myglobs.lpD3DRM2->CreateDeviceFromD3D(myglobs.lpD3D2, myglobs.lpD3DDevice2, &myglobs.lpD3DRMDevice2);
(FAILED(LastResult))
{
    Msg("Error creating D3DRMDevice2 from D3D\\n%s", D3DRMError(LastResult-1));
    goto exit_with_error;

There is a chance that our dimensions have changed, so we will do a quick check of the height and width. 

存在环境尺寸变化可能性我们要对环境宽、高进行快速检查
  

// Get the final width and height
(!myglobs.bFullscreen)
{
    myglobs.WindowWidth = myglobs.lpD3DRMDevice2->GetWidth;
    myglobs.WindowHeight = myglobs.lpD3DRMDevice2->GetHeight;
}
  
We can now create the scene and the camera frames. Since the camera is part of the scene, it is created inside the scene. The scene is the master frame so it has no parent (the NULL poer). The camera is then placed at 0,0,0 in the scene. 
现在可以创建场景和照相机桢照相机是场景部分是创建于场景中此场景是主画面对象没有祖先照相机是放置在场景圆点处(000)
  

// Create the master scene frame and camera frame.
myglobs.lpD3DRM2->CreateFrame(NULL, &myglobs.scene);
myglobs.lpD3DRM2->CreateFrame(myglobs.scene, &myglobs.camera);
myglobs.camera->SetPosition(myglobs.scene, D3DVAL(0.0),D3DVAL(0.0), D3DVAL(0.0)); 
Now that we have the camera, we must map 3D space to a 'viewport' which handles the translation of coordinates from 3D space to the 2D screen. 现在我们已经有了照相机但是还要将3D空间影射到把 3维空间坐标系转换到 2维屏幕坐标系“视口”上
  

// Create the viewport
LastResult = myglobs.lpD3DRM2->CreateViewport(myglobs.lpD3DRMDevice2,myglobs.camera, 0, 0, myglobs.WindowWidth, myglobs.WindowHeight,&myglobs.lpD3DRMView);
 (FAILED(LastResult))
{
    Msg("Error creating viewport\\n%s", D3DRMError(LastResult));
    goto exit_with_error;

The back clipping plane determines the cutoff po for rendering polygons. Here we're ting it to 5000. This value will vary depending on your coordinate system. 

背景剪裁平面决定了展现多边形时剪裁点数在这里我们设定值是5000这个值取决于您使用坐标系
  

// Set the back clipping plane
LastResult = myglobs.lpD3DRMView->SetBack(D3DVAL(5000.0));
 (FAILED(LastResult))
{
    Msg("Error ting back clipping plane\\n%s", D3DRMError(LastResult));
    goto exit_with_error;

 
The function call to SetRenderState s up the rendering state variables within RM to control the lighting, shading and texturing otions. A call is then made to BuildScene so the user can  up their objects. 
这个设置了展现状态变量来控制如光源、阴影和材质等这个将建立场景使用户可以在场景中放置他们要放置物体
  

// Set the render quality, fill mode, lighting state,
// and color shade info.
 
 (!SetRenderState)
{
    Msg("Error ting render state and/or building scene");
    goto exit_with_error;
}
 (!BuildScene(myglobs.lpD3DRMDevice2, myglobs.lpD3DRMView, myglobs.scene, myglobs.camera))
{
    Msg("Error ting render state and/or building scene

");
    goto exit_with_error;

The next two lines  up the statistics (FPS, TPS, mode). This code was basically stolen from Micro$oft's demo programs. 

下面 2行是进行设置统计表(FPSTPS模式)这 2行是从微软演举例子中抄来
  

D3DAppIClearBuffers;
InitFontAndTextBuffers
Finally, we release DD1 and  our RenderingIsOK flag. 

最后我们将释放DD1并且设置我们RenderingIsOK
  

// Done with DD1, release it.
RELEASE(lpDD1);
 
// Looks like everything is good,  TRUE.
myglobs.bRenderingIsOK = TRUE;
 TRUE; 
 
  The following code is called  an error occurs during the initialization. It releases any created erfaces and then s false. At the end a small test is done to see  we're in windowed mode or not. This is a workaround because when a screensaver is previewing in the Win95 display properties window quits, windows immediately respawns it. So,  an error occurs, you can't get out of the display properties dialog because the respawning screensaver monopolizes the system. 
下面代码用在化出错时它可以释放所有已创建接口并且返回个false在结尾处有个是否处于窗口模式测试当屏幕保护在瘟95显示属性窗口预览窗运行时关闭显示属性窗时瘟95要立刻关闭这个屏保如果这时产生屏保独占了系统资源将无法退出显示属性窗 

exit_with_error:
// An error occured. Release any created erfaces and  FALSE
RELEASE(myglobs.lpD3DRMView);
RELEASE(myglobs.camera);
RELEASE(myglobs.scene);
RELEASE(myglobs.lpD3DRMDevice2);
RELEASE(myglobs.lpD3DRM2);
RELEASE(myglobs.lpDDClipper);
RELEASE(myglobs.lpDD2);
RELEASE(lpD3DRM1);
RELEASE(lpDD1);
//  We're in preview mode, don't exit  there is an error. Otherwise,
// moronic windows will respawn the saver, screwing everything up.
(!myglobs.bFullscreen)
{
     TRUE;
}

{
     FALSE;

  
Home 
--------------------------------------------------------------------------------
1998.7.26 upload to  border=0>http://pigprince.yeah.net by pigprince, All Right Reserved.
1998.7.29 Fix the source link error and some stupid translation mistakes. 
本页内容和观点属于本页作者广州网易并未对其进行检查和核准
本页在此发布并不代表广州网易具有和其内容相同观点或看法
Tags: 

延伸阅读

最新评论

发表评论