четверг, 3 мая 2012 г.

Effects in DirectX 11

Я никогда не поверю, что Microsoft сделали доброе дело, так усложнив DirectX11. Effects framework - API которое поддерживало загрузку и использование файлов эффектов сгруппированных в HLSL код, рендерринг через passes и techniques – больше не являются неотъемлемой частью D3DX. Вместо этого они предоставили исходный код этой библиотеки, и это означает, что вы можете скомпилировать его самостоятельно!

Итак сделаем это: Зайдите в DX SDK подпапку "Samples\C++\Effects11", откройте "Effects11_*.sln".

Чтобы использовать эффекты API в своем проекте вы должны включить этот заголовок: "YOUR_DX_SDK_PATH\Samples\C++\Effects11\Inc\D3dx11effect.h" and link with this lib: "YOUR_DX_SDK_PATH\Samples\C++\Effects11\Debug\D3DX11EffectsD.lib (Debug) or "YOUR_DX_SDK_PATH\Samples\C++\Effects11\Release\D3DX11Effects.lib" (Release), as well as with "d3dcompiler.lib" (в обеих конфигурациях).

Вот пример того, как загружается эффект из файла. Вы должны сначала скомпилировать исходный код из файла или из памяти в бинарный эффект (ID3D10Blob), а затем создать реальный объект эффекта из него.

// Compile effect from HLSL file into binary Blob in memory
ID3D10Blob *effectBlob = 0, *errorsBlob = 0;
HRESULT hr = D3DX11CompileFromFile("Effect1.fx", 0, 0, 0, "fx_5_0", 0, 0, 0, &effectBlob, &errorsBlob, 0);
assert(SUCCEEDED(hr) && effectBlob);
if (errorsBlob) errorsBlob->Release();
// Create D3DX11 effect from compiled binary memory block
ID3DX11Effect *g_Effect;
hr = D3DX11CreateEffectFromMemory(effectBlob->GetBufferPointer(), effectBlob->GetBufferSize(), 0, g_Dev, &g_Effect);
assert(SUCCEEDED(hr));
effectBlob->Release();

Одного эффекта не достаточно. Вам нужно получить объект, который представляет "pass" чтобы использовать его. Если вы получите технику с эффектом (по индексу или по имени), то от нее получите и "pass".

ID3DX11EffectTechnique *g_EffectTechnique; // No need to be Release()-d.
g_EffectTechnique = g_Effect->GetTechniqueByIndex(0);
assert(g_EffectTechnique && g_EffectTechnique->IsValid());
ID3DX11EffectPass *g_EffectPass; // No need to be Release()-d.
g_EffectPass = g_EffectTechnique->GetPassByIndex(0);
assert(g_EffectPass && g_EffectPass->IsValid());

Теперь у вас есть этот объект, и вы можете применить настройки этого пасса к deviceContext во время рендеринга:

g_EffectPass->Apply(0, g_Ctx);
g_Ctx->Draw(3, 0);

Но все-таки одна проблема остается. В DirectX 11 вам нужно передать указатель на байт-код  вместе со скомпилированным шейдером при создании input layout - шаг, который вы, вероятно, не можете пропустить. К счастью, есть способ получить доступ к этому указателю. Он хранится внутри загруженного эффекта. Вам просто нужно пройти через два дескриптора, как здесь:

D3DX11_PASS_SHADER_DESC effectVsDesc;
g_EffectPass->GetVertexShaderDesc(&effectVsDesc);
D3DX11_EFFECT_SHADER_DESC effectVsDesc2;
effectVsDesc.pShaderVariable->GetShaderDesc(effectVsDesc.ShaderIndex, &effectVsDesc2);
const void *vsCodePtr = effectVsDesc2.pBytecode;
unsigned vsCodeLen = effectVsDesc2.BytecodeLength;
ID3D11InputLayout *g_InputLayout;
D3D11_INPUT_ELEMENT_DESC inputDesc[] = { /* ... */ };
hr = g_Dev->CreateInputLayout( inputDesc, _countof(inputDesc), vsCodePtr, vsCodeLen, &g_InputLayout);

К счастью, дела обстоят так, что effect framework не добавляет больше функциональности чем HLSL шейдеры поддерживающиеся в D3D11, поэтому вы можете его не использовать. Определение этих методов и passess не столь важно, в конце концов ...

Комментариев нет:

Отправить комментарий

Physically Based Rendering