Aracılığıyla paylaş


DirectX'te İşleme

Not

Bu makale, eski WinRT yerel API'leriyle ilgilidir. Yeni yerel uygulama projeleri için OpenXR API'sini kullanmanızı öneririz.

Windows Karma Gerçeklik, kullanıcılar için zengin, 3B grafik deneyimler üretmek üzere DirectX üzerine kurulmuştur. İşleme soyutlaması DirectX'in hemen üstünde yer alır ve bu da uygulamaların sistem tarafından tahmin edilen holografik sahne gözlemcilerinin konumu ve yönlendirmesi hakkında mantık yürütmesini sağlar. Geliştirici daha sonra hologramlarını her kameraya göre bulabilir ve kullanıcı hareket ettikçe uygulamanın bu hologramları çeşitli uzamsal koordinat sistemlerinde işlemesine izin verebilir.

Not: Bu kılavuz, Direct3D 11'de holografik işlemeyi açıklar. Karma Gerçeklik uygulama şablonları uzantısıyla birlikte bir Direct3D 12 Windows Karma Gerçeklik uygulama şablonu da sağlanır.

Geçerli çerçeve için güncelleştirme

Hologramların uygulama durumunu güncelleştirmek için, çerçeve başına bir kez uygulama şunları yapacaktır:

  • Görüntü yönetim sisteminden bir HolographicFrame alın.
  • İşleme tamamlandığında kamera görünümünün nerede olacağının geçerli tahminiyle sahneyi güncelleştirin. Holografik sahne için birden fazla kamera olabileceğini unutmayın.

Holografik kamera görünümlerine işlemek için, uygulama çerçeve başına bir kez şunları yapacaktır:

  • Her kamera için, sistemdeki kamera görünümünü ve projeksiyon matrislerini kullanarak geçerli karenin sahnesini işleyebilirsiniz.

Yeni bir holografik çerçeve oluşturma ve tahminini alma

HolographicFrame, uygulamanın geçerli çerçeveyi güncelleştirmek ve işlemek için ihtiyaç duyduğu bilgilere sahiptir. Uygulama her yeni çerçeveye CreateNextFrame yöntemini çağırarak başlar. Bu yöntem çağrıldığında, tahminler kullanılabilir en son algılayıcı verileri kullanılarak yapılır ve CurrentPrediction nesnesinde kapsüllenir.

İşlenen her çerçeve için yeni bir çerçeve nesnesi kullanılmalıdır, bu yalnızca anlık bir zaman için geçerlidir. CurrentPrediction özelliği, kamera konumu gibi bilgileri içerir. Bilgiler, çerçevenin kullanıcıya görünür olması beklenen tam zamanında tahmin edilir.

Aşağıdaki kod AppMain::Update'ten alıntılanır:

// 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();

Kamera güncelleştirmelerini işleme

Arka arabellekler çerçeveden çerçeveye değişebilir. Uygulamanızın her kamera için arka arabelleği doğrulaması ve gerektiğinde kaynak görünümlerini ve derinlik arabelleklerini serbest bırakması ve yeniden oluşturması gerekir. Tahmindeki poz kümesinin geçerli karede kullanılan kameraların yetkili listesi olduğuna dikkat edin. Genellikle, bu listeyi kamera setinde yinelemek için kullanırsınız.

AppMain::Update'ten:

m_deviceResources->EnsureCameraResources(holographicFrame, prediction);

DeviceResources ::EnsureCameraResources kaynağından:

for (HolographicCameraPose const& cameraPose : prediction.CameraPoses())
{
    HolographicCameraRenderingParameters renderingParameters = frame.GetRenderingParameters(cameraPose);
    CameraResources* pCameraResources = cameraResourceMap[cameraPose.HolographicCamera().Id()].get();
    pCameraResources->CreateResourcesForBackBuffer(this, renderingParameters);
}

İşleme için temel olarak kullanılacak koordinat sistemini alma

Windows Karma Gerçeklik, uygulamanızın fiziksel dünyadaki konumları izlemek için ekli ve sabit başvuru çerçeveleri gibi çeşitli koordinat sistemleri oluşturmasına olanak tanır. Uygulamanız daha sonra bu koordinat sistemlerini kullanarak her karede hologramların nerede işlendiğine dair bir mantık oluşturabilir. Bir API'den koordinat isterken, bu koordinatların ifade edilmesi için istediğiniz SpatialCoordinateSystem'ı her zaman geçirirsiniz.

AppMain::Update'ten:

pose = SpatialPointerPose::TryGetAtTimestamp(
    m_stationaryReferenceFrame.CoordinateSystem(), prediction.Timestamp());

Bu koordinat sistemleri daha sonra sahnenizdeki içeriği işlerken stereo görünüm matrisleri oluşturmak için kullanılabilir.

CameraResources::UpdateViewProjectionBuffer'dan:

// Get a container object with the view and projection matrices for the given
// pose in the given coordinate system.
auto viewTransformContainer = cameraPose.TryGetViewTransform(coordinateSystem);

İşleme bakış ve hareket girişi

Bakış ve el girişi zamana bağlı değildir ve StepTimer işlevinde güncelleştirilmek zorunda değildir. Ancak bu giriş, uygulamanın her kareye bakması gereken bir giriştir.

Zamana bağlı güncelleştirmeleri işleme

Herhangi bir gerçek zamanlı işleme uygulamasının zamana dayalı güncelleştirmeleri işlemek için bir yol kullanması gerekir. Windows Holographic uygulama şablonu, DirectX 11 UWP uygulama şablonunda sağlanan StepTimer'a benzer bir StepTimer uygulaması kullanır. Bu StepTimer örnek yardımcı sınıfı sabit zaman adımı güncelleştirmeleri, değişken zaman adımı güncelleştirmeleri sağlayabilir ve varsayılan mod değişken zaman adımlarıdır.

Holografik işleme için zamanlayıcı işlevine çok fazla eklememeyi seçtik çünkü bunu sabit bir zaman adımı olacak şekilde yapılandırabilirsiniz. Bazı kareler için çerçeve başına birden çok kez çağrılabilir (veya hiç çağrılmayabilir) ve holografik veri güncelleştirmelerimiz çerçeve başına bir kez gerçekleşmelidir.

AppMain::Update'ten:

m_timer.Tick([this]()
{
    m_spinningCubeRenderer->Update(m_timer);
});

Hologramları koordinat sisteminizde konumlandırma ve döndürme

Şablonun SpatialStationaryReferenceFrame ile yaptığı gibi tek bir koordinat sisteminde çalışıyorsanız, bu işlem 3B grafiklerde alışkın olduğunuz işlemden farklı değildir. Burada küpü döndürüyor ve model matrisini sabit koordinat sistemindeki konuma göre ayarlıyoruz.

SpinningCubeRenderer::Update'ten:

// 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));

Gelişmiş senaryolar hakkında not: Dönen küp, hologramı tek bir başvuru çerçevesi içinde konumlandırmanın basit bir örneğidir. Aynı işlenen çerçevede aynı anda birden çok SpatialCoordinateSystems kullanmak da mümkündür.

Sabit arabellek verilerini güncelleştirme

İçerik için model dönüşümleri her zamanki gibi güncelleştirilir. Şimdiye kadar, içinde işlenecek koordinat sistemi için geçerli dönüşümleri hesaplamış olacaksınız.

SpinningCubeRenderer::Update'ten:

// Update the model transform buffer for the hologram.
context->UpdateSubresource(
    m_modelConstantBuffer.Get(),
    0,
    nullptr,
    &m_modelConstantBufferData,
    0,
    0
);

Görünüm ve projeksiyon dönüşümleri ne olacak? En iyi sonuçları elde etmek için, bunları almadan önce çekiliş çağrılarımıza hazır olana kadar beklemek istiyoruz.

Geçerli çerçeveyi işleme

Windows Karma Gerçeklik üzerinde işleme, 2B mono ekranda işlemeden çok farklı değildir, ancak birkaç fark vardır:

  • Holografik çerçeve tahminleri önemlidir. Çerçeveniz sunulduğunda tahmin ne kadar yakın olursa hologramlarınız o kadar iyi görünür.
  • Windows Karma Gerçeklik kamera görünümlerini denetler. Holografik çerçeve daha sonra bunları size sunacağından her birine işleyin.
  • Bir işleme hedef dizisine örnek çizim kullanarak stereo işleme yapmanızı öneririz. Holografik uygulama şablonu, texture2DArray üzerinde işleme hedef görünümünü kullanan bir işleme hedef dizisine örnek çizimin önerilen yaklaşımını kullanır.
  • Stereo instancing kullanmadan işlemek istiyorsanız, her göz için bir tane olmak üzere iki dizi olmayan RenderTargetView oluşturmanız gerekir. Her RenderTargetViews, sistemden uygulamaya sağlanan Texture2DArray'deki iki dilimden birine başvurur. Bu önerilmiyor, çünkü genellikle daha yavaştır ve bu işlem, instancing'i kullanmaktan daha yavaştır.

Güncelleştirilmiş bir HolographicFrame tahmini alma

Çerçeve tahminini güncelleştirmek, görüntü sabitlemenin verimliliğini artırır. Tahmin arasındaki sürenin kısa olması ve çerçevenin kullanıcıya görünür olması nedeniyle hologramların daha doğru konumlandırılması sağlanır. İdeal olarak, işlemeden hemen önce çerçeve tahmininizi güncelleştirin.

holographicFrame.UpdateCurrentPrediction();
HolographicFramePrediction prediction = holographicFrame.CurrentPrediction();

Her kameraya işleme

Kamera kümesinde döngü, tahminde yer alır ve bu kümedeki her kameraya işlenir.

İşleme geçişinizi ayarlama

Windows Karma Gerçeklik, derinlik yanılsamasını geliştirmek ve stereoskopik olarak işlemek için stereoskopik işleme kullanır, böylece hem sol hem de sağ ekran etkin olur. Stereoskopik işleme ile iki ekran arasında bir uzaklık vardır ve beyin gerçek derinlik olarak uzlaştırılabilir. Bu bölüm, Windows Holographic uygulama şablonundaki kodu kullanarak, instancing kullanarak stereoskopik işlemeyi kapsar.

Her kameranın holografik alana kendi işleme hedefi (arka tampon) ve görüntüleme ve projeksiyon matrisleri vardır. Uygulamanızın kamera başına derinlik arabelleği gibi diğer kamera tabanlı kaynakları oluşturması gerekir. Windows Holographic uygulama şablonunda, bu kaynakları DX::CameraResources içinde birlikte paketlemek için bir yardımcı sınıfı sağlıyoruz. İşleme hedef görünümlerini ayarlayarak başlayın:

AppMain::Render'dan:

// 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);

Kameranın görünüm ve projeksiyon matrislerini almak için tahmini kullanma

Her holografik kamera için görünüm ve projeksiyon matrisleri her karede değişecektir. Her holografik kamera için sabit arabellekteki verileri yenileyin. Tahmini güncelleştirdikten sonra ve bu kamera için çizim çağrıları yapmadan önce bunu yapın.

AppMain::Render'dan:

// 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);

Burada matrislerin kamera pozundan nasıl elde edildiği gösterilmektedir. Bu işlem sırasında, kameranın geçerli görüş açısını da elde ederiz. Nasıl koordinat sistemi sağladığımıza dikkat edin: Bu bakışları anlamak için kullandığımız koordinat sistemidir ve dönen küpü konumlandırmak için kullandığımız koordinat sistemiyle aynıdır.

CameraResources::UpdateViewProjectionBuffer'dan:

// 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))
    );
}

Görünüm penceresi her çerçeveyi ayarlamalıdır. Köşe gölgelendiricinizin (en azından) genel olarak görünüm/projeksiyon verilerine erişmesi gerekir.

CameraResources::AttachViewProjectionBuffer'dan:

// 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()
);

Kamera arka tamponunu işleyin ve derinlik arabelleği işleyin:

Görünüm/projeksiyon verilerini kullanmaya çalışmadan önce TryGetViewTransform'un başarılı olup olmadığını denetlemek iyi bir fikirdir, çünkü koordinat sistemi lokatable değilse (örneğin, izleme kesintiye uğramışsa) uygulamanız bu çerçeve için onunla birlikte işleyemez. Şablon yalnızca CameraResources sınıfı başarılı bir güncelleştirme gösteriyorsa dönen küpte Render'i çağırır.

Windows Karma Gerçeklik, hologramları bir geliştiricinin veya kullanıcının dünyaya yerleştirdiği konumlarda tutmak için görüntü sabitleme özellikleri içerir. Görüntü sabitleme, kullanıcılar için en iyi holografik deneyimleri sağlamak için işleme işlem hattındaki gecikme süresini gizlemeye yardımcı olur. Görüntü sabitlemeyi daha da geliştirmek için bir odak noktası belirtilebilir veya iyileştirilmiş görüntü sabitlemeyi gerçek zamanlı olarak hesaplamak için bir derinlik arabelleği sağlanabilir.

En iyi sonuçları elde etmek için uygulamanızın CommitDirect3D11DepthBuffer API'sini kullanarak bir derinlik arabelleği sağlaması gerekir. Windows Karma Gerçeklik daha sonra derinlik arabelleğindeki geometri bilgilerini kullanarak görüntü sabitlemeyi gerçek zamanlı olarak iyileştirebilir. Windows Holographic uygulama şablonu, uygulamanın derinlik arabelleği varsayılan olarak işleyerek hologram kararlılığını iyileştirmeye yardımcı olur.

AppMain::Render'dan:

// 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);
    }
}

Not

Windows, derinlik dokunuzu GPU üzerinde işler, bu nedenle derinlik arabelleğinizi gölgelendirici kaynağı olarak kullanmak mümkün olmalıdır. Oluşturduğunuz ID3D11Texture2D türüz bir biçimde olmalı ve gölgelendirici kaynak görünümü olarak bağlanmalıdır. Burada, görüntü sabitleme için işlenebilen bir derinlik dokusunun nasıl oluşturulacağını gösteren bir örnek verilmiştir.

CommitDirect3D11DepthBuffer için Derinlik arabellek kaynağı oluşturma kodu:

// 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
    ));

Holografik içerik çizme

Windows Holographic uygulama şablonu, örneklenmiş geometriyi 2 boyutlu bir Texture2DArray'ye çizmenin önerilen tekniğini kullanarak içeriği stereo olarak işler. Şimdi bunun başlangıç bölümüne ve Windows Karma Gerçeklik'da nasıl çalıştığına bakalım.

SpinningCubeRenderer::Render'dan:

// 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.
);

Her örnek, sabit arabellekten farklı bir görünüm/projeksiyon matrise erişir. Burada, yalnızca iki matris içeren bir dizi olan sabit arabellek yapısı yer alır.

VpRTVertexShader.hlsl tarafından sunulan VertexShaderShared.hlsl'den:

// A constant buffer that stores each set of view and projection matrices in column-major format.
cbuffer ViewProjectionConstantBuffer : register(b1)
{
    float4x4 viewProjection[2];
};

İşleme hedef dizisi dizini her piksel için ayarlanmalıdır. Aşağıdaki kod parçacığında output.viewId SV_RenderTargetArrayIndex semantik ile eşlenir. Bu, hedef dizi dizini semantiğinin herhangi bir gölgelendirici aşamasından ayarlanmasını sağlayan isteğe bağlı bir Direct3D 11.3 özelliği için destek gerektirir.

VPRTVertexShader.hlsl'den:

// 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;
};

VpRTVertexShader.hlsl tarafından sunulan VertexShaderShared.hlsl'den:

// 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;
}

Mevcut örneklenmiş çizim tekniklerinizi bu stereo işleme hedef dizisine çizim yöntemiyle kullanmak istiyorsanız, normalde sahip olduğunuz örnek sayısının iki katını çizin. Gölgelendiricide input.instId değerini 2'ye bölerek özgün örnek kimliğini alın; bu kimlik nesne başına verilerin arabelleğine (örneğin) dizinlenebilir:int actualIdx = input.instId / 2;

HoloLens'te stereo içerik işleme hakkında önemli not

Windows Karma Gerçeklik, hedef dizi dizinini herhangi bir gölgelendirici aşamasından ayarlama özelliğini destekler. Normalde bu, semantiğin Direct3D 11 için tanımlanma biçimi nedeniyle yalnızca geometri gölgelendirici aşamasında yapabilen bir görevdir. Burada, yalnızca köşe ve piksel gölgelendirici aşamaları ayarlanmış bir işleme işlem hattının nasıl ayarlanacağına ilişkin eksiksiz bir örnek göstereceğiz. Gölgelendirici kodu yukarıda açıklandığı gibidir.

SpinningCubeRenderer::Render'dan:

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.
);

HoloLens olmayan cihazlarda işleme hakkında önemli not

Köşe gölgelendiricisinde işleme hedef dizisi dizinini ayarlamak için grafik sürücüsünün HoloLens'in desteklediği isteğe bağlı bir Direct3D 11.3 özelliğini desteklemesi gerekir. Uygulamanız yalnızca bu işleme tekniğini güvenle uygulayabilir ve Microsoft HoloLens'te çalıştırmak için tüm gereksinimler karşılanır.

HoloLens öykünücüsünüzü de kullanmak isteyebilirsiniz. Bu, holografik uygulamanız için güçlü bir geliştirme aracı olabilir ve Windows 10 bilgisayarlarına bağlı Windows Karma Gerçeklik çevreleyici kulaklık cihazlarını destekler. Tüm Windows Karma Gerçeklik için HoloLens olmayan işleme yolu desteği de Windows Holographic uygulama şablonunda yerleşik olarak bulunur. Şablon kodunda holografik uygulamanızın geliştirme bilgisayarınızda GPU üzerinde çalışmasını sağlayan kod bulacaksınız. DeviceResources sınıfı bu isteğe bağlı özellik desteğini şu şekilde denetler.

DeviceResources::CreateDeviceResources kaynağından:

// 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;
}

Bu isteğe bağlı özellik olmadan işlemeyi desteklemek için uygulamanızın işleme hedef dizi dizinini ayarlamak için geometri gölgelendiricisi kullanması gerekir. Bu kod parçacığı VSSetConstantBuffers'dan sonra ve önceki bölümde gösterilen ve HoloLens'te stereo'nun nasıl işleneceğini açıklayan kod örneğinde PSSetShader'dan önce eklenir.

SpinningCubeRenderer::Render'dan:

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 NOT: Bu durumda, TEXCOORD0 gibi her zaman izin verilen bir gölgelendirici semantiği kullanarak işleme hedef dizi dizinini geometri gölgelendiricisine geçiren biraz değiştirilmiş bir köşe gölgelendiricisi de yüklemeniz gerekir. Geometri gölgelendiricisinin herhangi bir iş yapması gerekmez; şablon geometri gölgelendiricisi, SV_RenderTargetArrayIndex semantiğini ayarlamak için kullanılan işleme hedef dizisi dizini dışında tüm verilerden geçer.

GeometryShader.hlsl için uygulama şablonu kodu:

// 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);
    }
}

Bugün

Holografik çerçevenin takas zincirini sunmasını sağlama

Windows Karma Gerçeklik ile sistem, takas zincirini denetler. Sistem daha sonra yüksek kaliteli bir kullanıcı deneyimi sağlamak için her holografik kameraya çerçeve sunmayı yönetir. Ayrıca sistemin görüntü sabitleme veya yakalama Karma Gerçeklik gibi yönlerini iyileştirmek için her kamera için her kare için bir görünüm penceresi güncelleştirmesi sağlar. Bu nedenle, DirectX kullanan holografik bir uygulama DXGI takas zincirinde Present çağrısı yapmaz. Bunun yerine, holographicframe sınıfını kullanarak çerçeveyi çizmeyi tamamladıktan sonra çerçevenin tüm takas zincirlerini sunarsınız.

DeviceResources::P resent'ten:

HolographicFramePresentResult presentResult = frame.PresentUsingCurrentPrediction();

Varsayılan olarak, bu API döndürülmeden önce çerçevenin bitmesini bekler. Holografik uygulamalar, yeni bir çerçeve üzerinde çalışmaya başlamadan önce önceki çerçevenin bitmesini beklemelidir, çünkü bu gecikme süresini azaltır ve holografik çerçeve tahminlerinden daha iyi sonuçlar elde edilmesini sağlar. Bu sabit bir kural değildir ve işlenmesi birden fazla ekran yenilemesi gerektiren çerçeveleriniz varsa, HolographicFramePresentWaitBehavior parametresini PresentUsingCurrentPrediction'a geçirerek bu beklemeyi devre dışı bırakabilirsiniz. Bu durumda, GPU üzerinde sürekli yük tutmak için büyük olasılıkla zaman uyumsuz bir işleme iş parçacığı kullanırsınız. HoloLens cihazının yenileme hızı 60 hz'dir ve bir çerçevenin süresi yaklaşık 16 ms'dir. Çevreleyici kulaklık cihazları 60 hz ile 90 hz arasında değişebilir; ekranı 90 hz'de yenilerken her çerçevenin süresi yaklaşık 11 ms olur.

HolographicFrame ile işbirliği içinde DeviceLost senaryolarını işleme

DirectX 11 uygulamaları genellikle Bir DeviceLost hatası olup olmadığını öğrenmek için DXGI takas zincirinin Present işlevi tarafından döndürülen HRESULT'u denetlemek ister. HolographicFrame sınıfı bunu sizin için işler. Direct3D cihazı ve cihaz tabanlı kaynakları serbest bırakmanız ve yeniden oluşturmanız gerekip gerekmediğini öğrenmek için döndürülen HolographicFramePresentResult'u inceleyin.

// 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();
}

Direct3D cihazı kaybolduysa ve yeniden oluşturmuşsanız HolographicSpace'e yeni cihazı kullanmaya başlamasını söylemeniz gerekir. Değiştirme zinciri bu cihaz için yeniden oluşturulur.

DeviceResources::InitializeUsingHolographicSpace'den:

m_holographicSpace.SetDirect3D11Device(m_d3dInteropDevice);

Çerçeveniz sunulduktan sonra ana program döngüsüne geri dönebilir ve bir sonraki çerçeveye devam etmelerine izin vekleyebilirsiniz.

Karma grafik bilgisayarları ve karma gerçeklik uygulamaları

Windows 10 Creators Update bilgisayarları hem ayrık hem de tümleşik GPU'larla yapılandırılabilir. Bu tür bilgisayarlarda Windows, mikrofonlu kulaklığın bağlı olduğu bağdaştırıcıyı seçer. Uygulamalar, oluşturduğu DirectX cihazının aynı bağdaştırıcıyı kullandığından emin olmalıdır.

Çoğu genel Direct3D örnek kodu, bir karma sistemde kulaklık için kullanılanla aynı olmayabilecek varsayılan donanım bağdaştırıcısını kullanarak bir DirectX cihazı oluşturmayı gösterir.

Herhangi bir sorunu geçici olarak çözmek için HolographicSpace'ten HolographicAdapterID kullanın. PrimaryAdapterId() veya HolographicDisplay. AdapterId(). Bu adapterId daha sonra IDXGIFactory4.EnumAdapterByLuid kullanılarak doğru DXGIAdapter'ı seçmek için kullanılabilir.

DeviceResources::InitializeUsingHolographicSpace'den:

// 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();
}

DeviceResources::CreateDeviceResources'u IDXGIAdapter kullanacak şekilde güncelleştirme kodu

// 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.
);

Karma grafikler ve Media Foundation

Media Foundation'ın karma sistemlerde kullanılması, Media Foundation'ın varsayılan olarak bir sistem davranışına sahip olması nedeniyle videoların işlenmeyeceği veya video dokusunın bozulmasına neden olan sorunlara neden olabilir. Bazı senaryolarda, çoklu iş parçacığı oluşturmayı desteklemek için ayrı bir ID3D11Device oluşturulması gerekir ve doğru oluşturma bayrakları ayarlanır.

ID3D11Device başlatılırken, D3D11_CREATE_DEVICE_VIDEO_SUPPORT bayrağı D3D11_CREATE_DEVICE_FLAG parçası olarak tanımlanmalıdır. Cihaz ve bağlam oluşturulduktan sonra, çoklu iş parçacığı oluşturmayı etkinleştirmek için SetMultithreadProtected öğesini çağırın. Cihazı IMFDXGIDeviceManager ile ilişkilendirmek için, IMFDXGIDeviceManager::ResetDevice işlevini kullanın.

ID3D11Cihazı IMFDXGIDeviceManager ile ilişkilendirme kodu:

// 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;

Ayrıca bkz.