In realer Größe zeichnen [DirectX]



  • Sorry für den Titel, ich kann mein Problem nicht wirklich in Worte fassen...

    Ich habe heute bemerkt, dass meine 2D-Engine einen großen Fehler beim Zeichnen von Sprites macht.
    Hier ist der entscheidende Teil der Draw() - Funktion:

    //scaling = scaling(1.0f, 1.0f) !
    	sprite->Begin(D3DXSPRITE_ALPHABLEND);
    
    	//Texture is 138x137
     	D3DXVECTOR2 spriteCenter((float)width/2, (float)heigth/2);
    
    	//Rotate based on time passed
    	//float rotation = timeGetTime()/300.0f;
    
    	//Screen position of the sprite
    	D3DXVECTOR2 trans((float)posx, (float)posy);
    
    	//Build a matrix to rotate, scale and position our sprite
    	D3DXMATRIX mat;
    
    	D3DXMatrixTransformation2D(&mat, &spriteCenter, 0.0, &scaling, &spriteCenter, NULL, &trans);
    
    	//Tell the sprite about the matrix
    	sprite->SetTransform(&mat);
    
    	sprite->Draw(texture, NULL, NULL, NULL, 0xFFFFFFFF);
    	sprite->End();
    

    Folgendes Problem: Ich möchte ein Bild zeichnen lassen, das genau 100x100 Pixel groß ist. Aber im DX-Fenster sieht es dennoch größer aus als z.b. der Explorer es mir zeigt.
    Hier ein kleiner Screenshot:
    http://uppics.net/images/1298827613.jpg

    Natürlich habe ich darauf geachtet, dass ich keine Auflösung von 800x600 einstelle (die Verzerrung wäre offensichtlich), sondern die gleiche wie bei meinem Betriebssystem.

    Hat jemand eine Idee, was ich vergessen haben könnte?

    Danke im Voraus!



  • //scaling = scaling(1.0f, 1.0f)
        //Texture is 138x137
    

    Habe ich was überlesen?



  • cooky451 schrieb:

    //scaling = scaling(1.0f, 1.0f)
        //Texture is 138x137
    

    Habe ich was überlesen?

    Hoppla, einen alten Kommentar vergessen 🙄
    Vergesst den 2ten Kommentar! Die Textur ist 100x100 groß, scaling =

    scaling.x = 1.0f; scaling.y = 1.0f
    

    posx bzw. posy haben den Wert 0. Rotation wird im Moment nicht gebraucht und wurde daher auskommentiert... 😉



  • Woher weist du dass die Windows Vorschau die original Pixelgröße nimmt?
    Was passiert mit:

    D3DXVECTOR3 pos(0.0f, 0.0f, 0.0f);
    sprite->Draw(texture, 0, 0, &pos, 0xFFFFFFFF);
    


  • cooky451 schrieb:

    Woher weist du dass die Windows Vorschau die original Pixelgröße nimmt?
    Was passiert mit:

    D3DXVECTOR3 pos(0.0f, 0.0f, 0.0f);
    sprite->Draw(texture, 0, 0, &pos, 0xFFFFFFFF);
    

    1. Habs auch mit Gimp und weiteren Bildbearbeitungsprogrammen getestet, die Originalgröße ist kleiner als das DirectX - Sprite.
    Mit deinem Code passiert nichts.

    Wenn ich

    scaling.x = 0.75f; scaling.y = 0.75f;
    

    nehme, ist es etwa genauso groß wie von Windows gezeigt. Ich kann mir das leider nicht erklären... 😕

    So wird die Textur erstellt:

    D3DXCreateTextureFromFileEx(dev, filename, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, NULL, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, D3DCOLOR_XRGB(255, 0, 255), NULL, NULL, tex);
    

    Und das Sprite einfach mit:
    http://msdn.microsoft.com/en-us/library/bb172797(v=vs.85).aspx (D3DXCreateSprite)



  • Ich drücke diesen Thread nochmal nach oben, weil mich das auch interessiert.



  • Dbof schrieb:

    Mit deinem Code passiert nichts.

    Es ändert sich nichts oder das Sprite wird nicht gezeichnet?



  • Mit deinem Code ändert sich nichts, das Sprite wird immer noch >100px angezeigt.



  • Welche Grösse hat dein Backbuffer? Und welche Grösse hat das Present-Rect?

    Ich würde mal darauf tippen dass der Backbuffer beim Present hochskaliert wird...



  • zeig den code wo du die orhtogonale projektionsmatrix setzt



  • hustbaer schrieb:

    Welche Grösse hat dein Backbuffer? Und welche Grösse hat das Present-Rect?

    Ich würde mal darauf tippen dass der Backbuffer beim Present hochskaliert wird...

    Öhm, ich setze einfach mal etwas Code hier rein.

    //Presentation parameters - how the device should work like	
    	pres_param.Windowed = Windowed;
    	pres_param.SwapEffect = D3DSWAPEFFECT_DISCARD;
    	pres_param.BackBufferCount = 1;
    
    	if (!Windowed)
    	{
    	    pres_param.BackBufferWidth = width;    // set the width of the buffer
    		pres_param.BackBufferHeight = heigth;    // set the height of the buffer
    	}
    	pres_param.BackBufferFormat = (Windowed) ? D3DFMT_UNKNOWN : D3DFMT_X8R8G8B8;
    	pres_param.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
    
    	//Now create the device!
    	HRESULT hr = d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &pres_param, &d3ddev);
    

    Present-Aufruf:

    d3ddev->EndScene();
    	state = d3ddev->Present(NULL, NULL, NULL, NULL);
    

    zeig den code wo du die orhtogonale projektionsmatrix setzt.

    Tut mir Leid, ich weiß leider nicht, wovon du redest. Wie in meinem 1. Code zu sehen ist, erstelle ich eine 2D-Matrix, um das Sprite zu kontrollieren.



  • Dir sagt Projektionsmatrix nichts?



  • welche D3D Version nutzt du?



  • Vertexwahn schrieb:

    welche D3D Version nutzt du?

    Ich nutze DirectX 9.

    d3d=Direct3DCreate9(D3D_SDK_VERSION);
    

    Eisflamme schrieb:

    Dir sagt Projektionsmatrix nichts?

    Doch, aber ich habe keine in meinem Code. Die einzige Matrix, die ich brauche, ist die Transformationsmatrix, um mein Sprite zu drehen, skalieren usw. (s. 1. Post).



  • Falsch, du brauchst auch eine Projektionsmatrix.

    D3DXMATRIX ortho;
    			D3DXMATRIX identity;
    
    			D3DXMatrixIdentity(&identity);
    			D3DXMatrixOrthoLH(&ortho, m_size.x, m_size.y, -1.0f, 1.0f );
    
    			m_d3d_device->SetTransform(D3DTS_VIEW, &identity);
    			m_d3d_device->SetTransform(D3DTS_PROJECTION, &ortho);
    			m_d3d_device->SetRenderState( D3DRS_LIGHTING, TRUE );
    

    So als bsp. wo m_size hier die Größe vom Fenster ist.



  • Du brauchst nicht unbedingt eine Projektionsmatrix. Aber wenn du nicht entsprechende Vorkehrungen triffst (z.B. eben durch eine entsprechende Projektionsmatrix) dann landest du direkt im Clipspace (d.h. (-1,1) ist links oben und (1, -1) rechts unten am Bildschirm) und musst deine Koordinaten natürlich auch entsprechend wählen...



  • Gerade wenn man 2D Sprites macht kann man auch einfach pretransformed Vertices verwenden.



  • Scorcher24 schrieb:

    Falsch, du brauchst auch eine Projektionsmatrix.

    D3DXMATRIX ortho;
    			D3DXMATRIX identity;
    
    			D3DXMatrixIdentity(&identity);
    			D3DXMatrixOrthoLH(&ortho, m_size.x, m_size.y, -1.0f, 1.0f );
    
    			m_d3d_device->SetTransform(D3DTS_VIEW, &identity);
    			m_d3d_device->SetTransform(D3DTS_PROJECTION, &ortho);
    			m_d3d_device->SetRenderState( D3DRS_LIGHTING, TRUE );
    

    So als bsp. wo m_size hier die Größe vom Fenster ist.

    Und wo soll ich deinen Code reinsetzen? In der Draw-Funktion funktioniert er auf jeden Fall nicht, dann wird gar nichts mehr gezeichnet.

    hustbaer schrieb:

    Gerade wenn man 2D Sprites macht kann man auch einfach pretransformed Vertices verwenden.

    Und wie implementiere ich diese? Ich bitte um Code oder um einen geeigneten Link zum Nachlesen. 🙂



  • Wie wär's damit wenn du dir mal ein paar Artikel zum Thema Direct3D suchst und diese liest?
    Ein bisschen Eigeninitiative ist schon erforderlich wenn man etwas programmieren möchte.



  • http://msdn.microsoft.com/en-us/library/bb219690(VS.85).aspx

    und nochmal von Nvidia: http://developer.nvidia.com/attach/6586

    abgesehen davon würde ich auf D3D11 wechseln 😉


Anmelden zum Antworten