Sign in to follow this  

How to change the region of windowed D3D8 device

This topic is 4851 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

How to change the region of windowed D3D8 device instead of just stretching/shrinking the 3D scene linearly, when change the window size? ============== Best Regards!

Share this post


Link to post
Share on other sites
Check:

IDirect3DDevice9::SetViewport(...)
IDirect3DDevice9::GetViewport(...)
and the D3DVIEWPORT9 structure.

I *think* that's what you're looking for?

Share this post


Link to post
Share on other sites
You need to reset your device.


Before resetting you have to release non-managed ressources and after resetting you ought to acquire them anew.

Take a look at the sample framework, it does that quite good.

Share this post


Link to post
Share on other sites
I have try the both method you've pointed out
1) try to change the viewport,


D3DVIEWPORT8 Viewport;

ZeroMemory(&Viewport, sizeof(Viewport));

RECT rect;
::GetClientRect(m_hWnd, &rect);

Viewport.Height = static_cast<FLOAT>(w);
Viewport.Width = static_cast<FLOAT>(h);
Viewport.MaxZ = 1000;
Viewport.MinZ = 0.001;
Viewport.X = 0;
Viewport.Y = 0;

g_pd3dDevice->SetViewport(&Viewport);



2) try to reset the device.(I have no resource to release, so the code is as below)


HRESULT hr
D3DDISPLAYMODE d3ddm;

hr = g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm);

if(FAILED(hr)) {
return hr;
}

D3DFORMAT d3dformat = D3DFMT_D16;

D3DPRESENT_PARAMETERS d3dparam;
ZeroMemory(&d3dparam, sizeof(d3dparam));

d3dparam.BackBufferFormat = d3ddm.Format;
d3dparam.Windowed = TRUE;
d3dparam.hDeviceWindow = g_hwnd;
d3dparam.EnableAutoDepthStencil = TRUE;
d3dparam.AutoDepthStencilFormat = d3dformat;
d3dparam.SwapEffect = D3DSWAPEFFECT_DISCARD;

g_pd3dDevice->Reset(&d3dparam);



but it seems no effect.
I am wonder I have not explained the effect I want to get. I want to know that using the windowed d3d device, and when the window is resized, I do not want the 3d scene zoom in/out, I want the 3d scene range enlarge/diminish and the 3d object at the same size.

[Edited by - Coder on August 27, 2004 10:01:00 AM]

Share this post


Link to post
Share on other sites
If I understand, you would have to adjust the field of view (FOV) to match the new window width and height. Modifying the FOV would keep the center of the screen the same, expanding in every direction. For instance, if a sphere is in the top, left corner, and you resize the window and change the FOV, the sphere will be closer to the center of the window now. It would expand the scene on all sides outward.

You would still have to reset the viewport also.

I'm not sure if this is entirely correct, as I haven't done it, but it seems like it would be the solution, but then again it's late and I'm tired, so sorry if it only causes the scene to "Zoom" in and out.

Chris

Share this post


Link to post
Share on other sites
WHat supernat is saying is thatyou have to change the projection matrix to match the new field of view (FOV).

Device->SetWorld( D3DTS_PROJECTION, ... );

I think that is what you want.

Share this post


Link to post
Share on other sites
Yes, sorry for that! I did mean modify the projection transform. I kind of just assumed you use the D3DX FOV function to setup your projection matrix. Oops. Anyway, that should do the trick, but the calculations might be a little tricky.

Chris

Share this post


Link to post
Share on other sites
Here is the code I've found to work for the most part. I haven't tried it in all cases.


RECT rClientArea;

GetClientRect(hWindowHandle, &rClientArea);
uiWidth = rClientArea.right - rClientArea.left;
uiHeight = rClientArea.bottom - rClientArea.top;

ppPresentParameters.BackBufferWidth = uiWidth;
ppPresentParameters.BackBufferHeight = uiHeight;
pViewManager->GetActivePerspective()->SetFovLH(PI/4*uiHeight/1024, ((float)uiWidth)/uiHeight,
1.0f, 1000.0f);





Here, replace 1024 with the max resolution of the current display. i.e. if you are running the desktop mode at 800x600, put 600 in here. Also, you may want to reset your D3D device (because you are changing the BackBuffer width and height...but you probably already do this.

Hope that helps!
Chris

EDIT: I don't know if DX8 function is different, but this is calling the D3DXMatrixPerspectiveFovLH function. The first parameter is FOV, second is Aspect Ratio, then Near Clip and then Far Clip.

Share this post


Link to post
Share on other sites
also Opalm, I just realized that when you are resetting your d3d device, you ar enot changing the BackBufferWidth and BackBufferHeight to the new window width and height. You should do that as well as remake the projection matrix.

Share this post


Link to post
Share on other sites
Thank a lot for all your suggestions. I will try your method ASAP.
In addition, I found that this problem can be solved by changing the create parameters of D3D device, when I use the following code,
-------------------------------------------------
D3DPRESENT_PARAMETERS d3dparam;
d3dparam.SwapEffect = D3DSWAPEFFECT_COPY_VSYNC/* or D3DSWAPEFFECT_COPY */;
-------------------------------------------------
the 3D scene do not zoom in/out any more when I resize the window. But when I refer to the MSDN online, it dose not describe the difference between
(D3DSWAPEFFECT_COPY,D3DSWAPEFFECT_COPY_VSYNC) and(D3DSWAPEFFECT_FLIP, D3DSWAPEFFECT_DISCARD) on this aspect. Would you please give me your advice? Thanks again!

Share this post


Link to post
Share on other sites
never seen or heard of D3DSWAPEFFECT_COPY_VSYNC before (??), it's not in the docs. But the sdk docs do explain the difference between COPY, DISCARD and FLIP very nicely, see the D3DSWAPEFFECT enum in the docs. It's all there.

Share this post


Link to post
Share on other sites
IFooBar--When I using SetViewPort, the 3D scene is stretched when resizing the window, I am wondering whether the SetViewPort has both clipping and scaling function?

Share this post


Link to post
Share on other sites
The reason your scene stretches when you resize the window is because the backbuffer is actually still the same size as the previous window size. So it has to be stretched into the new window size. Unless of course you reset the device and change the size of the back buffer. Have you tried doing that? Catch the WM_SIZE message in your window handle, calculate the new window size using GetClientRect and then set the new backbuffer size and reset the d3d device.

Also ont forget to change your projection matrix to math the new screen aspect ratio.

Share this post


Link to post
Share on other sites
Thank you!
You described very clarity, I deem that is the solution.

But to reset the device and change the back buffer size might reduce the efficiency, I think windowed mode is not suitable. Thus I should try another approach for the effect I wanted.

Share this post


Link to post
Share on other sites
Quote:
Original post by Opalm
But to reset the device and change the back buffer size might reduce the efficiency, I think windowed mode is not suitable. Thus I should try another approach for the effect I wanted.


While resetting does take up time, it is not something that is always done so it's no big deal. THe user isnt going to be resizing the window continuously right? s/he will probably size it once or twice to get the size that s/he likes, and resetting the device twice just for that is not unefficient, it's necessary if you don't want stretching to occur.

Share this post


Link to post
Share on other sites
From my understanding, the WM_SIZE message is called continuously whilst the window is being resized. This is probably not the best message to catch and use.

You may wish to try catching the WM_WINDOWPOSCHANGED message and check the resulting structure returned in LPARAM against the previous values for width and height, and only reset if the size has changed.

Share this post


Link to post
Share on other sites

This topic is 4851 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this