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.
- Stellen Sie eine Verbindung mit der Grafikschnittstelle her.
- Erstellen Sie die zum Zeichnen der Grafiken erforderlichen Ressourcen.
- 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.
- Aktualisieren
- Rendern
- 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.
- Mit derselben DiscardView-Methode verwerfen Sie den Inhalt der Tiefenschablone.
- Die HandleDeviceLost-Methode wird verwendet, um das Szenario des zu entfernenden Geräts zu verwalten. Wenn das Gerät entweder durch eine Verbindung oder ein Treiberupgrade entfernt wurde, müssen Sie alle Geräteressourcen neu erstellen. Weitere Informationen finden Sie unter Behandeln von Szenarien mit entfernten Geräten in Direct3D 11.
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.
- HLSL. Wir empfehlen die Verwendung von HLSL-Shadermodell 5.1 und höher für UWP-DirectX-Spiele.
- Shader.
- Vertex-Shader und Pixelshader.
- Shaderphasen.
- Verschiedene Shaderdateiformate.
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.