Отрисовка в DirectX

Примечание

Эта статья связана с устаревшими собственными API-интерфейсами WinRT. Для новых проектов собственных приложений рекомендуется использовать API опенкср.

Windows Mixed Reality построены на основе DirectX для создания полнофункциональных трехмерных графических интерфейсов для пользователей. Абстракция отрисовки располагается непосредственно над DirectX, что позволяет приложениям определить положение и ориентацию наблюдателей с holographic, прогнозируемых системой. После этого разработчик может размещать свои голограммы на каждой камере, позволяя приложению визуализировать эти голограммы в различных пространственных системах координат по мере перемещения пользователя.

Примечание. в этом пошаговом руководстве описывается обработка в Direct3D 11 более Holographic. шаблон приложения Direct3D 12 Windows Mixed Reality также предоставляется с расширением Смешанная реальностьных шаблонов приложений.

Обновление текущего кадра

Чтобы обновить состояние приложения для голограмм, один раз для каждого кадра приложение будет выполнять следующие действия:

  • Получение холографикфраме из системы управления отображением.
  • Обновите сцену, используя текущий прогноз, где будет отображаться представление камеры после завершения подготовки к просмотру. Обратите внимание, что для «holographic» сцены может существовать более одной камеры.

Для отображения в представлениях с Камером holographic, один раз для каждого кадра, приложение будет выполнять следующие действия:

  • Для каждой камеры Визуализируйте сцену для текущего кадра, используя матрицы представления камеры и проекции из системы.

Создание нового пакета holographic и получение его прогноза

Холографикфраме содержит сведения, необходимые приложению для обновления и отрисовки текущего кадра. Приложение начинает каждый новый кадр, вызывая метод креатенекстфраме . При вызове этого метода прогнозы выполняются с использованием последних доступных данных датчика и инкапсулированы в объект куррентпредиктион .

Для каждого отображаемого кадра должен использоваться новый объект Frame, так как он действителен только для мгновенного выполнения. Свойство куррентпредиктион содержит такие сведения, как расположение камеры. Данные выделяются на конкретный момент времени, когда фрейм должен быть видимым для пользователя.

Следующий код взят из аппмаин:: 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();

Обработка обновлений камеры

Задние буферы могут меняться от кадра к кадру. Приложению необходимо проверить задний буфер для каждой камеры, а также освободить и повторно создать представления ресурсов и буферы глубины по мере необходимости. Обратите внимание, что набор элементов прогноза является полномочным списком камер, используемых в текущем кадре. Обычно этот список используется для итерации по набору камер.

Из аппмаин:: Update:

m_deviceResources->EnsureCameraResources(holographicFrame, prediction);

Из DeviceResources:: енсурекамераресаурцес:

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

Получение системы координат для использования в качестве основания для подготовки к просмотру

Windows Mixed Reality позволяет вашему приложению создавать различные системы координат, например присоединенные и стационарные справочные фреймы для отслеживания расположений в физическом мире. Приложение может использовать эти системы координат в качестве причины, по которой следует визуализировать голограммы каждого кадра. При запросе координат из API вы всегда будете передавать спатиалкурдинатесистем , внутри которых должны выражаться эти координаты.

Из аппмаин:: Update:

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

Эти системы координат можно затем использовать для создания матрицы стерео View при отрисовке содержимого в сцене.

Из камераресаурцес:: упдатевиевпрожектионбуффер:

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

Обработка взгляда и ввод с жестом

Ввод « взгляд и рука » не зависит от времени и не должен обновляться функцией стептимер . Однако эти входные данные — это то, что приложению нужно взглянуть на каждый кадр.

Обработка обновлений на основе времени

любому приложению для подготовки к просмотру в режиме реального времени потребуется какой-то способ обработки обновлений на основе времени. шаблон Windows holographic приложение использует реализацию стептимер , аналогичную стептимер, предоставленной в шаблоне приложения UWP DirectX 11. Этот пример вспомогательного класса Стептимер может предоставлять фиксированные временные обновления, переменные время обновления, а режим по умолчанию — переменные временные действия.

В случае с holographic, мы решили не слишком много времени в функции таймера, так как вы можете настроить его как фиксированный шаг. Он может вызываться более одного раза для каждого кадра — или нет вообще, для некоторых кадров, а наши обновления данных — по одному на кадр.

Из аппмаин:: Update:

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

Размещение и поворот голограмм в системе координат

Если вы работаете в одной системе координат, так как шаблон работает с спатиалстатионариреференцефраме, этот процесс не отличается от того, что используется в трехмерной графике. Здесь мы вращающим куб и устанавливаем матрицу модели на основе места в стационарной системе координат.

Из спиннингкуберендерер:: 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));

Примечание о расширенных сценариях: Вращающийся куб — это простой пример размещения голограммы в пределах одного опорного кадра. Кроме того, можно одновременно использовать несколько спатиалкурдинатесистемс в одном и том же подготовленном фрейме.

Обновление данных буфера констант

Преобразования модели для содержимого обновляются обычным образом. Теперь вы получите вычисленные Допустимые преобразования для системы координат, в которой будет выполняться отрисовка.

Из спиннингкуберендерер:: Update:

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

Как насчет преобразований представлений и проекций? Для достижения лучших результатов мы хотим подождать, пока мы почти готовы к вызовам Draw, прежде чем они будут получены.

Отобразить текущий кадр

рендеринг на Windows Mixed Reality не намного отличается от отрисовки на 2d mono, но существует несколько отличий.

  • Важны прогнозы с Holographic. Чем ближе прогноз к представлению вашей рамки, тем лучше будет выглядеть голограмма.
  • Windows Mixed Reality управляет представлениями камеры. Подготавливается к каждому из них, так как в holographic кадр будет демонстрироваться позже.
  • Мы рекомендуем использовать стерео-отрисовку с помощью экземпляра Drawing в массиве целевых объектов прорисовки. Шаблон holographic App использует Рекомендуемый подход экземпляра Drawing к целевому массиву прорисовки, который использует представление целевого объекта отрисовки в Texture2DArray.
  • Если вы хотите подготовиться к просмотру без использования стерео-экземпляра, необходимо создать два Рендертаржетвиевс, не являющиеся массивами, по одному для каждого глаза. Каждый Рендертаржетвиевс ссылается на один из двух срезов в Texture2DArray , предоставленных приложению из системы. Это не рекомендуется, так как обычно медленнее, чем использование создания экземпляров.

Получение обновленного прогноза Холографикфраме

Обновление прогнозирования кадров повышает эффективность стабилизацииов изображений. Вы получаете более точное позиционирование голограмм из-за более короткого времени между прогнозом и отображением кадра для пользователя. В идеале перед отрисовкой обновите прогнозирование кадров.

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

Подготовка к просмотру на каждой камере

Loop на наборе единиц камеры в прогнозе и рендеринга на каждой камере в этом наборе.

Настройка этапа подготовки к просмотру

Windows Mixed Reality использует отрисовку стереоскопик, чтобы улучшить иллюзию глубины и отрисовку стереоскопикалли, поэтому активно и правое отображение активны. При подготовке к просмотру стереоскопик между двумя дисплеями имеется смещение, которое мозг может согласовать как фактическую глубину. в этом разделе рассматривается стереоскопикная визуализация с помощью создания экземпляров с помощью кода из шаблона Windows holographic приложений.

У каждой камеры есть собственный целевой буфер рендеринга (заднего буфера), а также матрицы просмотра и проекции в Holographic. Приложению потребуется создать любые другие ресурсы на основе камеры, такие как буфер глубины, для каждой камеры. в шаблоне приложения Windows holographic мы предоставляем вспомогательный класс для объединения этих ресурсов в DX:: камераресаурцес. Начните с настройки представлений целевого объекта прорисовки:

Из аппмаин:: 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);

Использование прогноза для получения матриц представления и проекции для камеры

Матрицы представления и проекции для каждой из этих камер Изменятся с каждым кадром. Обновите данные в буфере констант для каждой камеры Holographic. Сделайте это после обновления прогноза и перед выполнением вызовов рисования для этой камеры.

Из аппмаин:: 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);

Здесь мы покажем, как можно получить матрицы от самой камеры. В ходе этого процесса мы также получаем текущее окно просмотра для камеры. Обратите внимание на то, как мы предоставляем систему координат: это та же система координат, которая использовалась для понимания взгляда, и это то же самое, что мы использовали для размещения вращающегося куба.

Из камераресаурцес:: упдатевиевпрожектионбуффер:

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

Окно просмотра должно быть задано для каждого кадра. Как правило, шейдеру вершин (по крайней мере) необходим доступ к данным представления или проекции.

Из камераресаурцес:: аттачвиевпрожектионбуффер:

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

Подготавливается к просмотру в фоновом буфере камеры и зафиксируйте буфер глубины:

Прежде чем пытаться использовать данные представления или проекции, рекомендуется проверить, что трижетвиевтрансформ успешно выполнен, так как если система координат не размещаемые (например, отслеживание было прервано), приложение не сможет визуализировать его с помощью этого кадра. Шаблон вызывает визуализацию только для вращающегося куба, если класс камераресаурцес указывает на успешное обновление.

Windows Mixed Reality включает функции для стабилизации изображений , позволяющие размещать голограммы, где разработчик или пользователь помещает их в мир. Образ стабилизации помогает скрыть задержку, присущую конвейеру отрисовки, чтобы обеспечить наилучший опыт для пользователей. Можно указать точку фокусировки, чтобы улучшить стабилизации изображений, или можно предоставить буфер глубины для стабилизации оптимизированного изображения в режиме реального времени.

Для получения лучших результатов приложение должно предоставить буфер глубины с помощью API CommitDirect3D11DepthBuffer . Windows Mixed Reality может затем использовать сведения о геометрии из буфера глубины для оптимизации стабилизации изображений в режиме реального времени. шаблон Windows holographic приложение по умолчанию фиксирует буфер глубины приложения, помогая оптимизировать стабильность.

Из аппмаин:: 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);
    }
}

Примечание

Windows будет обрабатывать текстуру глубины на GPU, поэтому в качестве ресурса шейдера необходимо использовать буфер глубины. Создаваемый ID3D11Texture2D должен быть в формате без типа, и его следует привязать как представление ресурсов шейдера. Ниже приведен пример создания текстуры глубины, которую можно зафиксировать для изображения стабилизации.

Код для создания ресурсов буфера глубины для 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
    ));

Нарисуйте holographic, содержимое

шаблон Windows holographic приложение визуализирует содержимое на стереосистеме, используя рекомендуемый метод рисования экземпляров геометрии до Texture2DArray размера 2. Рассмотрим эту часть и то, как она работает с Windows Mixed Reality.

Из спиннингкуберендерер:: 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.
);

Каждый экземпляр обращается к другой матрице представления или проекции из буфера констант. Ниже приведена структура буфера констант, которая представляет собой просто массив из двух матриц.

Из вертексшадершаред. HLSL, входящего в впртвертексшадер. HLSL:

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

Индекс целевого массива прорисовки должен быть задан для каждого пикселя. В следующем фрагменте кода Output. viewId сопоставляется с семантикой SV_RenderTargetArrayIndex . Для этого требуется поддержка необязательной функции Direct3D 11,3, которая позволяет задать семантику индекса целевого массива прорисовки на любом этапе шейдера.

Из впртвертексшадер. 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;
};

Из вертексшадершаред. HLSL, входящего в впртвертексшадер. 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;
}

Если вы хотите использовать существующие методы рисования экземпляров с помощью этого метода рисования в массиве нацеливания на стерео прорисовки, дважды Нарисуйте число экземпляров, которые у них есть. В шейдере разделите input. куст Instid на 2, чтобы получить идентификатор исходного экземпляра, который можно проиндексировать в (например,) буфер данных для каждого объекта: int actualIdx = input.instId / 2;

Важное примечание о визуализации стерео содержимого на HoloLens

Windows Mixed Reality поддерживает возможность установки индекса массива целевых объектов прорисовки из любого этапа шейдера. Как правило, это задача, которую можно выполнить только на этапе шейдера Geometry, так как семантика определена для Direct3D 11. Здесь представлен полный пример настройки конвейера отрисовки с набором стадий вершин и шейдеров пикселей. Код шейдера описан выше.

Из спиннингкуберендерер:: 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.
);

важное замечание о подготовке к просмотру на устройствах, не являющихся HoloLens

для задания индекса массива целевых объектов прорисовки в шейдере вершин требуется, чтобы графический драйвер поддерживал дополнительную функцию Direct3D 11,3, которая HoloLens поддерживает. Приложение может безопасно реализовать только этот метод для подготовки к просмотру, и все требования будут выполнены для выполнения в Microsoft HoloLens.

возможно, вы хотите использовать также эмулятор HoloLens, который может быть мощным средством разработки для приложения holographic и поддерживать Windows Mixed Reality иммерсивное головные устройства, подключенные к Windows 10ным пк. поддержка неHoloLensного пути отрисовки (для всех Windows Mixed Reality) также встроена в шаблон приложения Windows holographic. В коде шаблона вы найдете код, позволяющий запускать приложение holographic на GPU на компьютере разработчика. Вот как класс DeviceResources проверяет наличие этой дополнительной поддержки компонентов.

Из DeviceResources:: креатедевицересаурцес:

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

Для поддержки отрисовки без этой дополнительной функции приложение должно использовать шейдер Geometry для задания индекса целевого массива прорисовки. Этот фрагмент кода будет добавлен послевссетконстантбуфферси передPSSetShader в примере, приведенном в предыдущем разделе, в котором объясняется, как визуализировать стерео на HoloLens.

Из спиннингкуберендерер:: Render:

if (!m_usingVprtShaders)
{
    // On devices that do not support the D3D11_FEATURE_D3D11_OPTIONS3::
    // VPAndRTArrayIndexFromAnyShaderFeedingRasterizer optional feature,
    // a pass-through geometry shader is used to set the render target 
    // array index.
    context->GSSetShader(
        m_geometryShader.Get(),
        nullptr,
        0
    );
}

HLSL Примечание. в этом случае необходимо также загрузить немного измененный шейдер вершин, передающий индекс массива целевых объектов отрисовки шейдеру Geometry с помощью семантики шейдера, которая всегда разрешена, например TEXCOORD0. Шейдер геометрии не должен выполнять никаких действий. Шейдер геометрии шаблона проходит через все данные, за исключением индекса целевого массива прорисовки, который используется для задания семантической SV_RenderTargetArrayIndex.

Код шаблона приложения для жеометришадер. 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);
    }
}

Присутствует

Включение в holographic фрейма цепочки буферов

при использовании Windows Mixed Reality система управляет цепочкой буферов обмена. Затем система управляет показом кадров на каждой из holographic камер для обеспечения высокого качества взаимодействия с пользователем. он также предоставляет окно просмотра, которое обновляет каждый кадр для каждой камеры, чтобы оптимизировать характеристики системы, такие как image стабилизации или Capture Смешанная реальность. Таким образом, holographic приложение, использующее DirectX, не вызывает Present в цепочке подкачки DXGI. Вместо этого используйте класс холографикфраме , чтобы показать все цепочек переключений для кадра после завершения его рисования.

Из DeviceResources::Pповторной отправки:

HolographicFramePresentResult presentResult = frame.PresentUsingCurrentPrediction();

По умолчанию этот API ожидает завершения кадра перед возвратом. Перед началом работы над новым кадром holographic приложения должны ожидать завершения предыдущего кадра, так как это сокращает задержку и обеспечивает лучшие результаты прогнозов с помощью Holographic. Это не жесткое правило, и если у вас есть кадры, которые занимают больше одного экрана для подготовки к просмотру, можно отключить это время, передав параметр Холографикфрамепресентваитбехавиор в пресентусингкуррентпредиктион. В этом случае, скорее всего, будет использоваться поток асинхронной отрисовки для поддержания непрерывной нагрузки на GPU. частота обновления HoloLens устройства составляет 60 гц, при этом длительность одного кадра составляет примерно 16 мс. Впечатляющие головные устройства могут находиться в диапазоне от 60 Гц до 90 Гц; При обновлении экрана с частотой 90 Гц каждый кадр будет иметь длительность примерно 11 мс.

Обрабатывайте сценарии Девицелост в сотрудничество с Холографикфраме

Приложениям DirectX 11 обычно требуется проверить значение HRESULT, возвращаемое функцией Present цепочки ПОДкачки DXGI, чтобы определить, была ли ошибка девицелост . Класс холографикфраме обрабатывает это за вас. Проверьте возвращенный холографикфрамепресентресулт , чтобы узнать, нужно ли освободить и повторно создать ресурсы на основе Direct3D и устройства.

// 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 было потеряно, и вы создали его повторно, вам нужно сообщить холографикспаце начать использовать новое устройство. Для этого устройства будет создана цепочка буферов.

Из DeviceResources:: инитиализеусингхолографикспаце:

m_holographicSpace.SetDirect3D11Device(m_d3dInteropDevice);

После представления кадра можно вернуться к главному циклу программы и разрешить переход к следующему кадру.

Гибридные графические компьютеры и приложения смешанной реальности

Windows 10 Creators Update пк могут быть настроены как дискретные, так и интегрированные gpu. с этими типами компьютеров Windows выберет адаптер, к которому подключена гарнитура. Приложения должны гарантировать, что создаваемое устройство DirectX использует тот же адаптер.

В большинстве общих примеров кода Direct3D демонстрируется создание устройства DirectX с помощью аппаратного адаптера по умолчанию, который в гибридной системе может отличаться от используемого для гарнитуры.

Чтобы обойти какие либо проблемы, используйте холографикадаптерид из холографикспаце. Примарядаптерид () или холографикдисплай. ИД адаптера (). Этот ИД адаптера можно затем использовать для выбора правильного Дксгиадаптер с помощью IDXGIFactory4. Енумадаптербилуид.

Из DeviceResources:: инитиализеусингхолографикспаце:

// 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:: креатедевицересаурцес для использования идксгиадаптер

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

Гибридная графика и Media Foundation

Использование Media Foundation в гибридных системах может вызвать проблемы, когда видео не будет отображаться или текстура видео повреждена, так как Media Foundation по умолчанию использует поведение системы. В некоторых сценариях для поддержки многопоточности и установки правильных флагов создания требуется создать отдельный ID3D11Device.

При инициализации ID3D11Device должен быть определен флаг D3D11_CREATE_DEVICE_VIDEO_SUPPORT в составе D3D11_CREATE_DEVICE_FLAG. После создания устройства и контекста вызовите сетмултисреадпротектед , чтобы включить многопоточность. Чтобы связать устройство с имфдксгидевицеманажер, используйте функцию Имфдксгидевицеманажер:: ресетдевице .

Код для связывания ID3D11Device с имфдксгидевицеманажер:

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

См. также раздел