Jump to content

  • Log In with Google      Sign In   
  • Create Account

Interested in a FREE copy of HTML5 game maker Construct 2?

We'll be giving away three Personal Edition licences in next Tuesday's GDNet Direct email newsletter!

Sign up from the right-hand sidebar on our homepage and read Tuesday's newsletter for details!


[Directx 11] [2D] problem positioning a 2D quad , center starting at bottom left and not top left


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
8 replies to this topic

#1 Joyal   Members   -  Reputation: 137

Like
0Likes
Like

Posted 03 December 2013 - 06:50 AM

I'm following some tutorials of directx 11,and i was able to draw a quad, but my problem began when i was applying transforms , for some reason, my quad at position 0,0, start  at bottom left of my screen, but i want to it starts at Top Left , i don't figure out why
 
this happend when i used XMMatrixOrthographicOffCenterLH , but if i use XMMatrixOrthographicLH , it start at the center of the screen, im doing something wrong? 
 
here is some screenshots:
 
using XMMatrixOrthographicOffCenterLH : http://troll.ws/image/27213361
 
using XMMatrixOrthographicLH : http://troll.ws/image/ebf0dbc8
 
 
SpriteTest.h 

    #pragma once
    #ifndef JDX_SPRITE_TEST_H
    #define JDX_SPRITE_TEST_H


    //DX Includes
    #include <DirectXMath.h>
    using namespace DirectX;
   
    class SpriteTest{
    public:
     void Draw();
    private:
     struct ShaderParameters { XMMATRIX worldMatrix; };
     struct VERTEX { XMFLOAT3 Position; XMFLOAT4 Color; };  
    ...
    ...
    };
    #endif
SpriteTest.cpp
 
    #include "SpriteTest.h"
    using namespace DirectX;
    
    void SpriteTest::Initialize(){
    
     // load and compile the two shaders
     ID3D10Blob *VS = NULL, *PS = NULL;
    
     m_pRenderManager->CompileShader("Shaders/SpriteBatchVS.hlsl","main","vs_5_0",&VS);
     m_pRenderManager->CompileShader("Shaders/SpriteBatchPS.hlsl","main","ps_5_0",&PS);
    
    
     // encapsulate both shaders into shader objects
     m_pDevice->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &m_pVertexShader);
     m_pDevice->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &m_pPixelShader);
    
     // set the shader objects
     m_pDeviceContext->VSSetShader(m_pVertexShader, 0, 0);
     m_pDeviceContext->PSSetShader(m_pPixelShader, 0, 0);
    
     // create the input layout object
     D3D11_INPUT_ELEMENT_DESC ied[] =
     {
     {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
     {"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
     };
    
     m_pDevice->CreateInputLayout(ied, 2, VS->GetBufferPointer(), VS->GetBufferSize(), &m_pInputLayout);
     m_pDeviceContext->IASetInputLayout(m_pInputLayout);
    
    
     // __________ Init Vertex Buffer
    
     // create a triangle using the VERTEX struct
     /*
     1__3
     |\ |
     | \|
     0--2
    
     struct VERTEX { XMFLOAT3 Position; XMFLOAT4 Color; };  
     */
     VERTEX QuadVertices[] =
     {
     { XMFLOAT3(-1.0f, -1.0f, 0.0f), XMFLOAT4(1.0f, 0.0f, 0.0f, 1.0f)},
     { XMFLOAT3(-1.0f,  1.0f, 0.0f), XMFLOAT4(0.0f, 1.0f, 0.0f, 1.0f)},
     { XMFLOAT3( 1.0f, -1.0f, 0.0f), XMFLOAT4(0.0f, 0.0f, 1.0f, 1.0f)},
     { XMFLOAT3 (1.0f,  1.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f)}, 
    
     };
    
     // create the vertex buffer
     D3D11_BUFFER_DESC bd;
     ZeroMemory(&bd, sizeof(bd));
    
     bd.Usage = D3D11_USAGE_DYNAMIC;                // write access access by CPU and GPU
     bd.ByteWidth = sizeof(VERTEX) * 4;             // size is the VERTEX struct * 4
     bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;       // use as a vertex buffer
     bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;    // allow CPU to write in buffer
    
     m_pDevice->CreateBuffer(&bd, NULL, &m_pVertexBuffer);       // create the buffer
    
     // copy the vertices into the buffer
     D3D11_MAPPED_SUBRESOURCE ms;
     m_pDeviceContext->Map(m_pVertexBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms);    // map the buffer
     memcpy(ms.pData, QuadVertices, sizeof(QuadVertices));  // copy the data
     m_pDeviceContext->Unmap(m_pVertexBuffer, NULL);                                      // unmap the buffer
     
    
     // __________ Init Index Buffer
    
     WORD indices[] =
     {
     0,1,2,
     2,1,3,
     };
    
    
     D3D11_BUFFER_DESC indexDesc; 
     ZeroMemory( &indexDesc, sizeof( indexDesc ) );
     
     indexDesc.Usage = D3D11_USAGE_DEFAULT;
     indexDesc.ByteWidth = sizeof( WORD ) * 6;
     indexDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
     indexDesc.CPUAccessFlags = 0;
    
     D3D11_SUBRESOURCE_DATA indexData; 
     ZeroMemory( &indexData, sizeof( indexData ) ); 
     indexData.pSysMem = indices;
    
     m_pDevice->CreateBuffer( &indexDesc, &indexData, &m_pIndexBuffer );
    
    
     // __________ Init Constant Buffer
     D3D11_BUFFER_DESC constDesc; 
     ZeroMemory( &constDesc, sizeof( constDesc ) );
     
     constDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; 
     constDesc.ByteWidth = sizeof( XMMATRIX ); 
     constDesc.Usage = D3D11_USAGE_DEFAULT;
     
     m_pDevice->CreateBuffer( &constDesc, 0, &m_pCostantBuffer );
    
    }
    
    void SpriteTest::Draw(){
     // select which vertex buffer to display
     
     UINT stride = sizeof(VERTEX);
     UINT offset = 0;
     m_pDeviceContext->IASetVertexBuffers(0, 1, &m_pVertexBuffer, &stride, &offset);
     
     // select which primtive type we are using
     m_pDeviceContext->IASetIndexBuffer( m_pIndexBuffer, DXGI_FORMAT_R16_UINT, 0 );
     m_pDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
    
     XMMATRIX view = XMMatrixIdentity(); 
     //XMMATRIX projection = XMMatrixOrthographicLH( 1024, 768, 0.0f, 100.0f );
     XMMATRIX projection  = XMMatrixOrthographicOffCenterLH( 0.0f,(float)m_pRenderManager->GetWidth(),0.0f,(float) m_pRenderManager->GetHeight(), 0.0f, 100.0f );
     XMMATRIX worldMatrix = XMMatrixMultiply( view, projection );
    
     ShaderParameters shaderParameters;
    
     // __________ Sprite World Coordinates
     float spriteWidth  = 32.0f,
       spriteHeight = 32.0f,
       spritePosX = 0.0f,
       spritePosY = 0.0f;
    
     XMMATRIX l_translation = XMMatrixTranslation(spritePosX, spritePosY, 0.0f ); 
     XMMATRIX l_rotationZ = XMMatrixRotationZ( 0.0f ); 
     XMMATRIX l_scale = XMMatrixScaling( 1.0f * spriteWidth,1.0f * spriteHeight, 1.0f );
     XMMATRIX l_spriteWVP  = l_translation * l_rotationZ * l_scale;
    
     // __________ Prepare World Coordinates to send to the shader
     XMMATRIX l_worldMatrix = XMMatrixMultiply( l_spriteWVP, worldMatrix ); 
     l_worldMatrix = XMMatrixTranspose( l_worldMatrix );
    
     shaderParameters.worldMatrix = l_worldMatrix;
     
     m_pDeviceContext->UpdateSubresource( m_pCostantBuffer, 0, NULL, &shaderParameters, 0, 0 );  
     m_pDeviceContext->VSSetConstantBuffers( 0, 1, &m_pCostantBuffer );
     
     m_pDeviceContext->DrawIndexed( 6, 0, 0 );
     
    }
vertex shader:
 
    cbuffer cbParameters : register( b0 ) { 
     float4x4 worldMatrix; 
    };
    
    struct VOut
    {
     float4 position : SV_POSITION;
     float4 color : COLOR;
    };
    
    VOut main(float4 position : POSITION, float4 color : COLOR)
    {
     VOut output;
    
     output.position = mul(position,worldMatrix);
     output.color = color;
    
     return output;
    }
 
pixel shader:
 
    float4 main(float4 position : SV_POSITION, float4 color : COLOR) : SV_TARGET
    {
     return color;
    }

 



Sponsor:

#2 Dave Hunt   Crossbones+   -  Reputation: 2468

Like
1Likes
Like

Posted 03 December 2013 - 12:32 PM

Swap the viewBottom and viewTop values for the orthographic matrix:

 

XMMatrixOrthographicOffCenterLH( 0.0f,(float)m_pRenderManager->GetWidth(),(float) m_pRenderManager->GetHeight(), 0.0f, 0.0f, 100.0f );

 

That should get 0,0 at the top-left of the viewport.


Edited by Dave Hunt, 03 December 2013 - 12:33 PM.


#3 Joyal   Members   -  Reputation: 137

Like
0Likes
Like

Posted 03 December 2013 - 01:19 PM

Swap the viewBottom and viewTop values for the orthographic matrix:

 

XMMatrixOrthographicOffCenterLH( 0.0f,(float)m_pRenderManager->GetWidth(),(float) m_pRenderManager->GetHeight(), 0.0f, 0.0f, 100.0f );

 

That should get 0,0 at the top-left of the viewport.

 

just tried but nothing showing on the window, all black, i change the position of the sprite, but nothing



#4 unbird   Crossbones+   -  Reputation: 5498

Like
1Likes
Like

Posted 03 December 2013 - 02:01 PM

Lucky guess: If don't set a rasterizer state explicitly the default is used, which culls backfacing triangles (with the new projection they got flipped). Use one with D3D11_CULL_FRONT (or D3D11_CULL_NONE) or flip your triangles.



#5 Dave Hunt   Crossbones+   -  Reputation: 2468

Like
1Likes
Like

Posted 03 December 2013 - 02:56 PM

Your l_spriteWVP matrix is wrong. The multiplication order should be scale * rotation * translation, not the other way around.

 

Also, I'm a bit confused by your matrix names and usages. You are including sprite position (translation) in your l_spriteWVP matrix, then multiplying that by another matrix (worldMatrix (which is really view * projection)) and setting that result on your shader as the world matrix. Then in your shader, you are multiplying the sprite position by the world matrix again. I'm pretty sure that's going to give strange results.

 

I would strongly recommend using the DirectX Tool Kit for sprite drawing. It's an official MS tool kit and takes care of all this for you. If you want to learn how to do it yourself, all the source code for the tool kit is available for your perusal.



#6 Joyal   Members   -  Reputation: 137

Like
0Likes
Like

Posted 03 December 2013 - 04:14 PM

Lucky guess: If don't set a rasterizer state explicitly the default is used, which culls backfacing triangles (with the new projection they got flipped). Use one with D3D11_CULL_FRONT (or D3D11_CULL_NONE) or flip your triangles.

 

@unbird , indeep change the culling to D3D11_CULL_NONE, is showing the QUAD but now i have this error http://screencast.com/t/S2ZsYcqQdkAG , i create the rasterizer after i create the Render Target

    D3D11_RASTERIZER_DESC rasterizerState;
    ZeroMemory(&rasterizerState, sizeof(D3D11_RASTERIZER_DESC));

    rasterizerState.AntialiasedLineEnable = false;
    rasterizerState.CullMode = D3D11_CULL_NONE; // D3D11_CULL_FRONT or D3D11_CULL_NONE D3D11_CULL_BACK
    rasterizerState.FillMode = D3D11_FILL_SOLID; // D3D11_FILL_SOLID  D3D11_FILL_WIREFRAME
    rasterizerState.DepthBias = 0;
    rasterizerState.DepthBiasClamp = 0.0f;
    rasterizerState.DepthClipEnable = true;
    rasterizerState.FrontCounterClockwise = false;
    rasterizerState.MultisampleEnable = false;
    rasterizerState.ScissorEnable = false;
    rasterizerState.SlopeScaledDepthBias = 0.0f;

    result = m_pDevice->CreateRasterizerState( &rasterizerState, &m_pRasterState );
    m_pDeviceContext->RSSetState(m_pRasterState);

 

Swap the viewBottom and viewTop values for the orthographic matrix:

 

XMMatrixOrthographicOffCenterLH( 0.0f,(float)m_pRenderManager->GetWidth(),(float) m_pRenderManager->GetHeight(), 0.0f, 0.0f, 100.0f );

 

That should get 0,0 at the top-left of the viewport.

 

just tried but nothing showing on the window, all black, i change the position of the sprite, but nothing

 

@davehunt after i change the culling settings, is showing at the TOP LEFT using the XMMatrixOrthographicOffCenterLH you gave me

 

Your l_spriteWVP matrix is wrong. The multiplication order should be scale * rotation * translation, not the other way around.

 

Also, I'm a bit confused by your matrix names and usages. You are including sprite position (translation) in your l_spriteWVP matrix, then multiplying that by another matrix (worldMatrix (which is really view * projection)) and setting that result on your shader as the world matrix. Then in your shader, you are multiplying the sprite position by the world matrix again. I'm pretty sure that's going to give strange results.

 

I would strongly recommend using the DirectX Tool Kit for sprite drawing. It's an official MS tool kit and takes care of all this for you. If you want to learn how to do it yourself, all the source code for the tool kit is available for your perusal.

 

spriteWVP multiplication was in deep wrong, i change to scale * rotation * translation, and is also positioning the sprite where they should

 

i create a worldMatrix that is the global matrix of the world, in this case is the screen coords , viewMatrix is XMMatrixIdentity  because i don't new a Look Up view that is normaly used for 3d,

 

then i need the actual matrix from the sprite, that needs to be multiply by the Screen coords, that is why is multiply with the "worldmatrix"

 

the last one you mention is the shader , that position is not the sprite position, is the position of each vertex , that need to be multiply with the entire worldmatrix to be converted to world coordinates, in this case, screen coords


Edited by Joyal, 03 December 2013 - 05:30 PM.


#7 Dave Hunt   Crossbones+   -  Reputation: 2468

Like
0Likes
Like

Posted 03 December 2013 - 06:41 PM

the last one you mention is the shader , that position is not the sprite position, is the position of each vertex , that need to be multiply with the entire worldmatrix to be converted to world coordinates, in this case, screen coords

 

Doh! I knew that, but I still had sprite positions on the brain. ;-)

 

You are correct.



#8 Joyal   Members   -  Reputation: 137

Like
0Likes
Like

Posted 04 December 2013 - 07:34 AM

@unbird , indeep change the culling to D3D11_CULL_NONE, is showing the QUAD but now i have this error http://screencast.com/t/S2ZsYcqQdkAG , i create the rasterizer after i create the Render Target

 

 

i rebuilt the entire solution and somehow it fixed that error



#9 Joyal   Members   -  Reputation: 137

Like
0Likes
Like

Posted 05 December 2013 - 08:26 AM

i also realized the quad was mirror-like (all inverse), after i applied those changes, but i was able to fix it changing the vertex position when i create the vertex buffer
 
    VERTEX QuadVertices[] =
    {
        { XMFLOAT3( 0.0f,  1.0f, 0.0f), XMFLOAT4(1.0f, 0.0f, 0.0f, 1.0f)},
        { XMFLOAT3( 0.0f,  0.0f, 0.0f), XMFLOAT4(0.0f, 1.0f, 0.0f, 1.0f)},
        { XMFLOAT3( 1.0f,  1.0f, 0.0f), XMFLOAT4(0.0f, 0.0f, 1.0f, 1.0f)},
        { XMFLOAT3 (1.0f,  0.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f)},  


    };

Edited by Joyal, 05 December 2013 - 08:27 AM.





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS