Reputation: 3376
I'm trying to clip a texture by hardcoding the texture coordinates through 0 and 1, and then sending a constantbuffer containing a 3x3 texture transform matrix to the vertexshader.
However, the texture is not rendering as I expected it to. I'm not sure where I went wrong. Could someone help? See code below.
For testing, I'm trying to use an Identity matrix to keep the texture coordinates untouched, but the texture shows up transformed in a very weird way.
This is the texture: (the colours showing up are actually transparent areas, except the black colour and the softer red colour of the heart)
Transformed texture:
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 hardcoded:
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 )}
};
Matrix definition:
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() definition:
void GameManager::GMSetTexTransformMatrix( const XMFLOAT3X3& rkTexTransform )
{
m_pContext->UpdateSubresource(m_pTexTransformCB,0,0,&rkTexTransform,0,0);
m_pContext->VSSetConstantBuffers(2,1,&m_pTexTransformCB);
}
Buffer Initialisation:
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);
Upvotes: 1
Views: 1181
Reputation: 569
The problem is the 16 byte alignment. An XMFLOAT3X3 is just 9 floats in a row. When this gets stored in registers, its just going to take the first four floats and put them in c0, the next four in c1, and the remaining float in c2.x. You can see this yourself with the following:
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;
}
Now when you pass your XMFLOAT3X3, the texture appears normally. The problem was that because of the register allocation, your texture transform matrix became screwed up. When you look at the registers, this is how your data looks coming in:
c0: 1 0 0 0
c1: 1 0 0 0
c2: 1
float3x3's are probably an array of float3's, so it would take the first three components of each register, giving you:
1, 0, 0
1, 0, 0
1, 0, 0
Its scaling your Y to 0, which is giving that wierd stretchy look. To solve this, you're going to either have to store your transform in a 4x4 matrix, or manually assign each part of the register. Switching to three float3's wouldn't work either, because they can't cross the 16-byte boundary.
Upvotes: 3