Freigeben über


Renderingframework I: Einführung in das Rendering

Hinweis

Dieses Thema ist Teil der Erstellen eines einfachen UWP-Spiels (Universelle Windows-Plattform) mit DirectX-Tutorial-Reihe. Das Thema unter diesem Link legt den Kontext für die Reihe fest.

Bisher haben wir behandelt, wie ein Universelle Windows-Plattform (UWP)-Spiel strukturiert wird und wie ein Zustandsautomat definiert wird, der den Spielfluss behandelt. Jetzt ist es an der Zeit, zu erfahren, wie Das Renderingframework entwickelt wird. Sehen wir uns an, wie das Beispielspiel die Spielszene mithilfe von Direct3D 11 rendert.

Direct3D 11 enthält eine Reihe von APIs, die Zugriff auf die erweiterten Features von Hochleistungsgrafikhardware bieten, die zum Erstellen von 3D-Grafiken für grafikintensive Anwendungen wie Spiele verwendet werden können.

Das Rendern von Spielgrafiken auf dem Bildschirm bedeutet im Wesentlichen das Rendern einer Sequenz von Frames auf dem Bildschirm. In jedem Frame müssen Sie Objekte rendern, die in der Szene sichtbar sind, basierend auf der Ansicht.

Um einen Frame zu rendern, müssen Sie die erforderlichen Szeneninformationen an die Hardware übergeben, damit er auf dem Bildschirm angezeigt werden kann. Wenn auf dem Bildschirm etwas angezeigt werden soll, müssen Sie mit dem Rendern beginnen, sobald das Spiel gestartet wird.

Ziele

So richten Sie ein grundlegendes Renderingframework ein, um die Grafikausgabe für ein UWP-DirectX-Spiel anzuzeigen. Sie können dies lose in diese drei Schritte unterteilen.

  1. Stellen Sie eine Verbindung mit der Grafikschnittstelle her.
  2. Erstellen Sie die zum Zeichnen der Grafiken erforderlichen Ressourcen.
  3. Zeigen Sie die Grafiken an, indem Sie den Frame rendern.

In diesem Thema wird erläutert, wie Grafiken gerendert werden, wobei die Schritte 1 und 3 behandelt werden.

Renderingframework II: Das Rendern von Spielen behandelt Schritt 2 – wie das Renderingframework eingerichtet wird und wie Daten vorbereitet werden, bevor das Rendering erfolgen kann.

Erste Schritte

Es ist ratsam, sich mit grundlegenden Grafik- und Renderingkonzepten vertraut zu machen. Wenn Sie mit Direct3D und Rendering noch nicht vertraut sind, finden Sie in den Begriffen und Konzepten eine kurze Beschreibung der in diesem Thema verwendeten Grafik- und Renderingbegriffe.

Für dieses Spiel stellt die GameRenderer-Klasse den Renderer für dieses Beispielspiel dar. Es ist für das Erstellen und Verwalten aller Direct3D 11- und Direct2D-Objekte verantwortlich, die zum Generieren der visuellen Spielelemente verwendet werden. Außerdem wird ein Verweis auf das Simple3DGame-Objekt verwaltet, das zum Abrufen der Liste der zu rendernden Objekte sowie den Status des Spiels für die Heads-up-Anzeige (HUD) verwendet wird.

In diesem Teil des Lernprogramms konzentrieren wir uns auf das Rendern von 3D-Objekten im Spiel.

Herstellen einer Verbindung mit der Grafikschnittstelle

Informationen zum Zugriff auf die Hardware zum Rendern finden Sie im Thema zum Definieren des UWP-App-Frameworks des Spiels.

Die App::Initialize-Methode

Die Funktion "std::make_shared ", wie unten dargestellt, wird verwendet, um eine shared_ptr für DX::D eviceResources zu erstellen, die auch Zugriff auf das Gerät ermöglicht.

In Direct3D 11 wird ein Gerät verwendet, um Objekte zuzuordnen und zu zerstören, Grundtypen zu rendern und mit der Grafikkarte über den Grafiktreiber zu kommunizieren.

void Initialize(CoreApplicationView const& applicationView)
{
    ...

    // At this point we have access to the device. 
    // We can create the device-dependent resources.
    m_deviceResources = std::make_shared<DX::DeviceResources>();
}

Anzeigen der Grafiken durch Rendern des Frames

Die Spielszene muss gerendert werden, wenn das Spiel gestartet wird. Die Anweisungen zum Rendern beginnen in der GameMain::Run-Methode , wie unten dargestellt.

Der einfache Fluss ist dies.

  1. Aktualisieren
  2. Rendern
  3. Vorhanden

GameMain::Run-Methode

void GameMain::Run()
{
    while (!m_windowClosed)
    {
        if (m_visible) // if the window is visible
        {
            switch (m_updateState)
            {
            ...
            default:
                CoreWindow::GetForCurrentThread().Dispatcher().ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
                Update();
                m_renderer->Render();
                m_deviceResources->Present();
                m_renderNeeded = false;
            }
        }
        else
        {
            CoreWindow::GetForCurrentThread().Dispatcher().ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending);
        }
    }
    m_game->OnSuspending();  // Exiting due to window close, so save state.
}

Aktualisieren

Weitere Informationen dazu, wie Spielzustände in der GameMain::Update-Methode aktualisiert werden, finden Sie im Thema "Spielflussverwaltung".

Rendern

Rendering wird durch Aufrufen der GameRenderer::Render-Methode aus GameMain::Run implementiert.

Wenn das Stereorendering aktiviert ist, gibt es zwei Renderingdurchläufe – eine für das linke Auge und eine für die rechte Seite. Bei jedem Renderingdurchlauf binden wir das Renderziel und die Tiefenschablonenansicht an das Gerät. Wir löschen auch die Tiefenschablonenansicht danach.

Hinweis

Das Stereorendering kann mit anderen Methoden wie Single Pass Stereo mithilfe von Vertex-Instancing- oder Geometrie-Shadern erreicht werden. Die Methode mit zwei Renderingdurchläufen ist eine langsamere, aber komfortablere Methode zum Erreichen des Stereorenderings.

Sobald das Spiel ausgeführt wird und Ressourcen geladen werden, aktualisieren wir die Projektionsmatrix einmal pro Renderingdurchlauf. Objekte unterscheiden sich geringfügig von jeder Ansicht. Als Nächstes richten wir die Grafikrenderingpipeline ein.

Hinweis

Weitere Informationen zum Laden von Ressourcen finden Sie unter Erstellen und Laden von DirectX-Grafikressourcen .

In diesem Beispielspiel ist der Renderer so konzipiert, dass ein Standardvertexlayout für alle Objekte verwendet wird. Dies vereinfacht den Shaderentwurf und ermöglicht einfache Änderungen zwischen Shadern, unabhängig von der Geometrie der Objekte.

GameRenderer::Render-Methode

Wir legen den Direct3D-Kontext so fest, dass ein Eingabevertexlayout verwendet wird. Eingabelayoutobjekte beschreiben, wie Vertexpufferdaten in die Renderingpipeline gestreamt werden.

Als Nächstes legen wir den Direct3D-Kontext so fest, dass die zuvor definierten Konstantenpuffer verwendet werden, die von der Vertex-Shaderpipelinephase und der Pixelshaderpipelinephase verwendet werden.

Hinweis

Weitere Informationen zur Definition der Konstantenpuffer finden Sie unter Rendering framework II: Spielrendering .

Da dasselbe Eingabelayout und ein Satz von Konstantenpuffern für alle Shader verwendet werden, die sich in der Pipeline befinden, wird es einmal pro Frame eingerichtet.

void GameRenderer::Render()
{
    bool stereoEnabled{ m_deviceResources->GetStereoState() };

    auto d3dContext{ m_deviceResources->GetD3DDeviceContext() };
    auto d2dContext{ m_deviceResources->GetD2DDeviceContext() };

    int renderingPasses = 1;
    if (stereoEnabled)
    {
        renderingPasses = 2;
    }

    for (int i = 0; i < renderingPasses; i++)
    {
        // Iterate through the number of rendering passes to be completed.
        // 2 rendering passes if stereo is enabled.
        if (i > 0)
        {
            // Doing the Right Eye View.
            ID3D11RenderTargetView* const targets[1] = { m_deviceResources->GetBackBufferRenderTargetViewRight() };

            // Resets render targets to the screen.
            // OMSetRenderTargets binds 2 things to the device.
            // 1. Binds one render target atomically to the device.
            // 2. Binds the depth-stencil view, as returned by the GetDepthStencilView method, to the device.
            // For more info, see
            // https://learn.microsoft.com/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-omsetrendertargets

            d3dContext->OMSetRenderTargets(1, targets, m_deviceResources->GetDepthStencilView());

            // Clears the depth stencil view.
            // A depth stencil view contains the format and buffer to hold depth and stencil info.
            // For more info about depth stencil view, go to: 
            // https://learn.microsoft.com/windows/uwp/graphics-concepts/depth-stencil-view--dsv-
            // A depth buffer is used to store depth information to control which areas of 
            // polygons are rendered rather than hidden from view. To learn more about a depth buffer,
            // go to: https://learn.microsoft.com/windows/uwp/graphics-concepts/depth-buffers
            // A stencil buffer is used to mask pixels in an image, to produce special effects. 
            // The mask determines whether a pixel is drawn or not,
            // by setting the bit to a 1 or 0. To learn more about a stencil buffer,
            // go to: https://learn.microsoft.com/windows/uwp/graphics-concepts/stencil-buffers

            d3dContext->ClearDepthStencilView(m_deviceResources->GetDepthStencilView(), D3D11_CLEAR_DEPTH, 1.0f, 0);

            // Direct2D -- discussed later
            d2dContext->SetTarget(m_deviceResources->GetD2DTargetBitmapRight());
        }
        else
        {
            // Doing the Mono or Left Eye View.
            // As compared to the right eye:
            // m_deviceResources->GetBackBufferRenderTargetView instead of GetBackBufferRenderTargetViewRight
            ID3D11RenderTargetView* const targets[1] = { m_deviceResources->GetBackBufferRenderTargetView() };

            // Same as the Right Eye View.
            d3dContext->OMSetRenderTargets(1, targets, m_deviceResources->GetDepthStencilView());
            d3dContext->ClearDepthStencilView(m_deviceResources->GetDepthStencilView(), D3D11_CLEAR_DEPTH, 1.0f, 0);

            // d2d -- Discussed later under Adding UI
            d2dContext->SetTarget(m_deviceResources->GetD2DTargetBitmap());
        }

        const float clearColor[4] = { 0.5f, 0.5f, 0.8f, 1.0f };

        // Only need to clear the background when not rendering the full 3D scene since
        // the 3D world is a fully enclosed box and the dynamics prevents the camera from
        // moving outside this space.
        if (i > 0)
        {
            // Doing the Right Eye View.
            d3dContext->ClearRenderTargetView(m_deviceResources->GetBackBufferRenderTargetViewRight(), clearColor);
        }
        else
        {
            // Doing the Mono or Left Eye View.
            d3dContext->ClearRenderTargetView(m_deviceResources->GetBackBufferRenderTargetView(), clearColor);
        }

        // Render the scene objects
        if (m_game != nullptr && m_gameResourcesLoaded && m_levelResourcesLoaded)
        {
            // This section is only used after the game state has been initialized and all device
            // resources needed for the game have been created and associated with the game objects.
            if (stereoEnabled)
            {
                // When doing stereo, it is necessary to update the projection matrix once per rendering pass.

                auto orientation = m_deviceResources->GetOrientationTransform3D();

                ConstantBufferChangeOnResize changesOnResize;
                // Apply either a left or right eye projection, which is an offset from the middle
                XMStoreFloat4x4(
                    &changesOnResize.projection,
                    XMMatrixMultiply(
                        XMMatrixTranspose(
                            i == 0 ?
                            m_game->GameCamera().LeftEyeProjection() :
                            m_game->GameCamera().RightEyeProjection()
                            ),
                        XMMatrixTranspose(XMLoadFloat4x4(&orientation))
                        )
                    );

                d3dContext->UpdateSubresource(
                    m_constantBufferChangeOnResize.get(),
                    0,
                    nullptr,
                    &changesOnResize,
                    0,
                    0
                    );
            }

            // Update variables that change once per frame.
            ConstantBufferChangesEveryFrame constantBufferChangesEveryFrameValue;
            XMStoreFloat4x4(
                &constantBufferChangesEveryFrameValue.view,
                XMMatrixTranspose(m_game->GameCamera().View())
                );
            d3dContext->UpdateSubresource(
                m_constantBufferChangesEveryFrame.get(),
                0,
                nullptr,
                &constantBufferChangesEveryFrameValue,
                0,
                0
                );

            // Set up the graphics pipeline. This sample uses the same InputLayout and set of
            // constant buffers for all shaders, so they only need to be set once per frame.
            // For more info about the graphics or rendering pipeline, see
            // https://learn.microsoft.com/windows/win32/direct3d11/overviews-direct3d-11-graphics-pipeline

            // IASetInputLayout binds an input-layout object to the input-assembler (IA) stage. 
            // Input-layout objects describe how vertex buffer data is streamed into the IA pipeline stage.
            // Set up the Direct3D context to use this vertex layout. For more info, see
            // https://learn.microsoft.com/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-iasetinputlayout
            d3dContext->IASetInputLayout(m_vertexLayout.get());

            // VSSetConstantBuffers sets the constant buffers used by the vertex shader pipeline stage.
            // Set up the Direct3D context to use these constant buffers. For more info, see
            // https://learn.microsoft.com/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-vssetconstantbuffers

            ID3D11Buffer* constantBufferNeverChanges{ m_constantBufferNeverChanges.get() };
            d3dContext->VSSetConstantBuffers(0, 1, &constantBufferNeverChanges);
            ID3D11Buffer* constantBufferChangeOnResize{ m_constantBufferChangeOnResize.get() };
            d3dContext->VSSetConstantBuffers(1, 1, &constantBufferChangeOnResize);
            ID3D11Buffer* constantBufferChangesEveryFrame{ m_constantBufferChangesEveryFrame.get() };
            d3dContext->VSSetConstantBuffers(2, 1, &constantBufferChangesEveryFrame);
            ID3D11Buffer* constantBufferChangesEveryPrim{ m_constantBufferChangesEveryPrim.get() };
            d3dContext->VSSetConstantBuffers(3, 1, &constantBufferChangesEveryPrim);

            // Sets the constant buffers used by the pixel shader pipeline stage. 
            // For more info, see
            // https://learn.microsoft.com/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-pssetconstantbuffers

            d3dContext->PSSetConstantBuffers(2, 1, &constantBufferChangesEveryFrame);
            d3dContext->PSSetConstantBuffers(3, 1, &constantBufferChangesEveryPrim);
            ID3D11SamplerState* samplerLinear{ m_samplerLinear.get() };
            d3dContext->PSSetSamplers(0, 1, &samplerLinear);

            for (auto&& object : m_game->RenderObjects())
            {
                // The 3D object render method handles the rendering.
                // For more info, see Primitive rendering below.
                object->Render(d3dContext, m_constantBufferChangesEveryPrim.get());
            }
        }

        // Start of 2D rendering
        ...
    }
}

Primitives Rendering

Beim Rendern der Szene durchlaufen Sie alle Objekte, die gerendert werden müssen. Die folgenden Schritte werden für jedes Objekt (Grundtyp) wiederholt.

  • Aktualisieren Sie den Konstantenpuffer (m_constantBufferChangesEveryPrim) mit der Welttransformationsmatrix und den Materialinformationen des Modells.
  • Die m_constantBufferChangesEveryPrim enthält Parameter für jedes Objekt. Sie enthält die Objekt-zu-Welt-Transformationsmatrix sowie Materialeigenschaften wie Farbe und Glanz exponent für Beleuchtungsberechnungen.
  • Legen Sie den Direct3D-Kontext fest, um das Eingabevertexlayout für die Gitterobjektdaten zu verwenden, die in die Eingabeassemblerphase (IA) der Renderingpipeline gestreamt werden sollen.
  • Legen Sie den Direct3D-Kontext fest, um einen Indexpuffer in der IA-Phase zu verwenden. Geben Sie die Grundtypinformationen an: Typ, Datenreihenfolge.
  • Senden Sie einen Draw-Aufruf, um den indizierten, nicht instanziierten Grundtyp zu zeichnen. Die GameObject::Render-Methode aktualisiert den Grundtypkonstantenpuffer mit den Daten, die für einen bestimmten Grundtyp spezifisch sind. Dies führt zu einem DrawIndexed-Aufruf für den Kontext, um die Geometrie der einzelnen Grundtypen zu zeichnen. Insbesondere werden mit diesem Zeichnen Befehle und Daten an die Grafikverarbeitungseinheit (GPU) in die Warteschlange gestellt, die durch die Konstantenpufferdaten parametrisiert werden. Jeder Draw-Aufruf führt den Vertex-Shader einmal pro Vertex und dann den Pixelshader einmal für jedes Pixel jedes Dreiecks im Grundtyp aus. Die Texturen sind Teil des Zustands, den der Pixelshader zum Rendern verwendet.

Hier sind die Gründe für die Verwendung mehrerer Konstantenpuffer.

  • Das Spiel verwendet mehrere Konstantenpuffer, muss diese Puffer jedoch nur einmal pro Grundtyp aktualisieren. Wie bereits erwähnt, sind Konstantenpuffer wie Eingaben für die Shader, die für jeden Grundtyp ausgeführt werden. Einige Daten sind statisch (m_constantBufferNeverChanges); einige Daten sind über dem Frame (m_constantBufferChangesEveryFrame), z. B. die Position der Kamera, und einige Daten sind spezifisch für den Grundtyp, z. B. ihre Farbe und Texturen (m_constantBufferChangesEveryPrim).
  • Der Spielrenderer trennt diese Eingaben in verschiedene Konstantenpuffer, um die von der CPU und GPU verwendete Speicherbandbreite zu optimieren. Dieser Ansatz trägt auch dazu bei, die Datenmenge zu minimieren, die die GPU nachverfolgen muss. Die GPU verfügt über eine große Warteschlange mit Befehlen, und jedes Mal, wenn das Spiel Draw aufruft, wird dieser Befehl zusammen mit den damit verbundenen Daten in die Warteschlange eingereiht. Wenn das Spiel den Grundtypkonstantenpuffer aktualisiert und den nächsten Befehl "Zeichnen " ausgibt, fügt der Grafiktreiber diesen nächsten Befehl und die zugehörigen Daten zur Warteschlange hinzu. Wenn das Spiel 100 Grundtypen zeichnet, könnte es möglicherweise 100 Kopien der Konstantenpufferdaten in der Warteschlange haben. Um die Datenmenge zu minimieren, die das Spiel an die GPU sendet, verwendet das Spiel einen separaten Grundtypkonstantenpuffer, der nur die Updates für jeden Grundtyp enthält.

GameObject::Render-Methode

void GameObject::Render(
    _In_ ID3D11DeviceContext* context,
    _In_ ID3D11Buffer* primitiveConstantBuffer
    )
{
    if (!m_active || (m_mesh == nullptr) || (m_normalMaterial == nullptr))
    {
        return;
    }

    ConstantBufferChangesEveryPrim constantBuffer;

    // Put the model matrix info into a constant buffer, in world matrix.
    XMStoreFloat4x4(
        &constantBuffer.worldMatrix,
        XMMatrixTranspose(ModelMatrix())
        );

    // Check to see which material to use on the object.
    // If a collision (a hit) is detected, GameObject::Render checks the current context, which 
    // indicates whether the target has been hit by an ammo sphere. If the target has been hit, 
    // this method applies a hit material, which reverses the colors of the rings of the target to 
    // indicate a successful hit to the player. Otherwise, it applies the default material 
    // with the same method. In both cases, it sets the material by calling Material::RenderSetup, 
    // which sets the appropriate constants into the constant buffer. Then, it calls 
    // ID3D11DeviceContext::PSSetShaderResources to set the corresponding texture resource for the 
    // pixel shader, and ID3D11DeviceContext::VSSetShader and ID3D11DeviceContext::PSSetShader 
    // to set the vertex shader and pixel shader objects themselves, respectively.

    if (m_hit && m_hitMaterial != nullptr)
    {
        m_hitMaterial->RenderSetup(context, &constantBuffer);
    }
    else
    {
        m_normalMaterial->RenderSetup(context, &constantBuffer);
    }

    // Update the primitive constant buffer with the object model's info.
    context->UpdateSubresource(primitiveConstantBuffer, 0, nullptr, &constantBuffer, 0, 0);

    // Render the mesh.
    // See MeshObject::Render method below.
    m_mesh->Render(context);
}

MeshObject::Render-Methode

void MeshObject::Render(_In_ ID3D11DeviceContext* context)
{
    // PNTVertex is a struct. stride provides us the size required for all the mesh data
    // struct PNTVertex
    //{
    //  DirectX::XMFLOAT3 position;
    //  DirectX::XMFLOAT3 normal;
    //  DirectX::XMFLOAT2 textureCoordinate;
    //};
    uint32_t stride{ sizeof(PNTVertex) };
    uint32_t offset{ 0 };

    // Similar to the main render loop.
    // Input-layout objects describe how vertex buffer data is streamed into the IA pipeline stage.
    ID3D11Buffer* vertexBuffer{ m_vertexBuffer.get() };
    context->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);

    // IASetIndexBuffer binds an index buffer to the input-assembler stage.
    // For more info, see
    // https://learn.microsoft.com/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-iasetindexbuffer.
    context->IASetIndexBuffer(m_indexBuffer.get(), DXGI_FORMAT_R16_UINT, 0);

    // Binds information about the primitive type, and data order that describes input data for the input assembler stage.
    // For more info, see
    // https://learn.microsoft.com/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-iasetprimitivetopology.
    context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

    // Draw indexed, non-instanced primitives. A draw API submits work to the rendering pipeline.
    // For more info, see
    // https://learn.microsoft.com/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-drawindexed.
    context->DrawIndexed(m_indexCount, 0, 0);
}

DeviceResources::P resent-Methode

Wir rufen die DeviceResources::P resent-Methode auf, um den Inhalt anzuzeigen, den wir in den Puffern platziert haben.

Wir verwenden die Ausdrucks-Swapchain für eine Sammlung von Puffern, die zum Anzeigen von Frames für den Benutzer verwendet werden. Jedes Mal, wenn eine Anwendung einen neuen Frame für die Anzeige darstellt, wird der erste Puffer in der Swapchain anstelle des angezeigten Puffers verwendet. Dieser Vorgang wird als Swapping oder Flipping bezeichnet. Weitere Informationen finden Sie unter Swapchains.

  • Die Present-Methode der IDXGISwapChain1-Schnittstelle weist DXGI an, zu blockieren, bis die vertikale Synchronisierung (VSync) stattfindet, wodurch die Anwendung bis zum nächsten VSync in den Ruhezustand versetzt wird. Dadurch wird sichergestellt, dass Sie keine Zyklen beim Rendern von Frames verschwenden, die niemals auf dem Bildschirm angezeigt werden.
  • Die DiscardView-Methode der ID3D11DeviceContext3-Schnittstelle verwirft den Inhalt des Renderziels. Dies ist nur dann ein gültiger Vorgang, wenn der vorhandene Inhalt vollständig überschrieben wird. Wenn schmutzige oder Bildlaufrechtecke verwendet werden, sollte dieser Aufruf entfernt werden.

Tipp

Um eine reibungslose Framerate zu erzielen, müssen Sie sicherstellen, dass die Menge der Arbeit zum Rendern eines Frames in die Zeit zwischen VSyncs passt.

// Present the contents of the swap chain to the screen.
void DX::DeviceResources::Present()
{
    // The first argument instructs DXGI to block until VSync, putting the application
    // to sleep until the next VSync. This ensures we don't waste any cycles rendering
    // frames that will never be displayed to the screen.
    HRESULT hr = m_swapChain->Present(1, 0);

    // Discard the contents of the render target.
    // This is a valid operation only when the existing contents will be entirely
    // overwritten. If dirty or scroll rects are used, this call should be removed.
    m_d3dContext->DiscardView(m_d3dRenderTargetView.get());

    // Discard the contents of the depth stencil.
    m_d3dContext->DiscardView(m_d3dDepthStencilView.get());

    // If the device was removed either by a disconnection or a driver upgrade, we 
    // must recreate all device resources.
    if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
    {
        HandleDeviceLost();
    }
    else
    {
        winrt::check_hresult(hr);
    }
}

Nächste Schritte

In diesem Thema wird erläutert, wie Grafiken auf dem Display gerendert werden, und es enthält eine kurze Beschreibung für einige der verwendeten Renderingbegriffe (unten). Erfahren Sie mehr über das Rendern im Rendering-Framework II: Thema zum Rendern von Spielen, und erfahren Sie, wie Sie die benötigten Daten vor dem Rendern vorbereiten.

Begriffe und Konzepte

Einfache Spielszene

Eine einfache Spielszene besteht aus einigen Objekten mit mehreren Lichtquellen.

Die Form eines Objekts wird durch eine Reihe von X-, Y-, Z-Koordinaten im Raum definiert. Die tatsächliche Renderposition in der Spielwelt kann durch Anwenden einer Transformationsmatrix auf die Position X-, Y-, Z-Koordinaten bestimmt werden. Es kann auch eine Reihe von Texturkoordinaten ( Sie und V ) aufweisen, die angeben, wie ein Material auf das Objekt angewendet wird. Dies definiert die Oberflächeneigenschaften des Objekts und gibt Ihnen die Möglichkeit, zu sehen, ob ein Objekt eine raue Oberfläche hat (z. B. einen Tennisball), oder eine glatte glanzige Oberfläche (z. B. einen Kegelball).

Szenen- und Objektinformationen werden vom Renderingframe verwendet, um den Szenenframe nach Frame neu zu erstellen, sodass er auf dem Displaymonitor lebendig wird.

Renderingpipeline

Die Renderingpipeline ist der Prozess, mit dem 3D-Szeneninformationen in ein Bild übersetzt werden, das auf dem Bildschirm angezeigt wird. In Direct3D 11 ist diese Pipeline programmierbar. Sie können die Phasen anpassen, um Ihre Renderinganforderungen zu unterstützen. Phasen, die allgemeine Shaderkerne enthalten, können mithilfe der HLSL-Programmiersprache programmiert werden. Es wird auch als Grafikrenderingpipeline oder einfach als Pipeline bezeichnet.

Damit Sie diese Pipeline erstellen können, müssen Sie mit diesen Details vertraut sein.

Weitere Informationen finden Sie unter Grundlegendes zur Direct3D 11-Renderingpipeline und grafikpipeline.

HLSL

HLSL ist die High-Level-Shadersprache für DirectX. Mit HLSL können Sie C-ähnliche programmierbare Shader für die Direct3D-Pipeline erstellen. Weitere Informationen finden Sie unter HLSL.

Shader

Ein Shader kann als eine Reihe von Anweisungen betrachtet werden, die bestimmen, wie die Oberfläche eines Objekts angezeigt wird, wenn sie gerendert wird. Diejenigen, die mit HLSL programmiert werden, werden als HLSL-Shader bezeichnet. Quellcodedateien für [HLSL])(#hlsl)-Shader haben die .hlsl Dateierweiterung. Diese Shader können zur Buildzeit oder zur Laufzeit kompiliert und zur Laufzeit in die entsprechende Pipelinephase festgelegt werden. Ein kompiliertes Shaderobjekt verfügt über eine .cso Dateierweiterung.

Direct3D 9-Shader können mit Shadermodell 1, Shadermodell 2 und Shadermodell 3 entworfen werden; Direct3D 10-Shader können nur für Shadermodell 4 entworfen werden. Direct3D 11-Shader können auf Shadermodell 5 entworfen werden. Direct3D 11.3 und Direct3D 12 können auf Shadermodell 5.1 entworfen werden, und Direct3D 12 kann auch auf Shadermodell 6 entworfen werden.

Vertex-Shader und Pixelshader

Daten geben die Grafikpipeline als Datenstrom von Grundtypen ein und werden von verschiedenen Shadern wie vertex-Shadern und Pixelshadern verarbeitet.

Vertex-Shader verarbeiten Scheitelpunkte, führen in der Regel Vorgänge wie Transformationen, Skinning und Beleuchtung aus. Pixelshader ermöglichen umfangreiche Schattierungstechniken wie Beleuchtung pro Pixel und Nachbearbeitung. Es kombiniert Konstantenvariablen, Texturdaten, interpolierte Pro-Vertex-Werte und andere Daten, um Pro-Pixel-Ausgaben zu erzeugen.

Shaderstufen

Eine Sequenz dieser verschiedenen Shader, die zum Verarbeiten dieses Grundtyps definiert sind, wird als Shaderstufen in einer Renderingpipeline bezeichnet. Die tatsächlichen Phasen hängen von der Version von Direct3D ab, enthalten jedoch in der Regel die Vertex-, Geometrie- und Pixelphasen. Es gibt auch andere Phasen, z. B. die Hull- und Domänen-Shader für die Tessellation und den Compute-Shader. Alle diese Stufen sind vollständig mit HLSL programmierbar. Weitere Informationen finden Sie unter Grafikpipeline.

Verschiedene Shaderdateiformate

Hier sind die Shadercodedateierweiterungen.

  • Eine Datei mit der .hlsl Erweiterung enthält den Quellcode [HLSL])(#hlsl).
  • Eine Datei mit der .cso Erweiterung enthält ein kompiliertes Shaderobjekt.
  • Eine Datei mit der .h Erweiterung ist eine Headerdatei, aber in einem Shadercodekontext definiert diese Headerdatei ein Bytearray, das Shaderdaten enthält.
  • Eine Datei mit der .hlsli Erweiterung enthält das Format der Konstantenpuffer. Im Beispielspiel ist die Datei Shader>ConstantBuffers.hlsli.

Hinweis

Sie betten einen Shader ein, indem Sie eine .cso Datei zur Laufzeit laden oder eine .h Datei in Ihrem ausführbaren Code hinzufügen. Sie würden jedoch nicht beide für denselben Shader verwenden.

Tieferes Verständnis von DirectX

Direct3D 11 ist eine Reihe von APIs, die uns helfen können, Grafiken für grafikintensive Anwendungen wie Spiele zu erstellen, bei denen wir eine gute Grafikkarte haben möchten, um eine intensive Berechnung zu verarbeiten. In diesem Abschnitt werden kurz die Konzepte der Direct3D 11-Grafikprogrammierung erläutert: Ressource, Unterressource, Gerät und Gerätekontext.

Resource

Sie können sich Ressourcen (auch als Geräteressourcen bezeichnet) als Informationen zum Rendern eines Objekts vorstellen, z. B. Textur, Position oder Farbe. Ressourcen stellen Daten für die Pipeline bereit und definieren, was während der Szene gerendert wird. Ressourcen können aus Ihren Spielmedien geladen oder dynamisch zur Laufzeit erstellt werden.

Eine Ressource ist tatsächlich ein Bereich im Arbeitsspeicher, auf den über die Direct3D-Pipeline zugegriffen werden kann. Damit die Pipeline effizient auf den Speicher zugreifen kann, müssen für die Pipeline bereitgestellte Daten (etwa Eingabegeometrie, Shaderressourcen und Texturen) in einer Ressource gespeichert werden. Es gibt zwei Arten von Ressourcen, aus denen alle Direct3D-Ressourcen abgeleitet sind: Puffer und Textur. Für jede Pipelinephase können bis zu 128 Ressourcen aktiv sein. Weitere Informationen finden Sie unter Ressourcen.

Unterressource

Der Begriff "Unterressource" bezieht sich auf eine Teilmenge einer Ressource. Direct3D kann auf eine gesamte Ressource verweisen oder auf Teilmengen einer Ressource verweisen. Weitere Informationen finden Sie unter "Unterressource".

Tiefenschablone

Eine Tiefenschablonenressource enthält das Format und den Puffer zum Speichern von Tiefen- und Schabloneninformationen. Sie wird mithilfe einer Texturressource erstellt. Weitere Informationen zum Erstellen einer Tiefenschablonenressource finden Sie unter Configuring Depth-Stencil Functionality. Wir greifen auf die Tiefenschablonenressource über die Tiefenschablonenansicht zu, die mithilfe der ID3D11DepthStencilView-Schnittstelle implementiert wurde.

Tiefeninformationen geben uns an, welche Bereiche von Polygonen sich hinter anderen befinden, damit wir bestimmen können, welche ausgeblendet sind. Schabloneninformationen sagen uns, welche Pixel maskiert sind. Sie kann verwendet werden, um Spezialeffekte zu erzeugen, da sie bestimmt, ob ein Pixel gezeichnet wird oder nicht. legt das Bit auf 1 oder 0 fest.

Weitere Informationen finden Sie in der Tiefenschablonenansicht, im Tiefenpuffer und im Schablonenpuffer.

Renderziel

Ein Renderziel ist eine Ressource, in die wir am Ende eines Renderdurchlaufs schreiben können. Sie wird häufig mithilfe der ID3D11Device::CreateRenderTargetView-Methode mithilfe des Swapchain-Hintergrundpuffers (auch eine Ressource) als Eingabeparameter erstellt.

Jedes Renderziel sollte auch über eine entsprechende Tiefenschablonenansicht verfügen, da bei Verwendung von OMSetRenderTargets , um das Renderziel vor der Verwendung festzulegen, auch eine Tiefenschablonenansicht erforderlich ist. Wir greifen über die mithilfe der ID3D11RenderTargetView-Schnittstelle implementierte Renderzielansicht auf die Renderzielressource zu.

Sicherungsmedium

Sie können sich ein Gerät als Möglichkeit vorstellen, Objekte zuzuweisen und zu zerstören, Grundtypen zu rendern und mit der Grafikkarte über den Grafiktreiber zu kommunizieren.

Für eine genauere Erläuterung ist ein Direct3D-Gerät die Renderingkomponente von Direct3D. Ein Gerät kapselt und speichert den Renderstatus, führt Transformationen und Beleuchtungsvorgänge aus und rastert ein Bild auf einer Oberfläche. Weitere Informationen finden Sie unter "Geräte"

Ein Gerät wird durch die ID3D11Device-Schnittstelle dargestellt. Mit anderen Worten: Die ID3D11Device-Schnittstelle stellt einen virtuellen Anzeigeadapter dar und wird verwendet, um Ressourcen zu erstellen, die sich im Besitz eines Geräts befinden.

Es gibt verschiedene Versionen von ID3D11Device. ID3D11Device5 ist die neueste Version und fügt neue Methoden zu den Methoden in ID3D11Device4 hinzu. Weitere Informationen zur Kommunikation von Direct3D mit der zugrunde liegenden Hardware finden Sie unter der Windows Device Driver Model (WDDM)-Architektur.

Jede Anwendung muss über mindestens ein Gerät verfügen; Die meisten Anwendungen erstellen nur eine. Erstellen Sie ein Gerät für einen der Hardwaretreiber, die auf Ihrem Computer installiert sind, indem Sie D3D11CreateDevice oder D3D11CreateDeviceAndSwapChain aufrufen und den Treibertyp mit dem D3D_DRIVER_TYPE Flag angeben. Jedes Gerät kann je nach gewünschter Funktionalität einen oder mehrere Gerätekontexte verwenden. Weitere Informationen finden Sie unter D3D11CreateDevice-Funktion.

Gerätekontext

Ein Gerätekontext wird verwendet, um den Pipelinestatus festzulegen und Renderbefehle mithilfe der Ressourcen zu generieren, die einem Gerät gehören.

Direct3D 11 implementiert zwei Gerätekontexttypen, eine für das sofortige Rendering und die andere für verzögertes Rendering; Beide Kontexte werden mit einer ID3D11DeviceContext-Schnittstelle dargestellt.

Die ID3D11DeviceContext-Schnittstellen weisen unterschiedliche Versionen auf; ID3D11DeviceContext4 fügt neue Methoden zu den Methoden in ID3D11DeviceContext3 hinzu.

ID3D11DeviceContext4 wird im Windows 10 Creators Update eingeführt und ist die neueste Version der ID3D11DeviceContext-Schnittstelle . Anwendungen für Windows 10 Creators Update und höher sollten diese Schnittstelle anstelle früherer Versionen verwenden. Weitere Informationen finden Sie unter ID3D11DeviceContext4.

DX::D eviceResources

Die DX::D eviceResources-Klasse befindet sich in den Dateien DeviceResources.cpp.h/ und steuert alle DirectX-Geräteressourcen.

Buffer

Eine Pufferressource ist eine Sammlung vollständig typierter Daten, die in Elemente gruppiert sind. Sie können Puffer verwenden, um eine Vielzahl von Daten zu speichern, einschließlich Positionsvektoren, Normalvektoren, Texturkoordinaten in einem Vertexpuffer, Indizes in einem Indexpuffer oder Gerätestatus. Pufferelemente können gepackte Datenwerte (z . B. R8G8B8A8 Oberflächenwerte), einzelne 8-Bit-Ganzzahlen oder vier 32-Bit-Gleitkommawerte enthalten.

Es stehen drei Typen von Puffern zur Verfügung: Vertexpuffer, Indexpuffer und Konstantenpuffer.

Vertexpuffer

Enthält die Vertexdaten, die zum Definieren der Geometrie verwendet werden. Vertexdaten umfassen Positionskoordinaten, Farbdaten, Texturkoordinatendaten, normale Daten usw.

Indexpuffer

Enthält ganzzahlige Offsets in Vertexpuffer und werden verwendet, um Grundtypen effizienter zu rendern. Ein Indexpuffer enthält einen sequenziellen Satz von 16-Bit- oder 32-Bit-Indizes; Jeder Index wird verwendet, um einen Scheitelpunkt in einem Vertexpuffer zu identifizieren.

Konstantenpuffer oder Shaderkonstantenpuffer

Ermöglicht Es Ihnen, Shaderdaten effizient an die Pipeline zu übermitteln. Sie können Konstantenpuffer als Eingaben für die Shader verwenden, die für jeden Grundtyp ausgeführt werden, und Ergebnisse der Streamausgabephase der Renderingpipeline speichern. Konzeptionell sieht ein Konstantenpuffer genauso aus wie ein Einelement-Vertexpuffer.

Entwurf und Implementierung von Puffern

Sie können Puffer basierend auf dem Datentyp entwerfen, z. B. wie in unserem Beispielspiel, wird ein Puffer für statische Daten erstellt, eine andere für Daten, die über dem Frame konstant sind, und eine andere für Daten, die für einen Grundtyp spezifisch sind.

Alle Puffertypen werden von der ID3D11Buffer-Schnittstelle gekapselt, und Sie können eine Pufferressource erstellen, indem Sie ID3D11Device::CreateBuffer aufrufen. Ein Puffer muss jedoch an die Pipeline gebunden werden, bevor auf sie zugegriffen werden kann. Puffer können gleichzeitig an mehrere Pipelinephasen zum Lesen gebunden werden. Ein Puffer kann auch an eine einzelne Pipelinestufe zum Schreiben gebunden werden; Derselbe Puffer kann jedoch nicht für das gleichzeitige Lesen und Schreiben gebunden werden.

Sie können Puffer auf diese Weise binden.

  • Zur Eingabeassemblerphase durch Aufrufen von ID3D11DeviceContext-Methoden wie ID3D11DeviceContext::IASetVertexBuffers und ID3D11DeviceContext::IASetIndexBuffer.
  • Zur Streamausgabestufe durch Aufrufen von ID3D11DeviceContext::SOSetTargets.
  • Zur Shaderphase durch Aufrufen von Shadermethoden, z . B. ID3D11DeviceContext::VSSetConstantBuffers.

Weitere Informationen finden Sie unter Einführung in Puffer in Direct3D 11.

DXGI

Microsoft DirectX Graphics Infrastructure (DXGI) ist ein Subsystem, das einige der Aufgaben auf niedriger Ebene kapselt, die von Direct3D benötigt werden. Bei verwendung von DXGI in einer Multithread-Anwendung muss besondere Sorgfalt beachtet werden, um sicherzustellen, dass Deadlocks nicht auftreten. Weitere Informationen finden Sie unter Multithreading und DXGI

Featureebene

Featureebene ist ein Konzept, das in Direct3D 11 eingeführt wurde, um die Vielfalt von Grafikkarten auf neuen und vorhandenen Computern zu behandeln. Eine Featureebene ist eine gut definierte Gruppe von Gpu-Funktionen (Graphics Processing Unit).

Jede Grafikkarte implementiert je nach installierten GPUs eine bestimmte DirectX-Funktionalitätsebene. In früheren Versionen von Microsoft Direct3D konnten Sie die Version von Direct3D ermitteln, die die Grafikkarte implementiert hat, und dann Ihre Anwendung entsprechend programmieren.

Bei der Featureebene können Sie beim Erstellen eines Geräts versuchen, ein Gerät für die Featureebene zu erstellen, die Sie anfordern möchten. Wenn die Geräteerstellung funktioniert, ist diese Featureebene vorhanden, wenn dies nicht der Fall ist, unterstützt die Hardware diese Featureebene nicht. Sie können entweder versuchen, ein Gerät auf einer niedrigeren Featureebene neu zu erstellen, oder Sie können die Anwendung beenden. Die Featureebene 12_0 erfordert beispielsweise Direct3D 11.3 oder Direct3D 12 und Shadermodell 5.1. Weitere Informationen finden Sie unter Direct3D-Featureebenen: Übersicht für jede Featureebene.

Mithilfe von Featureebenen können Sie eine Anwendung für Direct3D 9, Microsoft Direct3D 10 oder Direct3D 11 entwickeln und dann auf 9, 10 oder 11 Hardware (mit einigen Ausnahmen) ausführen. Weitere Informationen finden Sie unter Direct3D-Featureebenen.

Stereorendering

Stereorendering wird verwendet, um die Illusion der Tiefe zu verbessern. Es verwendet zwei Bilder, eines aus dem linken Auge und das andere aus dem rechten Auge, um eine Szene auf dem Bildschirm anzuzeigen.

Mathematisch wenden wir eine Stereoprojektionsmatrix an, bei der es sich um einen leichten horizontalen Offset nach rechts und links der regulären Monoprojektionsmatrix handelt, um dies zu erreichen.

Wir haben zwei Renderingdurchläufe gemacht, um das Stereorendering in diesem Beispielspiel zu erzielen.

  • Binden Sie an das rechte Renderziel, wenden Sie die rechte Projektion an, und zeichnen Sie dann das primitive Objekt.
  • Binden sie an das linke Renderziel, wenden Sie die linke Projektion an, und zeichnen Sie dann das primitive Objekt.

Kamera- und Koordinatenbereich

Das Spiel verfügt über den Code zum Aktualisieren der Welt in einem eigenen Koordinatensystem (manchmal auch als Weltraum oder Szenenbereich bezeichnet). Alle Objekte, einschließlich der Kamera, werden in diesem Raum positioniert und ausgerichtet. Weitere Informationen finden Sie unter Koordinatensysteme.

Ein Vertex-Shader führt die schwere Umstellung von den Modellkoordinaten in Gerätekoordinaten mit dem folgenden Algorithmus durch (wobei V ein Vektor ist und M eine Matrix ist).

V(device) = V(model) x M(model-to-world) x M(world-to-view) x M(view-to-device)

  • M(model-to-world)ist eine Transformationsmatrix für Modellkoordinaten in Weltkoordinaten, auch bekannt als Welttransformationsmatrix. Dies wird vom Grundtyp bereitgestellt.
  • M(world-to-view) ist eine Transformationsmatrix für Weltkoordinaten zum Anzeigen von Koordinaten, auch bekannt als Ansichtstransformationsmatrix.
    • Dies wird von der Ansichtsmatrix der Kamera bereitgestellt. Sie wird durch die Position der Kamera zusammen mit den Blickvektoren definiert (der Blickvektor, der direkt von der Kamera auf die Szene zeigt, und der Nachschlagevektor, der sich senkrecht nach oben befindet).
    • Im Beispielspiel ist m_viewMatrix die Ansichtstransformationsmatrix und wird mithilfe von Camera::SetViewParams berechnet.
  • M(view-to-device) ist eine Transformationsmatrix für Ansichtskoordinaten zu Gerätekoordinaten, auch als Projektionstransformationsmatrix bezeichnet.
    • Dies wird durch die Projektion der Kamera bereitgestellt. Es enthält Informationen dazu, wie viel dieser Raum tatsächlich in der endgültigen Szene sichtbar ist. Das Ansichtsfeld (FoV), das Seitenverhältnis und die Clippingebenen definieren die Projektionstransformationsmatrix.
    • Im Beispielspiel definiert m_projectionMatrix die Transformation in die Projektionskoordinaten, berechnet mit Camera::SetProjParams (Für stereoprojektion verwenden Sie zwei Projektionsmatrizen – eine für die Ansicht der einzelnen Augen).

Der Shadercode wird VertexShader.hlsl mit diesen Vektoren und Matrizen aus den Konstantenpuffern geladen und führt diese Transformation für jeden Vertex aus.

Transformation in Koordinatensystemen

Direct3D verwendet drei Transformationen, um Ihre 3D-Modellkoordinaten in Pixelkoordinaten (Bildschirmraum) zu ändern. Diese Transformationen sind Welttransformationen, Ansichtstransformationen und Projektionstransformationen. Weitere Informationen finden Sie unter Transformieren (Übersicht).

Welttransformationsmatrix

Eine Welttransformation ändert Koordinaten aus dem Modellbereich, wobei Scheitelpunkte relativ zum lokalen Ursprung eines Modells zum Weltraum definiert werden, wobei Scheitelpunkte relativ zu einem Ursprung definiert werden, der allen Objekten in einer Szene gemeinsam ist. Im Wesentlichen platziert die Welt ein Modell in die Welt; daher sein Name. Weitere Informationen finden Sie unter World Transform.

Ansichtstransformationsmatrix

Die Ansichtstransformation sucht den Betrachter im Weltraum und wandelt Scheitelpunkte in den Kamerabereich um. Im Kamerabereich befindet sich die Kamera oder der Betrachter am Ursprung, der in die positive Z-Richtung schaut. Weitere Informationen finden Sie unter " Ansichtstransformation".

Projektionstransformationsmatrix

Die Projektionstransformation wandelt das Anzeige-Frustum in eine Cuboidform um. Ein Anzeige-Frustum ist ein 3D-Volume in einer Szene, die relativ zur Kamera des Viewports positioniert ist. Ein Viewport ist ein 2D-Rechteck, in das eine 3D-Szene projiziert wird. Weitere Informationen finden Sie unter Viewports und Clipping

Da das nahe Ende des Seh-Frustums kleiner als das weit entfernte Ende ist, hat dies die Wirkung, Objekte zu erweitern, die nahe an der Kamera liegen; So wird die Perspektive auf die Szene angewendet. Objekte, die dem Spieler näher sind, erscheinen also größer; Objekte, die weiter entfernt sind, werden kleiner angezeigt.

Mathematisch ist die Projektionstransformation eine Matrix, die in der Regel sowohl eine Skalierung als auch eine perspektivische Projektion ist. Es funktioniert wie das Objektiv einer Kamera. Weitere Informationen finden Sie unter Projektionstransformation.

Samplerstatus

Der Samplerzustand bestimmt, wie Texturdaten mithilfe von Texturadressierungsmodi, Filterung und Detailebene beispielt werden. Das Sampling erfolgt jedes Mal, wenn ein Texturpixel (oder Texel) aus einer Textur gelesen wird.

Eine Textur enthält ein Array von Texeln. Die Position der einzelnen Texel wird durch (u,v)angegeben , wobei u die Breite und v die Höhe angegeben ist und basierend auf der Texturbreite und -höhe zwischen 0 und 1 zugeordnet wird. Die resultierenden Texturkoordinaten werden verwendet, um ein Texel beim Sampling einer Textur zu adressieren.

Wenn Texturkoordinaten unter 0 oder höher 1 liegen, definiert der Texturadressmodus, wie die Texturkoordinate eine Texelposition adressiert. Wenn Sie beispielsweise TextureAddressMode.Clamp verwenden, wird eine beliebige Koordinate außerhalb des 0-1-Bereichs auf einen Maximalwert von 1 und den Minimalwert 0 vor dem Sampling geklemmt.

Wenn die Textur für das Polygon zu groß oder zu klein ist, wird die Textur so gefiltert, dass sie in den Raum passt. Ein Vergrößerungsfilter vergrößert eine Textur, ein Minimierungsfilter reduziert die Textur so, dass sie in einen kleineren Bereich passt. Die Texturvergrößerung wiederholt das Beispiel-Texel für eine oder mehrere Adressen, die ein verschwommenes Bild liefern. Texturminierung ist komplizierter, da sie mehrere Texelwerte in einen einzelnen Wert kombinieren muss. Dies kann abhängig von den Texturdaten zu Aliasing oder gezackten Kanten führen. Der beliebteste Ansatz für die Minimierung ist die Verwendung einer Mipmap. Eine Mipmap ist eine Textur mit mehreren Ebenen. Die Größe jeder Ebene ist eine Leistung von 2 kleiner als die vorherige Ebene bis zu einer Textur von 1 x 1. Wenn die Minimierung verwendet wird, wählt ein Spiel die Mipmap-Ebene aus, die der zum Renderzeit benötigten Größe am nächsten kommt.

Die BasicLoader-Klasse

BasicLoader ist eine einfache Ladeklasse, die Unterstützung für das Laden von Shadern, Texturen und Gittern von Dateien auf dem Datenträger bietet. Sie stellt synchrone und asynchrone Methoden bereit. In diesem Beispielspiel befinden sich die BasicLoader.h/.cpp Dateien im Ordner "Dienstprogramme ".

Weitere Informationen finden Sie unter Basic Loader.