Матрица преобразования текстуры в константном буфере не работает должным образом - PullRequest
1 голос
/ 25 сентября 2011

Я пытаюсь обрезать текстуру, жестко кодируя координаты текстуры через 0 и 1, а затем отправляя постоянный буфер, содержащий матрицу преобразования текстуры 3x3, в вершинный шейдер.

Однако текстура не отображается какЯ ожидал этого.Я не уверен, где я ошибся.Может ли кто-нибудь помочь?См. Код ниже.

Для тестирования я пытаюсь использовать матрицу идентичности, чтобы не трогать координаты текстуры, но текстура оказывается преобразованной очень странным образом.

Это текстура: (отображаемые цвета на самом деле являются прозрачными областями, за исключением черного цвета и более мягкого красного цвета сердца)

normal

Преобразованотекстура:

transformed


HLSL:

cbuffer cbChangesPerFrame : register( b0 )
{
    matrix g_Mvp;
};

cbuffer cbTexTransform : register( b2 )
{
    float3x3 g_TexTransform;
};

Texture2D g_ColorMap : register(t0);
SamplerState g_ColorSampler : register(s0);

struct VS_Input
{
    float4 pos : POSITION0;
    float2 tex0 : TEXCOORD0;
};

struct PS_Input
{
    float4 pos : SV_POSITION0;
    float2 tex0 : TEXCOORD0;
};

PS_Input VS_Main(VS_Input vertex)
{
    PS_Input vsOut = (PS_Input)0;
    vsOut.pos = mul(vertex.pos,g_Mvp);

    //vsOut.tex0 = vertex.tex0;
    float3 coord = float3(vertex.tex0, 1.0);
    coord = mul(coord, g_TexTransform);
    vsOut.tex0 = coord.xy ;

    return vsOut;
}

float4 PS_Main( PS_Input frag ) : SV_TARGET
{
    return g_ColorMap.Sample( g_ColorSampler, frag.tex0 );
}

VБуфер в жестком коде:

Vertex::PosTex vertices[]=
{
    {XMFLOAT3( 0.5f, 0.5f, 1.0f ),  XMFLOAT2( 1.0f, 0.0f )},
    {XMFLOAT3( 0.5f, -0.5f, 1.0f ), XMFLOAT2( 1.0f, 1.0f )},
    {XMFLOAT3( -0.5f, -0.5f, 1.0f ), XMFLOAT2( 0.0f, 1.0f )},

    {XMFLOAT3( -0.5f, -0.5f, 1.0f ), XMFLOAT2( 0.0f, 1.0f )},
    {XMFLOAT3( -0.5f, 0.5f, 1.0f ), XMFLOAT2( 0.0f, 0.0f )},
    {XMFLOAT3( 0.5f, 0.5f, 1.0f ),  XMFLOAT2( 1.0f, 0.0f )}
};

Определение матрицы:

XMFLOAT3X3 f3x3;
f3x3.m[0][0] = 1.0f;    f3x3.m[0][1] = 0.0f;    f3x3.m[0][2] = 0.0f;
f3x3.m[1][0] = 0.0f;    f3x3.m[1][1] = 1.0f;    f3x3.m[1][2] = 0.0f;
f3x3.m[2][0] = 0.0f;    f3x3.m[2][1] = 0.0f;    f3x3.m[2][2] = 1.0f;
GAME_MANAGER->GMSetTexTransformMatrix(f3x3);

Game_Manager GMSetTransformMatrix () определение:

void GameManager::GMSetTexTransformMatrix( const XMFLOAT3X3& rkTexTransform )
{
    m_pContext->UpdateSubresource(m_pTexTransformCB,0,0,&rkTexTransform,0,0);
    m_pContext->VSSetConstantBuffers(2,1,&m_pTexTransformCB);
}

Инициализация буфера:

ZeroMemory(&constDesc, sizeof(constDesc));
constDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
constDesc.ByteWidth = 48;
constDesc.Usage = D3D11_USAGE_DEFAULT;

result = m_pDevice->CreateBuffer(&constDesc,0,&m_pTexTransformCB);

1 Ответ

3 голосов
/ 25 сентября 2011

Проблема в 16-байтовом выравнивании.XMFLOAT3X3 - это всего 9 поплавков подряд.Когда это сохраняется в регистрах, оно просто берет первые четыре числа с плавающей запятой и помещает их в c0, следующие четыре - в c1, а оставшееся число - в c2.x.Вы можете увидеть это сами со следующим:

cbuffer cbChangesEveryFrame : register( b1 )
{

    float a1 : packoffset(c0.x);
    float a2 : packoffset(c0.y);
    float a3 : packoffset(c0.z);

    float b1 : packoffset(c0.w);
    float b2 : packoffset(c1.x);
    float b3 : packoffset(c1.y);

    float c1 : packoffset(c1.z);
    float c2 : packoffset(c1.w);
    float c3 : packoffset(c2.x);

};

PS_INPUT VS( VS_INPUT input )
{
    PS_INPUT output = (PS_INPUT)0;
    output.Pos = mul( input.Pos, World );
    output.Pos = mul( output.Pos, View );
    output.Pos = mul( output.Pos, Projection );

    float3 coord = float3(input.Tex, 1.0);

    float3x3 g_TexTransform = {a1, a2, a3, b1, b2, b3, c1, c2, c3};

    coord = mul(coord, g_TexTransform);

    output.Tex = coord.xy;

    return output;
}

Теперь, когда вы передаете свой XMFLOAT3X3, текстура выглядит нормально.Проблема заключалась в том, что из-за распределения регистров ваша матрица преобразования текстур испортилась.Когда вы смотрите на регистры, вот как выглядят ваши данные:

c0: 1 0 0 0
c1: 1 0 0 0
c2: 1

float3x3 - это, вероятно, массив float3, поэтому потребуется три первых компонента каждого регистра, давая вам:*

1, 0, 0
1, 0, 0
1, 0, 0

Его масштабирование Y до 0, что придает этому странному растягивающему виду.Чтобы решить эту проблему, вам нужно либо сохранить свое преобразование в матрице 4x4, либо вручную назначить каждую часть регистра.Переключение на три float3 также не сработает, потому что они не могут пересечь 16-байтовую границу.

...