зеркало из https://github.com/microsoft/DirectXTK.git
735 строки
21 KiB
C++
735 строки
21 KiB
C++
//--------------------------------------------------------------------------------------
|
|
// File: PBREffect.cpp
|
|
//
|
|
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT License.
|
|
//
|
|
// http://go.microsoft.com/fwlink/?LinkID=615561
|
|
//--------------------------------------------------------------------------------------
|
|
|
|
#include "pch.h"
|
|
#include "EffectCommon.h"
|
|
|
|
namespace DirectX
|
|
{
|
|
namespace EffectDirtyFlags
|
|
{
|
|
constexpr int ConstantBufferBones = 0x100000;
|
|
}
|
|
}
|
|
|
|
using namespace DirectX;
|
|
using Microsoft::WRL::ComPtr;
|
|
|
|
namespace
|
|
{
|
|
// Constant buffer layout. Must match the shader!
|
|
struct PBREffectConstants
|
|
{
|
|
XMVECTOR eyePosition;
|
|
XMMATRIX world;
|
|
XMVECTOR worldInverseTranspose[3];
|
|
XMMATRIX worldViewProj;
|
|
XMMATRIX prevWorldViewProj; // for velocity generation
|
|
|
|
XMVECTOR lightDirection[IEffectLights::MaxDirectionalLights];
|
|
XMVECTOR lightDiffuseColor[IEffectLights::MaxDirectionalLights];
|
|
|
|
// PBR Parameters
|
|
XMVECTOR Albedo;
|
|
float Metallic;
|
|
float Roughness;
|
|
int numRadianceMipLevels;
|
|
|
|
// Size of render target
|
|
float targetWidth;
|
|
float targetHeight;
|
|
};
|
|
|
|
static_assert((sizeof(PBREffectConstants) % 16) == 0, "CB size not padded correctly");
|
|
|
|
XM_ALIGNED_STRUCT(16) BoneConstants
|
|
{
|
|
XMVECTOR Bones[SkinnedPBREffect::MaxBones][3];
|
|
};
|
|
|
|
static_assert((sizeof(BoneConstants) % 16) == 0, "CB size not padded correctly");
|
|
|
|
// Traits type describes our characteristics to the EffectBase template.
|
|
struct PBREffectTraits
|
|
{
|
|
using ConstantBufferType = PBREffectConstants;
|
|
|
|
static constexpr int VertexShaderCount = 8;
|
|
static constexpr int PixelShaderCount = 5;
|
|
static constexpr int ShaderPermutationCount = 22;
|
|
static constexpr int RootSignatureCount = 1;
|
|
};
|
|
}
|
|
|
|
// Internal PBREffect implementation class.
|
|
class PBREffect::Impl : public EffectBase<PBREffectTraits>
|
|
{
|
|
public:
|
|
explicit Impl(_In_ ID3D11Device* device);
|
|
|
|
void Initialize(_In_ ID3D11Device* device, bool enableSkinning);
|
|
|
|
ComPtr<ID3D11ShaderResourceView> albedoTexture;
|
|
ComPtr<ID3D11ShaderResourceView> normalTexture;
|
|
ComPtr<ID3D11ShaderResourceView> rmaTexture;
|
|
ComPtr<ID3D11ShaderResourceView> emissiveTexture;
|
|
|
|
ComPtr<ID3D11ShaderResourceView> radianceTexture;
|
|
ComPtr<ID3D11ShaderResourceView> irradianceTexture;
|
|
|
|
bool biasedVertexNormals;
|
|
bool velocityEnabled;
|
|
bool instancing;
|
|
int weightsPerVertex;
|
|
|
|
XMVECTOR lightColor[MaxDirectionalLights];
|
|
|
|
int GetCurrentShaderPermutation() const noexcept;
|
|
|
|
void Apply(_In_ ID3D11DeviceContext* deviceContext);
|
|
|
|
BoneConstants boneConstants;
|
|
|
|
private:
|
|
ConstantBuffer<BoneConstants> mBones;
|
|
};
|
|
|
|
|
|
// Include the precompiled shader code.
|
|
namespace
|
|
{
|
|
#if defined(_XBOX_ONE) && defined(_TITLE)
|
|
#include "XboxOnePBREffect_VSConstant.inc"
|
|
#include "XboxOnePBREffect_VSConstantBn.inc"
|
|
|
|
#include "XboxOnePBREffect_VSConstantInst.inc"
|
|
#include "XboxOnePBREffect_VSConstantBnInst.inc"
|
|
|
|
#include "XboxOnePBREffect_VSConstantVelocity.inc"
|
|
#include "XboxOnePBREffect_VSConstantVelocityBn.inc"
|
|
|
|
#include "XboxOnePBREffect_VSSkinned.inc"
|
|
#include "XboxOnePBREffect_VSSkinnedBn.inc"
|
|
|
|
#include "XboxOnePBREffect_PSConstant.inc"
|
|
#include "XboxOnePBREffect_PSTextured.inc"
|
|
#include "XboxOnePBREffect_PSTexturedEmissive.inc"
|
|
#include "XboxOnePBREffect_PSTexturedVelocity.inc"
|
|
#include "XboxOnePBREffect_PSTexturedEmissiveVelocity.inc"
|
|
#else
|
|
#include "PBREffect_VSConstant.inc"
|
|
#include "PBREffect_VSConstantBn.inc"
|
|
|
|
#include "PBREffect_VSConstantInst.inc"
|
|
#include "PBREffect_VSConstantBnInst.inc"
|
|
|
|
#include "PBREffect_VSConstantVelocity.inc"
|
|
#include "PBREffect_VSConstantVelocityBn.inc"
|
|
|
|
#include "PBREffect_VSSkinned.inc"
|
|
#include "PBREffect_VSSkinnedBn.inc"
|
|
|
|
#include "PBREffect_PSConstant.inc"
|
|
#include "PBREffect_PSTextured.inc"
|
|
#include "PBREffect_PSTexturedEmissive.inc"
|
|
#include "PBREffect_PSTexturedVelocity.inc"
|
|
#include "PBREffect_PSTexturedEmissiveVelocity.inc"
|
|
#endif
|
|
}
|
|
|
|
|
|
template<>
|
|
const ShaderBytecode EffectBase<PBREffectTraits>::VertexShaderBytecode[] =
|
|
{
|
|
{ PBREffect_VSConstant, sizeof(PBREffect_VSConstant) },
|
|
{ PBREffect_VSConstantVelocity, sizeof(PBREffect_VSConstantVelocity) },
|
|
{ PBREffect_VSConstantBn, sizeof(PBREffect_VSConstantBn) },
|
|
{ PBREffect_VSConstantVelocityBn, sizeof(PBREffect_VSConstantVelocityBn) },
|
|
|
|
{ PBREffect_VSConstantInst, sizeof(PBREffect_VSConstantInst) },
|
|
{ PBREffect_VSConstantBnInst, sizeof(PBREffect_VSConstantBnInst) },
|
|
|
|
{ PBREffect_VSSkinned, sizeof(PBREffect_VSSkinned) },
|
|
{ PBREffect_VSSkinnedBn, sizeof(PBREffect_VSSkinnedBn) },
|
|
};
|
|
|
|
|
|
template<>
|
|
const int EffectBase<PBREffectTraits>::VertexShaderIndices[] =
|
|
{
|
|
0, // constant
|
|
0, // textured
|
|
0, // textured + emissive
|
|
|
|
4, // instancing + constant
|
|
4, // instancing + textured
|
|
4, // instancing + textured + emissive
|
|
|
|
6, // skinning + constant
|
|
6, // skinning + textured
|
|
6, // skinning + textured + emissive
|
|
|
|
1, // textured + velocity
|
|
1, // textured + emissive + velocity
|
|
|
|
2, // constant (biased vertex normals)
|
|
2, // textured (biased vertex normals)
|
|
2, // textured + emissive (biased vertex normals)
|
|
|
|
5, // instancing + constant (biased vertex normals)
|
|
5, // instancing + textured (biased vertex normals)
|
|
5, // instancing + textured + emissive (biased vertex normals)
|
|
|
|
7, // skinning + constant (biased vertex normals)
|
|
7, // skinning + textured (biased vertex normals)
|
|
7, // skinning + textured + emissive (biased vertex normals)
|
|
|
|
3, // textured + velocity (biased vertex normals)
|
|
3, // textured + emissive + velocity (biased vertex normals)
|
|
};
|
|
|
|
|
|
template<>
|
|
const ShaderBytecode EffectBase<PBREffectTraits>::PixelShaderBytecode[] =
|
|
{
|
|
{ PBREffect_PSConstant, sizeof(PBREffect_PSConstant) },
|
|
{ PBREffect_PSTextured, sizeof(PBREffect_PSTextured) },
|
|
{ PBREffect_PSTexturedEmissive, sizeof(PBREffect_PSTexturedEmissive) },
|
|
{ PBREffect_PSTexturedVelocity, sizeof(PBREffect_PSTexturedVelocity) },
|
|
{ PBREffect_PSTexturedEmissiveVelocity, sizeof(PBREffect_PSTexturedEmissiveVelocity) },
|
|
};
|
|
|
|
|
|
template<>
|
|
const int EffectBase<PBREffectTraits>::PixelShaderIndices[] =
|
|
{
|
|
0, // constant
|
|
1, // textured
|
|
2, // textured + emissive
|
|
|
|
0, // instancing + constant
|
|
1, // instancing + textured
|
|
2, // instancing + textured + emissive
|
|
|
|
0, // skinning + constant
|
|
1, // skinning + textured
|
|
2, // skinning + textured + emissive
|
|
|
|
3, // textured + velocity
|
|
4, // textured + emissive + velocity
|
|
|
|
0, // constant (biased vertex normals)
|
|
1, // textured (biased vertex normals)
|
|
2, // textured + emissive (biased vertex normals)
|
|
|
|
0, // instancing + constant (biased vertex normals)
|
|
1, // instancing + textured (biased vertex normals)
|
|
2, // instancing + textured + emissive (biased vertex normals)
|
|
|
|
0, // skinning + constant (biased vertex normals)
|
|
1, // skinning + textured (biased vertex normals)
|
|
2, // skinning + textured + emissive (biased vertex normals)
|
|
|
|
3, // textured + velocity (biased vertex normals)
|
|
4, // textured + emissive + velocity (biased vertex normals)
|
|
};
|
|
|
|
// Global pool of per-device PBREffect resources. Required by EffectBase<>, but not used.
|
|
template<>
|
|
SharedResourcePool<ID3D11Device*, EffectBase<PBREffectTraits>::DeviceResources> EffectBase<PBREffectTraits>::deviceResourcesPool = {};
|
|
|
|
// Constructor.
|
|
PBREffect::Impl::Impl(_In_ ID3D11Device* device)
|
|
: EffectBase(device),
|
|
biasedVertexNormals(false),
|
|
velocityEnabled(false),
|
|
instancing(false),
|
|
weightsPerVertex(0),
|
|
lightColor{},
|
|
boneConstants{}
|
|
{
|
|
if (device->GetFeatureLevel() < D3D_FEATURE_LEVEL_10_0)
|
|
{
|
|
throw std::runtime_error("PBREffect requires Feature Level 10.0 or later");
|
|
}
|
|
|
|
static_assert(static_cast<int>(std::size(EffectBase<PBREffectTraits>::VertexShaderIndices)) == PBREffectTraits::ShaderPermutationCount, "array/max mismatch");
|
|
static_assert(static_cast<int>(std::size(EffectBase<PBREffectTraits>::VertexShaderBytecode)) == PBREffectTraits::VertexShaderCount, "array/max mismatch");
|
|
static_assert(static_cast<int>(std::size(EffectBase<PBREffectTraits>::PixelShaderBytecode)) == PBREffectTraits::PixelShaderCount, "array/max mismatch");
|
|
static_assert(static_cast<int>(std::size(EffectBase<PBREffectTraits>::PixelShaderIndices)) == PBREffectTraits::ShaderPermutationCount, "array/max mismatch");
|
|
}
|
|
|
|
void PBREffect::Impl::Initialize(_In_ ID3D11Device* device, bool enableSkinning)
|
|
{
|
|
// Lighting
|
|
static const XMVECTORF32 defaultLightDirection = { { { 0, -1, 0, 0 } } };
|
|
for (int i = 0; i < MaxDirectionalLights; i++)
|
|
{
|
|
lightColor[i] = g_XMOne;
|
|
constants.lightDirection[i] = defaultLightDirection;
|
|
constants.lightDiffuseColor[i] = g_XMZero;
|
|
}
|
|
|
|
// Default PBR values
|
|
constants.Albedo = g_XMOne;
|
|
constants.Metallic = 0.5f;
|
|
constants.Roughness = 0.2f;
|
|
constants.numRadianceMipLevels = 1;
|
|
|
|
if (enableSkinning)
|
|
{
|
|
weightsPerVertex = 4;
|
|
|
|
mBones.Create(device);
|
|
|
|
for (size_t j = 0; j < SkinnedPBREffect::MaxBones; ++j)
|
|
{
|
|
boneConstants.Bones[j][0] = g_XMIdentityR0;
|
|
boneConstants.Bones[j][1] = g_XMIdentityR1;
|
|
boneConstants.Bones[j][2] = g_XMIdentityR2;
|
|
}
|
|
}
|
|
}
|
|
|
|
int PBREffect::Impl::GetCurrentShaderPermutation() const noexcept
|
|
{
|
|
int permutation = 0;
|
|
|
|
// Using an emissive texture?
|
|
if (emissiveTexture)
|
|
{
|
|
permutation += 1;
|
|
}
|
|
|
|
if (biasedVertexNormals)
|
|
{
|
|
// Compressed normals need to be scaled and biased in the vertex shader.
|
|
permutation += 11;
|
|
}
|
|
|
|
if (weightsPerVertex > 0)
|
|
{
|
|
// Vertex skinning.
|
|
permutation += 6;
|
|
}
|
|
else if (instancing)
|
|
{
|
|
// Vertex shader needs to use vertex matrix transform.
|
|
permutation += 3;
|
|
}
|
|
else if (velocityEnabled)
|
|
{
|
|
// Optional velocity buffer (implies textured).
|
|
permutation += 9;
|
|
}
|
|
|
|
if (albedoTexture && !velocityEnabled)
|
|
{
|
|
// Textured RMA vs. constant albedo/roughness/metalness.
|
|
permutation += 1;
|
|
}
|
|
|
|
return permutation;
|
|
}
|
|
|
|
|
|
// Sets our state onto the D3D device.
|
|
void PBREffect::Impl::Apply(_In_ ID3D11DeviceContext* deviceContext)
|
|
{
|
|
assert(deviceContext != nullptr);
|
|
|
|
// Store old wvp for velocity calculation in shader
|
|
constants.prevWorldViewProj = constants.worldViewProj;
|
|
|
|
// Compute derived parameter values.
|
|
matrices.SetConstants(dirtyFlags, constants.worldViewProj);
|
|
|
|
// World inverse transpose matrix.
|
|
if (dirtyFlags & EffectDirtyFlags::WorldInverseTranspose)
|
|
{
|
|
constants.world = XMMatrixTranspose(matrices.world);
|
|
|
|
const XMMATRIX worldInverse = XMMatrixInverse(nullptr, matrices.world);
|
|
|
|
constants.worldInverseTranspose[0] = worldInverse.r[0];
|
|
constants.worldInverseTranspose[1] = worldInverse.r[1];
|
|
constants.worldInverseTranspose[2] = worldInverse.r[2];
|
|
|
|
dirtyFlags &= ~EffectDirtyFlags::WorldInverseTranspose;
|
|
dirtyFlags |= EffectDirtyFlags::ConstantBuffer;
|
|
}
|
|
|
|
// Eye position vector.
|
|
if (dirtyFlags & EffectDirtyFlags::EyePosition)
|
|
{
|
|
const XMMATRIX viewInverse = XMMatrixInverse(nullptr, matrices.view);
|
|
|
|
constants.eyePosition = viewInverse.r[3];
|
|
|
|
dirtyFlags &= ~EffectDirtyFlags::EyePosition;
|
|
dirtyFlags |= EffectDirtyFlags::ConstantBuffer;
|
|
}
|
|
|
|
if (weightsPerVertex > 0)
|
|
{
|
|
#if defined(_XBOX_ONE) && defined(_TITLE)
|
|
void* grfxMemoryBone;
|
|
mBones.SetData(deviceContext, boneConstants, &grfxMemoryBone);
|
|
|
|
ComPtr<ID3D11DeviceContextX> deviceContextX;
|
|
ThrowIfFailed(deviceContext->QueryInterface(IID_GRAPHICS_PPV_ARGS(deviceContextX.GetAddressOf())));
|
|
|
|
deviceContextX->VSSetPlacementConstantBuffer(1, mBones.GetBuffer(), grfxMemoryBone);
|
|
#else
|
|
if (dirtyFlags & EffectDirtyFlags::ConstantBufferBones)
|
|
{
|
|
mBones.SetData(deviceContext, boneConstants);
|
|
dirtyFlags &= ~EffectDirtyFlags::ConstantBufferBones;
|
|
}
|
|
|
|
ID3D11Buffer* buffer = mBones.GetBuffer();
|
|
deviceContext->VSSetConstantBuffers(1, 1, &buffer);
|
|
#endif
|
|
}
|
|
|
|
// Set the textures
|
|
if (albedoTexture)
|
|
{
|
|
ID3D11ShaderResourceView* textures[6] =
|
|
{
|
|
albedoTexture.Get(), normalTexture.Get(), rmaTexture.Get(),
|
|
emissiveTexture.Get(),
|
|
radianceTexture.Get(), irradianceTexture.Get()
|
|
};
|
|
deviceContext->PSSetShaderResources(0, 6, textures);
|
|
}
|
|
else
|
|
{
|
|
ID3D11ShaderResourceView* textures[6] =
|
|
{
|
|
nullptr, nullptr, nullptr,
|
|
nullptr,
|
|
radianceTexture.Get(), irradianceTexture.Get()
|
|
};
|
|
deviceContext->PSSetShaderResources(0, 6, textures);
|
|
}
|
|
|
|
// Set shaders and constant buffers.
|
|
ApplyShaders(deviceContext, GetCurrentShaderPermutation());
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// PBREffect
|
|
//--------------------------------------------------------------------------------------
|
|
|
|
PBREffect::PBREffect(_In_ ID3D11Device* device, bool skinningEnabled)
|
|
: pImpl(std::make_unique<Impl>(device))
|
|
{
|
|
pImpl->Initialize(device, skinningEnabled);
|
|
}
|
|
|
|
PBREffect::PBREffect(PBREffect&&) noexcept = default;
|
|
PBREffect& PBREffect::operator= (PBREffect&&) noexcept = default;
|
|
PBREffect::~PBREffect() = default;
|
|
|
|
|
|
// IEffect methods.
|
|
void PBREffect::Apply(_In_ ID3D11DeviceContext* deviceContext)
|
|
{
|
|
pImpl->Apply(deviceContext);
|
|
}
|
|
|
|
|
|
void PBREffect::GetVertexShaderBytecode(_Out_ void const** pShaderByteCode, _Out_ size_t* pByteCodeLength)
|
|
{
|
|
pImpl->GetVertexShaderBytecode(pImpl->GetCurrentShaderPermutation(), pShaderByteCode, pByteCodeLength);
|
|
}
|
|
|
|
|
|
// Camera settings.
|
|
void XM_CALLCONV PBREffect::SetWorld(FXMMATRIX value)
|
|
{
|
|
pImpl->matrices.world = value;
|
|
|
|
pImpl->dirtyFlags |= EffectDirtyFlags::WorldViewProj | EffectDirtyFlags::WorldInverseTranspose;
|
|
}
|
|
|
|
|
|
void XM_CALLCONV PBREffect::SetView(FXMMATRIX value)
|
|
{
|
|
pImpl->matrices.view = value;
|
|
|
|
pImpl->dirtyFlags |= EffectDirtyFlags::WorldViewProj | EffectDirtyFlags::EyePosition;
|
|
}
|
|
|
|
|
|
void XM_CALLCONV PBREffect::SetProjection(FXMMATRIX value)
|
|
{
|
|
pImpl->matrices.projection = value;
|
|
|
|
pImpl->dirtyFlags |= EffectDirtyFlags::WorldViewProj;
|
|
}
|
|
|
|
|
|
void XM_CALLCONV PBREffect::SetMatrices(FXMMATRIX world, CXMMATRIX view, CXMMATRIX projection)
|
|
{
|
|
pImpl->matrices.world = world;
|
|
pImpl->matrices.view = view;
|
|
pImpl->matrices.projection = projection;
|
|
|
|
pImpl->dirtyFlags |= EffectDirtyFlags::WorldViewProj | EffectDirtyFlags::WorldInverseTranspose | EffectDirtyFlags::EyePosition;
|
|
}
|
|
|
|
|
|
// Light settings
|
|
void PBREffect::SetLightingEnabled(bool value)
|
|
{
|
|
if (!value)
|
|
{
|
|
throw std::invalid_argument("PBREffect does not support turning off lighting");
|
|
}
|
|
}
|
|
|
|
|
|
void PBREffect::SetPerPixelLighting(bool)
|
|
{
|
|
// Unsupported interface method.
|
|
}
|
|
|
|
|
|
void XM_CALLCONV PBREffect::SetAmbientLightColor(FXMVECTOR)
|
|
{
|
|
// Unsupported interface.
|
|
}
|
|
|
|
|
|
void PBREffect::SetLightEnabled(int whichLight, bool value)
|
|
{
|
|
EffectLights::ValidateLightIndex(whichLight);
|
|
|
|
pImpl->constants.lightDiffuseColor[whichLight] = (value) ? pImpl->lightColor[whichLight] : g_XMZero;
|
|
|
|
pImpl->dirtyFlags |= EffectDirtyFlags::ConstantBuffer;
|
|
}
|
|
|
|
|
|
void XM_CALLCONV PBREffect::SetLightDirection(int whichLight, FXMVECTOR value)
|
|
{
|
|
EffectLights::ValidateLightIndex(whichLight);
|
|
|
|
pImpl->constants.lightDirection[whichLight] = value;
|
|
|
|
pImpl->dirtyFlags |= EffectDirtyFlags::ConstantBuffer;
|
|
}
|
|
|
|
|
|
void XM_CALLCONV PBREffect::SetLightDiffuseColor(int whichLight, FXMVECTOR value)
|
|
{
|
|
EffectLights::ValidateLightIndex(whichLight);
|
|
|
|
pImpl->lightColor[whichLight] = value;
|
|
pImpl->constants.lightDiffuseColor[whichLight] = value;
|
|
|
|
pImpl->dirtyFlags |= EffectDirtyFlags::ConstantBuffer;
|
|
}
|
|
|
|
|
|
void XM_CALLCONV PBREffect::SetLightSpecularColor(int, FXMVECTOR)
|
|
{
|
|
// Unsupported interface.
|
|
}
|
|
|
|
|
|
void PBREffect::EnableDefaultLighting()
|
|
{
|
|
EffectLights::EnableDefaultLighting(this);
|
|
}
|
|
|
|
|
|
// PBR Settings
|
|
void PBREffect::SetAlpha(float value)
|
|
{
|
|
// Set w to new value, but preserve existing xyz (constant albedo).
|
|
pImpl->constants.Albedo = XMVectorSetW(pImpl->constants.Albedo, value);
|
|
|
|
pImpl->dirtyFlags |= EffectDirtyFlags::ConstantBuffer;
|
|
}
|
|
|
|
|
|
void PBREffect::SetConstantAlbedo(FXMVECTOR value)
|
|
{
|
|
// Set xyz to new value, but preserve existing w (alpha).
|
|
pImpl->constants.Albedo = XMVectorSelect(pImpl->constants.Albedo, value, g_XMSelect1110);
|
|
|
|
pImpl->dirtyFlags |= EffectDirtyFlags::ConstantBuffer;
|
|
}
|
|
|
|
|
|
void PBREffect::SetConstantMetallic(float value)
|
|
{
|
|
pImpl->constants.Metallic = value;
|
|
|
|
pImpl->dirtyFlags |= EffectDirtyFlags::ConstantBuffer;
|
|
}
|
|
|
|
|
|
void PBREffect::SetConstantRoughness(float value)
|
|
{
|
|
pImpl->constants.Roughness = value;
|
|
|
|
pImpl->dirtyFlags |= EffectDirtyFlags::ConstantBuffer;
|
|
}
|
|
|
|
|
|
// Texture settings.
|
|
void PBREffect::SetAlbedoTexture(_In_opt_ ID3D11ShaderResourceView* value)
|
|
{
|
|
pImpl->albedoTexture = value;
|
|
}
|
|
|
|
|
|
void PBREffect::SetNormalTexture(_In_opt_ ID3D11ShaderResourceView* value)
|
|
{
|
|
pImpl->normalTexture = value;
|
|
}
|
|
|
|
|
|
void PBREffect::SetRMATexture(_In_opt_ ID3D11ShaderResourceView* value)
|
|
{
|
|
pImpl->rmaTexture = value;
|
|
}
|
|
|
|
void PBREffect::SetEmissiveTexture(_In_opt_ ID3D11ShaderResourceView* value)
|
|
{
|
|
pImpl->emissiveTexture = value;
|
|
}
|
|
|
|
|
|
void PBREffect::SetSurfaceTextures(
|
|
_In_opt_ ID3D11ShaderResourceView* albedo,
|
|
_In_opt_ ID3D11ShaderResourceView* normal,
|
|
_In_opt_ ID3D11ShaderResourceView* roughnessMetallicAmbientOcclusion)
|
|
{
|
|
pImpl->albedoTexture = albedo;
|
|
pImpl->normalTexture = normal;
|
|
pImpl->rmaTexture = roughnessMetallicAmbientOcclusion;
|
|
}
|
|
|
|
|
|
void PBREffect::SetIBLTextures(
|
|
_In_opt_ ID3D11ShaderResourceView* radiance,
|
|
int numRadianceMips,
|
|
_In_opt_ ID3D11ShaderResourceView* irradiance)
|
|
{
|
|
pImpl->radianceTexture = radiance;
|
|
pImpl->irradianceTexture = irradiance;
|
|
|
|
pImpl->constants.numRadianceMipLevels = numRadianceMips;
|
|
pImpl->dirtyFlags |= EffectDirtyFlags::ConstantBuffer;
|
|
}
|
|
|
|
|
|
// Normal compression settings.
|
|
void PBREffect::SetBiasedVertexNormals(bool value)
|
|
{
|
|
pImpl->biasedVertexNormals = value;
|
|
}
|
|
|
|
|
|
// Instancing settings.
|
|
void PBREffect::SetInstancingEnabled(bool value)
|
|
{
|
|
if (value && (pImpl->weightsPerVertex > 0))
|
|
{
|
|
throw std::invalid_argument("Instancing is not supported for SkinnedPBREffect");
|
|
}
|
|
|
|
pImpl->instancing = value;
|
|
}
|
|
|
|
|
|
// Additional settings.
|
|
void PBREffect::SetVelocityGeneration(bool value)
|
|
{
|
|
if (value && (pImpl->weightsPerVertex > 0))
|
|
{
|
|
throw std::invalid_argument("Velocity generation is not supported for SkinnedPBREffect");
|
|
}
|
|
|
|
pImpl->velocityEnabled = value;
|
|
}
|
|
|
|
|
|
void PBREffect::SetRenderTargetSizeInPixels(int width, int height)
|
|
{
|
|
pImpl->constants.targetWidth = static_cast<float>(width);
|
|
pImpl->constants.targetHeight = static_cast<float>(height);
|
|
|
|
pImpl->dirtyFlags |= EffectDirtyFlags::ConstantBuffer;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// SkinnedPBREffect
|
|
//--------------------------------------------------------------------------------------
|
|
|
|
// Animation settings.
|
|
void SkinnedPBREffect::SetWeightsPerVertex(int value)
|
|
{
|
|
if ((value != 1) &&
|
|
(value != 2) &&
|
|
(value != 4))
|
|
{
|
|
throw std::invalid_argument("WeightsPerVertex must be 1, 2, or 4");
|
|
}
|
|
|
|
pImpl->weightsPerVertex = value;
|
|
}
|
|
|
|
|
|
void SkinnedPBREffect::SetBoneTransforms(_In_reads_(count) XMMATRIX const* value, size_t count)
|
|
{
|
|
if (count > MaxBones)
|
|
throw std::invalid_argument("count parameter exceeds MaxBones");
|
|
|
|
auto boneConstant = pImpl->boneConstants.Bones;
|
|
|
|
for (size_t i = 0; i < count; i++)
|
|
{
|
|
#if DIRECTX_MATH_VERSION >= 313
|
|
XMStoreFloat3x4A(reinterpret_cast<XMFLOAT3X4A*>(&boneConstant[i]), value[i]);
|
|
#else
|
|
// Xbox One XDK has an older version of DirectXMath
|
|
XMMATRIX boneMatrix = XMMatrixTranspose(value[i]);
|
|
|
|
boneConstant[i][0] = boneMatrix.r[0];
|
|
boneConstant[i][1] = boneMatrix.r[1];
|
|
boneConstant[i][2] = boneMatrix.r[2];
|
|
#endif
|
|
}
|
|
|
|
pImpl->dirtyFlags |= EffectDirtyFlags::ConstantBufferBones;
|
|
}
|
|
|
|
|
|
void SkinnedPBREffect::ResetBoneTransforms()
|
|
{
|
|
auto boneConstant = pImpl->boneConstants.Bones;
|
|
|
|
for (size_t i = 0; i < MaxBones; ++i)
|
|
{
|
|
boneConstant[i][0] = g_XMIdentityR0;
|
|
boneConstant[i][1] = g_XMIdentityR1;
|
|
boneConstant[i][2] = g_XMIdentityR2;
|
|
}
|
|
|
|
pImpl->dirtyFlags |= EffectDirtyFlags::ConstantBufferBones;
|
|
}
|