Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Feljegyzés
Ez a cikk az örökölt WinRT natív API-kkal kapcsolatos. Új natív alkalmazásprojektekhez az OpenXR API használatát javasoljuk.
A Windows Mixed Reality a DirectX-re épül, így gazdag, 3D grafikus élményt biztosít a felhasználóknak. A renderelési absztrakció közvetlenül a DirectX fölött helyezkedik el, amely lehetővé teszi az alkalmazások számára a rendszer által előrejelzett holografikus jelenetmegjelenítők pozícióját és tájolását. A fejlesztő ezután megkeresheti a hologramokat az egyes kamerák alapján, így az alkalmazás ezeket a hologramokat különböző térbeli koordináta-rendszerekben jeleníti meg a felhasználó mozgása során.
Megjegyzés: Ez az útmutató a Direct3D 11 holografikus renderelését ismerteti. A Mixed Reality alkalmazássablonok bővítménye egy Direct3D 12 Windows Mixed Reality alkalmazássablont is biztosít.
Az aktuális keret frissítése
A hologramok alkalmazásállapotának frissítéséhez keretenként egyszer az alkalmazás a következőt fogja tenni:
- HolographicFrame lekérése a megjelenítési felügyeleti rendszerből.
- Frissítse a jelenetet az aktuális előrejelzéssel arra, hogy hol lesz a kameranézet a renderelés befejezésekor. Vegye figyelembe, hogy a holografikus jelenethez több kamera is lehet.
A holografikus kameranézetek megjelenítéséhez az alkalmazás keretenként egyszer a következőket fogja tenni:
- Minden kamera esetében renderelje az aktuális keret jelenetét a kameranézet és a rendszerből származó vetítési mátrixok használatával.
Új holografikus keret létrehozása és előrejelzésének lekérése
A HolographicFrame olyan információkkal rendelkezik, amelyeket az alkalmazásnak frissítenie kell és renderelnie kell az aktuális keretet. Az alkalmazás a CreateNextFrame metódus meghívásával indítja el az egyes új kereteket. A metódus meghívásakor az előrejelzések a legújabb elérhető érzékelőadatokkal jönnek létre, és a CurrentPrediction objektumba ágyazódnak.
Minden renderelt kerethez új keretobjektumot kell használni, mivel az csak egy pillanatig érvényes. A CurrentPrediction tulajdonság olyan információkat tartalmaz, mint a kamera helyzete. Az információk pontosan arra az időpontra lesznek extrapolálva, amikor a keret várhatóan látható lesz a felhasználó számára.
A következő kód az AppMain::Update elemből származik:
// The HolographicFrame has information that the app needs in order
// to update and render the current frame. The app begins each new
// frame by calling CreateNextFrame.
HolographicFrame holographicFrame = m_holographicSpace.CreateNextFrame();
// Get a prediction of where holographic cameras will be when this frame
// is presented.
HolographicFramePrediction prediction = holographicFrame.CurrentPrediction();
Kamerafrissítések feldolgozása
A háttérpufferek keretről keretre válthatnak. Az alkalmazásnak ellenőriznie kell az egyes kamerák háttérpufferét, és szükség szerint ki kell szabadítnia és újra létre kell hoznia az erőforrásnézeteket és a mélységi puffereket. Figyelje meg, hogy az előrejelzésben szereplő pózok halmaza az aktuális keretben használt kamerák mérvadó listája. Általában ezzel a listával iterálhat a kamerák készletén.
Forrás : AppMain::Update:
m_deviceResources->EnsureCameraResources(holographicFrame, prediction);
DeviceResources ::EnsureCameraResources:
for (HolographicCameraPose const& cameraPose : prediction.CameraPoses())
{
HolographicCameraRenderingParameters renderingParameters = frame.GetRenderingParameters(cameraPose);
CameraResources* pCameraResources = cameraResourceMap[cameraPose.HolographicCamera().Id()].get();
pCameraResources->CreateResourcesForBackBuffer(this, renderingParameters);
}
A leképezés alapjául szolgáló koordinátarendszer lekérése
A Windows Mixed Reality lehetővé teszi, hogy az alkalmazás különböző koordinátarendszereket hozzon létre, például csatolt és helyhez kötött referenciakereteket a fizikai világ helyeinek nyomon követéséhez. Az alkalmazás ezután ezeket a koordináta-rendszereket használhatja arra, hogy megindokolja az egyes keretek hologramjait. Amikor koordinátákat kér egy API-tól, mindig a SpatialCoordinateSystembe kerül, amelyen belül meg szeretné adni ezeket a koordinátákat.
Forrás : AppMain::Update:
pose = SpatialPointerPose::TryGetAtTimestamp(
m_stationaryReferenceFrame.CoordinateSystem(), prediction.Timestamp());
Ezek a koordinátarendszerek ezután sztereó nézet-mátrixok létrehozására használhatók a jelenet tartalmának megjelenítésekor.
A CameraResourcesból::UpdateViewProjectionBuffer:
// Get a container object with the view and projection matrices for the given
// pose in the given coordinate system.
auto viewTransformContainer = cameraPose.TryGetViewTransform(coordinateSystem);
Folyamatnézet és kézmozdulatok bemenete
A tekintet és a kézi bevitel nem időalapú, és nem kell frissítenie a StepTimer függvényben. Ezt a bemenetet azonban az alkalmazásnak meg kell vizsgálnia az egyes kereteken.
Időalapú frissítések feldolgozása
Minden valós idejű renderelő alkalmazásnak szüksége lesz valamilyen módon az időalapú frissítések feldolgozására – a Windows Holographic alkalmazássablon a DirectX 11 UWP alkalmazássablonban megadott StepTimer-implementációhoz hasonló StepTimer-implementációt használ. Ez a StepTimer-minta segédosztály rögzített időlépési frissítéseket, változó időlépés-frissítéseket, az alapértelmezett mód pedig a változó időlépések.
A holografikus rendereléshez úgy döntöttünk, hogy nem helyezünk túl sokat az időzítőfüggvénybe, mert konfigurálhatja rögzített időlépésként. Előfordulhat, hogy a rendszer képkockánként többször hívja meg – vagy egyáltalán nem, néhány képkockánál –, és a holografikus adatfrissítéseknek keretenként egyszer kell történniük.
Forrás : AppMain::Update:
m_timer.Tick([this]()
{
m_spinningCubeRenderer->Update(m_timer);
});
Hologramok elhelyezése és elforgatása a koordináta-rendszerben
Ha egyetlen koordinátarendszerben dolgozik, ahogyan a sablon a SpatialStationaryReferenceFrame-ben is, ez a folyamat nem különbözik a 3D-s ábrákban használttól. Itt elforgatjuk a kockát, és beállítjuk a modellmátrixot a helyhez kötött koordináta-rendszerben elfoglalt pozíció alapján.
Forrás: SpinningCubeRenderer::Update:
// Rotate the cube.
// Convert degrees to radians, then convert seconds to rotation angle.
const float radiansPerSecond = XMConvertToRadians(m_degreesPerSecond);
const double totalRotation = timer.GetTotalSeconds() * radiansPerSecond;
const float radians = static_cast<float>(fmod(totalRotation, XM_2PI));
const XMMATRIX modelRotation = XMMatrixRotationY(-radians);
// Position the cube.
const XMMATRIX modelTranslation = XMMatrixTranslationFromVector(XMLoadFloat3(&m_position));
// Multiply to get the transform matrix.
// Note that this transform does not enforce a particular coordinate system. The calling
// class is responsible for rendering this content in a consistent manner.
const XMMATRIX modelTransform = XMMatrixMultiply(modelRotation, modelTranslation);
// The view and projection matrices are provided by the system; they are associated
// with holographic cameras, and updated on a per-camera basis.
// Here, we provide the model transform for the sample hologram. The model transform
// matrix is transposed to prepare it for the shader.
XMStoreFloat4x4(&m_modelConstantBufferData.model, XMMatrixTranspose(modelTransform));
Megjegyzés a speciális forgatókönyvekről: A forgó kocka egy egyszerű példa arra, hogyan helyezhet el hologramot egyetlen referenciakereten belül. Egyszerre több SpatialCoordinateSystems is használható ugyanabban a renderelt keretben.
Állandó pufferadatok frissítése
A tartalom modellátalakításai a szokásos módon frissülnek. Mostanra már érvényes átalakításokat kell kiszámítania ahhoz a koordinátarendszerhez, amelyben renderelni fog.
Forrás: SpinningCubeRenderer::Update:
// Update the model transform buffer for the hologram.
context->UpdateSubresource(
m_modelConstantBuffer.Get(),
0,
nullptr,
&m_modelConstantBufferData,
0,
0
);
Mi a helyzet a nézet- és vetítésátalakításokkal? A legjobb eredmény érdekében meg szeretnénk várni, amíg majdnem készen állunk a hívásainkra, mielőtt megkapnánk ezeket.
Az aktuális keret megjelenítése
A Windows Mixed Reality renderelése nem sokban különbözik a 2D-s monokijelzők renderelésétől, de van néhány különbség:
- A holografikus keret előrejelzései fontosak. Minél közelebb van az előrejelzés a keret megjelenéséhez, annál jobb lesz a hologramok megjelenése.
- A Windows Mixed Reality vezérli a kameranézeteket. Renderelje mindegyikre, mert a holografikus keret később bemutatja őket.
- Azt javasoljuk, hogy a renderelési céltömbhöz példányos rajz használatával végezjön sztereó renderelést. A holografikus alkalmazássablon a példányos rajz javasolt megközelítését használja egy renderelési céltömbhöz, amely renderelési célnézetet használ a Texture2DArray-ra.
- Ha sztereó instancing használata nélkül szeretne renderelni, két nem tömbön kívüli RenderTargetView-t kell létrehoznia, egyet minden szemhez. Minden RenderTargetViews a rendszerből az alkalmazásnak biztosított Texture2DArray két szeletének egyikére hivatkozik. Ez nem ajánlott, mivel általában lassabb, mint az instancing használata.
Frissített HolographicFrame-előrejelzés lekérése
A keret előrejelzésének frissítése javítja a képstabilizálás hatékonyságát. A hologramok pontosabb elhelyezését az előrejelzés közötti rövidebb idő és a felhasználó számára látható keret miatt érheti el. Ideális esetben a renderelés előtt frissítse a keret előrejelzését.
holographicFrame.UpdateCurrentPrediction();
HolographicFramePrediction prediction = holographicFrame.CurrentPrediction();
Renderelés minden kamerára
Az előrejelzésben megjelenik a kamerakészlet hurkoja, és rendereli a halmaz minden kameráját.
A renderelési bérlet beállítása
A Windows Mixed Reality sztereoszkopikus renderelést használ a mélység illúziójának javítására és a sztereoszkopikus megjelenítésre, így a bal és a jobb oldali kijelző is aktív. A sztereoszkopikus renderelésnek van egy eltolása a két kijelző között, amelyet az agy képes összeegyeztetni tényleges mélységként. Ez a szakasz a sztereoszkopikus renderelést mutatja be instancing használatával, a Windows Holographic alkalmazássablonból származó kód használatával.
Minden kamera saját renderelési célhelyet (háttérpuffert) és nézet- és vetítési mátrixokat használ a holografikus térbe. Az alkalmazásnak minden más kameraalapú erőforrást – például a mélységi puffert – kameránként kell létrehoznia. A Windows Holographic alkalmazássablonban egy segédosztályt biztosítunk az erőforrások összecsomagolásához a DX::CameraResources fájlban. Először állítsa be a renderelési célnézeteket:
Forrás : AppMain::Render:
// This represents the device-based resources for a HolographicCamera.
DX::CameraResources* pCameraResources = cameraResourceMap[cameraPose.HolographicCamera().Id()].get();
// Get the device context.
const auto context = m_deviceResources->GetD3DDeviceContext();
const auto depthStencilView = pCameraResources->GetDepthStencilView();
// Set render targets to the current holographic camera.
ID3D11RenderTargetView *const targets[1] =
{ pCameraResources->GetBackBufferRenderTargetView() };
context->OMSetRenderTargets(1, targets, depthStencilView);
// Clear the back buffer and depth stencil view.
if (m_canGetHolographicDisplayForCamera &&
cameraPose.HolographicCamera().Display().IsOpaque())
{
context->ClearRenderTargetView(targets[0], DirectX::Colors::CornflowerBlue);
}
else
{
context->ClearRenderTargetView(targets[0], DirectX::Colors::Transparent);
}
context->ClearDepthStencilView(
depthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
Az előrejelzés használatával lekérheti a kamera nézet- és vetítési mátrixát
Az egyes holografikus fényképezőgépek nézet- és vetítési mátrixai minden képkockával változnak. Frissítse az adatokat az állandó pufferben minden holografikus kamera esetében. Tegye ezt az előrejelzés frissítése után, és mielőtt hívásokat kezdeményez a kamerához.
Forrás : AppMain::Render:
// The view and projection matrices for each holographic camera will change
// every frame. This function refreshes the data in the constant buffer for
// the holographic camera indicated by cameraPose.
if (m_stationaryReferenceFrame)
{
pCameraResources->UpdateViewProjectionBuffer(
m_deviceResources, cameraPose, m_stationaryReferenceFrame.CoordinateSystem());
}
// Attach the view/projection constant buffer for this camera to the graphics pipeline.
bool cameraActive = pCameraResources->AttachViewProjectionBuffer(m_deviceResources);
Itt bemutatjuk, hogyan szerezték be a mátrixokat a kamera pózából. A folyamat során a kamera aktuális nézetportja is lekérjük. Figyelje meg, hogyan biztosítunk koordinátarendszert: ez ugyanaz a koordinátarendszer, amelyet a tekintet megértéséhez használtunk, és ugyanaz, mint amit a forgó kocka elhelyezéséhez használtunk.
A CameraResourcesból::UpdateViewProjectionBuffer:
// The system changes the viewport on a per-frame basis for system optimizations.
auto viewport = cameraPose.Viewport();
m_d3dViewport = CD3D11_VIEWPORT(
viewport.X,
viewport.Y,
viewport.Width,
viewport.Height
);
// The projection transform for each frame is provided by the HolographicCameraPose.
HolographicStereoTransform cameraProjectionTransform = cameraPose.ProjectionTransform();
// Get a container object with the view and projection matrices for the given
// pose in the given coordinate system.
auto viewTransformContainer = cameraPose.TryGetViewTransform(coordinateSystem);
// If TryGetViewTransform returns a null pointer, that means the pose and coordinate
// system cannot be understood relative to one another; content cannot be rendered
// in this coordinate system for the duration of the current frame.
// This usually means that positional tracking is not active for the current frame, in
// which case it is possible to use a SpatialLocatorAttachedFrameOfReference to render
// content that is not world-locked instead.
DX::ViewProjectionConstantBuffer viewProjectionConstantBufferData;
bool viewTransformAcquired = viewTransformContainer != nullptr;
if (viewTransformAcquired)
{
// Otherwise, the set of view transforms can be retrieved.
HolographicStereoTransform viewCoordinateSystemTransform = viewTransformContainer.Value();
// Update the view matrices. Holographic cameras (such as Microsoft HoloLens) are
// constantly moving relative to the world. The view matrices need to be updated
// every frame.
XMStoreFloat4x4(
&viewProjectionConstantBufferData.viewProjection[0],
XMMatrixTranspose(XMLoadFloat4x4(&viewCoordinateSystemTransform.Left) *
XMLoadFloat4x4(&cameraProjectionTransform.Left))
);
XMStoreFloat4x4(
&viewProjectionConstantBufferData.viewProjection[1],
XMMatrixTranspose(XMLoadFloat4x4(&viewCoordinateSystemTransform.Right) *
XMLoadFloat4x4(&cameraProjectionTransform.Right))
);
}
A nézetportot minden egyes keretnek be kell állítania. A csúcspont-árnyékolónak (legalábbis) általában hozzá kell férnie a nézet-/vetítési adatokhoz.
A CameraResources::AttachViewProjectionBuffer fájlból:
// Set the viewport for this camera.
context->RSSetViewports(1, &m_d3dViewport);
// Send the constant buffer to the vertex shader.
context->VSSetConstantBuffers(
1,
1,
m_viewProjectionConstantBuffer.GetAddressOf()
);
Renderelje a kamera hátpufferét, és véglegesítse a mélységi puffert:
Érdemes ellenőrizni, hogy a TryGetViewTransform sikeres volt-e a nézet-/vetítési adatok használata előtt, mert ha a koordináta-rendszer nem található (például a nyomon követés megszakadt), az alkalmazás nem tudja megjeleníteni az adott kerethez. A sablon csak akkor hívja meg a Renderet a forgó kockán, ha a CameraResources osztály sikeres frissítést jelez.
A Windows Mixed Reality olyan funkciókat tartalmaz a képstabilizáláshoz, amelyek lehetővé teszik a hologramok elhelyezését ott, ahol egy fejlesztő vagy felhasználó elhelyezi őket a világon. A képstabilizálás segít elrejteni a renderelési folyamat késését, hogy a felhasználók számára a legjobb holografikus élményt biztosítsa. Megadható fókuszpont a képstabilizálás további fokozásához, vagy mélységi puffer is biztosítható az optimalizált képstabilizálás valós idejű kiszámításához.
A legjobb eredmény érdekében az alkalmazásnak mélységi puffert kell biztosítania a CommitDirect3D11DepthBuffer API használatával. A Windows Mixed Reality ezután a mélységi puffer geometriai adatait használhatja a képstabilizálás valós idejű optimalizálásához. A Windows Holographic alkalmazássablon alapértelmezés szerint véglegesíti az alkalmazás mélységi pufferét, így optimalizálva a hologram stabilitását.
Forrás : AppMain::Render:
// Only render world-locked content when positional tracking is active.
if (cameraActive)
{
// Draw the sample hologram.
m_spinningCubeRenderer->Render();
if (m_canCommitDirect3D11DepthBuffer)
{
// On versions of the platform that support the CommitDirect3D11DepthBuffer API, we can
// provide the depth buffer to the system, and it will use depth information to stabilize
// the image at a per-pixel level.
HolographicCameraRenderingParameters renderingParameters =
holographicFrame.GetRenderingParameters(cameraPose);
IDirect3DSurface interopSurface =
DX::CreateDepthTextureInteropObject(pCameraResources->GetDepthStencilTexture2D());
// Calling CommitDirect3D11DepthBuffer causes the system to queue Direct3D commands to
// read the depth buffer. It will then use that information to stabilize the image as
// the HolographicFrame is presented.
renderingParameters.CommitDirect3D11DepthBuffer(interopSurface);
}
}
Feljegyzés
A Windows feldolgozni fogja a mélységi textúrát a GPU-n, ezért lehetővé kell tenni a mélységi puffer használatát árnyékoló erőforrásként. A létrehozott ID3D11Texture2D formátumnak típus nélkülinek kell lennie, és árnyékoló erőforrásnézetként kell megkötni. Íme egy példa a képstabilizáláshoz véglegesített mélységi textúra létrehozására.
A CommitDirect3D11DepthBuffer mélységi puffererőforrás-létrehozásának kódja:
// Create a depth stencil view for use with 3D rendering if needed.
CD3D11_TEXTURE2D_DESC depthStencilDesc(
DXGI_FORMAT_R16_TYPELESS,
static_cast<UINT>(m_d3dRenderTargetSize.Width),
static_cast<UINT>(m_d3dRenderTargetSize.Height),
m_isStereo ? 2 : 1, // Create two textures when rendering in stereo.
1, // Use a single mipmap level.
D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE
);
winrt::check_hresult(
device->CreateTexture2D(
&depthStencilDesc,
nullptr,
&m_d3dDepthStencil
));
CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(
m_isStereo ? D3D11_DSV_DIMENSION_TEXTURE2DARRAY : D3D11_DSV_DIMENSION_TEXTURE2D,
DXGI_FORMAT_D16_UNORM
);
winrt::check_hresult(
device->CreateDepthStencilView(
m_d3dDepthStencil.Get(),
&depthStencilViewDesc,
&m_d3dDepthStencilView
));
Holografikus tartalom rajzolása
A Windows holografikus alkalmazássablonja sztereó módon jeleníti meg a tartalmat a példányos geometria 2. méretű Texture2DArray-ra való rajzolásának ajánlott technikája segítségével. Tekintsük át ennek instancing részét, és hogy hogyan működik a Windows Mixed Realityben.
Forrás: SpinningCubeRenderer::Render:
// Draw the objects.
context->DrawIndexedInstanced(
m_indexCount, // Index count per instance.
2, // Instance count.
0, // Start index location.
0, // Base vertex location.
0 // Start instance location.
);
Minden példány egy másik nézet-/vetítési mátrixhoz fér hozzá az állandó puffertől. Itt van az állandó pufferszerkezet, amely csak egy tömb két mátrixból.
A VPRTVertexShader.hlsl által tartalmazott VertexShaderShared.hlsl fájlból:
// A constant buffer that stores each set of view and projection matrices in column-major format.
cbuffer ViewProjectionConstantBuffer : register(b1)
{
float4x4 viewProjection[2];
};
A renderelési céltömb indexét minden képponthoz be kell állítani. Az alábbi kódrészletben az output.viewId a SV_RenderTargetArrayIndex szemantikai értékre van leképezve. Ez egy opcionális Direct3D 11.3-funkció támogatását igényli, amely lehetővé teszi a renderelési céltömb indexének szemantikai beállítását bármely árnyékoló fázisból.
Forrás : VPRTVertexShader.hlsl:
// Per-vertex data passed to the geometry shader.
struct VertexShaderOutput
{
min16float4 pos : SV_POSITION;
min16float3 color : COLOR0;
// The render target array index is set here in the vertex shader.
uint viewId : SV_RenderTargetArrayIndex;
};
A VPRTVertexShader.hlsl által tartalmazott VertexShaderShared.hlsl fájlból:
// Per-vertex data used as input to the vertex shader.
struct VertexShaderInput
{
min16float3 pos : POSITION;
min16float3 color : COLOR0;
uint instId : SV_InstanceID;
};
// Simple shader to do vertex processing on the GPU.
VertexShaderOutput main(VertexShaderInput input)
{
VertexShaderOutput output;
float4 pos = float4(input.pos, 1.0f);
// Note which view this vertex has been sent to. Used for matrix lookup.
// Taking the modulo of the instance ID allows geometry instancing to be used
// along with stereo instanced drawing; in that case, two copies of each
// instance would be drawn, one for left and one for right.
int idx = input.instId % 2;
// Transform the vertex position into world space.
pos = mul(pos, model);
// Correct for perspective and project the vertex position onto the screen.
pos = mul(pos, viewProjection[idx]);
output.pos = (min16float4)pos;
// Pass the color through without modification.
output.color = input.color;
// Set the render target array index.
output.viewId = idx;
return output;
}
Ha a meglévő példányos rajztechnikát szeretné használni ezzel a módszerrel egy sztereó renderelési céltömbbe való rajzoláshoz, rajzoljon kétszer annyi példányt, mint általában. A shaderben ossza el az input.instId azonosítót 2-vel az eredeti példányazonosító lekéréséhez, amely indexelhető (például) objektumonkénti adatok pufferébe: int actualIdx = input.instId / 2;
Fontos megjegyzés a sztereó tartalmak HoloLensen való megjelenítéséről
A Windows Mixed Reality támogatja a renderelési céltömb indexének beállítását bármely árnyékolószakaszból. Ez a feladat általában csak a geometriai árnyékoló fázisban végezhető el, mivel a szemantika a Direct3D 11-hez van definiálva. Itt egy teljes példát mutatunk be arra, hogyan állíthat be renderelési folyamatot csak a csúcspont és a képpontárnyékoló fázisainak beállításával. A shader-kód a fent leírtak szerint van bemutatva.
Forrás: SpinningCubeRenderer::Render:
const auto context = m_deviceResources->GetD3DDeviceContext();
// Each vertex is one instance of the VertexPositionColor struct.
const UINT stride = sizeof(VertexPositionColor);
const UINT offset = 0;
context->IASetVertexBuffers(
0,
1,
m_vertexBuffer.GetAddressOf(),
&stride,
&offset
);
context->IASetIndexBuffer(
m_indexBuffer.Get(),
DXGI_FORMAT_R16_UINT, // Each index is one 16-bit unsigned integer (short).
0
);
context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
context->IASetInputLayout(m_inputLayout.Get());
// Attach the vertex shader.
context->VSSetShader(
m_vertexShader.Get(),
nullptr,
0
);
// Apply the model constant buffer to the vertex shader.
context->VSSetConstantBuffers(
0,
1,
m_modelConstantBuffer.GetAddressOf()
);
// Attach the pixel shader.
context->PSSetShader(
m_pixelShader.Get(),
nullptr,
0
);
// Draw the objects.
context->DrawIndexedInstanced(
m_indexCount, // Index count per instance.
2, // Instance count.
0, // Start index location.
0, // Base vertex location.
0 // Start instance location.
);
Fontos megjegyzés a nem HoloLens-eszközökön történő renderelésről
A renderelési céltömb indexének a csúcsárnyékolóban való beállításához a grafikus illesztőprogramnak támogatnia kell egy választható Direct3D 11.3 funkciót, amelyet a HoloLens támogat. Az alkalmazás biztonságosan implementálhatja a renderelési technikát, és minden követelmény teljesül a Microsoft HoloLensen való futtatáshoz.
Előfordulhat, hogy a HoloLens emulátort is használni szeretné, amely hatékony fejlesztőeszköz lehet a holografikus alkalmazáshoz – és támogatja a Windows 10 rendszerű számítógépekhez csatlakoztatott Modern Windows Mixed Reality modern headset-eszközöket. A nem HoloLens megjelenítési útvonal támogatása – az összes Windows Mixed Reality esetében – a Windows Holographic alkalmazássablonba is be van építve. A sablonkódban talál egy kódot, amely lehetővé teszi a holografikus alkalmazás futtatását a GPU-n a fejlesztői pc-n. A DeviceResources osztály így ellenőrzi ezt az opcionális funkciótámogatást.
DeviceResources ::CreateDeviceResources:
// Check for device support for the optional feature that allows setting the render target array index from the vertex shader stage.
D3D11_FEATURE_DATA_D3D11_OPTIONS3 options;
m_d3dDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS3, &options, sizeof(options));
if (options.VPAndRTArrayIndexFromAnyShaderFeedingRasterizer)
{
m_supportsVprt = true;
}
Az opcionális funkció nélküli renderelés támogatásához az alkalmazásnak geometriai árnyékolót kell használnia a renderelési céltömb indexének beállításához. Ez a kódrészlet a VSSetConstantBuffers és a PSSetShader után lesz hozzáadva az előző szakaszban bemutatott kódpéldában, amely elmagyarázza, hogyan jeleníthető meg sztereó a HoloLensen.
Forrás: SpinningCubeRenderer::Render:
if (!m_usingVprtShaders)
{
// On devices that do not support the D3D11_FEATURE_D3D11_OPTIONS3::
// VPAndRTArrayIndexFromAnyShaderFeedingRasterizer optional feature,
// a pass-through geometry shader is used to set the render target
// array index.
context->GSSetShader(
m_geometryShader.Get(),
nullptr,
0
);
}
HLSL MEGJEGYZÉS: Ebben az esetben egy kissé módosított csúcspont-árnyékolót is be kell töltenie, amely a renderelési céltömb indexét egy mindig engedélyezett árnyékoló szemantika használatával továbbítja a geometriai árnyékolónak, például TEXCOORD0. A geometriai árnyékolónak nem kell semmilyen munkát végeznie; a sablongeometriai árnyékoló az összes adatot átvezeti a render céltömbindex kivételével, amely a SV_RenderTargetArrayIndex szemantikai beállítására szolgál.
A GeometryShader.hlsl alkalmazássablon-kódja:
// Per-vertex data from the vertex shader.
struct GeometryShaderInput
{
min16float4 pos : SV_POSITION;
min16float3 color : COLOR0;
uint instId : TEXCOORD0;
};
// Per-vertex data passed to the rasterizer.
struct GeometryShaderOutput
{
min16float4 pos : SV_POSITION;
min16float3 color : COLOR0;
uint rtvId : SV_RenderTargetArrayIndex;
};
// This geometry shader is a pass-through that leaves the geometry unmodified
// and sets the render target array index.
[maxvertexcount(3)]
void main(triangle GeometryShaderInput input[3], inout TriangleStream<GeometryShaderOutput> outStream)
{
GeometryShaderOutput output;
[unroll(3)]
for (int i = 0; i < 3; ++i)
{
output.pos = input[i].pos;
output.color = input[i].color;
output.rtvId = input[i].instId;
outStream.Append(output);
}
}
Jelen
A holografikus keret engedélyezése a felcserélési lánc bemutatásához
A Windows Mixed Reality használatával a rendszer vezérli a felcserélési láncot. A rendszer ezután felügyeli az egyes holografikus fényképezőgépek képkockáinak bemutatását a magas színvonalú felhasználói élmény biztosítása érdekében. Emellett minden egyes kamerához egy nézetportot is biztosít, amely optimalizálja a rendszer olyan aspektusait, mint a képstabilizálás vagy a Mixed Reality Capture. A DirectX-et használó holografikus alkalmazások tehát nem hívják meg a Presentt egy DXGI-felcserélési láncon. Ehelyett a HolographicFrame osztály használatával jeleníti meg a keret összes swapchains elemét, miután elkészült a rajzolással.
Forrás: DeviceResources::P resent:
HolographicFramePresentResult presentResult = frame.PresentUsingCurrentPrediction();
Alapértelmezés szerint ez az API megvárja, amíg a keret befejeződik, mielőtt visszatér. A holografikus alkalmazásoknak várniuk kell, amíg az előző keret befejeződik, mielőtt megkezdik a munkát egy új kereten, mivel ez csökkenti a késést, és jobb eredményeket tesz lehetővé a holografikus keret előrejelzéseiből. Ez nem egy kemény szabály, és ha egynél több képernyőfrissítést igénylő kerettel rendelkezik a megjelenítéshez, letilthatja ezt a várakozást, ha a HolographicFramePresentWaitBehavior paramétert átadja a PresentUsingCurrentPrediction paraméternek. Ebben az esetben valószínűleg aszinkron renderelési szálat használna a GPU folyamatos terhelésének fenntartásához. A HoloLens-eszköz frissítési sebessége 60 hz, ahol egy keret időtartama körülbelül 16 ms. A modern fejhallgató-eszközök 60 Hz és 90 Hz között mozoghatnak; a kijelző 90 hz-es frissítésekor minden keret körülbelül 11 ms időtartamú lesz.
DeviceLost-forgatókönyvek kezelése a HolographicFrame-lel együttműködve
A DirectX 11-alkalmazások általában a DXGI swaplánc Present függvénye által visszaadott HRESULT-t szeretnék ellenőrizni, hogy történt-e DeviceLost-hiba. Ezt a HolographicFrame osztály kezeli. A visszaadott HolographicFramePresentResult vizsgálatával megállapíthatja, hogy ki kell-e szabadítania és újra létre kell-e hoznia a Direct3D-eszközt és az eszközalapú erőforrásokat.
// The PresentUsingCurrentPrediction API will detect when the graphics device
// changes or becomes invalid. When this happens, it is considered a Direct3D
// device lost scenario.
if (presentResult == HolographicFramePresentResult::DeviceRemoved)
{
// The Direct3D device, context, and resources should be recreated.
HandleDeviceLost();
}
Ha a Direct3D-eszköz elveszett, és újra létrehozta, meg kell adnia a HolographicSpace-nek , hogy kezdje el használni az új eszközt. A felcserélési lánc újra létre lesz hozva ehhez az eszközhöz.
Forrás : DeviceResources::InitializeUsingHolographicSpace:
m_holographicSpace.SetDirect3D11Device(m_d3dInteropDevice);
A keret bemutatása után visszatérhet a fő programhurkhoz, és folytathatja a következő kerettel.
Hibrid grafikus számítógépek és vegyes valóságú alkalmazások
Windows 10 alkotói frissítés számítógépek különálló és integrált GPU-kkal is konfigurálhatók. Az ilyen típusú számítógépek esetében a Windows kiválasztja azt az adaptert, amelyhez a headset csatlakoztatva van. Az alkalmazásoknak gondoskodniuk kell arról, hogy az általa létrehozott DirectX-eszköz ugyanazt az adaptert használja.
A legtöbb általános Direct3D-mintakód bemutatja, hogyan hozható létre DirectX-eszköz az alapértelmezett hardveradapterrel, amely hibrid rendszeren nem feltétlenül ugyanaz, mint a headsethez használt.
A problémák megoldásához használja bármelyik HolographicSpace HolographicAdapterID azonosítóját. PrimaryAdapterId() vagy HolographicDisplay. AdapterId(). Ez az adapterId ezután a megfelelő DXGIAdapter kiválasztásához használható az IDXGIFactory4.EnumAdapterByLuid használatával.
Forrás : DeviceResources::InitializeUsingHolographicSpace:
// The holographic space might need to determine which adapter supports
// holograms, in which case it will specify a non-zero PrimaryAdapterId.
LUID id =
{
m_holographicSpace.PrimaryAdapterId().LowPart,
m_holographicSpace.PrimaryAdapterId().HighPart
};
// When a primary adapter ID is given to the app, the app should find
// the corresponding DXGI adapter and use it to create Direct3D devices
// and device contexts. Otherwise, there is no restriction on the DXGI
// adapter the app can use.
if ((id.HighPart != 0) || (id.LowPart != 0))
{
UINT createFlags = 0;
// Create the DXGI factory.
ComPtr<IDXGIFactory1> dxgiFactory;
winrt::check_hresult(
CreateDXGIFactory2(
createFlags,
IID_PPV_ARGS(&dxgiFactory)
));
ComPtr<IDXGIFactory4> dxgiFactory4;
winrt::check_hresult(dxgiFactory.As(&dxgiFactory4));
// Retrieve the adapter specified by the holographic space.
winrt::check_hresult(
dxgiFactory4->EnumAdapterByLuid(
id,
IID_PPV_ARGS(&m_dxgiAdapter)
));
}
else
{
m_dxgiAdapter.Reset();
}
A DeviceResources frissítésének kódja::CreateDeviceResources az IDXGIAdapter használatához
// Create the Direct3D 11 API device object and a corresponding context.
ComPtr<ID3D11Device> device;
ComPtr<ID3D11DeviceContext> context;
const D3D_DRIVER_TYPE driverType = m_dxgiAdapter == nullptr ? D3D_DRIVER_TYPE_HARDWARE : D3D_DRIVER_TYPE_UNKNOWN;
const HRESULT hr = D3D11CreateDevice(
m_dxgiAdapter.Get(), // Either nullptr, or the primary adapter determined by Windows Holographic.
driverType, // Create a device using the hardware graphics driver.
0, // Should be 0 unless the driver is D3D_DRIVER_TYPE_SOFTWARE.
creationFlags, // Set debug and Direct2D compatibility flags.
featureLevels, // List of feature levels this app can support.
ARRAYSIZE(featureLevels), // Size of the list above.
D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Runtime apps.
&device, // Returns the Direct3D device created.
&m_d3dFeatureLevel, // Returns feature level of device created.
&context // Returns the device immediate context.
);
Hibrid grafika és Media Foundation
A Media Foundation hibrid rendszereken való használata problémákat okozhat, ha a videó nem jelenik meg, vagy a videó textúra sérült, mert a Media Foundation alapértelmezés szerint a rendszer viselkedését használja. Bizonyos esetekben külön ID3D11Device létrehozása szükséges a többszálas készítés támogatásához, és a megfelelő létrehozási jelzők vannak beállítva.
Az ID3D11Device inicializálásakor D3D11_CREATE_DEVICE_VIDEO_SUPPORT jelzőt a D3D11_CREATE_DEVICE_FLAG részeként kell definiálni. Az eszköz és a környezet létrehozása után hívja meg a SetMultithreadProtected parancsot a többszálúság engedélyezéséhez. Ha az eszközt az IMFDXGIDeviceManagerhez szeretné társítani, használja az IMFDXGIDeviceManager::ResetDevice függvényt .
Kód az ID3D11Device és az IMFDXGIDeviceManager társításához:
// create dx device for media pipeline
winrt::com_ptr<ID3D11Device> spMediaDevice;
// See above. Also make sure to enable the following flags on the D3D11 device:
// * D3D11_CREATE_DEVICE_VIDEO_SUPPORT
// * D3D11_CREATE_DEVICE_BGRA_SUPPORT
if (FAILED(CreateMediaDevice(spAdapter.get(), &spMediaDevice)))
return;
// Turn multithreading on
winrt::com_ptr<ID3D10Multithread> spMultithread;
if (spContext.try_as(spMultithread))
{
spMultithread->SetMultithreadProtected(TRUE);
}
// lock the shared dxgi device manager
// call MFUnlockDXGIDeviceManager when no longer needed
UINT uiResetToken;
winrt::com_ptr<IMFDXGIDeviceManager> spDeviceManager;
hr = MFLockDXGIDeviceManager(&uiResetToken, spDeviceManager.put());
if (FAILED(hr))
return hr;
// associate the device with the manager
hr = spDeviceManager->ResetDevice(spMediaDevice.get(), uiResetToken);
if (FAILED(hr))
return hr;