Sign in to follow this  

Multiple viewports

This topic is 4199 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

Hi What I want to do is drawing to two different parts of the same window. Which is the best method, using viewports, the present parameters. I want to draw different studd to both areas and drawing them at the same time. So how should I set this up? Something like this doesnt work, why? clear() beginScene(); SetViewport(&v); // v set to one of the parts drawSomePart1(); SetViewport(&v); // v set to the other part drawSomePart2(); endScene(); present();

Share this post


Link to post
Share on other sites
Quote:
Original post by ProblemBaby
Something like this doesnt work, why?


I believe you have to wrap each viewport in its own BeginScene / EndScene pair. So something like this:


clear()
beginScene();

SetViewport(&v); // v set to one of the parts

drawSomePart1();

endScene();
beginScene();

SetViewport(&v); // v set to the other part

drawSomePart2();

endScene();
present();

Share this post


Link to post
Share on other sites
For multiple areas of the same back buffer surface in the same window, multiple viewports is indeed the way to go.

You'd use multiple swap chains if you had multiple windows; but since it's the same window, viewports are fine.


Quote:
Something like this doesnt work, why?


It should work. What problems are you experiencing with using multiple viewports?


I just modified the source of the Vertices tutorial from the SDK to illustrate this for you:

The relevent modifications are in bold; the other modifications are just for creating a second, different coloured triangle to render.

[edit]
Aaargh, the board software seems to want to eat my bold tags (GD.NET or HTML style) when they're inside a source block. Search the source for <B> to find the bits that should be bold.
[/edit]


//-----------------------------------------------------------------------------
// File: Vertices.cpp
//
// Desc: In this tutorial, we are rendering some vertices. This introduces the
// concept of the vertex buffer, a Direct3D object used to store
// vertices. Vertices can be defined any way we want by defining a
// custom structure and a custom FVF (flexible vertex format). In this
// tutorial, we are using vertices that are transformed (meaning they
// are already in 2D window coordinates) and lit (meaning we are not
// using Direct3D lighting, but are supplying our own colors).
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------


#include <d3d9.h>
#pragma warning( disable : 4996 ) // disable deprecated warning
#include <strsafe.h>
#pragma warning( default : 4996 )




//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------
LPDIRECT3D9 g_pD3D = NULL; // Used to create the D3DDevice
LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; // Our rendering device
LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; // Buffer to hold vertices
LPDIRECT3DVERTEXBUFFER9 g_pVB2 = NULL; // Buffer to hold vertices

D3DVIEWPORT9 g_VP;

// A structure for our custom vertex type
struct CUSTOMVERTEX
{
FLOAT x, y, z, rhw; // The transformed position for the vertex
DWORD color; // The vertex color
};

// Our custom FVF, which describes our custom vertex structure
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)




//-----------------------------------------------------------------------------
// Name: InitD3D()
// Desc: Initializes Direct3D
//-----------------------------------------------------------------------------
HRESULT InitD3D( HWND hWnd )
{
// Create the D3D object.
if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
return E_FAIL;

// Set up the structure used to create the D3DDevice
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = TRUE;
d3dpp.BackBufferCount = 1;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;

// Create the D3DDevice
if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &g_pd3dDevice ) ) )
{
return E_FAIL;
}
<B>
// fetch the default viewport. This is the one D3D creates automatically
// for you when you create the IDirect3DDevice
g_pd3dDevice->GetViewport(&g_VP);
</B>
return S_OK;
}




//-----------------------------------------------------------------------------
// Name: InitVB()
// Desc: Creates a vertex buffer and fills it with our vertices. The vertex
// buffer is basically just a chuck of memory that holds vertices. After
// creating it, we must Lock()/Unlock() it to fill it. For indices, D3D
// also uses index buffers. The special thing about vertex and index
// buffers is that they can be created in device memory, allowing some
// cards to process them in hardware, resulting in a dramatic
// performance gain.
//-----------------------------------------------------------------------------
HRESULT InitVB()
{
// Initialize three vertices for rendering a triangle
CUSTOMVERTEX vertices[] =
{
{ 150.0f, 50.0f, 0.5f, 1.0f, 0xffff0000, }, // x, y, z, rhw, color
{ 250.0f, 250.0f, 0.5f, 1.0f, 0xffff0000, },
{ 50.0f, 250.0f, 0.5f, 1.0f, 0xffff0000, },
};

CUSTOMVERTEX vertices2[] =
{
{ 150.0f, 50.0f, 0.5f, 1.0f, 0xff00ff00, }, // x, y, z, rhw, color
{ 250.0f, 250.0f, 0.5f, 1.0f, 0xff00ff00, },
{ 50.0f, 250.0f, 0.5f, 1.0f, 0xff00ff00, },
};


// Create the vertex buffer. Here we are allocating enough memory
// (from the default pool) to hold all our 3 custom vertices. We also
// specify the FVF, so the vertex buffer knows what data it contains.
if( FAILED( g_pd3dDevice->CreateVertexBuffer( 3*sizeof(CUSTOMVERTEX),
0, D3DFVF_CUSTOMVERTEX,
D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )
{
return E_FAIL;
}

if( FAILED( g_pd3dDevice->CreateVertexBuffer( 3*sizeof(CUSTOMVERTEX),
0, D3DFVF_CUSTOMVERTEX,
D3DPOOL_DEFAULT, &g_pVB2, NULL ) ) )
{
return E_FAIL;
}


// Now we fill the vertex buffer. To do this, we need to Lock() the VB to
// gain access to the vertices. This mechanism is required becuase vertex
// buffers may be in device memory.
VOID* pVertices;
if( FAILED( g_pVB->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 ) ) )
return E_FAIL;
memcpy( pVertices, vertices, sizeof(vertices) );
g_pVB->Unlock();

if( FAILED( g_pVB2->Lock( 0, sizeof(vertices2), (void**)&pVertices, 0 ) ) )
return E_FAIL;
memcpy( pVertices, vertices2, sizeof(vertices2) );
g_pVB2->Unlock();


return S_OK;
}




//-----------------------------------------------------------------------------
// Name: Cleanup()
// Desc: Releases all previously initialized objects
//-----------------------------------------------------------------------------
VOID Cleanup()
{
if( g_pVB != NULL )
g_pVB->Release();

if( g_pd3dDevice != NULL )
g_pd3dDevice->Release();

if( g_pD3D != NULL )
g_pD3D->Release();
}




//-----------------------------------------------------------------------------
// Name: Render()
// Desc: Draws the scene
//-----------------------------------------------------------------------------
VOID Render()
{
// Clear the backbuffer to a blue color
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 );

// Begin the scene
if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
{
<B>
// left hand side viewport
D3DVIEWPORT9 a = g_VP;
a.Width = a.Width / 2; // half the width
g_pd3dDevice->SetViewport(&a);
</B>
// draw stuff
g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );
g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 );

<B>
// right hand side viewport
D3DVIEWPORT9 b = g_VP;
b.X = b.Width / 2; // starts to the right of the left hand viewport
b.Width = b.Width / 2; // half the width
g_pd3dDevice->SetViewport(&b);
</B>
// draw stuff
g_pd3dDevice->SetStreamSource( 0, g_pVB2, 0, sizeof(CUSTOMVERTEX) );
g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 );


// End the scene
g_pd3dDevice->EndScene();
}

// Present the backbuffer contents to the display
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}




//-----------------------------------------------------------------------------
// Name: MsgProc()
// Desc: The window's message handler
//-----------------------------------------------------------------------------
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_DESTROY:
Cleanup();
PostQuitMessage( 0 );
return 0;
}

return DefWindowProc( hWnd, msg, wParam, lParam );
}




//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: The application's entry point
//-----------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
// Register the window class
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
"D3D Tutorial", NULL };
RegisterClassEx( &wc );

RECT rc = {100,100, 100+300,100+300};
AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE );

// Create the application's window
HWND hWnd = CreateWindow( "D3D Tutorial", "D3D Tutorial 02: Vertices",
WS_OVERLAPPEDWINDOW, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top,
NULL, NULL, wc.hInstance, NULL );

// Initialize Direct3D
if( SUCCEEDED( InitD3D( hWnd ) ) )
{
// Create the vertex buffer
if( SUCCEEDED( InitVB() ) )
{
// Show the window
ShowWindow( hWnd, SW_SHOWDEFAULT );
UpdateWindow( hWnd );

// Enter the message loop
MSG msg;
ZeroMemory( &msg, sizeof(msg) );
while( msg.message!=WM_QUIT )
{
if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else
Render();
}
}
}

UnregisterClass( "D3D Tutorial", wc.hInstance );
return 0;
}





Share this post


Link to post
Share on other sites
Quote:
Original post by ProblemBaby
Thanks it works, but Ive to set the viewport to the whole area before calling clear else it doesnt clear everything.


Ah yes, forgot about that! The last viewport you set can affect the subsequent Clear() call(s), so you should set the viewport back to the original size before any call to Clear().


BEWARE: the device drivers for some older graphics cards don't honour the current viewport rectangle for their Clear() calls, some didn't even honour the rectangle you pass to Clear(). Newer drivers/cards are ok, but it's something to remember if you're targetting older h/w.

Share this post


Link to post
Share on other sites

This topic is 4199 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