DirectX viewports

Started by
23 comments, last by Evil Steve 16 years, 2 months ago
I want it so that the top left of the screen isn't always 0,0 but could be some other part of my game area (eg 100,75) where the entire game is like 4096,4096. I think I can do this with view ports so that the "view" direct x is drawing isn't alway from 0,0 and 800 wide by 600 high. However I have no idea how to use viewport or if thats even the correct way and I couldn't find anything useful online as everything seem to be for 3d but i'm useing 2d :( I'm noit sure if my D3D device is set up correctly for this so heres the code where I create the device.

//HRESULT d3d_int(int width, int height, D3DFORMAT format, bool fullscreen)
bool d3d_int (D3DFORMAT format)
{
    HRESULT hr;

    //Make Direct3D object
	d3d = Direct3DCreate9(D3D_SDK_VERSION);

    //Make sure NULL pointer was not returned
    if (!d3d) return false;

    //Get device capabilities
    ZeroMemory (&d3d_capabilities, sizeof(d3d_capabilities));
    if (FAILED(d3d->GetDeviceCaps (D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3d_capabilities))) return false;

    //Setup present parameters
	ZeroMemory(&d3d_parameters, sizeof(d3d_parameters));
    d3d_parameters.SwapEffect      = D3DSWAPEFFECT_DISCARD;
    d3d_parameters.hDeviceWindow   = cgm::hwnd;
    d3d_parameters.BackBufferCount = 1;
	d3d_parameters.EnableAutoDepthStencil = true;
	d3d_parameters.AutoDepthStencilFormat = D3DFMT_D16;

    if (fullscreen)
    {        
        d3d_parameters.Windowed = false;
        d3d_parameters.BackBufferWidth = window_width;
        d3d_parameters.BackBufferHeight = window_height;
        d3d_parameters.BackBufferFormat = format;
    }
	else
    {
        D3DDISPLAYMODE d3ddm;
        RECT rWindow;

        //Get display mode
        d3d->GetAdapterDisplayMode (D3DADAPTER_DEFAULT, &d3ddm);

        //Get window bounds
        GetClientRect (cgm::hwnd, &rWindow);

        //Setup screen dimensions
        window_width  = (unsigned short)(rWindow.right - rWindow.left);
        window_height = (unsigned short)(rWindow.bottom - rWindow.top);

        //Setup backbuffer
        d3d_parameters.Windowed = true;
        d3d_parameters.BackBufferFormat = d3ddm.Format;
        d3d_parameters.BackBufferWidth = rWindow.right - rWindow.left;
        d3d_parameters.BackBufferHeight = rWindow.bottom - rWindow.top;
    }

    //Check if hardware vertex processing is available
    if (d3d_capabilities.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
    {    
        //Create device with hardware vertex processing
		hr = d3d->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL, hwnd,
            D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3d_parameters, d3d_device);        
    }
    else
    {
        //Create device with software vertex processing
        hr = d3d->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL, hwnd,
            D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3d_parameters, &d3d_device);
    }

    //Make sure device was created
    if (FAILED(hr)) return false;

    //Set vertex shader
    d3d_device->SetVertexShader(NULL);
    d3d_device->SetFVF(cgm::d3d_vertexformat);

    //Create vertex buffer and set as stream source
	d3d_device->CreateVertexBuffer(sizeof(cgm::d3d_vertex) * 256, NULL, d3d_vertexformat, D3DPOOL_MANAGED,
                                  &d3d_vertex_buffer, NULL);
	d3d_device->SetStreamSource (0, d3d_vertex_buffer, 0, sizeof(cgm::d3d_vertex));

    //Setup rendering states
	d3d_device->SetRenderState(D3DRS_ZENABLE, FALSE);
	d3d_device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
	d3d_device->SetRenderState(D3DRS_LIGHTING, FALSE);
	cgm::d3d_device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
	d3d_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
	d3d_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
        d3d_device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
    return true;
}

Advertisement
You just need to have a form of offset in your rendering function and just add that to all x,y values. This will give the illusion of drawing at 60,800 or similar.
I did that. Then I came up with the idea of zooming in/out so relised I needed to add some scaling stuff as well.

Then I saw viewports and wondered if I was reinventing something that is done with a few simple function calls...
IDirect3DDevice9::SetViewport

Definitely would recommend viewports instead of ad-hoc modifying coordinates yourself.
link? Cause I don't know how to do any of that and google just found me the msdn2 thing that doesn't say how to do just what the params and stuff are for...
First, let me make sure I understand. I could have sworn I just saw another post that made me question my suggestion, but now it's gone? Hmmm... Anyway, are you (1) trying to scroll the view your game world but still render to the full screen? Or, are are you (2) trying to restrict the area of your rendering to a smaller sub-rectangle of the screen?
err... I'm trying to make it so my world is lets say 5000,5000 units and I want to make it so that when everything draws it's self (eg my obj_ball object calls "draw_sprite(x, y, spr_ball, 0xFF00FFFF);" so draw a sprite at it's location).

Now I want it so if my "viewport" is at 500,500 and the ball is at 600,700 the sprite gets drawn to 100,200 on the screen. But I also want this to work with zooming so...

If the screen is 800,400 and the viewport is at 500,500 and 1600 wide by 800 high then I the ball drawn to 50,100 on the screen. I also wouldn't mind being able to rotate the view but thats not on my prioity list.
Alright, my apologies then if I led you astray, this is NOT a case you should use a viewport for. This is where the View Matrix comes into play. Your objects shouldn't have to add offsets to compensate for the current View or Camera, they should get rendered appropriately when you set the view matrix. Are you using the fixed function for your rendering? Or shaders? If fixed function, then are you using device->SetTransform( D3DTS_VIEW, &viewMatrix )? And, if so, how are you computing your view matrix?
what?
this is the basic function I'm useing for drawing. All my other ones are following the same general lines.

bool draw_sprite(const int id, double x, double y){return draw_sprite(id, x, y, c_white, c_white, c_white, c_white);}bool draw_sprite(const int id, double x, double y, unsigned long c1){return draw_sprite(id, x, y, c1, c1, c1, c1);}bool draw_sprite(const int id, double x, double y, unsigned long c1, unsigned long c2, unsigned long c3, unsigned long c4){	if(!sprite_exists(id))return false;	if(d3d_lost)return true;	x -= 0.5 + cgm::sprite_list[id]->offset_x;	y -= 0.5 + cgm::sprite_list[id]->offset_y;	cgm::d3d_device->SetTexture (0, cgm::sprite_list[id]->image);	draw_quad(		x, y,		x + cgm::sprite_list[id]->w, y,		x + cgm::sprite_list[id]->w, y + cgm::sprite_list[id]->h,		x, y + cgm::sprite_list[id]->h,		c1, c2, c3, c4);}bool draw_quad(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4,  unsigned long c1, unsigned long c2, unsigned long c3, unsigned long c4){	if (d3d_lost)return true;	cgm::d3d_vertex* vertices;	cgm::d3d_vertex_buffer->Lock(0, 0, (void**)&vertices, NULL);	vertices[0].colour = c1;	vertices[0].x = (float)x1;	vertices[0].y = (float)y1;	vertices[0].z = 0.0;	vertices[0].rhw = 1.0;	vertices[0].u = 0.0;	vertices[0].v = 0.0;	vertices[1].colour = c2;	vertices[1].x = (float)x2;	vertices[1].y = (float)y2;	vertices[1].z = 0.0;	vertices[1].rhw = 1.0;	vertices[1].u = 1.0;	vertices[1].v = 0.0;	vertices[2].colour = c3;	vertices[2].x = (float)x3;	vertices[2].y = (float)y3;	vertices[2].z = 0.0;	vertices[2].rhw = 1.0;	vertices[2].u = 1.0;	vertices[2].v = 1.0;	vertices[3].colour = c4;	vertices[3].x = (float)x4;	vertices[3].y = (float)y4;	vertices[3].z = 0.0;	vertices[3].rhw = 1.0;	vertices[3].u = 0.0;	vertices[3].v = 1.0;	cgm::d3d_vertex_buffer->Unlock();	cgm::d3d_device->DrawPrimitive (D3DPT_TRIANGLEFAN, 0, 2);	return true;}
If none of that made sense, then I think maybe you need to have a look at the "Transforms" section of your DirectX sdk help file. Type in "Transforms" in the "Index" tab and it should yield a pretty useful page.

This topic is closed to new replies.

Advertisement