1
\$\begingroup\$

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;
}
\$\endgroup\$
5
  • \$\begingroup\$ try using XMMatrixOrthographicRH \$\endgroup\$ – Raxvan Dec 3 '13 at 10:34
  • \$\begingroup\$ can you please remove all the non relevant parts of the code. All contexts, memory etc are not relevant. What you only need to show is the transformations part and the parameters to the projection function. \$\endgroup\$ – concept3d Dec 3 '13 at 10:38
  • \$\begingroup\$ @Raxvan i tried using XMMatrixOrthographicOffCenterRH , but the same result, showing the quad on the Bottom Left, \$\endgroup\$ – Joyal Dec 3 '13 at 10:54
  • 1
    \$\begingroup\$ Another reason for this issue could be related to the fact that screen coordinates are from (-1, -1: Top, Left) to (1, 1: Bottom Right). \$\endgroup\$ – user121635 Oct 31 '18 at 15:04
  • \$\begingroup\$ @PerpetualJ yeap i endup changing the coordinates too \$\endgroup\$ – Joyal Nov 20 '18 at 9:37
3
\$\begingroup\$

i was able to fix the problem with help of other forums, just in case somebody has this same issue this is how to fix it

swaping the viewBottom and viewTop values for the orthographic matrix should get 0,0 at the top-left of the viewport.

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

other issue i had was the sprite world matrix multiplication that should be scale * rotation * translation

XMMATRIX l_spriteWVP    = l_scale * l_rotationZ * l_translation;

and i had to set the culling mode to CULL_NONE

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);

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)},  

};
\$\endgroup\$
1
  • 1
    \$\begingroup\$ this was extremely helpful to me, thank you \$\endgroup\$ – GuidedHacking Jul 9 '20 at 20:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.