我试图通过将纹理坐标硬编码为0和1来剪裁纹理,然后将包含3x3纹理变换矩阵的常量缓冲区发送到顶点着色器。
然而,纹理没有像我预期的那样呈现。我不确定我哪里出错了。有人可以帮忙吗?请参阅下面的代码。
为了进行测试,我正在尝试使用Identity矩阵来保持纹理坐标不受影响,但纹理会以非常奇怪的方式显示出来。
这是纹理:(显示的颜色实际上是透明区域,除了黑色和心脏的红色外)
转换纹理
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);
答案 0 :(得分: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字节边界。