Representación en DirectXRendering in DirectX

Nota

Este artículo está relacionado con las API nativas de WinRT heredadas.This article relates to the legacy WinRT native APIs. En el caso de los nuevos proyectos de aplicaciones nativas, se recomienda usar la API de OpenXR.For new native app projects, we recommend using the OpenXR API.

Windows Mixed Reality se basa en DirectX para generar experiencias gráficas 3D enriquecidas para los usuarios.Windows Mixed Reality is built on DirectX to produce rich, 3D graphical experiences for users. La abstracción de representación se encuentra justo encima de DirectX, que permite que las aplicaciones demuestren la posición y la orientación de los observadores de la escena holográfica previstos por el sistema.The rendering abstraction sits just above DirectX, which lets apps reason about the position and orientation of holographic scene observers predicted by the system. A continuación, el desarrollador puede localizar sus hologramas en función de cada cámara, lo que permite que la aplicación represente estos hologramas en varios sistemas de coordenadas espaciales a medida que el usuario se desplaza.The developer can then locate their holograms based on each camera, letting the app render these holograms in various spatial coordinate systems as the user moves around.

Nota: en este tutorial se describe la representación holográfica en Direct3D 11.Note: This walkthrough describes holographic rendering in Direct3D 11. También se proporciona una plantilla de aplicación de Windows mixed reality de Direct3D 12 con la extensión de plantillas de aplicación de realidad mixta.A Direct3D 12 Windows Mixed Reality app template is also supplied with the Mixed Reality app templates extension.

Actualizar para el marco actualUpdate for the current frame

Para actualizar el estado de la aplicación para los hologramas, una vez por fotograma, la aplicación:To update the application state for holograms, once per frame the app will:

  • Obtiene un HolographicFrame del sistema de administración de pantalla.Get a HolographicFrame from the display management system.
  • Actualice la escena con la predicción actual de en la que se mostrará la vista de cámara cuando se complete el procesamiento.Update the scene with the current prediction of where the camera view will be when render is completed. Tenga en cuenta que puede haber más de una cámara para la escena holográfica.Note, there can be more than one camera for the holographic scene.

Para representar vistas de cámara holográfica, una vez por fotograma, la aplicación:To render to holographic camera views, once per frame the app will:

  • Para cada cámara, represente la escena del fotograma actual, usando la vista de cámara y las matrices de proyección del sistema.For each camera, render the scene for the current frame, using the camera view and projection matrices from the system.

Crear un nuevo marco holográfica y obtener su predicciónCreate a new holographic frame and get its prediction

HolographicFrame tiene información que la aplicación necesita para actualizar y representar el marco actual.The HolographicFrame has information that the app needs to update and render the current frame. La aplicación comienza cada nuevo fotograma llamando al método CreateNextFrame .The app begins each new frame by calling the CreateNextFrame method. Cuando se llama a este método, las predicciones se realizan utilizando los datos del sensor más recientes disponibles y se encapsulan en el objeto CurrentPrediction .When this method is called, predictions are made using the latest sensor data available, and encapsulated in CurrentPrediction object.

Se debe usar un nuevo objeto de marco para cada fotograma representado, ya que solo es válido para un momento dado.A new frame object must be used for each rendered frame as it is only valid for an instant in time. La propiedad CurrentPrediction contiene información como la posición de la cámara.The CurrentPrediction property contains information such as the camera position. La información se extrapola al momento exacto en que se espera que el marco sea visible para el usuario.The information is extrapolated to the exact moment in time when the frame is expected to be visible to the user.

El código siguiente se ha extraído de AppMain:: Update:The following code is excerpted from AppMain::Update:

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

Procesar actualizaciones de la cámaraProcess camera updates

Los búferes de reserva pueden cambiar de fotograma a fotograma.Back buffers can change from frame to frame. La aplicación debe validar el búfer de reserva de cada cámara y liberar y volver a crear las vistas de recursos y los búferes de profundidad según sea necesario.Your app needs to validate the back buffer for each camera, and release and recreate resource views and depth buffers as needed. Observe que el conjunto de supuestos de la predicción es la lista autoritativa de cámaras que se usan en el marco actual.Notice that the set of poses in the prediction is the authoritative list of cameras being used in the current frame. Normalmente, esta lista se usa para iterar en el conjunto de cámaras.Usually, you use this list to iterate on the set of cameras.

Desde AppMain:: Update:From AppMain::Update:

m_deviceResources->EnsureCameraResources(holographicFrame, prediction);

De DeviceResources:: EnsureCameraResources:From DeviceResources::EnsureCameraResources:

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

Obtención del sistema de coordenadas que se va a usar como base para la representaciónGet the coordinate system to use as a basis for rendering

Windows Mixed Reality permite que la aplicación cree varios sistemas de coordenadas, como los fotogramas de referencia fijos y de referencia para realizar el seguimiento de las ubicaciones del mundo físico.Windows Mixed Reality lets your app create various coordinate systems, like attached and stationary reference frames for tracking locations in the physical world. A continuación, la aplicación puede usar estos sistemas de coordenadas para pensar en dónde representar los hologramas en cada fotograma.Your app can then use these coordinate systems to reason about where to render holograms each frame. Cuando se solicitan coordenadas de una API, siempre se pasa el SpatialCoordinateSystem en el que se desea expresar esas coordenadas.When requesting coordinates from an API, you'll always pass in the SpatialCoordinateSystem within which you want those coordinates to be expressed.

Desde AppMain:: Update:From AppMain::Update:

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

Estos sistemas de coordenadas se pueden usar para generar matrices de vista estéreo al representar el contenido de la escena.These coordinate systems can then be used to generate stereo view matrices when rendering the content in your scene.

Desde CameraResources:: UpdateViewProjectionBuffer:From CameraResources::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);

Entrada de movimiento y miración de procesoProcess gaze and gesture input

La entrada de la mirada y la mano no se basa en el tiempo y no tiene que actualizarse en la función StepTimer .Gaze and hand input aren't time-based and don't have to update in the StepTimer function. Sin embargo, esta entrada es algo que la aplicación debe buscar en cada fotograma.However this input is something that the app needs to look at each frame.

Procesar actualizaciones basadas en el tiempoProcess time-based updates

Cualquier aplicación de representación en tiempo real necesitará alguna manera de procesar las actualizaciones basadas en el tiempo: la plantilla de aplicación de Windows Holographic usa una implementación de StepTimer , similar a la StepTimer proporcionada en la plantilla de aplicación para UWP de DirectX 11.Any real-time rendering app will need some way to process time-based updates - the Windows Holographic app template uses a StepTimer implementation, similar to the StepTimer provided in the DirectX 11 UWP app template. Esta clase auxiliar de ejemplo StepTimer puede proporcionar actualizaciones de pasos temporales fijas, actualizaciones de pasos temporales variables y el modo predeterminado es un paso de tiempo variable.This StepTimer sample helper class can provide fixed time-step updates, variable time-step updates, and the default mode is variable time steps.

En la representación holográfica, hemos elegido no incluir demasiado en la función de temporizador porque puede configurarla para que sea un paso de tiempo fijo.For holographic rendering, we've chosen not to put too much into the timer function because you can configure it to be a fixed time step. Es posible que se le llame más de una vez por fotograma, o no, en algunos fotogramas, y que las actualizaciones de datos holográficas se realicen una vez por fotograma.It might get called more than once per frame – or not at all, for some frames – and our holographic data updates should happen once per frame.

Desde AppMain:: Update:From AppMain::Update:

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

Colocar y girar los hologramas en el sistema de coordenadasPosition and rotate holograms in your coordinate system

Si está trabajando en un único sistema de coordenadas, como hace la plantilla con el SpatialStationaryReferenceFrame, este proceso no es diferente de lo que se usa en los gráficos 3D.If you're operating in a single coordinate system, as the template does with the SpatialStationaryReferenceFrame, this process isn't different from what you're otherwise used to in 3D graphics. Aquí se gira el cubo y se establece la matriz del modelo en función de la posición en el sistema de coordenadas estacionales.Here, we rotate the cube and set the model matrix based on the position in the stationary coordinate system.

Desde SpinningCubeRenderer:: Update:From 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));

Tenga en cuenta los escenarios avanzados: El cubo giratorio es un ejemplo sencillo de cómo colocar un holograma dentro de un solo fotograma de referencia.Note about advanced scenarios: The spinning cube is a simple example of how to position a hologram within a single reference frame. También es posible usar varios SpatialCoordinateSystems en el mismo fotograma representado al mismo tiempo.It's also possible to use multiple SpatialCoordinateSystems in the same rendered frame, at the same time.

Actualizar datos de búfer de constantesUpdate constant buffer data

Las transformaciones del modelo para el contenido se actualizan de la forma habitual.Model transforms for content are updated as usual. De momento, habrá calculado las transformaciones válidas para el sistema de coordenadas en el que se va a representar.By now, you'll have computed valid transforms for the coordinate system you'll be rendering in.

Desde SpinningCubeRenderer:: Update:From SpinningCubeRenderer::Update:

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

¿Qué ocurre con las transformaciones de visualización y proyección?What about view and projection transforms? Para obtener los mejores resultados, queremos esperar hasta que podamos estar casi preparados para las llamadas a Draw antes de obtenerlas.For best results, we want to wait until we're almost ready for our draw calls before we get these.

Representar el marco actualRender the current frame

La representación en Windows Mixed Reality no es muy diferente de la representación en una pantalla mono 2D, pero hay algunas diferencias:Rendering on Windows Mixed Reality isn't much different from rendering on a 2D mono display, but there are a few differences:

  • Las predicciones de tramas holográficas son importantes.Holographic frame predictions are important. Cuanto más se acerque la predicción a la presentación del fotograma, mejor se verán los hologramas.The closer the prediction is to when your frame is presented, the better your holograms will look.
  • Windows Mixed Reality controla las vistas de la cámara.Windows Mixed Reality controls the camera views. Se representan en cada una de ellas, ya que el marco holográfica las presentará más adelante.Render to each one because the holographic frame will be presenting them for you later.
  • Se recomienda realizar la representación en estéreo mediante un dibujo con instancias en una matriz de destino de representación.We recommend doing stereo rendering using instanced drawing to a render target array. La plantilla de aplicación holográfica usa el enfoque recomendado del dibujo con instancias en una matriz de destino de representación, que usa una vista de destino de representación en un Texture2DArray.The holographic app template uses the recommended approach of instanced drawing to a render target array, which uses a render target view onto a Texture2DArray.
  • Si desea representar sin usar la creación de instancias de estéreo, deberá crear dos RenderTargetViews que no sean de matriz, uno para cada ojo.If you want to render without using stereo instancing, you'll need to create two non-array RenderTargetViews, one for each eye. Cada RenderTargetViews hace referencia a uno de los dos segmentos del Texture2DArray proporcionado a la aplicación desde el sistema.Each RenderTargetViews references one of the two slices in the Texture2DArray provided to the app from the system. Esto no se recomienda, ya que suele ser más lento que el uso de la creación de instancias.This isn't recommended, as it's typically slower than using instancing.

Obtener una predicción HolographicFrame actualizadaGet an updated HolographicFrame prediction

La actualización de la predicción de fotogramas mejora la eficacia de la estabilización de la imagen.Updating the frame prediction enhances the effectiveness of image stabilization. Obtiene un posicionamiento más preciso de los hologramas debido al tiempo más corto entre la predicción y el momento en el que el usuario puede ver el marco.You get more accurate positioning of holograms because of the shorter time between the prediction and when the frame is visible to the user. Idealmente, actualice la predicción de fotogramas justo antes de la representación.Ideally update your frame prediction just before rendering.

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

Representar en cada cámaraRender to each camera

Bucle en el conjunto de repeticiones de la cámara en la predicción y representar en cada cámara de este conjunto.Loop on the set of camera poses in the prediction, and render to each camera in this set.

Configurar el paso de representaciónSet up your rendering pass

Windows Mixed Reality usa la representación Stereoscopic para mejorar la ilusión de profundidad y representar stereoscopically, por lo que tanto la pantalla izquierda como la derecha están activas.Windows Mixed Reality uses stereoscopic rendering to enhance the illusion of depth and to render stereoscopically, so both the left and the right display are active. Con la representación Stereoscopic, hay un desplazamiento entre las dos pantallas, que el cerebro puede conciliar como profundidad real.With stereoscopic rendering, there's an offset between the two displays, which the brain can reconcile as actual depth. En esta sección se describe la representación de Stereoscopic mediante la creación de instancias, mediante el uso de código de la plantilla de aplicación de Windows Holographic.This section covers stereoscopic rendering using instancing, using code from the Windows Holographic app template.

Cada cámara tiene su propio destino de representación (búfer de reserva) y las matrices de vistas y proyección en el espacio holográfica.Each camera has its own render target (back buffer), and view and projection matrices, into the holographic space. La aplicación tendrá que crear cualquier otro recurso basado en la cámara, como el búfer de profundidad, por cada cámara.Your app will need to create any other camera-based resources - such as the depth buffer - on a per-camera basis. En la plantilla de aplicación de Windows Holographic, se proporciona una clase auxiliar para agrupar estos recursos en DX:: CameraResources.In the Windows Holographic app template, we provide a helper class to bundle these resources together in DX::CameraResources. Empiece por configurar las vistas de destino de representación:Start by setting up the render target views:

Desde AppMain:: Render:From 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);

Usar la predicción para obtener las matrices de vista y proyección de la cámaraUse the prediction to get the view and projection matrices for the camera

Las matrices de vista y proyección de cada cámara holográfica cambiarán con cada fotograma.The view and projection matrices for each holographic camera will change with every frame. Actualice los datos en el búfer de constantes de cada cámara holográfica.Refresh the data in the constant buffer for each holographic camera. Hágalo después de actualizar la predicción y antes de realizar cualquier llamada a Draw para esa cámara.Do this after you updated the prediction, and before you make any draw calls for that camera.

Desde AppMain:: Render:From 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);

Aquí se muestra cómo se adquieren las matrices de la pose de la cámara.Here, we show how the matrices are acquired from the camera pose. Durante este proceso, también se obtiene la ventanilla actual de la cámara.During this process, we also obtain the current viewport for the camera. Observe cómo se proporciona un sistema de coordenadas: este es el mismo sistema de coordenadas que se usa para comprender la mirada y es el mismo que se usa para colocar el cubo giratorio.Note how we provide a coordinate system: this is the same coordinate system we used to understand gaze, and it's the same one we used to position the spinning cube.

Desde CameraResources:: UpdateViewProjectionBuffer:From CameraResources::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))
    );
}

La ventanilla debe establecerse en cada fotograma.The viewport should be set each frame. Normalmente, el sombreador de vértices (al menos) necesitará tener acceso a los datos de vista o proyección.Your vertex shader (at least) will generally need access to the view/projection data.

Desde CameraResources:: AttachViewProjectionBuffer:From CameraResources::AttachViewProjectionBuffer:

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

Se representa en el búfer de reserva de la cámara y se confirma el búfer de profundidad:Render to the camera back buffer and commit the depth buffer:

Es conveniente comprobar que TryGetViewTransform se ha ejecutado correctamente antes de intentar usar los datos de vista o proyección, porque si el sistema de coordenadas no es localizable (por ejemplo, se ha interrumpido el seguimiento), la aplicación no puede representarse con él para ese marco.It's a good idea to check that TryGetViewTransform succeeded before trying to use the view/projection data, because if the coordinate system isn't locatable (for example, tracking was interrupted) your app can't render with it for that frame. La plantilla solo llama a Render en el cubo giratorio Si la clase CameraResources indica una actualización correcta.The template only calls Render on the spinning cube if the CameraResources class indicates a successful update.

Windows Mixed Reality incluye características para la estabilización de imágenes con el fin de mantener los hologramas colocados donde un desarrollador o usuario los pone en el mundo.Windows Mixed Reality includes features for image stabilization to keep holograms positioned where a developer or user puts them in the world. La estabilización de imágenes ayuda a ocultar la latencia inherente en una canalización de representación para garantizar las mejores experiencias holográficas para los usuarios.Image stabilization helps hide the latency inherent in a rendering pipeline to ensure the best holographic experiences for users. Se puede especificar un punto de enfoque para mejorar la estabilización de la imagen aún más, o se puede proporcionar un búfer de profundidad para calcular la estabilización de la imagen optimizada en tiempo real.A focus point may be specified to enhance image stabilization even further, or a depth buffer may be provided to compute optimized image stabilization in real time.

Para obtener los mejores resultados, la aplicación debe proporcionar un búfer de profundidad mediante la API de CommitDirect3D11DepthBuffer .For best results, your app should provide a depth buffer using the CommitDirect3D11DepthBuffer API. Windows Mixed Reality puede usar la información de geometría del búfer de profundidad para optimizar la estabilización de la imagen en tiempo real.Windows Mixed Reality can then use geometry information from the depth buffer to optimize image stabilization in real time. La plantilla de aplicación de Windows Holographic confirma el búfer de profundidad de la aplicación de forma predeterminada, lo que ayuda a optimizar la estabilidad del holograma.The Windows Holographic app template commits the app's depth buffer by default, helping optimize hologram stability.

Desde AppMain:: Render:From 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);
    }
}

Nota

Windows procesará la textura de profundidad en la GPU, por lo que debe ser posible usar el búfer de profundidad como un recurso de sombreador.Windows will process your depth texture on the GPU, so it must be possible to use your depth buffer as a shader resource. El ID3D11Texture2D que cree debe tener un formato sin tipo y debe enlazarse como una vista de recursos del sombreador.The ID3D11Texture2D that you create should be in a typeless format and it should be bound as a shader resource view. Este es un ejemplo de cómo crear una textura de profundidad que se puede confirmar para la estabilización de la imagen.Here is an example of how to create a depth texture that can be committed for image stabilization.

Código para la creación de recursos de búfer de profundidad para CommitDirect3D11DepthBuffer:Code for Depth buffer resource creation for CommitDirect3D11DepthBuffer:

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

Dibujo de contenido holográficaDraw holographic content

La plantilla de aplicación de Windows Holographic representa el contenido en estéreo mediante el uso de la técnica recomendada de dibujar geometría con instancias en un Texture2DArray de tamaño 2.The Windows Holographic app template renders content in stereo by using the recommended technique of drawing instanced geometry to a Texture2DArray of size 2. Echemos un vistazo a la parte de la creación de instancias de este y cómo funciona en Windows Mixed Reality.Let's look at the instancing part of this, and how it works on Windows Mixed Reality.

Desde SpinningCubeRenderer:: Render:From 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.
);

Cada instancia tiene acceso a una matriz de vista/proyección diferente del búfer de constantes.Each instance accesses a different view/projection matrix from the constant buffer. Esta es la estructura de búfer de constantes, que es simplemente una matriz de dos matrices.Here's the constant buffer structure, which is just an array of two matrices.

En VertexShaderShared. HLSL, incluido VPRTVertexShader. HLSL:From VertexShaderShared.hlsl, included by VPRTVertexShader.hlsl:

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

El índice de la matriz de destino de representación se debe establecer para cada píxel.The render target array index must be set for each pixel. En el siguiente fragmento de código, Output. viewId se asigna a la semántica SV_RenderTargetArrayIndex .In the following snippet, output.viewId is mapped to the SV_RenderTargetArrayIndex semantic. Esto requiere compatibilidad con una característica opcional de Direct3D 11,3, que permite establecer la semántica de índice de la matriz de destino de representación desde cualquier fase del sombreador.This requires support for an optional Direct3D 11.3 feature, which allows the render target array index semantic to be set from any shader stage.

Desde VPRTVertexShader. HLSL:From 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;
};

En VertexShaderShared. HLSL, incluido VPRTVertexShader. HLSL:From VertexShaderShared.hlsl, included by VPRTVertexShader.hlsl:

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

Si desea usar las técnicas de dibujo con instancias existentes con este método de dibujo en una matriz de destino de representación estéreo, dibuje dos veces el número de instancias que tiene normalmente.If you want to use your existing instanced drawing techniques with this method of drawing to a stereo render target array, draw twice the number of instances you normally have. En el sombreador, divida Input. instId por 2 para obtener el identificador de instancia original, que se puede indizar en (por ejemplo,) un búfer de datos por objeto: int actualIdx = input.instId / 2;In the shader, divide input.instId by 2 to get the original instance ID, which can be indexed into (for example) a buffer of per-object data: int actualIdx = input.instId / 2;

Nota importante sobre la representación de contenido estéreo en HoloLensImportant note about rendering stereo content on HoloLens

Windows Mixed Reality admite la capacidad de establecer el índice de matriz de destino de representación desde cualquier fase del sombreador.Windows Mixed Reality supports the ability to set the render target array index from any shader stage. Normalmente, se trata de una tarea que solo podría realizarse en la fase del sombreador de geometría debido a la manera en que se define la semántica para Direct3D 11.Normally, this is a task that could only be done in the geometry shader stage because of the way the semantic is defined for Direct3D 11. Aquí se muestra un ejemplo completo de cómo configurar una canalización de representación con solo las etapas del sombreador de vértices y píxeles establecidos.Here, we show a complete example of how to set up a rendering pipeline with just the vertex and pixel shader stages set. El código del sombreador es como se describió anteriormente.The shader code is as described above.

Desde SpinningCubeRenderer:: Render:From 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.
);

Nota importante sobre la representación en dispositivos que no sean HoloLensImportant note about rendering on non-HoloLens devices

La configuración del índice de matriz de destino de representación en el sombreador de vértices requiere que el controlador de gráficos admita una característica de Direct3D 11,3 opcional, que es compatible con HoloLens.Setting the render target array index in the vertex shader requires that the graphics driver supports an optional Direct3D 11.3 feature, which HoloLens does support. Es posible que la aplicación pueda implementar de forma segura solo esa técnica para la representación y que se cumplan todos los requisitos para ejecutarse en Microsoft HoloLens.Your app may can safely implement just that technique for rendering, and all requirements will be met for running on the Microsoft HoloLens.

También puede ser el caso de que quiera usar el emulador de HoloLens, que puede ser una herramienta de desarrollo eficaz para su aplicación holográfica, y que admiten dispositivos con auriculares de gran rendimiento con Windows Mixed Reality que están conectados a equipos con Windows 10.It may be the case that you want to use the HoloLens emulator as well, which can be a powerful development tool for your holographic app - and support Windows Mixed Reality immersive headset devices that are attached to Windows 10 PCs. La compatibilidad con la ruta de representación que no es de HoloLens (para todas las aplicaciones de realidad mixta de Windows) también está integrada en la plantilla de aplicación de Windows Holographic.Support for the non-HoloLens rendering path - for all of Windows Mixed Reality - is also built into the Windows Holographic app template. En el código de plantilla, encontrará código para permitir que la aplicación holográfica se ejecute en la GPU del equipo de desarrollo.In the template code, you'll find code to enable your holographic app to run on the GPU in your development PC. Este es el modo en que la clase DeviceResources comprueba esta compatibilidad de características opcional.Here's how the DeviceResources class checks for this optional feature support.

De DeviceResources:: CreateDeviceResources:From 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;
}

Para admitir la representación sin esta característica opcional, la aplicación debe usar un sombreador de geometría para establecer el índice de la matriz de destino de representación.To support rendering without this optional feature, your app must use a geometry shader to set the render target array index. Este fragmento de código se agregaría después de VSSetConstantBuffers y antes de PSSetShader en el ejemplo de código mostrado en la sección anterior que explica cómo representar el estéreo en HoloLens.This snippet would be added after VSSetConstantBuffers, and before PSSetShader in the code example shown in the previous section that explains how to render stereo on HoloLens.

Desde SpinningCubeRenderer:: Render:From 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
    );
}

Nota HLSL: en este caso, también debe cargar un sombreador de vértices ligeramente modificado que pase el índice de la matriz de destino de representación al sombreador de geometría mediante una semántica de sombreador siempre permitida, como TEXCOORD0.HLSL NOTE: In this case, you must also load a slightly modified vertex shader that passes the render target array index to the geometry shader using an always-allowed shader semantic, such as TEXCOORD0. El sombreador de geometría no tiene que hacer ningún trabajo; el sombreador de geometría de la plantilla pasa todos los datos, con la excepción del índice de la matriz de destino de representación, que se usa para establecer la semántica SV_RenderTargetArrayIndex.The geometry shader doesn't have to do any work; the template geometry shader passes through all data, with the exception of the render target array index, which is used to set the SV_RenderTargetArrayIndex semantic.

Código de plantilla de aplicación para GeometryShader. HLSL:App template code for GeometryShader.hlsl:

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

PresentePresent

Habilitación del marco holográfica para presentar la cadena de intercambioEnable the holographic frame to present the swap chain

Con Windows Mixed Reality, el sistema controla la cadena de intercambio.With Windows Mixed Reality, the system controls the swap chain. Después, el sistema administra la presentación de fotogramas a cada cámara holográfica para garantizar una experiencia de usuario de alta calidad.The system then manages presenting frames to each holographic camera to ensure a high-quality user experience. También proporciona una actualización de la ventanilla cada fotograma, para cada cámara, para optimizar aspectos del sistema, como la estabilización de imágenes o la captura de realidad mixta.It also provides a viewport update each frame, for each camera, to optimize aspects of the system such as image stabilization or Mixed Reality Capture. Por lo tanto, una aplicación holográfica con DirectX no llama a presente en una cadena de intercambio de DXGI.So, a holographic app using DirectX doesn't call Present on a DXGI swap chain. En su lugar, use la clase HolographicFrame para mostrar todos los intercambio de un fotograma una vez que haya terminado de dibujarlo.Instead, you use the HolographicFrame class to present all swapchains for a frame once you're done drawing it.

De DeviceResources::P reenviado:From DeviceResources::Present:

HolographicFramePresentResult presentResult = frame.PresentUsingCurrentPrediction();

De forma predeterminada, esta API espera a que el fotograma finalice antes de que se devuelva.By default, this API waits for the frame to finish before it returns. Las aplicaciones holográficas deben esperar a que finalice el fotograma anterior antes de empezar a trabajar en un nuevo fotograma, ya que esto reduce la latencia y permite obtener mejores resultados de las predicciones de fotogramas holográficas.Holographic apps should wait for the previous frame to finish before starting work on a new frame, because this reduces latency and allows for better results from holographic frame predictions. No es una regla rígida y, si tiene fotogramas que tardan más de una actualización de pantalla en representarse, puede deshabilitar esta espera Si pasa el parámetro HolographicFramePresentWaitBehavior a PresentUsingCurrentPrediction.This isn't a hard rule, and if you have frames that take longer than one screen refresh to render you can disable this wait by passing the HolographicFramePresentWaitBehavior parameter to PresentUsingCurrentPrediction. En este caso, podría usar un subproceso de representación asincrónico para mantener una carga continua en la GPU.In this case, you would likely use an asynchronous rendering thread to maintain a continuous load on the GPU. La frecuencia de actualización del dispositivo HoloLens es de 60 Hz, donde un fotograma tiene una duración aproximada de 16 ms.The refresh rate of the HoloLens device is 60 hz, where one frame has a duration of approximately 16 ms. Los auriculares envolventes pueden oscilar entre 60 Hz y 90 Hz; al actualizar la pantalla a 90 Hz, cada fotograma tendrá una duración aproximada de 11 ms.Immersive headset devices can range from 60 hz to 90 hz; when refreshing the display at 90 hz, each frame will have a duration of approximately 11 ms.

Controle los escenarios de DeviceLost en cooperación con HolographicFrameHandle DeviceLost scenarios in cooperation with the HolographicFrame

Las aplicaciones de DirectX 11 normalmente querrán comprobar el valor HRESULT devuelto por la función present de la cadena de intercambio de DXGI para averiguar si se produjo un error DeviceLost .DirectX 11 apps would typically want to check the HRESULT returned by the DXGI swap chain's Present function to find out if there was a DeviceLost error. La clase HolographicFrame se encarga de ello.The HolographicFrame class handles this for you. Inspeccione el HolographicFramePresentResult devuelto para averiguar si necesita liberar y volver a crear el dispositivo Direct3D y los recursos basados en dispositivos.Inspect the returned HolographicFramePresentResult to find out if you need to release and recreate the Direct3D device and device-based resources.

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

Si se perdió el dispositivo Direct3D y lo volvió a crear, debe indicar a HolographicSpace que empiece a usar el nuevo dispositivo.If the Direct3D device was lost, and you did recreate it, you have to tell the HolographicSpace to start using the new device. La cadena de intercambio se volverá a crear para este dispositivo.The swap chain will be recreated for this device.

De DeviceResources:: InitializeUsingHolographicSpace:From DeviceResources::InitializeUsingHolographicSpace:

m_holographicSpace.SetDirect3D11Device(m_d3dInteropDevice);

Una vez que se presenta el fotograma, puede volver al bucle del programa principal y permitir que continúe con el siguiente fotograma.Once your frame is presented, you can return back to the main program loop and allow it to continue to the next frame.

Equipos de gráficos híbridos y aplicaciones de realidad mixtaHybrid graphics PCs and mixed reality applications

Los equipos con Windows 10 Creators Update se pueden configurar con GPU discretas e integradas.Windows 10 Creators Update PCs may be configured with both discrete and integrated GPUs. Con estos tipos de equipos, Windows elegirá el adaptador al que está conectado el casco.With these types of computers, Windows will choose the adapter the headset is connected to. Las aplicaciones deben asegurarse de que el dispositivo DirectX que crea usa el mismo adaptador.Applications must ensure the DirectX device it creates uses the same adapter.

La mayoría del código de ejemplo de Direct3D general muestra la creación de un dispositivo DirectX mediante el adaptador de hardware predeterminado, que en un sistema híbrido puede no ser el mismo que el usado para el casco.Most general Direct3D sample code demonstrates creating a DirectX device using the default hardware adapter, which on a hybrid system may not be the same as the one used for the headset.

Para solucionar cualquier problema, use HolographicAdapterID desde HolographicSpace. PrimaryAdapterId () o HolographicDisplay. AdapterId ().To work around any issues, use the HolographicAdapterID from either HolographicSpace.PrimaryAdapterId() or HolographicDisplay.AdapterId(). Este adapterId se puede usar para seleccionar el DXGIAdapter adecuado mediante IDXGIFactory4. EnumAdapterByLuid.This adapterId can then be used to select the right DXGIAdapter using IDXGIFactory4.EnumAdapterByLuid.

De DeviceResources:: InitializeUsingHolographicSpace:From 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();
}

Código para Actualizar DeviceResources:: CreateDeviceResources para usar IDXGIAdapterCode to update DeviceResources::CreateDeviceResources to use IDXGIAdapter

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

Gráficos y Media Foundation híbridosHybrid graphics and Media Foundation

El uso de Media Foundation en sistemas híbridos puede causar problemas en los que el vídeo no se represente o la textura de vídeo está dañada porque Media Foundation tiene como valor predeterminado un comportamiento del sistema.Using Media Foundation on hybrid systems may cause issues where video won't render or video texture are corrupt because Media Foundation is defaulting to a system behavior. En algunos escenarios, se requiere la creación de un ID3D11Device independiente para admitir el subprocesamiento múltiple y se establecen las marcas de creación correctas.In some scenarios, creating a separate ID3D11Device is required to support multi-threading and the correct creation flags are set.

Al inicializar ID3D11Device, se debe definir D3D11_CREATE_DEVICE_VIDEO_SUPPORT marca como parte de la D3D11_CREATE_DEVICE_FLAG.When initializing the ID3D11Device, D3D11_CREATE_DEVICE_VIDEO_SUPPORT flag must be defined as part of the D3D11_CREATE_DEVICE_FLAG. Una vez creado el dispositivo y el contexto, llame a SetMultithreadProtected para habilitar el multithreading.Once the device and context is created, call SetMultithreadProtected to enable multithreading. Para asociar el dispositivo a IMFDXGIDeviceManager, use la función IMFDXGIDeviceManager:: ResetDevice .To associate the device with the IMFDXGIDeviceManager, use the IMFDXGIDeviceManager::ResetDevice function.

Código para asociar un ID3D11Device con IMFDXGIDeviceManager:Code to associate a ID3D11Device with IMFDXGIDeviceManager:

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

Consulte tambiénSee also