DirectX 'te uzamsal eşleme

Özellik HoloLens (1. genel) HoloLens 2 Modern kulaklıklar
Uzamsal eşleme ✔️ ✔️

DirectX geliştirmesine genel bakış

Uzamsal eşleme için yerel uygulama geliştirme Windows API 'Leri kullanır . Perception. uzamsal ad alanı. Bu API 'Ler, uzamsal eşleme API 'lerinin Unitytarafından kullanıma sunulduğunu aynı şekilde uzamsal eşleme işlevlerine tam denetim sağlar.

Perception API 'Leri

Uzamsal eşleme geliştirmesi için belirtilen birincil türler aşağıdaki gibidir:

  • Spatialsurcetıı gözlemci hakkında, kullanıcının yakınında yer alan, Spatialsurçok yönlü bilgi nesneleri biçimindeki yüzeyler hakkında bilgi sağlar.
  • Spatialsurceial , BENZERSIZ bir kimlik, sınırlayıcı birim ve son değişiklik saati dahil olmak üzere tek bir uzamsal yüzeyi açıklar. İstek üzerine zaman uyumsuz bir Spatialsurçok yönlü ağ sağlar.
  • Spatialsurçok yönlü Meshoptions , Spatialsurceınfo 'Dan Istenen Spatialsurçok yönlü kafes nesnelerini özelleştirmek için kullanılan parametreleri içerir.
  • Spatialsurcemi kafesi tek bir uzamsal yüzey için ağ verilerini temsil eder. Köşe konumları, köşe normalleri ve üçgen indisler için veri, üye Spatialsurçok yönlü Meshbuffer nesnelerinde bulunur.
  • Spatialsurçok yönlü Meshbuffer tek bir kafes verileri türünü sarmalanmış.

Bu API 'Leri kullanarak bir uygulama geliştirirken, temel program akışınız şöyle görünür (aşağıda açıklanan örnek uygulamada gösterildiği gibi):

  • Spatialsurçok yönlü Gözlemcinizi ayarlama
    • Kullanıcının uygulamanızın uzamsal eşleme yeteneklerini kullanması için izin verilmesini sağlamak üzere Requestaccessasyncçağrısı yapın.
    • Bir Spatialsurçok yönlü gözlemci nesnesi örneği oluşturun.
    • Uzamsal yüzeyler hakkında bilgi almak istediğiniz alan bölgelerini belirtmek için Setboundingvolumes ' i çağırın. Bu işlevleri daha sonra tekrar çağırarak bu bölgeleri daha sonra değiştirebilirsiniz. Her bölge, bir Spatialboundingvolumekullanılarak belirtilir.
    • Belirttiğiniz alan bölgelerindeki uzamsal yüzeyler hakkında her yeni bilgi olduğunda harekete geçi ObservedSurfacesChanged olayına kaydolun.
  • ObservedSurfacesChanged olaylarını işle
    • Olay işleyicinizde, Spatialsurçok yönlü bilgi nesnelerinin haritasını almak için Getobservedsurface ' ı çağırın. Bu eşlemeyi kullanarak, uzamsal yüzeylerinizin Kullanıcı ortamındabulunduğu kayıtlarınızı güncelleştirebilirsiniz.
    • Her bir Spatialsurçok yönlü bilgi nesnesi için, seçtiğiniz bir uzamsal koordinat sisteminde ifade edilen uzamsal kapsamları belirlemek Için trygetlimitlerinizi sorgulayabilirsiniz.
    • Bir uzamsal yüzey için isteğe yönelik ağ oluşturma seçeneğine karar verirseniz, TryComputeLatestMeshAsyncçağırın. Üçgenin yoğunluğunu ve döndürülen kafes verilerinin biçimini belirten seçenekler sağlayabilirsiniz.
  • Ağı al ve işle
    • Her TryComputeLatestMeshAsync çağrısı, zaman uyumsuz bir Spatialsurçok yönlü kafes nesnesi döndürür.
    • Bu nesneden, kapsanan Spatialsurçok yönlü Meshbuffer nesnelerine erişerek, bunları istemeniz durumunda kafesin üçgen dizinlerine, köşe konumlarına ve köşe normalsine erişmenizi sağlayabilirsiniz. Bu veriler, kafesleri işlemek için kullanılan Direct3D 11 API 'leriyle doğrudan uyumlu bir biçimde olacaktır.
    • Buradaki uygulamanız, isteğe bağlı olarak ağ verilerini çözümleyebilir veya işleyebilir ve bunu işleme ve fizik rayması ve çarpışmaiçin kullanabilir.
    • Dikkat etmeniz gereken önemli bir ayrıntı, kafes köşe konumlarına (örneğin, kafeslerin işlenmesi için kullanılan köşe gölgelendiricide) bir ölçek uygulamanız ve bunları arabellekte depolandıkları en iyileştirilmiş tamsayı birimlerinden ölçümlere dönüştürmeniz gerekir. Bu ölçeği, Vertexpositionscaleçağırarak alabilirsiniz.

Sorun giderme

Uzamsal eşleme kodu örnek izlenecek yol

Holographic uzamsal eşleme kod örneği, Surface kafesleri yönetme ve işleme altyapısı dahil, Surface kafesleri uygulamanıza yüklemeye başlamak için kullanabileceğiniz kodu içerir.

Şimdi, DirectX uygulamanıza Surface eşleme özelliği ekleme hakkında yol göstereceğiz. bu kodu Windows Holographic app template projenize ekleyebilir veya yukarıda bahsedilen kod örneğine göz atarak ilerleyebilirsiniz. bu kod örneği, Windows Holographic uygulama şablonunu temel alır.

Uygulamanızı spatialPerception özelliğini kullanacak şekilde ayarlama

Uygulamanız, uzamsal eşleme özelliğini kullanabilir. Bu, uzamsal ağ Kullanıcı ortamının bir gösterimi olduğundan (özel veriler olarak kabul edilebilir olması gerekir). Uygulamanız için Package. appxmanifest dosyasında bu özelliği bildirin. Aşağıda bir örnek verilmiştir:

<Capabilities>
  <uap2:Capability Name="spatialPerception" />
</Capabilities>

Özelliği uap2 ad alanından gelir. Bildiriminizde bu ad alanına erişim sağlamak için, paket öğesine xlmns özniteliği olarak ekleyin > . Aşağıda bir örnek verilmiştir:

<Package
    xmlns="https://schemas.microsoft.com/appx/manifest/foundation/windows10"
    xmlns:mp="https://schemas.microsoft.com/appx/2014/phone/manifest"
    xmlns:uap="https://schemas.microsoft.com/appx/manifest/uap/windows10"
    xmlns:uap2="https://schemas.microsoft.com/appx/manifest/uap/windows10/2"
    IgnorableNamespaces="uap uap2 mp"
    >

Uzamsal eşleme özelliği desteğini denetle

Windows Mixed Reality, uzamsal eşlemeyi desteklemeyen cihazlar dahil olmak üzere çok çeşitli cihazları destekler. Uygulamanız, uzamsal eşleme kullanabilir veya uzamsal eşlemeyi kullanması gerekiyorsa, işlevselliği sağlamak için, bunu kullanmaya çalışmadan önce uzamsal eşlemenin desteklendiğinden emin olmak için kontrol etmelidir. Örneğin, karma gerçeklik uygulamanız için uzamsal eşleme gerekliyse, bir Kullanıcı onu uzamsal eşleme olmadan bir cihazda çalıştırmayı denediğinde bu etkiye bir ileti göstermelidir. Ya da uygulamanız, Kullanıcı ortamının yerine kendi sanal ortamını işleyebilir, bu da uzamsal eşleme kullanılabilir olduğunda ne olacağı hakkında bir deneyim sağlar. Herhangi bir olayda, bu API, uzamsal eşleme verilerini almaz ve uygun şekilde yanıt vermezse uygulamanızın farkında olmasını sağlar.

Geçerli cihazı uzamsal eşleme desteğiyle denetlemek için, önce UWP sözleşmesinin 4. düzey 4 veya daha büyük olduğundan emin olun ve ardından Spatialsurcegözlemci:: IsSupported () öğesini çağırın. Bunun için, holographic uzamsal eşleme kod örneği bağlamında bunu yapabilirsiniz. Destek yalnızca erişim istenmeden önce denetlenir.

Spatialsurcegözlemci:: IsSupported () API 'SI SDK sürüm 15063 ' den başlayarak kullanılabilir. Gerekirse, bu API 'yi kullanmadan önce projenizi Platform sürüm 15063 ' e yeniden hedefleyin.

if (m_surfaceObserver == nullptr)
   {
       using namespace Windows::Foundation::Metadata;
       if (ApiInformation::IsApiContractPresent(L"Windows.Foundation.UniversalApiContract", 4))
       {
           if (!SpatialSurfaceObserver::IsSupported())
           {
               // The current system does not have spatial mapping capability.
               // Turn off spatial mapping.
               m_spatialPerceptionAccessRequested = true;
               m_surfaceAccessAllowed = false;
           }
       }

       if (!m_spatialPerceptionAccessRequested)
       {
           /// etc ...

UWP sözleşmesi düzey 4 ' ten az olduğunda, cihazın uzamsal eşleme yapma yeteneğine sahip olmasına rağmen uygulama devam etmelidir.

Uzamsal eşleme verilerine erişim isteyin

Herhangi bir Surface Observer oluşturmayı denemeden önce uygulamanızın uzamsal eşleme verilerine erişim izni istemesi gerekir. Aşağıda bu sayfada daha sonra sağlanmış daha fazla ayrıntı ile Surface eşleme kod örneğimize göre bir örnek verilmiştir:

auto initSurfaceObserverTask = create_task(SpatialSurfaceObserver::RequestAccessAsync());
initSurfaceObserverTask.then([this, coordinateSystem](Windows::Perception::Spatial::SpatialPerceptionAccessStatus status)
{
    if (status == SpatialPerceptionAccessStatus::Allowed)
    {
        // Create a surface observer.
    }
    else
    {
        // Handle spatial mapping unavailable.
    }
}

Surface gözlemci oluşturma

Windows::P erception:: uzamsal:: yüzeyler ad alanı, bir spatialkoordinatı tesystemiçinde belirttiğiniz bir veya daha fazla birime hizmet eden spatialsurcesuya gözlemci sınıfını içerir. Surface Networks verilerine gerçek zamanlı olarak erişmek için bir Spatialsurçok yönlü gözlemci örneği kullanın.

Appmain. h'den:

// Obtains surface mapping data from the device in real time.
Windows::Perception::Spatial::Surfaces::SpatialSurfaceObserver^     m_surfaceObserver;
Windows::Perception::Spatial::Surfaces::SpatialSurfaceMeshOptions^  m_surfaceMeshOptions;

Önceki bölümde belirtildiği gibi, uygulamanızın kullanabilmesi için uzamsal eşleme verilerine erişim istemeniz gerekir. Bu erişim HoloLens otomatik olarak verilir.

// The surface mapping API reads information about the user's environment. The user must
// grant permission to the app to use this capability of the Windows Mixed Reality device.
auto initSurfaceObserverTask = create_task(SpatialSurfaceObserver::RequestAccessAsync());
initSurfaceObserverTask.then([this, coordinateSystem](Windows::Perception::Spatial::SpatialPerceptionAccessStatus status)
{
    if (status == SpatialPerceptionAccessStatus::Allowed)
    {
        // If status is allowed, we can create the surface observer.
        m_surfaceObserver = ref new SpatialSurfaceObserver();

Ardından, Surface gözlemci 'yi belirli bir sınırlayıcı birimi gözlemleyecek şekilde yapılandırmanız gerekir. Burada, koordinat sisteminin başlangıcına ortalanmış olan 20x20x5 metreler için bir kutu gözlemliyoruz.

// The surface observer can now be configured as needed.

        // In this example, we specify one area to be observed using an axis-aligned
        // bounding box 20 meters in width and 5 meters in height and centered at the
        // origin.
        SpatialBoundingBox aabb =
        {
            { 0.f,  0.f, 0.f },
            {20.f, 20.f, 5.f },
        };

        SpatialBoundingVolume^ bounds = SpatialBoundingVolume::FromBox(coordinateSystem, aabb);
        m_surfaceObserver->SetBoundingVolume(bounds);

Yerine birden çok sınırlama birimi ayarlayabilirsiniz.

Bu sahte bir koddur:

m_surfaceObserver->SetBoundingVolumes(/* iterable collection of bounding volumes*/);

Ayrıca, bir görünüm Frustum veya eksen hizalı olmayan bir sınırlayıcı kutu gibi diğer sınırlayıcı şekilleri de kullanmak mümkündür.

Bu sahte bir koddur:

m_surfaceObserver->SetBoundingVolume(
            SpatialBoundingVolume::FromFrustum(/*SpatialCoordinateSystem*/, /*SpatialBoundingFrustum*/)
            );

Surface eşleme verileri kullanılamadığında uygulamanızın bir şeyi farklı yapması gerekiyorsa, SpatialPerceptionAccessStatusizin verilmeyen bir durumda, bu cihazların uzamsal eşleme için donanıma sahip olmaması nedeniyle, bu cihazların ekli olduğu bilgisayarlarda izin verilmez. Bu cihazlar için, bunun yerine kullanıcının ortamı ve cihaz yapılandırması hakkında bilgi edinmek için uzamsal aşamaya güvenmelisiniz.

Surface kafes koleksiyonunu başlatma ve güncelleştirme

Surface gözlemci başarıyla oluşturulduysa Surface kafes koleksiyonumuzu başlatmaya devam edebiliriz. Burada, istek modeli API 'sini kullanarak, gözlemlenen yüzeylerin geçerli kümesini hemen elde edin:

auto mapContainingSurfaceCollection = m_surfaceObserver->GetObservedSurfaces();
        for (auto& pair : mapContainingSurfaceCollection)
        {
            // Store the ID and metadata for each surface.
            auto const& id = pair->Key;
            auto const& surfaceInfo = pair->Value;
            m_meshCollection->AddOrUpdateSurface(id, surfaceInfo);
        }

Ayrıca Surface kafes verilerini almak için kullanılabilecek bir gönderme modeli de vardır. Uygulamanızı yalnızca çekme modelini kullanmak üzere tasarlayacaksınız. Bu durumda, her zaman her ne kadar sıklıkla, her karede bir kez veya belirli bir süre boyunca (örneğin, oyun kurulumu sırasında) veri yoklamaya devam edersiniz. Bu durumda, yukarıdaki kod ihtiyacınız olan şeydir.

Kod örneğimizde, pedadgogical amaçları için her iki modelin de kullanımını göstermemiz önerilir. Burada, sistem bir değişikliği her tanırken güncel Surface kafes verileri almak için bir olaya abone olabiliriz.

m_surfaceObserver->ObservedSurfacesChanged += ref new TypedEventHandler<SpatialSurfaceObserver^, Platform::Object^>(
            bind(&HolographicDesktopAppMain::OnSurfacesChanged, this, _1, _2)
            );

Kod örneğimiz Ayrıca bu olaylara yanıt verecek şekilde yapılandırılmıştır. Bunu nasıl yaptığımız konusunda inceleyelim.

Note: Bu, uygulamanızın kafes verilerini işlemesi için en etkili yol olmayabilir. Bu kod açıklık için yazılmıştır ve iyileştirilmez.

Yüzey ağı verileri, anahtar değerleri olarak Platform:: Guid 'leri kullanarak Spatialsurcede bilgi nesnelerini depolayan salt okunurdur bir haritada sunulmaktadır.

IMapView<Guid, SpatialSurfaceInfo^>^ const& surfaceCollection = sender->GetObservedSurfaces();

Bu verileri işlemek için ilk olarak topladığımız anahtar değerleri inceliyoruz. Bu konunun ilerleyen kısımlarında, verilerin örnek uygulamamızda nasıl depolanabileceği hakkında ayrıntılar sunulacaktır.

// Process surface adds and updates.
for (const auto& pair : surfaceCollection)
{
    auto id = pair->Key;
    auto surfaceInfo = pair->Value;

    if (m_meshCollection->HasSurface(id))
    {
        // Update existing surface.
        m_meshCollection->AddOrUpdateSurface(id, surfaceInfo);
    }
    else
    {
        // New surface.
        m_meshCollection->AddOrUpdateSurface(id, surfaceInfo);
    }
}

Surface kafes koleksiyonumuzda olan ancak artık sistem koleksiyonunda olmayan Surface kafesleri kaldırdık. Bunu yapmak için, kafesleri ekleme ve güncelleştirme hakkında daha fazla şey yapmanız gereken bir işlem yapacağız. Uygulama koleksiyonumuza döngü yaptık ve sahip olduğumuz GUID 'in sistem koleksiyonunda olup olmadığını kontrol edin. Sistem koleksiyonunda değilse, bizden kaldırdık.

AppMain. cpp içindeki olay işleyicimizden:

m_meshCollection->PruneMeshCollection(surfaceCollection);

Realtimesurcemeshrenderer. cpp içinde ağ ayıklama uygulamasının uygulanması:

void RealtimeSurfaceMeshRenderer::PruneMeshCollection(IMapView<Guid, SpatialSurfaceInfo^>^ const& surfaceCollection)
{
    std::lock_guard<std::mutex> guard(m_meshCollectionLock);
    std::vector<Guid> idsToRemove;

    // Remove surfaces that moved out of the culling frustum or no longer exist.
    for (const auto& pair : m_meshCollection)
    {
        const auto& id = pair.first;
        if (!surfaceCollection->HasKey(id))
        {
            idsToRemove.push_back(id);
        }
    }

    for (const auto& id : idsToRemove)
    {
        m_meshCollection.erase(id);
    }
}

Surface kafes veri arabellekleri edinin ve kullanın

Surface kafes bilgilerinin alınması, bir veri toplamayı ve bu koleksiyona yönelik güncelleştirmeleri işlemeyi kolaylaştırıyor. Şimdi, verileri nasıl kullanabileceğinizi öğrenmek için ayrıntılara gideceğiz.

Kod örneğimizde, işleme için Surface kafesleri kullanmayı seçtik. Bu, gerçek hayatta oluşan hologramlar için yaygın bir senaryodur. Ayrıca, uygulama veya oyun işlevselliği sağlamaya başlamadan önce odanın hangi alanlarında tarandığı hakkında kullanıcıyı göstermek için kafesleri işleyebilir veya işlenen sürümlerini işleyebilirsiniz.

Kod örneği, önceki bölümde açıklandığımız olay işleyicisinden Surface kafes güncelleştirmelerini aldığında işlemi başlatır. Bu işlevdeki önemli kod satırı, yüzey kafesinigüncelleştirmek için kullanılan çağrıdır: Bu süre, ağ bilgilerini zaten işledik ve uygun gördüğünüz gibi kullanım için köşe ve dizin verilerini almak istiyoruz.

Realtimesurcemeshrenderer. cpp öğesinden:

void RealtimeSurfaceMeshRenderer::AddOrUpdateSurface(Guid id, SpatialSurfaceInfo^ newSurface)
{
    auto options = ref new SpatialSurfaceMeshOptions();
    options->IncludeVertexNormals = true;

    auto createMeshTask = create_task(newSurface->TryComputeLatestMeshAsync(1000, options));
    createMeshTask.then([this, id](SpatialSurfaceMesh^ mesh)
    {
        if (mesh != nullptr)
        {
            std::lock_guard<std::mutex> guard(m_meshCollectionLock);
            '''m_meshCollection[id].UpdateSurface(mesh);'''
        }
    }, task_continuation_context::use_current());
}

Örnek kodumuz, bir veri sınıfı olan surçok yönlü kafesinveri işleme ve işlemesini işlemesi için tasarlanmıştır. Bu kafesler, Realtimesurcemeshrenderer 'in gerçekten bir haritasını sakladığı şeydir. Her birinin tarafından verilen Spatialsurceçine bir başvurusu vardır. bu sayede, kafes köşesi veya dizin arabelleklerine erişmeniz veya ağ için bir dönüşüm elde etmeniz her zaman kullanılabilir. Şimdilik, ağı bir güncelleştirmeye ihtiyaç duyan şekilde işaretliyoruz.

Surçok yönlü ağ. cpp:

void SurfaceMesh::UpdateSurface(SpatialSurfaceMesh^ surfaceMesh)
{
    m_surfaceMesh = surfaceMesh;
    m_updateNeeded = true;
}

Daha sonra kafesin kendisini çizmesi istendiğinde, önce bayrağı kontrol eder. Bir güncelleştirme gerekiyorsa, köşe ve dizin arabellekleri GPU 'da güncelleştirilir.

void SurfaceMesh::CreateDeviceDependentResources(ID3D11Device* device)
{
    m_indexCount = m_surfaceMesh->TriangleIndices->ElementCount;
    if (m_indexCount < 3)
    {
        // Not enough indices to draw a triangle.
        return;
    }

İlk olarak, ham veri arabelleklerini alırız:

Windows::Storage::Streams::IBuffer^ positions = m_surfaceMesh->VertexPositions->Data;
    Windows::Storage::Streams::IBuffer^ normals   = m_surfaceMesh->VertexNormals->Data;
    Windows::Storage::Streams::IBuffer^ indices   = m_surfaceMesh->TriangleIndices->Data;

Daha sonra, HoloLens tarafından sağlanmış olan ağ verileriyle Direct3D cihaz arabellekleri oluşturacağız:

CreateDirectXBuffer(device, D3D11_BIND_VERTEX_BUFFER, positions, m_vertexPositions.GetAddressOf());
    CreateDirectXBuffer(device, D3D11_BIND_VERTEX_BUFFER, normals,   m_vertexNormals.GetAddressOf());
    CreateDirectXBuffer(device, D3D11_BIND_INDEX_BUFFER,  indices,   m_triangleIndices.GetAddressOf());

    // Create a constant buffer to control mesh position.
    CD3D11_BUFFER_DESC constantBufferDesc(sizeof(SurfaceTransforms), D3D11_BIND_CONSTANT_BUFFER);
    DX::ThrowIfFailed(
        device->CreateBuffer(
            &constantBufferDesc,
            nullptr,
            &m_modelTransformBuffer
            )
        );

    m_loadingComplete = true;
}

Note: Önceki kod parçacığında kullanılan CreateDirectXBuffer yardımcı işlevi için bkz. Surface Mapping Code örneği: Surcekafesi. cpp, Getdatafromıbuffer. h. Artık cihaz kaynağı oluşturma tamamlanmıştır ve ağ, güncelleştirme ve işlemeye hazır olarak kabul edilir.

Surface kafesleri güncelleştirme ve işleme

Surcemi kafes sınıfımızın özelleştirilmiş bir güncelleştirme işlevi vardır. Her bir Spatialsurçok yönlü kafesin dönüştürmesi vardır ve örneğimiz, dönüştürmeyi almak Için Spatialstationaryreferenceframe için geçerli koordinat sistemini kullanır. Ardından GPU 'daki model sabit arabelleğini güncelleştirir.

void SurfaceMesh::UpdateTransform(
    ID3D11DeviceContext* context,
    SpatialCoordinateSystem^ baseCoordinateSystem
    )
{
    if (m_indexCount < 3)
    {
        // Not enough indices to draw a triangle.
        return;
    }

    XMMATRIX transform = XMMatrixIdentity();

    auto tryTransform = m_surfaceMesh->CoordinateSystem->TryGetTransformTo(baseCoordinateSystem);
    if (tryTransform != nullptr)
    {
        transform = XMLoadFloat4x4(&tryTransform->Value);
    }

    XMMATRIX scaleTransform = XMMatrixScalingFromVector(XMLoadFloat3(&m_surfaceMesh->VertexPositionScale));

    XMStoreFloat4x4(
        &m_constantBufferData.vertexWorldTransform,
        XMMatrixTranspose(
            scaleTransform * transform
            )
        );

    // Normals don't need to be translated.
    XMMATRIX normalTransform = transform;
    normalTransform.r[3] = XMVectorSet(0.f, 0.f, 0.f, XMVectorGetW(normalTransform.r[3]));
    XMStoreFloat4x4(
        &m_constantBufferData.normalWorldTransform,
        XMMatrixTranspose(
            normalTransform
        )
        );

    if (!m_loadingComplete)
    {
        return;
    }

    context->UpdateSubresource(
        m_modelTransformBuffer.Get(),
        0,
        NULL,
        &m_constantBufferData,
        0,
        0
        );
}

Surface kafeslerin işlenmesi sırasında, koleksiyonu oluşturmadan önce bazı Prep işleri yaptık. Geçerli işleme yapılandırması için gölgelendirici ardışık düzeni ayarlanıyor ve giriş assembler aşamasını ayarladık. Holographic Camera yardımcı sınıfı CameraResources. cpp zaten görünüm/projeksiyon sabit arabelleğini ayarlamış.

Realtimesurcemeshrenderer:: Render:

auto context = m_deviceResources->GetD3DDeviceContext();

context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
context->IASetInputLayout(m_inputLayout.Get());

// Attach our vertex shader.
context->VSSetShader(
    m_vertexShader.Get(),
    nullptr,
    0
    );

// The constant buffer is per-mesh, and will be set as such.

if (depthOnly)
{
    // Explicitly detach the later shader stages.
    context->GSSetShader(nullptr, nullptr, 0);
    context->PSSetShader(nullptr, nullptr, 0);
}
else
{
    if (!m_usingVprtShaders)
    {
        // Attach the passthrough geometry shader.
        context->GSSetShader(
            m_geometryShader.Get(),
            nullptr,
            0
            );
    }

    // Attach our pixel shader.
    context->PSSetShader(
        m_pixelShader.Get(),
        nullptr,
        0
        );
}

Bu işlem tamamlandıktan sonra, kafeslerimiz üzerinde döngü yaptık ve her birinin kendisini çizmesini söyliyoruz. Note: Bu örnek kod, herhangi bir Frustum yüzey kaldırma kullanımı için en iyi duruma getirilmemiştir, ancak bu özelliği uygulamanıza dahil etmeniz gerekir.

std::lock_guard<std::mutex> guard(m_meshCollectionLock);

auto device = m_deviceResources->GetD3DDevice();

// Draw the meshes.
for (auto& pair : m_meshCollection)
{
    auto& id = pair.first;
    auto& surfaceMesh = pair.second;

    surfaceMesh.Draw(device, context, m_usingVprtShaders, isStereo);
}

Tek tek kafesler, köşe ve Dizin arabelleğini, ilerlemesiyle ve model dönüştürme sabit arabelleğini ayarlamaktan sorumludur. Windows Holographic app şablonundaki dönen küpte olduğu gibi, örnek oluşturma kullanarak stereoscopic arabelleklerine işlenir.

Surçok yönlü ağ::D RAW:

// The vertices are provided in {vertex, normal} format

const auto& vertexStride = m_surfaceMesh->VertexPositions->Stride;
const auto& normalStride = m_surfaceMesh->VertexNormals->Stride;

UINT strides [] = { vertexStride, normalStride };
UINT offsets [] = { 0, 0 };
ID3D11Buffer* buffers [] = { m_vertexPositions.Get(), m_vertexNormals.Get() };

context->IASetVertexBuffers(
    0,
    ARRAYSIZE(buffers),
    buffers,
    strides,
    offsets
    );

const auto& indexFormat = static_cast<DXGI_FORMAT>(m_surfaceMesh->TriangleIndices->Format);

context->IASetIndexBuffer(
    m_triangleIndices.Get(),
    indexFormat,
    0
    );

context->VSSetConstantBuffers(
    0,
    1,
    m_modelTransformBuffer.GetAddressOf()
    );

if (!usingVprtShaders)
{
    context->GSSetConstantBuffers(
        0,
        1,
        m_modelTransformBuffer.GetAddressOf()
        );
}

context->PSSetConstantBuffers(
    0,
    1,
    m_modelTransformBuffer.GetAddressOf()
    );

context->DrawIndexedInstanced(
    m_indexCount,       // Index count per instance.
    isStereo ? 2 : 1,   // Instance count.
    0,                  // Start index location.
    0,                  // Base vertex location.
    0                   // Start instance location.
    );

Yüzey eşleme ile seçimleri işleme

Yüzey eşleme kod örneği, occlusiyon-yalnızca Surface kafes verilerinin işlenmesi ve Surface kafes verilerinin ekran üzerinde işlenmesi için kod sunar. Seçtiğiniz yol veya her ikisi de uygulamanıza bağlıdır. Bu belgedeki her iki yapılandırmada da izlenecek.

Holographic efekti için occlusiyon arabellekleri işleniyor

Geçerli sanal kameranın işleme hedefi görünümünü temizleyerek başlayın.

AppMain. cpp öğesinden:

context->ClearRenderTargetView(pCameraResources->GetBackBufferRenderTargetView(), DirectX::Colors::Transparent);

Bu bir "önceden oluşturma" geçişdir. Burada, ağ işleyicisinin yalnızca derinliği işlemesini isteyerek bir occlusbuffer oluşturacağız. Bu yapılandırmada bir işleme hedefi görünümü iliştiriyoruz ve ağ Oluşturucu, GPU 'nun piksel çizmesini istemediğiniz için piksel gölgelendirici aşamasını nullptr olarak ayarlıyor. Geometri, derinlik arabelleğine rasterleştirilir ve grafik işlem hattı bu şekilde durur.

// Pre-pass rendering: Create occlusion buffer from Surface Mapping data.
context->ClearDepthStencilView(pCameraResources->GetSurfaceDepthStencilView(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);

// Set the render target to null, and set the depth target occlusion buffer.
// We will use this same buffer as a shader resource when drawing holograms.
context->OMSetRenderTargets(0, nullptr, pCameraResources->GetSurfaceOcclusionDepthStencilView());

// The first pass is a depth-only pass that generates an occlusion buffer we can use to know which
// hologram pixels are hidden behind surfaces in the environment.
m_meshCollection->Render(pCameraResources->IsRenderingStereoscopic(), true);

Surface Mapping occlusıg arabelleği için fazladan bir derinlik testi ile hologramlar çizebiliriz. Bu kod örneğinde, bir yüzey arkasında olmaları durumunda küp üzerinde pikselleri farklı bir renkte işliyoruz.

AppMain. cpp öğesinden:

// Hologram rendering pass: Draw holographic content.
context->ClearDepthStencilView(pCameraResources->GetHologramDepthStencilView(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);

// Set the render target, and set the depth target drawing buffer.
ID3D11RenderTargetView *const targets[1] = { pCameraResources->GetBackBufferRenderTargetView() };
context->OMSetRenderTargets(1, targets, pCameraResources->GetHologramDepthStencilView());

// Render the scene objects.
// In this example, we draw a special effect that uses the occlusion buffer we generated in the
// Pre-Pass step to render holograms using X-Ray Vision when they are behind physical objects.
m_xrayCubeRenderer->Render(
    pCameraResources->IsRenderingStereoscopic(),
    pCameraResources->GetSurfaceOcclusionShaderResourceView(),
    pCameraResources->GetHologramOcclusionShaderResourceView(),
    pCameraResources->GetDepthTextureSamplerState()
    );

SpecialEffectPixelShader. HLSL kodu temel alınarak:

// Draw boundaries
min16int surfaceSum = GatherDepthLess(envDepthTex, uniSamp, input.pos.xy, pixelDepth, input.idx.x);

if (surfaceSum <= -maxSum)
{
    // The pixel and its neighbors are behind the surface.
    // Return the occluded 'X-ray' color.
    return min16float4(0.67f, 0.f, 0.f, 1.0f);
}
else if (surfaceSum < maxSum)
{
    // The pixel and its neighbors are a mix of in front of and behind the surface.
    // Return the silhouette edge color.
    return min16float4(1.f, 1.f, 1.f, 1.0f);
}
else
{
    // The pixel and its neighbors are all in front of the surface.
    // Return the color of the hologram.
    return min16float4(input.color, 1.0f);
}

Note:Gatherdepuz yordamımız için bkz. Surface Mapping Code örneği: SpecialEffectPixelShader. HLSL.

Yüzey ağ verilerini ekranda işleme

Ayrıca, stereo görüntü arabelleklerine yüzey kafesleri çizebilirsiniz. Işıklandırma ile tam yüz çizmeyi seçtik, ancak tel çerçeve çizmeyi, işlemeden önce kafesleri işlemeyi, doku haritasını uygulamayı ve benzerlerini yapmayı tercih ediyoruz.

Burada, kod örneğimiz, ağ işleyicisinin koleksiyonu çizmesini söyler. Bu kez yalnızca bir derinlik geçişi belirttiğimiz için, bir piksel gölgelendiricisi ekler ve geçerli sanal kamera için belirttiğimiz hedefleri kullanarak işleme işlem hattını tamamlar.

// Spatial Mapping mesh rendering pass: Draw Spatial Mapping mesh over the world.
context->ClearDepthStencilView(pCameraResources->GetSurfaceOcclusionDepthStencilView(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);

// Set the render target to the current holographic camera's back buffer, and set the depth buffer.
ID3D11RenderTargetView *const targets[1] = { pCameraResources->GetBackBufferRenderTargetView() };
context->OMSetRenderTargets(1, targets, pCameraResources->GetSurfaceDepthStencilView());

// This drawing pass renders the surface meshes to the stereoscopic display. The user will be
// able to see them while wearing the device.
m_meshCollection->Render(pCameraResources->IsRenderingStereoscopic(), false);

Ayrıca bkz.

Not

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

bu konuda, Evrensel Windows Platformu SDK ile paketlenmiş uzamsal eşleme örnek uygulamasının ayrıntılı açıklaması dahil olmak üzere, DirectX uygulamanızda uzamsal eşlemenin nasıl uygulanacağı açıklanmaktadır.

Bu konu, Holographicspatialmapping UWP kod örneğindeki kodu kullanır.

Not

Bu makaledeki kod parçacıkları şu anda C++ holographic proje şablonundakullanılan C + +17-uyumlu c++/Wınrt yerine c++/cx kullanımını göstermektedir. Kavramlar bir C++/Wınrt projesi için eşdeğerdir, ancak kodu çevirmeniz gerekir.

Cihaz desteği