微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

DirectX纹理变形

如何解决DirectX纹理变形

| 我正在编写WIN32 DirectX 9程序,其中加载了一些纹理(一个人和一个背景)并将它们显示在屏幕上。但是,它们会变形(拉伸),而不是我在Paint中绘制的内容的一对一表示。我尝试了不同的窗口大小和不同的屏幕分辨率,但是仍然无法正常工作。 在绘制精灵之前,我可以通过调用D3DXMatrixTransformation2D来强行模仿原始事物。但是,这不能解决问题。我的程序依赖于我确切地知道该人与背景相关的位置(实际上,背景在移动并且该人停留在屏幕中间)。 我缺少一些简单的东西,还是由于某种原因我无法做到这一点?我可以提供代码,而不只是简单的解决方法,但我希望不会。根据记录,我没有收到任何错误或警告;这只是视觉和运动跟踪问题。谢谢。 编辑:这是一些代码
    //start of program
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdshow)
{

    //Define and register the Windows Class ***Function
    createWindowClass(hInstance);

    //Create the window (still not shown)
    HWND hWnd = CreateWindow(\"Sample Window Class\",\"Person With Ship\",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,800,600,NULL,hInstance,NULL);

    //Define and create the DirectX9 object ***Function
    HRESULT hr = createDirectX(hWnd);

    D3dxcreateSprite(d3dDevice,&sprite);
    D3dxcreateTextureFromFile(d3dDevice,\"landingPad2.png\",&texture);
    D3dxcreateTextureFromFile(d3dDevice,\"person.png\",&person);
    //D3dxcreateTextureFromFile(d3dDevice,\"secondRoom.png\",&secondRoom);





    //Set up text
    LPD3DXFONT mFont;
    D3dxcreateFont(d3dDevice,20,FW_BOLD,FALSE,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH | FF_DONTCARE,TEXT(\"Arial\"),&mFont );


    //Finally show window
    ShowWindow(hWnd,nCmdshow);
    UpdateWindow(hWnd);

    //setup keyboard
    RAWINPUTDEVICE Rid[1]; // array of structs for input devices
    Rid[0].usUsagePage = 1; // use 1 for most inputs
    Rid[0].usUsage = 6; //2-mouse,4-joystick,6-keyboard
    Rid[0].dwFlags = 0; //use 0
    Rid[0].hwndTarget=NULL; //use NULL
    RegisterRawInputDevices(Rid,1,sizeof(RAWINPUTDEVICE)); // registers all of the input devices


    //MAIN LOOP!!
    MSG msg;
    ZeroMemory(&msg,sizeof(msg));
    while (msg.message!=WM_QUIT) 
    {
        while(PeekMessage(&msg,0U,PM_REMOVE))
        {
            TranslateMessage(&msg);
            dispatchMessage(&msg);
        }

        updateGraphics(hr,mFont);
        updatePosition();

    }
    mFont->Release();
    texture->Release();
    return msg.wParam;
}


void createWindowClass(HINSTANCE hInstance)
{
    const LPCSTR CLASS_NAME  = \"Sample Window Class\";

    //create windows object
    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX); 
    wcex.style= CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc= (WNDPROC)WndProc;
    wcex.cbClsExtra= 0;
    wcex.cbWndExtra= 0;
    wcex.hInstance= hInstance;
    wcex.hIcon= 0;
    wcex.hCursor= LoadCursor(NULL,IDC_ARROW);
    wcex.hbrBackground= (HBrush)(COLOR_WINDOW+1);
    wcex.lpszMenuName= 0;
    wcex.lpszClassName= CLASS_NAME;
    wcex.hIconSm= 0;

    //register windows class
    RegisterClassEx(&wcex);
}

HRESULT createDirectX(HWND hWnd)
{
    //create directx object
    d3dobject = Direct3DCreate9(D3D_SDK_VERSION);
    if (d3dobject==NULL)
    {
        exit(1);
    }

    //Present Parameters struct
    D3DPRESENT_ParaMETERS presParams;

    //Sets everything to 0
    ZeroMemory(&presParams,sizeof(presParams));

    presParams.Windowed = TRUE;
    presParams.SwapEffect = D3DSWAPEFFECT_disCARD;
    presParams.BackBufferFormat = D3DFMT_UNKNowN;
    presParams.PresentationInterval = D3DPRESENT_INTERVAL_ONE;

    //DIRECT3D Stuff (not used currently)
    //presParams.EnableAutoDepthStencil = TRUE;
    //presParams.AutoDepthStencilFormat = D3DFMT_D16;
    //d3dDevice->SetRenderState(D3DRS_ZENABLE,D3DZB_TRUE);
    //D3DXMatrixIdentity( &worldMatrix );

    HRESULT hr = d3dobject->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWnd,D3DCREATE_HARDWARE_VERTEXPROCESSING,&presParams,&d3dDevice);
    return hr;
}
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WParaM wParam,LParaM lParam)
{
    switch (message) 
    {
        case WM_INPUT:
        {


            UINT bufferSize;
            GetRawInputData((HRAWINPUT)lParam,RID_INPUT,&bufferSize,sizeof (RAWINPUTHEADER));

            // Create a buffer of the correct size
            BYTE *buffer=new BYTE[bufferSize];

            // Call the function again,this time with the buffer to get the data
            GetRawInputData((HRAWINPUT)lParam,(LPVOID)buffer,sizeof (RAWINPUTHEADER));

            PRAWINPUT raw = (RAWINPUT*) buffer;

            getInput(raw);

            break;
        }
        case WM_COMMAND:
        {
            int wmId    = LOWORD(wParam); 
            int wmEvent = HIWORD(wParam); 

            // Parse the menu selections:
            switch (wmId)
            {
                case IDM_EXIT:
                   DestroyWindow(hWnd);
                break;
            }
            break;
        }
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hWnd,message,wParam,lParam);
    }
    return 0;
}

void getInput(PRAWINPUT raw)
{
    if (raw->header.dwType== RIM_TYPEKEYBOARD)
            {
                USHORT keyCode = raw->data.keyboard.VKey;

                switch(keyCode)
                {
                    case VK_LEFT:
                        keyUp=raw->data.keyboard.Flags & RI_KEY_BREAK;
                        if (keyUp == false)
                            counterTrue = true;
                        else
                            counterTrue = false;
                        break;
                    case VK_RIGHT:
                        keyUp=raw->data.keyboard.Flags & RI_KEY_BREAK;
                        if (keyUp == false)
                            clockwiseTrue = true;
                        else
                            clockwiseTrue = false;
                        break;
                    case VK_UP:
                        keyUp=raw->data.keyboard.Flags & RI_KEY_BREAK;
                        if (keyUp == false)
                            upTrue = true;
                        else
                            upTrue = false;
                        break;
                    case VK_DOWN:
                        keyUp=raw->data.keyboard.Flags & RI_KEY_BREAK;
                        if (keyUp == false)
                            downTrue = true;
                        else
                            downTrue = false;
                        break;
                    default:
                        break;
                }
                if (keyCode == \'A\')
                {
                    keyUp=raw->data.keyboard.Flags & RI_KEY_BREAK;
                    if (keyUp == false)
                        leftTrue = true;
                    else
                        leftTrue = false;
                }
                if (keyCode == \'D\')
                {
                    keyUp=raw->data.keyboard.Flags & RI_KEY_BREAK;
                    if (keyUp == false)
                        rightTrue = true;
                    else
                        rightTrue = false;
                }
                if (keyCode == \'W\')
                {
                    keyUp=raw->data.keyboard.Flags & RI_KEY_BREAK;
                    if (keyUp == false)
                        upTrue = true;
                    else
                        upTrue = false;
                }
                if (keyCode == \'S\')
                {
                    keyUp=raw->data.keyboard.Flags & RI_KEY_BREAK;
                    if (keyUp == false)
                        downTrue = true;
                    else
                        downTrue = false;
                }
        }
}

void updateGraphics(HRESULT hr,LPD3DXFONT mFont)
{
        hr = d3dDevice->Clear(0,D3DCLEAR_TARGET| D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(0,0),1.0f,0);
        hr = d3dDevice->BeginScene();



        sprite->Begin(D3DXSPRITE_ALPHABLEND);

        // Texture being used is 64 by 64:
        D3DXVECTOR2 spriteCentre=D3DXVECTOR2(rotationCenter.x,rotationCenter.y);

        // Screen position of the sprite
        D3DXVECTOR2 trans=D3DXVECTOR2(pos.x,pos.y);

        // Build our matrix to rotate,scale and position our sprite
        D3DXMATRIX mat;

        D3DXVECTOR2 scaling(0.5798f,0.784f);

        // out,scaling centre,scaling rotation,scaling,rotation centre,rotation,translation
        D3DXMatrixTransformation2D(&mat,&scaling,&spriteCentre,NULL/*&trans*/);

        // Tell the sprite about the matrix
        sprite->SetTransform(&mat);

        sprite->Draw(texture,&rotationCenter,&pos,0xFFFFFFFF);

        scaling.x = 0.53;
        scaling.y = 0.57f;

        D3DXMatrixTransformation2D(&mat,0.0,NULL/*&trans*/);
        sprite->SetTransform(&mat);

        sprite->Draw(person,&personPos,0xFFFFFFFF);

        sprite->End();

        displaySomeText(mFont);

        d3dDevice->EndScene();
        d3dDevice->Present(NULL,NULL);
}

void updatePosition()
{
        if (clockwiseTrue == true)
        {
            rotation -= (float)0.03;
        }
        else if (counterTrue == true)
        {
            rotation += (float)0.03;
        }

        if (rotation >(PI))
        {
            rotation -= (float)(2*PI);
        }
        if (rotation <= -(PI))
        {
            rotation += (float)(2*PI);
        }

        if (upTrue == true)
        {
            pos.y += (3*cos(rotation));
            pos.x += (3*sin(rotation));
        }
        else if (downTrue == true)
        {
            pos.y -= (3*cos(rotation));
            pos.x -= (3*sin(rotation));
        }

        if (leftTrue == true)
        {
            pos.x += (3*cos(rotation));
            pos.y -= (3*sin(rotation));
        }
        else if (rightTrue == true)
        {
            pos.x -= (3*cos(rotation));
            pos.y += (3*sin(rotation));
        }

        //collision detection
        if (rotation >=0 && rotation < (PI/2))
        {
            if (pos.y - (30*cos(rotation)) - (30*sin(rotation)) < -138 && pos.x < 350 && pos.x > -550)
            {
                pos.y = -142 + (30*cos(rotation)) + (30*sin(rotation));
            }
        }
        if (rotation < 0 && rotation > -(PI/2))
        {
            if (pos.y - (51*cos(rotation)) + (14*sin(rotation)) < -142 && pos.x < 350 && pos.x > -550)
            {
                pos.y = -142 + (51*cos(rotation)) - (14*sin(rotation));
            }
        }
        if (rotation < -(PI/2) && rotation > -(PI))
        {
            if (pos.y + (51*cos(rotation)) + (14*sin(rotation)) < -142 && pos.x < 350 && pos.x > -550)
            {
                pos.y = -142 - (51*cos(rotation)) - (14*sin(rotation));
            }
        }
        if (rotation > (PI/2) && rotation <= (PI))
        {
            if (pos.y + (51*cos(rotation)) - (14*sin(rotation)) < -142 && pos.x < 350 && pos.x > -550)
            {
                pos.y = -142 - (51*cos(rotation)) + (14*sin(rotation));
            }
        }
}

void displaySomeText(LPD3DXFONT mFont)
{

// Create a colour for the text - in this case blue
D3DCOLOR fontColor = D3DCOLOR_ARGB(255,255);    

// Create a rectangle to indicate where on the screen it should be drawn
RECT rct;
rct.left=200;
rct.right=780;
rct.top=10;
rct.bottom=rct.top+20;





TCHAR cX[30] = \"x\";
TCHAR cY[30] = \"y\";
TCHAR cR[30] = \"r\";
TCHAR cQ[30] = \"q\";
size_t cchDest = 30;

LPCTSTR pszFormat = TEXT(\"%f\");

HRESULT har = StringCchPrintf(cX,cchDest,pszFormat,pos.x);
HRESULT her = StringCchPrintf(cY,pos.y);
HRESULT hir = StringCchPrintf(cR,rotation);
HRESULT hur = StringCchPrintf(cQ,(pos.y - (43*cos(rotation))));


mFont->DrawText(NULL,cX,-1,&rct,fontColor);

rct.left += 100;

mFont->DrawText(NULL,cY,cR,cQ,fontColor);

}
    

解决方法

因此,最后:问题是由于纹理尺寸不是2的幂:)这种现象很常见,但仍取决于硬件:理论上可能存在一些视频卡,它们以与幂相同的方式处理任意纹理大小两种尺寸的要知道它们的作用,我们必须通过IDirect3DDevice9 :: GetDeviceCaps检查其功能。     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。