使用 DirectXTK 将纹理应用于自定义效果会导致纹理被拉伸
Applying a texture to a custom effect using DirectXTK results in the texture being stretched
我正在尝试使用 DirectXTK 应用自定义效果。效果应该是只有一个纹理的“未点亮”着色器。但由于某种原因,纹理在整个模型上都被拉伸了。我查看了渲染文档,纹理坐标似乎已正确加载,所以我不确定发生了什么。
UnlitEffect.h
#pragma once
#include <vector>
class UnlitEffect : public DirectX::IEffect, public DirectX::IEffectMatrices
{
public:
explicit UnlitEffect(ID3D11Device* device);
UnlitEffect() = default;
virtual void Apply(_In_ ID3D11DeviceContext* deviceContext) override;
virtual void GetVertexShaderBytecode(_Out_ void const** pShaderByteCode, _Out_ size_t* pByteCodeLength) override;
void SetTexture(ID3D11ShaderResourceView* value);
void XM_CALLCONV SetWorld(DirectX::FXMMATRIX value) override;
void XM_CALLCONV SetView(DirectX::FXMMATRIX value) override;
void XM_CALLCONV SetProjection(DirectX::FXMMATRIX value) override;
void XM_CALLCONV SetMatrices(DirectX::FXMMATRIX world, DirectX::CXMMATRIX view, DirectX::CXMMATRIX projection) override;
struct __declspec(align(16)) UnlitEffectConstants
{
DirectX::XMMATRIX MVP;
};
DirectX::ConstantBuffer<UnlitEffectConstants> m_constantBuffer;
protected:
Microsoft::WRL::ComPtr<ID3D11VertexShader> m_vs;
Microsoft::WRL::ComPtr<ID3D11PixelShader> m_ps;
Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> m_texture;
std::vector<uint8_t> m_vsBlob;
DirectX::SimpleMath::Matrix m_World;
DirectX::SimpleMath::Matrix m_View;
DirectX::SimpleMath::Matrix m_Projection;
DirectX::SimpleMath::Matrix m_MVP;
uint32_t m_dirtyFlags;
};
UnlitEffect.cpp
#include "pch.h"
#include "UnlitEffect.h"
#include "ReadData.h"
namespace
{
constexpr uint32_t DirtyConstantBuffer = 0x1;
constexpr uint32_t DirtyMVPMatrix= 0x2;
}
UnlitEffect::UnlitEffect(ID3D11Device* device)
:m_constantBuffer(device),m_dirtyFlags(uint32_t(-1))
{
m_vsBlob = DX::ReadData(L"Shaders/UnlitVS.cso");
DX::ThrowIfFailed(
device->CreateVertexShader(m_vsBlob.data(), m_vsBlob.size(), nullptr, m_vs.ReleaseAndGetAddressOf())
);
auto ps_blob = DX::ReadData(L"Shaders/UnlitPS.cso");
DX::ThrowIfFailed(
device->CreatePixelShader(ps_blob.data(), ps_blob.size(), nullptr, m_ps.ReleaseAndGetAddressOf())
);
}
void UnlitEffect::Apply(_In_ ID3D11DeviceContext* deviceContext)
{
if(m_dirtyFlags & DirtyMVPMatrix)
{
m_MVP = m_World * m_View;
m_MVP = m_MVP * m_Projection;
m_dirtyFlags &= ~DirtyMVPMatrix;
m_dirtyFlags |= DirtyConstantBuffer;
}
if(m_dirtyFlags & DirtyConstantBuffer)
{
UnlitEffectConstants constants;
constants.MVP = m_MVP.Transpose();
m_constantBuffer.SetData(deviceContext, constants);
m_dirtyFlags &= ~DirtyConstantBuffer;
}
auto cb = m_constantBuffer.GetBuffer();
deviceContext->VSSetConstantBuffers(0, 1, &cb);
deviceContext->PSSetShaderResources(0, 1, m_texture.GetAddressOf());
deviceContext->VSSetShader(m_vs.Get(), nullptr, 0);
deviceContext->PSSetShader(m_ps.Get(), nullptr, 0);
}
void UnlitEffect::GetVertexShaderBytecode(_Out_ void const** pShaderByteCode, _Out_ size_t* pByteCodeLength)
{
assert(pShaderByteCode != nullptr && pByteCodeLength != nullptr);
*pShaderByteCode = m_vsBlob.data();
*pByteCodeLength = m_vsBlob.size();
}
void UnlitEffect::SetTexture(ID3D11ShaderResourceView* value)
{
m_texture = value;
}
void XM_CALLCONV UnlitEffect::SetWorld(DirectX::FXMMATRIX value)
{
m_World = value;
m_dirtyFlags |= DirtyMVPMatrix;
}
void XM_CALLCONV UnlitEffect::SetView(DirectX::FXMMATRIX value)
{
m_View = value;
m_dirtyFlags |= DirtyMVPMatrix;
}
void XM_CALLCONV UnlitEffect::SetProjection(DirectX::FXMMATRIX value)
{
m_Projection = value;
m_dirtyFlags |= DirtyMVPMatrix;
}
void XM_CALLCONV UnlitEffect::SetMatrices(DirectX::FXMMATRIX world, DirectX::CXMMATRIX view, DirectX::CXMMATRIX projection)
{
m_View = view;
m_World = world;
m_Projection = projection;
m_dirtyFlags |= DirtyMVPMatrix;
}
Unlit.hlsli
#ifndef __UNLINT_HLSLI__
#define __UNLINT_HLSLI__
cbuffer UnlitConstants : register(b0)
{
float4x4 MVP;
}
struct VSOutput
{
float4 PositionPS : SV_Position;
float2 TexCoord : TEXCOORD0;
};
struct VSInput
{
float4 Position : SV_Position;
float2 TexCoord : TEXCOORD0;
};
#endif
UnlitPS.hlsl
#include "Unlit.hlsli"
Texture2D BaseColor : register(t0);
SamplerState SampleType : register(s0);
float4 main(VSOutput vout) : SV_TARGET0
{
return BaseColor.Sample(SampleType, normalize(vout.TexCoord));
}
UnlitVS.hlsl
#include "Unlit.hlsli"
VSOutput main(VSInput vin)
{
VSOutput vout;
vout.PositionPS = mul(vin.Position, MVP);
vout.TexCoord = vin.TexCoord;
return vout;
}
here is the result
Chuck Walbourn 是正确的。我的问题是我在像素着色器中标准化我的纹理坐标。
正确的代码是
return BaseColor.Sample(SampleType, vout.TexCoord);
我正在尝试使用 DirectXTK 应用自定义效果。效果应该是只有一个纹理的“未点亮”着色器。但由于某种原因,纹理在整个模型上都被拉伸了。我查看了渲染文档,纹理坐标似乎已正确加载,所以我不确定发生了什么。
UnlitEffect.h
#pragma once
#include <vector>
class UnlitEffect : public DirectX::IEffect, public DirectX::IEffectMatrices
{
public:
explicit UnlitEffect(ID3D11Device* device);
UnlitEffect() = default;
virtual void Apply(_In_ ID3D11DeviceContext* deviceContext) override;
virtual void GetVertexShaderBytecode(_Out_ void const** pShaderByteCode, _Out_ size_t* pByteCodeLength) override;
void SetTexture(ID3D11ShaderResourceView* value);
void XM_CALLCONV SetWorld(DirectX::FXMMATRIX value) override;
void XM_CALLCONV SetView(DirectX::FXMMATRIX value) override;
void XM_CALLCONV SetProjection(DirectX::FXMMATRIX value) override;
void XM_CALLCONV SetMatrices(DirectX::FXMMATRIX world, DirectX::CXMMATRIX view, DirectX::CXMMATRIX projection) override;
struct __declspec(align(16)) UnlitEffectConstants
{
DirectX::XMMATRIX MVP;
};
DirectX::ConstantBuffer<UnlitEffectConstants> m_constantBuffer;
protected:
Microsoft::WRL::ComPtr<ID3D11VertexShader> m_vs;
Microsoft::WRL::ComPtr<ID3D11PixelShader> m_ps;
Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> m_texture;
std::vector<uint8_t> m_vsBlob;
DirectX::SimpleMath::Matrix m_World;
DirectX::SimpleMath::Matrix m_View;
DirectX::SimpleMath::Matrix m_Projection;
DirectX::SimpleMath::Matrix m_MVP;
uint32_t m_dirtyFlags;
};
UnlitEffect.cpp
#include "pch.h"
#include "UnlitEffect.h"
#include "ReadData.h"
namespace
{
constexpr uint32_t DirtyConstantBuffer = 0x1;
constexpr uint32_t DirtyMVPMatrix= 0x2;
}
UnlitEffect::UnlitEffect(ID3D11Device* device)
:m_constantBuffer(device),m_dirtyFlags(uint32_t(-1))
{
m_vsBlob = DX::ReadData(L"Shaders/UnlitVS.cso");
DX::ThrowIfFailed(
device->CreateVertexShader(m_vsBlob.data(), m_vsBlob.size(), nullptr, m_vs.ReleaseAndGetAddressOf())
);
auto ps_blob = DX::ReadData(L"Shaders/UnlitPS.cso");
DX::ThrowIfFailed(
device->CreatePixelShader(ps_blob.data(), ps_blob.size(), nullptr, m_ps.ReleaseAndGetAddressOf())
);
}
void UnlitEffect::Apply(_In_ ID3D11DeviceContext* deviceContext)
{
if(m_dirtyFlags & DirtyMVPMatrix)
{
m_MVP = m_World * m_View;
m_MVP = m_MVP * m_Projection;
m_dirtyFlags &= ~DirtyMVPMatrix;
m_dirtyFlags |= DirtyConstantBuffer;
}
if(m_dirtyFlags & DirtyConstantBuffer)
{
UnlitEffectConstants constants;
constants.MVP = m_MVP.Transpose();
m_constantBuffer.SetData(deviceContext, constants);
m_dirtyFlags &= ~DirtyConstantBuffer;
}
auto cb = m_constantBuffer.GetBuffer();
deviceContext->VSSetConstantBuffers(0, 1, &cb);
deviceContext->PSSetShaderResources(0, 1, m_texture.GetAddressOf());
deviceContext->VSSetShader(m_vs.Get(), nullptr, 0);
deviceContext->PSSetShader(m_ps.Get(), nullptr, 0);
}
void UnlitEffect::GetVertexShaderBytecode(_Out_ void const** pShaderByteCode, _Out_ size_t* pByteCodeLength)
{
assert(pShaderByteCode != nullptr && pByteCodeLength != nullptr);
*pShaderByteCode = m_vsBlob.data();
*pByteCodeLength = m_vsBlob.size();
}
void UnlitEffect::SetTexture(ID3D11ShaderResourceView* value)
{
m_texture = value;
}
void XM_CALLCONV UnlitEffect::SetWorld(DirectX::FXMMATRIX value)
{
m_World = value;
m_dirtyFlags |= DirtyMVPMatrix;
}
void XM_CALLCONV UnlitEffect::SetView(DirectX::FXMMATRIX value)
{
m_View = value;
m_dirtyFlags |= DirtyMVPMatrix;
}
void XM_CALLCONV UnlitEffect::SetProjection(DirectX::FXMMATRIX value)
{
m_Projection = value;
m_dirtyFlags |= DirtyMVPMatrix;
}
void XM_CALLCONV UnlitEffect::SetMatrices(DirectX::FXMMATRIX world, DirectX::CXMMATRIX view, DirectX::CXMMATRIX projection)
{
m_View = view;
m_World = world;
m_Projection = projection;
m_dirtyFlags |= DirtyMVPMatrix;
}
Unlit.hlsli
#ifndef __UNLINT_HLSLI__
#define __UNLINT_HLSLI__
cbuffer UnlitConstants : register(b0)
{
float4x4 MVP;
}
struct VSOutput
{
float4 PositionPS : SV_Position;
float2 TexCoord : TEXCOORD0;
};
struct VSInput
{
float4 Position : SV_Position;
float2 TexCoord : TEXCOORD0;
};
#endif
UnlitPS.hlsl
#include "Unlit.hlsli"
Texture2D BaseColor : register(t0);
SamplerState SampleType : register(s0);
float4 main(VSOutput vout) : SV_TARGET0
{
return BaseColor.Sample(SampleType, normalize(vout.TexCoord));
}
UnlitVS.hlsl
#include "Unlit.hlsli"
VSOutput main(VSInput vin)
{
VSOutput vout;
vout.PositionPS = mul(vin.Position, MVP);
vout.TexCoord = vin.TexCoord;
return vout;
}
here is the result
Chuck Walbourn 是正确的。我的问题是我在像素着色器中标准化我的纹理坐标。
正确的代码是
return BaseColor.Sample(SampleType, vout.TexCoord);