Author Topic: letterboxing in directx  (Read 7469 times)

0 Members and 1 Guest are viewing this topic.

Offline Meduusa

  • ZX 81
  • *
  • Posts: 14
  • Karma: 1
    • View Profile
letterboxing in directx
« on: June 13, 2008 »
How can I achieve letterboxing in directx so that my graphics wont get stretched with differet aspect ratios?

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17412
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
Re: letterboxing in directx
« Reply #1 on: June 13, 2008 »
Like this?
Code: [Select]
   //45 degree field of view
   float field_of_view = (float)Math.PI / 4.0f;

   //Typical aspect ratio is approximately 1.333...
   float aspect_ratio = (float)ClientSize.Width / ClientSize.Height;

   m_device.Transform.Projection = Matrix.PerspectiveFovLH(field_of_view,
                                                           aspect_ratio,
                                                           1.0f,        //ZNear
                                                           100.0f);

Found it here;

http://www.drunkenhyena.com/cgi-bin/view_net_article.pl?chapter=2;article=27
Shockwave ^ Codigos
Challenge Trophies Won:

Offline Meduusa

  • ZX 81
  • *
  • Posts: 14
  • Karma: 1
    • View Profile
Re: letterboxing in directx
« Reply #2 on: June 13, 2008 »
I dont understand source code of those examples since they are c# and vb and i would prefere c++ or c sample

but looking at those they wont still add black lines to top and bottom if I would scale window

Offline Motorherp

  • C= 64
  • **
  • Posts: 57
  • Karma: 8
    • View Profile
    • Shmup Dev
Re: letterboxing in directx
« Reply #3 on: June 13, 2008 »
You should be able to use the above code to at least render to the correct dimensions for the inner letter box bit without distorting your image.  Probably what you'll want to do is render that to an off screen target, then clear the screen to black and render the saved target to a billboard placed in the middle of the screen.  Alternatively but somewhat wasteful you could render your scene to the back buffer as normal then turn of the depth buffer and render two black quads at the top and bottom ;p.

Offline Meduusa

  • ZX 81
  • *
  • Posts: 14
  • Karma: 1
    • View Profile
Re: letterboxing in directx
« Reply #4 on: June 13, 2008 »
Mayby I can explain myselve a litte better. If I design a program to use a 1280x720 resolution (aspec ratio 16:9) but I give user an opportunity to run a program in 1024x768 (aspect ratio 4:3). I still want to forse users to use 16:9 aspect ratio in 1024x768 mode and i can do that by adding borders to tom and bottomm but how do I add them?

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: letterboxing in directx
« Reply #5 on: June 15, 2008 »
There's no automatic setting for doing it.  You have to build a projection matrix like the one Shockwave pasted (C# code is almost identical to C++).  To get the sums right you need to know if you are already on a 16:9 screen, and then set the aspect ratio to 16/9.  If you want 16:9 on a 4:3, then it'd be 1024 x (1024*9/16) = 1024x576 with 96pixel high black bars top and bottom.

Jim
Challenge Trophies Won:

Offline Meduusa

  • ZX 81
  • *
  • Posts: 14
  • Karma: 1
    • View Profile
Re: letterboxing in directx
« Reply #6 on: June 19, 2008 »
Am I doing this right

first I create a window like
Code: [Select]
hWnd = CreateWindowEx(NULL, L"WindowClass", L"test",
                          WS_OVERLAPPED, 0, 0, 1024, 768,
                          NULL, NULL, hInstance, NULL);

Then I create device like
Code: [Select]
    d3d = Direct3DCreate9(D3D_SDK_VERSION);

    D3DPRESENT_PARAMETERS d3dpp;

    ZeroMemory(&d3dpp, sizeof(d3dpp));
    d3dpp.Windowed = true;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.hDeviceWindow = hWnd;
    d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
    d3dpp.BackBufferWidth = 1024;
    d3dpp.BackBufferHeight = 768;

    d3d->CreateDevice(D3DADAPTER_DEFAULT,
                      D3DDEVTYPE_HAL,
                      hWnd,
                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                      &d3dpp,
                      &d3ddev);

And i have
Code: [Select]
D3DXMATRIX matRotateY;

static float index = 0.0f; index+=0.05f;
D3DXMatrixRotationY(&matRotateY, index);
d3ddev->SetTransform(D3DTS_WORLD, &matRotateY);

D3DXMATRIX matView;
D3DXMatrixLookAtLH(&matView,
                       &D3DXVECTOR3 (0.0f, 0.0f, 10.0f),
                       &D3DXVECTOR3 (0.0f, 0.0f, 0.0f),
                       &D3DXVECTOR3 (0.0f, 1.0f, 0.0f));
d3ddev->SetTransform(D3DTS_VIEW, &matView);

D3DXMATRIX matProjection;
D3DXMatrixPerspectiveFovLH(&matProjection,
                               D3DXToRadian(45),
                               589824.0f,                            //is this right?
                               1.0f,
                               100.0f);
d3ddev->SetTransform(D3DTS_PROJECTION, &matProjection);

How do I add black lines since they dont come automatically?

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: letterboxing in directx
« Reply #7 on: June 24, 2008 »
Set the view to 2d (orthographic, width x height - it's another d3dx function), which should give you pixel coordinates, and draw a 1024x96 black quad top and bottom.  Or, blank the screen out each frame and just set the viewport to the widescreen rectangle.

Jim
Challenge Trophies Won:

Offline ferris

  • Pentium
  • *****
  • Posts: 841
  • Karma: 84
    • View Profile
    • Youth Uprising Home
Re: letterboxing in directx
« Reply #8 on: June 29, 2008 »
How I do it is this (it's opengl, but the function names are self-explanatory and this method should still work with direct3d):


Code: [Select]
gluPerspective(45.0,16.0 / 9.0,.2,1000.0); // FOV angle, aspect ratio (fixed), near clipping plane, far clipping plane

int bh = (getscrh() - (int) ((getaspectratio() * 9.0 / 16.0) * (float) getscrh()));

glViewport(0,bh >> 1,getscrw(),getscrh() - bh); // start x, start y, width, height

getscrw() and getscrh() are the screen width and height, and getaspectratio() is the desired aspect ratio. As you can see, how this works is, there's a regular opengl window that is fullscreen and can be any resolution. I do my whole demo in a 16:9 viewport (box where the stuff is drawn); the letterbox effect is just blank space where my opengl viewport isn't covering. Since monitors with different aspect ratios will stretch the screen horizontally (and my viewport since it's always the same width as the screen), to compensate these calculations stretch my viewport to make it taller.

I think this is what Jim was trying to explain, actually. And if you want to see a good example of this, check out Gamma by Outracks ( http://www.pouet.net/prod.php?which=30223 ) and run it windowed with different aspect ratios.
« Last Edit: June 30, 2008 by Ferris »
http://iamferris.com/
http://youth-uprising.com/

Where the fun's at.
Challenge Trophies Won: