noslopforever [天堂里的死神]

我浴血奋战,只为了神圣永久不变的传言

李巍ID:noslopforever
71239次访问,排名1377好友4人,关注者9
3D、图形学、游戏、哲学、历史、音乐,一个都不能少。
noslopforever的文章
原创 83 篇
翻译 2 篇
转载 4 篇
评论 201 篇
noslopforever(天堂里的死神)的公告

-欢迎大家来到我的空间。这里关注游戏相关学科的问题。
-自我介绍:男,25岁,程序员,喜欢战争、历史和哲学题材游戏。作为一位普通的初学者,希望众位前辈们能多多包涵和帮助。
-欢迎大家拍砖。本Blog原创的文章,如要转载,请注明出处和姓名。本Blog放置的代码,大部分是伪码,不保证能够运行。
*留言本1:没有CSDN帐号的网友留言请点击此链接
*留言本2:CSDN网友请在个人空间留言 ^_^




烽火过千年,往事如烟。争斗一生归何处?黄土青山。 繁华总易逝,回首不堪。敢叫天地换新颜,铁马连天。 ——《无题》 李巍于2008年6月9日

-最近在做:做好自己的项目,安排自己的时间。

-有些栏目的文章是不放在主页显示的,如果有感兴趣的可以到相应栏目查询。杂项和Just As Gamer栏目的,仅作为个人喜好,恕不回复。

最近评论
夫妻肺片:尽管历史不能“如果”,但历史的教训可以汲取。汲取的目的只是在下一次的偶然中把握住必然的东西。
新浪网友:这是对西方文明的绝好讽刺!谢谢博主让我们看到这封信.
夫妻肺片:其实世界上只有三种关系:人与自然,人与社会,人与自己。其中人与自然那是环保局的事,人与社会那是老板的事,而人与自己才是自己的事。
夫妻肺片:“变是唯一的不变”。
闲人:为眼前利益太攻于心计的人往往做不成大事!
不过应防范这些人.
文章分类
收藏
相册
misc杂项
朝圣者的路途
文档所需图片册
我的书单
我的照片
!飞龙在天!
cproom前辈的Blog
eXtreme 3D —— Dreams的Blog(RSS)
flymemory的Blog
johnson的Blog——我的老师和第一个上司 ^_^
nhsoft——野猪大大的Blog
Nightmare of Design/Dev(RSS)
游戏编程实践——我的老师的Blog
马肝前辈的Blog
!虎狼成群!
亮——同学、引擎程序员
江自流——另一位同学兼才思敏捷的策划
游戏王——同学,一位才思敏捷的策划
推荐网页
Boost——C++准标准库
Boost中文站
GameDev.net
OGRE3D中文站
OGRE3D——开源的3D图形引擎
Sourceforge
有关WOW格式的Wiki
涂鸦软件——一个很牛的国产游戏引擎
喜欢的站点
《闪电战》杂志讨论区
帝国之鹰
德军总部
英雄世界
存档
软件项目交易
订阅我的博客
XML聚合  FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
订阅到BlogLines
订阅到Yahoo
订阅到GouGou
订阅到飞鸽
订阅到Rojo
订阅到newsgator
订阅到netvibes

翻译 关于DX多窗口编程的一篇翻译(感谢Happy_888网友给出的原文 ^_^)收藏

新一篇: [荐]游戏编程的三本“新”书 | 旧一篇: 解释型脚本向编译型脚本转化的一个简单转变

Introduction

In DirectX 8, support for rendering to multiple windows is provided through the creation of additional swap chains.  However, there are currently no examples of this in the SDK, and the documentation is a bit vague.  This article is provided to fill the gaps, and will explain the steps you need to take to write an application that will render multiple views in separate windows.

DX8中,对多窗口的支持是通过创建更多的Swap Chains来提供的。SDK中没有相关的例子而且文档也只是泛泛而谈。这篇文章就是为了解决这个问题,它将向您展示应当如何一步步地实现在多个分离窗口中渲染多个视图。

 

Step 1 - Setting Up The Parent Frame

第一步:设置父框架窗口

 

In an application with multiple views, we start with a top level frame that will contain child windows in its client area to display various views.  Once the parent frame parent frame has been created, we create our Direct3D device interface, specifying windowed mode and setting the top level window handle as the focus window:

在多视图的应用程序中,我们需要从最高层次的框架——这个框架将包含所有在他用户区之内的子视图窗口——开始我们的旅程。当父框架创建的时候,我们需要创建Direct3D Device接口,为其指定使用窗口模式,而且设置这最高层次的窗口句柄作为“焦点窗口”的句柄:

 

g_pD3D=Direct3DCreate8(D3D_SDK_VERSION);

if (!g_pD3D) return -1;

D3DPRESENT_PARAMETERS d3dpp;

ZeroMemory( &d3dpp, sizeof(d3dpp) );

d3dpp.Windowed = TRUE;

d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;

// Use the current display mode. 使用当前的显示模式

D3DDISPLAYMODE mode;

if(FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT , &mode))) {

    SAFE_RELEASE(g_pD3D);

    return -1;

}

d3dpp.BackBufferFormat = mode.Format;

d3dpp.BackBufferWidth = mode.Width;

d3dpp.BackBufferHeight = mode.Height;

d3dpp.EnableAutoDepthStencil=TRUE;

d3dpp.AutoDepthStencilFormat = D3DFMT_D16;

// m_hWnd is handle to top level window    m_hWnd是最高层窗口的句柄

if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hWnd,

                                  D3DCREATE_SOFTWARE_VERTEXPROCESSING,

                                  &d3dpp, &g_pd3dDevice) ) ) {

    SAFE_RELEASE(g_pD3D);

    return -1;

}

 

Note that for simplicity the above code does not test depth format, instead choosing a fixed format.  Your application should determine a compatible depth format for the format of the rendering target.

注意上面代码处于简单考虑并没有去测试深度缓存的格式(?depth format),而只是选择了一个确定的格式(D3DFMT_D16)。您的程序应该为需要渲染的Render Target选择一个可接受的深度缓存格式。

 

The device has a frame buffer, which the child views will be rendered into, as well as a depth buffer which will be shared among the views.  The frame buffer and depth buffer are sized to the full screen resolution, to allow for the fact that the window may later be resized.  Otherwise, window size changes would require resetting the device and re-creating the swap chains.

Device都需要有帧缓存,这样子视图才能进行渲染,同时,深度缓冲也应当被不同的视图进行共享。帧缓存和深度缓存都被设置为全屏幕大小,以考虑到可能窗口会被改变大小的情况。如果不的话,窗口改变大小的时候,就需要Reset Device和重新创建Swap Chain

 

Step 2 - Setting Up View Windows

第二步:设置子视图窗口

 

Now we are ready to create our view windows, and associate them with swap chains that can be rendered to the device.  Once the windows have been created, the following code generates a swap chain for the child window:

现在我们可以准备创建我们的子窗口也就是视图窗口,并把它们与交换链关联以使得他们可以被渲染到Device上。当窗口创建后,下面的代码将为子窗口创建一个交换链:

 

D3DPRESENT_PARAMETERS d3dpp;

ZeroMemory( &d3dpp, sizeof(d3dpp) );

d3dpp.Windowed = TRUE;

d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;

// Use the current display mode.  使用当前的显示模式

D3DDISPLAYMODE mode;

g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT , &mode);

d3dpp.BackBufferFormat = mode.Format;

// m_hWnd contains child window handle  m_hWnd储存子窗口的句柄

d3dpp.hDeviceWindow=m_hWnd;

// m_pSwapChain is IDirect3DSwapChain *   m_pSwapChain是一个IDirect3DSwapChain*对象

g_pd3dDevice->CreateAdditionalSwapChain(&d3dpp, &m_pSwapChain);

 

After executing this code, the m_pSwapChain variable will contain a pointer to an IDirect3DSwapChain interface, which contains a frame buffer corresponding to the client area of the child window.  This process is performed for each view window, so that that there is a swap chain for each view window.

经过这些代码之后,m_pSwapChain变量就储存了IDirect3DSwapChain接口的指针,这个接口将储存子窗口视图区所对应的帧缓冲。

 

Step 3 - Rendering a View

第三步:渲染视图

 

Prior to rendering each view, we must direct the device to render to the appropriate frame buffer, using the SetRenderTarget() method.  We pass the back buffer from the window's swap chain, while using the depth buffer that was originally created with the device:

在渲染每个视图窗口之前,我们必须使得Device来渲染对应的帧缓冲,这我们就需要用到SetRenderTarget方法。我们向其中传入子窗口SwapChain交换链的后备缓冲BackBuffer,以及使用最开始跟着Device一起创建的深度缓冲。

 

LPDIRECT3DSURFACE8 pBack=NULL,pStencil=NULL;

m_pSwapChain->GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO,&pBack);

g_pd3dDevice->GetDepthStencilSurface(&pStencil);

g_pd3dDevice->SetRenderTarget(pBack,pStencil);

pBack->Release();

pStencil->Release();

 

Note that we release the stencil and backbuffer pointers after we use them, because the GetBackBuffer() and GetDepthStencilSurface() functions call AddRef() on these interfaces to increment their reference counters.  Failing to release them would lead to a memory leak.

注意我们必须ReleaseStencilBackBuffer的指针,因为GetBackBufferGetDepthStencilSurface这两个函数都会调用COMAddRef方法,来增加相应COM接口的引用计数,因此如果不删除它们,将会导致内存泄露。

 

We are now ready to render the view.  Rendering is performed within a scene in the normal manner, except that we call Present() on the swap chain interface rather than the device interface:

我们现在已经做好准备渲染视图窗口了。渲染的方法看起来和我们平常用的方法差不多,只是有一点:我们现在需要调用Swap Chain的接口,而不是Device的接口。

 

g_pd3dDevice->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,0x00000000,1.0,0);

if (SUCCEEDED(g_pd3dDevice->BeginScene())) {

   

    // rendering code goes here  渲染代码写在这里

 

    g_pd3dDevice->EndScene();

}

m_pSwapChain->Present(NULL,NULL,NULL,NULL);

 

Step 4 - Handling Resize of Child Views

第四步,子窗口的Resize问题

 

DirectX will automatically deal with changes in the child view by using a stretch blit to present the swap chain if the dimensions have client area is not the same size as the swap chain's frame buffer.  However, this may not be desirable, as it will cause aliasing if the client area is increased in size.

如果窗口的视图区大小和SwapChain的大小不一,那么DirectX将通过Stretch Blit来自动处理图像的伸缩变化。尽管这可能并不令人期待,因为这在视图区变大的时候将导致图像的模糊。

 

To prevent this, you can write a handler for the WM_SIZE message of the child window.  The handler should release the existing swap chain, and create a new swap chain using the code from Step 2.

如果要解决这个问题,您需要为子窗口的WM_SIZE消息写一段处理代码,这段代码Release已经存在的Swap Chain交换链,并且使用第二步中的代码创建一个崭新的Swap Chain交换链。

发表于 @ 2005年03月09日 22:59:00|评论(loading...)|编辑

新一篇: [荐]游戏编程的三本“新”书 | 旧一篇: 解释型脚本向编译型脚本转化的一个简单转变

评论

#noslopforever 发表于2005-03-14 22:03:00  IP: 61.54.196.*
按照文章的观点,应该给MainFrm创建一个Device,而每个View应最好建一个SwapChain,而不是Device。
您有信箱么?Happy888曾给过我一个多窗口的例子,用的就是MFC,我给你发过去。

SDK里面的说法比较模糊,用了“至少一个”,但没有说能“生成多少”:
Direct3D only hooks up the focus windows instead of the device window with the Direct3D message processing function, and only processes the focus window messages. So, the focus window should be the parent of any device window.

For any application, multiple monitor or single monitor, at least one device window must be the focus window. In practical terms, this means that you cannot use a child window of your focus window as the device window in single monitor systems. You must use the parent focus window as both the focus and device windows. For a multiple monitor system, at least one monitor must use the focus window as its device window.
#noslopforever 发表于2005-03-14 22:28:00  IP: 61.54.196.*
那个程序的做法是:当Application建立的时候就创建一个与MainWnd相关的Device,然后无论创建什么View,都使用这个Device创建一个SwapChain挂上去。
#timesking 发表于2005-03-13 16:18:00  IP: 219.237.6.*
不知道你考虑过在MDI的MFC工程里使用DirectX3D吗,每一个view要单独使用一个D3DDevice吧?那么,一个D3D对象能生成多少个Device来用呢?
#Pony 发表于2005-09-20 17:22:00  IP: 211.100.21.*
一般来说,D3D很难实现多窗口的绘制;我看了你的文章以后,觉得很有道理,相信能够解决D3D多窗口绘制的问题。不知你能否把那个例子发给我,我也想好好的研究一下。多谢!
Email: mjg_pony@163.com
#swallow 发表于2005-09-21 09:08:00  IP: 211.100.21.*
好文!发一个例子给我看看如何?0320080102@smail.tongji.edu.cn
#noslopforever 发表于2005-10-13 16:43:00  IP: 211.100.21.*
对不起,今天才有空上来,刚刚给你们法过去了,不知道是否来得及。在此表示道歉,对不起。
#荣芝 发表于2007-10-16 10:38:28  IP: 222.208.96.*
Very good,我顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶!!!!!!!!!!!!!!!!!!!
发表评论  


登录
Csdn Blog version 3.1a
Copyright © noslopforever(天堂里的死神)