2011-09-24 74 views
1

我试图通过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); 
} 

VBuffer硬编码:

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

回答

3

问题是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个字节的边界。

+0

谢谢!所以,一个恒定的缓冲区总是16字节对齐? – xcrypt

+0

是的。为了安全起见,尽量使用自然对齐的类型,比如float4,float4x4等。如果需要的话,仍然可以使用包装。 –