Erweiterte Rendering-Konfiguration
Standardmäßig generiert das SDK Konfigurationswerte für eine möglichst hohe Rendering-Qualität.
Es bietet auch ein gewisses Maß an Flexibilität. Beispielsweise können Änderungen vorgenommen werden, wenn Rendering-Zieltexturen erstellt werden.
In diesem Abschnitt werden Änderungen erläutert, die vorgenommen werden können, wenn zwischen Rendering-Qualität und Leistung gewählt wird oder wenn die verwendete Engine Einschränkungen auferlegt.
Umgang mit Grafik-API oder Hardware-Rendering-Zielgranularität
Das SDK wurde unter der Annahme entwickelt, dass du deinen Videospeicher so sorgfältig wie möglich nutzen möchtest und dass du genau die richtige Rendering-Zielgröße für deine Anforderungen erstellen kannst.
Allerdings haben echte Videokarten und echte Grafik-APIs Größenbeschränkungen (alle haben eine maximale Größe, einige auch eine Mindestgröße). Sie können auch Granularitätseinschränkungen aufweisen, zum Beispiel können nur Rendering-Ziele erstellt werden, die ein Vielfaches von 32 Pixeln groß sind, oder es gibt eine Begrenzung der möglichen Seitenverhältnisse. Als Entwickler*in von Apps kannst du auch zusätzliche Einschränkungen festlegen, um zu vermeiden, dass zu viel Grafikspeicher verwendet wird.
Zusätzlich zu den oben genannten Punkten ist die Größe der tatsächlichen Rendering-Zieloberfläche im Speicher nicht unbedingt gleich groß wie der Teil, auf den gerendert wird. Letzteres kann etwas kleiner sein. Da es jedoch als Viewport angegeben ist, unterliegt es normalerweise keinen Granularitätseinschränkungen. Wenn du das Rendering-Ziel jedoch als Textur bindest, wird die gesamte Oberfläche verwendet, und daher müssen die UV-Koordinaten für den Unterschied zwischen der Größe des Renderings und der Größe der Oberfläche, auf der es sich befindet, korrigiert werden. Die API erledigt dies für dich, aber du musst ihr die relevanten Informationen mitteilen.
Der folgende Code zeigt einen zweistufigen Ansatz für die Einstellungen der Auflösung des Rendering-Ziels. Der Code ruft zuerst ovr_GetFovTextureSize auf, um die ideale Größe des Rendering-Ziels zu berechnen. Als Nächstes wird die Grafikbibliothek aufgerufen, um ein Rendering-Ziel mit der gewünschten Auflösung zu erstellen. Im Allgemeinen kann die resultierende Texturgröße aufgrund von Eigenheiten der Plattform und der Hardware von der angeforderten Größe abweichen.
// Get recommended left and right eye render target sizes.
Sizei recommenedTex0Size = ovr_GetFovTextureSize(session, ovrEye_Left,
session->DefaultEyeFov[0], pixelsPerDisplayPixel);
Sizei recommenedTex1Size = ovr_GetFovTextureSize(session, ovrEye_Right,
session->DefaultEyeFov[1], pixelsPerDisplayPixel);
// Determine dimensions to fit into a single render target.
Sizei renderTargetSize;
renderTargetSize.w = recommenedTex0Size.w + recommenedTex1Size.w;
renderTargetSize.h = max ( recommenedTex0Size.h, recommenedTex1Size.h );
// Create texture.
pRendertargetTexture = pRender->CreateTexture(renderTargetSize.w, renderTargetSize.h);
// The actual RT size may be different due to HW limits.
renderTargetSize.w = pRendertargetTexture->GetWidth();
renderTargetSize.h = pRendertargetTexture->GetHeight();
// Initialize eye rendering information.
// The viewport sizes are re-computed in case RenderTargetSize changed due to HW limitations.
ovrFovPort eyeFov[2] = { session->DefaultEyeFov[0], session->DefaultEyeFov[1] };
EyeRenderViewport[0].Pos = Vector2i(0,0);
EyeRenderViewport[0].Size = Sizei(renderTargetSize.w / 2, renderTargetSize.h);
EyeRenderViewport[1].Pos = Vector2i((renderTargetSize.w + 1) / 2, 0);
EyeRenderViewport[1].Size = EyeRenderViewport[0].Size;
Diese Daten werden als Teil der Ebenenbeschreibung an ovr_EndFrame übergeben.
Die Größe der Rendering-Zieltextur und die Viewports für das linke und rechte Auge können nach Belieben ausgewählt werden, vorausgesetzt, dass diese Werte beim Aufruf von ovr_EndFrame mit ovrTexture angegeben werden. Durch die Verwendung von ovr_GetFovTextureSize wird jedoch sichergestellt, dass die optimale Größe für das verwendete HMD zugewiesen wird. In den folgenden Abschnitten wird beschrieben, wie die Standardkonfigurationen geändert werden können, um Kompromisse bei Qualität und Leistung einzugehen. Du solltest auch beachten, dass die API die Verwendung verschiedener Rendering-Ziele für jedes Auge unterstützt, wenn dies von deiner Engine benötigt wird (obwohl die Verwendung eines einzelnen Rendering-Ziels wahrscheinlich eine bessere Leistung bietet, da es Kontextwechsel reduziert). Mit OculusWorldDemo kannst du zwischen der Verwendung eines einzelnen kombinierten Rendering-Ziels und separaten Rendering-Zielen für jedes Auge wechseln, indem du zum Einstellungsmenü navigierst (drücke die Tabulatortaste) und die Option „Rendering-Ziel teilen“ auswählst.
Ein symmetrisches Sichtfeld erzwingen
Normalerweise gibt die API für jedes Auge ein Sichtfeld zurück, das nicht symmetrisch ist, d. h. der linke Rand ist nicht gleich weit von der Mitte entfernt wie der rechte Rand.
Dies liegt daran, dass der Mensch, ebenso wie der Rift, ein breiteres Sichtfeld hat, wenn er nach außen schaut. Wenn man nach innen schaut, ist die Nase im Weg. Wir können auch besser nach unten als nach oben schauen. Aus ähnlichen Gründen ist die Sicht des Rift nicht symmetrisch. Sie wird durch die Form der Linse, verschiedene Kunststoffteile und die Ränder des Bildschirms beeinflusst. Die genauen Details hängen von der Form deines Gesichts, deinem IPD und der genauen Position des Rift auf deinem Gesicht ab. Alle diese Einstellungen werden im Konfigurationstool eingestellt und im Nutzer*innenprofil gespeichert. Das bedeutet, dass fast niemand alle vier Ränder seines Sichtfelds auf den gleichen Winkel eingestellt hat, sodass der erzeugte Kegelstumpf nicht mittig ist. Darüber hinaus ist das Sichtfeld der meisten Menschen für beide Augen unterschiedlich. Sie sind zwar ähnlich, aber selten identisch.
Im Code und in der Dokumentation werden diese als „halbe Winkel“ bezeichnet, da ein Sichtfeld traditionell als Gesamtwinkel von Kante zu Kante ausgedrückt wird. In diesem Beispiel beträgt das gesamte horizontale Sichtfeld 50,3 + 58,7 = 109,0 Grad und das gesamte vertikale Sichtfeld 53,6 + 58,9 = 112,5 Grad.
Die empfohlenen und maximalen Sichtfelder können wie unten dargestellt über das HMD aufgerufen werden:
ovrFovPort defaultLeftFOV = session->DefaultEyeFov[ovrEye_Left];
ovrFovPort maxLeftFOV = session->MaxEyeFov[ovrEye_Left];
DefaultEyeFov bezieht sich auf die empfohlenen Sichtfeldwerte, die auf den aktuellen Profileinstellungen des*der Nutzer*in (IPD, Augenabstand usw.) basieren. MaxEyeFov bezieht sich auf das maximale Sichtfeld, welches das Headset unabhängig von den Profileinstellungen anzeigen kann.
Die Standardwerte bieten eine gute Nutzungserfahrung ohne unnötige zusätzliche GPU-Last. Wenn deine App keine erheblichen GPU-Ressourcen verbraucht, solltest du die maximalen Sichtfeldeinstellungen verwenden, um die Abhängigkeit von der Genauigkeit der Profileinstellungen zu verringern. Du kannst in der Systemsteuerung der App einen Schieberegler bereitstellen, mit dem Nutzer*innen interpolierte Sichtfeld-Einstellungen zwischen dem Standardwert und dem Maximalwert auswählen können. Wenn deine App jedoch viel GPU-Leistung beansprucht, solltest du das FOV unter die Standardwerte reduzieren, wie unter
Improving Performance by Decreasing Field of View (Verbesserung der Leistung durch Verringerung des Sichtfelds) beschrieben.
Die Sichtfeldwinkel für oben, unten, links und rechts (ausgedrückt als Tangenten der Halbwinkel) sind die bequemste Form, um in deiner Grafik-Engine Begrenzungen für das Culling oder das Portal einzurichten. Die Sichtfeldwerte werden auch verwendet, um die Projektionsmatrix zu bestimmen, die beim Rendern von Szenen für das linke und rechte Auge verwendet wird. Zu diesem Zweck stellen wir eine API-Hilfsfunktion „ovrMatrix4f_Projection“ zur Verfügung:
ovrFovPort fov;
// Determine fov.
...
ovrMatrix4f projMatrix = ovrMatrix4f_Projection(fov, znear, zfar, 0);
Es ist üblich, dass die oberen und unteren Ränder des Sichtfelds nicht mit den linken und rechten Rändern übereinstimmen, wenn man einen PC-Monitor betrachtet. Dies wird allgemein als „Seitenverhältnis“ der Anzeige bezeichnet, und nur sehr wenige Anzeigen sind quadratisch. Einige Grafik-Engines unterstützen jedoch keine außermittigen Kegelstümpfe. Um mit diesen Engines kompatibel zu sein, müssen die von der Struktur ovrHmdDesc gemeldeten Sichtfeld-Werte geändert werden. Im Allgemeinen ist es besser, die Ränder zu vergrößern, als sie zu verkleinern. Dadurch wird die Grafik-Engine zwar etwas stärker belastet, aber der*die Nutzer*in erhält ein umfassendes Erlebnis, auch wenn er*sie einige der gerenderten Pixel nicht sehen kann.
Bestimmte Grafik-Engines erfordern die Angabe symmetrischer horizontaler und vertikaler Sichtfelder und einige benötigen eine noch weniger direkte Methode wie ein horizontales Sichtfeld und ein Seitenverhältnis. Einige lehnen auch häufige Änderungen des Sichtfelds ab und bestehen möglicherweise darauf, dass beide Augen auf dasselbe eingestellt werden. Im Folgenden findest du ein Beispiel für einen Code zur Handhabung dieses restriktiven Falls:
ovrFovPort fovLeft = session->DefaultEyeFov[ovrEye_Left];
ovrFovPort fovRight = session->DefaultEyeFov[ovrEye_Right];
ovrFovPort fovMax = FovPort::Max(fovLeft, fovRight);
float combinedTanHalfFovHorizontal = max ( fovMax.LeftTan, fovMax.RightTan );
float combinedTanHalfFovVertical = max ( fovMax.UpTan, fovMax.DownTan );
ovrFovPort fovBoth;
fovBoth.LeftTan = fovBoth.RightTan = combinedTanHalfFovHorizontal;
fovBoth.UpTan = fovBoth.DownTan = combinedTanHalfFovVertical;
// Create render target.
Sizei recommenedTex0Size = ovr_GetFovTextureSize(session, ovrEye_Left,
fovBoth, pixelsPerDisplayPixel);
Sizei recommenedTex1Size = ovr_GetFovTextureSize(session, ovrEye_Right,
fovBoth, pixelsPerDisplayPixel);
...
// Initialize rendering info.
ovrFovPort eyeFov[2];
eyeFov[0] = fovBoth;
eyeFov[1] = fovBoth;
...
// Compute the parameters to feed to the rendering engine.
// In this case we are assuming it wants a horizontal FOV and an aspect ratio.
float horizontalFullFovInRadians = 2.0f * atanf ( combinedTanHalfFovHorizontal );
float aspectRatio = combinedTanHalfFovHorizontal / combinedTanHalfFovVertical;
GraphicsEngineSetFovAndAspect ( horizontalFullFovInRadians, aspectRatio );
...
Hinweis: Du musst das Sichtfeld bestimmen, bevor du die Rendering-Ziele erstellst, da das Sichtfeld die Größe des empfohlenen Rendering-Ziels für eine bestimmte Qualität beeinflusst.
Bei der virtuellen Realität führt eine Verringerung unter 60 Hz zu einer schlechten Nutzungserfahrung. Es ist immer besser, die Auflösung zu verringern, um die Bildrate beizubehalten. Dies ist vergleichbar mit einem*einer Nutzer*in, der*die einen hochauflösenden Monitor mit 2560 x 1600 Pixeln verwendet. Nur sehr wenige 3D-Apps können bei dieser nativen Auflösung mit voller Geschwindigkeit ausgeführt werden. Daher bieten die meisten Apps dem*der Nutzer*in die Möglichkeit, eine niedrigere Auflösung auszuwählen, auf die der Monitor hochskaliert, um den Bildschirm auszufüllen.
Die gleiche Strategie kann auf das HMD angewendet werden. Das heißt, es wird mit einer niedrigeren Videoauflösung betrieben und die Hardware übernimmt die Hochskalierung. Dadurch werden jedoch zwei Filterungsschritte eingeführt: einer durch die Verzerrungsverarbeitung und einer durch den Video-Upscaler. Leider führt diese doppelte Filterung zu erheblichen Artefakten. In der Regel ist es effektiver, den Videomodus bei der nativen Auflösung zu belassen, aber die Größe des Zwischen-Rendering-Ziels zu begrenzen. Dadurch wird eine ähnliche Leistungssteigerung erzielt, aber es bleiben mehr Details erhalten.
Eine Möglichkeit, dieses Problem zu lösen, besteht darin, dem*der Nutzer*in die Anpassung der Auflösung über einen Auflösungswähler zu ermöglichen. Die tatsächliche Auflösung des Rendering-Ziels hängt jedoch von der Konfiguration des*der Nutzer*in und nicht von einer Standard-Hardwareeinstellung ab. Das bedeutet, dass die „native“ Auflösung für verschiedene Personen unterschiedlich ist. Darüber hinaus kann die Darstellung von Auflösungen, die höher sind als die physische Hardwareauflösung, zu Verwirrung bei einigen Nutzer*innen führen. Sie verstehen möglicherweise nicht, dass die Auswahl von 1280 x 800 einen erheblichen Qualitätsverlust bedeutet, auch wenn dies die von der Hardware gemeldete Auflösung ist.
Eine bessere Option ist es, den Wert „pixelsPerDisplayPixel“ zu ändern, der an die Funktion „ovr_GetFovTextureSize“ übergeben wird. Dies könnte auch auf einem Schieberegler basieren, der in den Render-Einstellungen der App angezeigt wird. Dadurch wird die relative Größe der Rendering-Zielpixel bestimmt, wenn sie den Pixeln in der Mitte der Anzeigefläche zugeordnet werden. Beispielsweise würde ein Wert von 0,5 die Rendering-Zielgröße von 2000 x 1056 auf 1000 x 528 Pixel reduzieren, sodass Grafikkarten der mittleren Preisklasse möglicherweise 60 Hz beibehalten können.
float pixelsPerDisplayPixel = GetPixelsPerDisplayFromApplicationSettings();
Sizei recommenedTexSize = ovr_GetFovTextureSize(session, ovrEye_Left, fovLeft,
pixelsPerDisplayPixel);
Zwar kannst du den Parameter auf einen Wert größer als 1,0 einstellen, um ein höher aufgelöstes Zwischen-Rendering-Ziel zu erzeugen, allerdings haben wir keine nennenswerte Qualitätssteigerung festgestellt – und das bei hohen Leistungskosten.
Mit OculusWorldDemo kannst du mit der Änderung der Pixeldichte des Rendering-Ziels experimentieren. Navigiere zum Einstellungsmenü (drücke die Tabulatortaste) und wähle „Pixeldichte“ aus. Drücke die Pfeiltasten nach oben und unten, um die Pixeldichte in der Mitte der Augenprojektion anzupassen. Ein Wert von 1,0 setzt die Pixeldichte des Rendering-Ziels an dieser Stelle auf der Anzeige auf 1:1. Ein Wert von 0,5 bedeutet, dass die Dichte der Rendering-Zielpixel auf die Hälfte der Anzeigefläche eingestellt wird. Zusätzlich kann die dynamische Auflösungsskalierung ausgewählt werden, wodurch die Pixeldichte automatisch zwischen 0 und 1 angepasst wird.
Zusätzlich zur Reduzierung der Pixelanzahl im Zwischen-Rendering-Ziel kann die Leistung durch Verringerung des Sichtfelds, über das die Pixel verteilt sind, erhöht werden.
Je nach Verkleinerung kann dies zu einem Tunnelblick führen, der das Gefühl des Eintauchens verringert. Dennoch erhöht die Verkleinerung des Sichtfelds die Leistung auf zweierlei Weise. Der offensichtlichste Grund ist die Füllrate. Bei einer festen Pixeldichte auf der Netzhaut hat ein kleineres Sichtfeld weniger Pixel. Aufgrund der Eigenschaften der projektiven Mathematik sind die äußersten Ränder des Sichtfelds in Bezug auf die Anzahl der Pixel am teuersten. Der zweite Grund ist, dass in jedem Frame weniger Objekte sichtbar sind, was weniger Animation, weniger Zustandsänderungen und weniger Draw Calls bedeutet.
Die Reduzierung des vom*von der Spieler*in eingestellten Sichtfelds ist eine sehr unangenehme Entscheidung. Zu den Schlüsselerlebnissen der virtuellen Realität gehört das Eintauchen in die simulierte Welt und ein großer Teil davon ist das breite Sichtfeld. Diesen Aspekt zu verlieren, ist nichts, was wir jemals empfehlen würden. Wenn du jedoch bereits so viel Auflösung wie möglich geopfert hast und die App auf dem Computer des*der Nutzer*in immer noch nicht mit 60 Hz läuft, ist dies eine Option der letzten Wahl.
Wir empfehlen, den Spieler*innen einen Schieberegler für das maximale Sichtfeld zur Verfügung zu stellen, mit dem die vier Ränder des Sichtfelds jedes Auges definiert werden können.
ovrFovPort defaultFovLeft = session->DefaultEyeFov[ovrEye_Left];
ovrFovPort defaultFovRight = session->DefaultEyeFov[ovrEye_Right];
float maxFovAngle = ...get value from game settings panel...;
float maxTanHalfFovAngle = tanf ( DegreeToRad ( 0.5f * maxFovAngle ) );
ovrFovPort newFovLeft = FovPort::Min(defaultFovLeft, FovPort(maxTanHalfFovAngle));
ovrFovPort newFovRight = FovPort::Min(defaultFovRight, FovPort(maxTanHalfFovAngle));
// Create render target.
Sizei recommenedTex0Size = ovr_GetFovTextureSize(session, ovrEye_Left newFovLeft, pixelsPerDisplayPixel);
Sizei recommenedTex1Size = ovr_GetFovTextureSize(session, ovrEye_Right, newFovRight, pixelsPerDisplayPixel);
...
// Initialize rendering info.
ovrFovPort eyeFov[2];
eyeFov[0] = newFovLeft;
eyeFov[1] = newFovRight;
...
// Determine projection matrices.
ovrMatrix4f projMatrixLeft = ovrMatrix4f_Projection(newFovLeft, znear, zfar, 0);
ovrMatrix4f projMatrixRight = ovrMatrix4f_Projection(newFovRight, znear, zfar, 0);
Experimentiere doch mal mit nicht-quadratischen Sichtfeldern. Du könntest beispielsweise den oberen und unteren Bereich deutlich einschränken (z. B. 70-Grad- Sichtfeld), während das horizontale Sichtfeld vollständig erhalten bleibt, um ein „Cinemascope“-Gefühl zu erzeugen.
Mit OculusWorldDemo kannst du mit der Reduzierung des Sichtfelds unter die Standardwerte experimentieren. Navigiere zum Einstellungsmenü (drücke die Tabulatortaste) und wähle den Wert „Max FOV“ aus. Drücke die Pfeiltasten nach oben und unten, um den maximalen Winkel in Grad zu ändern.
Ein wesentlicher Kostenfaktor beim Stereo-Rendering ist das Rendern von zwei Ansichten, eine für jedes Auge.
Bei einigen Apps ist der stereoskopische Aspekt möglicherweise nicht besonders wichtig und eine monokulare Ansicht könnte im Gegenzug für eine gewisse Leistung akzeptabel sein. In anderen Fällen kann eine Stereoansicht für einige Nutzer*innen zu einer Überanstrengung der Augen führen, sodass sie auf eine monokulare Ansicht umschalten möchten. Sie möchten jedoch weiterhin das HMD tragen, da es ihnen ein hohes Sichtfeld und Head-Tracking bietet.
OculusWorldDemo ermöglicht es dem*der Nutzer*in, durch Drücken der Taste F7 in den Mono-Rendering-Modus zu wechseln.
Um in Mono zu rendern, sollte der Code wie folgt geändert werden:
- Stelle das Sichtfeld auf das maximale symmetrische Sichtfeld basierend auf beiden Augen ein.
- Rufe ovhHmd_GetFovTextureSize mit diesem Sichtfeld auf, um die empfohlene Rendering-Zielgröße zu bestimmen.
- Konfiguriere beide Augen so, dass sie dasselbe Renderziel und denselben Viewport verwenden, wenn ovr_EndFrame aufgerufen wird.
- Rendere die Szene einmal auf das gemeinsame Rendering-Ziel.
Dadurch wird das Sichtfeld des linken und rechten Auges in einem einzigen Zwischenrendering zusammengeführt. Dieses Rendering ist immer noch zweimal verzerrt, einmal pro Auge, da sich die Linsen nicht genau vor den Augen des*der Nutzer*in befinden. Dennoch ist dies eine erhebliche Leistungssteigerung.
Wenn man eine virtuelle IPD auf Null setzt, erscheint alles gigantisch und unendlich weit entfernt, und natürlich verliert der*die Nutzer*in viel von dem Gefühl für die Tiefe der Szene.
Hinweis: Es ist wichtig, die virtuelle IPD und die virtuelle Kopfbewegung gemeinsam zu skalieren. Wenn die virtuelle IPD auf Null gesetzt wird, werden auch alle virtuellen Kopfbewegungen aufgrund von Halsbewegungen eliminiert. Leider gehen dadurch aufgrund der Parallaxe viele Tiefeneindrücke verloren. Wenn jedoch die Kopfbewegung und die IPD nicht übereinstimmen, kann dies zu erheblicher Orientierungslosigkeit und Unbehagen führen. Experimentiere mit Vorsicht!
Oktilineares Rendering für NVIDIA Lens Matched Shading verwenden
Oktilineares Rendering implementiert NVIDIA Lens Matched Shading. Du kannst oktilineares Rendering verwenden, um die Leistung deiner App zu verbessern, wenn sie auf einem NVIDIA-Grafikprozessor ausgeführt wird.
Durch die oktilineare Darstellung wird vermieden, dass eine erhebliche Anzahl von Pixeln gerendert werden muss, die andernfalls verworfen würden, bevor das Bild an das Headset ausgegeben wird. Die App muss ein größeres Bild zeichnen, als auf dem Rift angezeigt wird. Das Zeichnen dieser größeren Bilder erfordert zusätzliche Zeit. Durch Lens Matched Shading kann das System ein kleineres Bild darstellen, da es ein vorkomprimiertes Bild zeichnet. Ein oktilineares Bild sieht wie folgt aus:

Durch die Verwendung der oktilinearen Darstellung wird die Größe des Zeichenbereichs um etwa 20 % reduziert. Der Begrenzungsrahmen bleibt derselbe wie bei einem nicht oktilinearen Bild.
Für die Verwendung der oktilinearen Darstellung gelten folgende Anforderungen:
- Du musst deine App auf einem NVIDIA-Grafikprozessor ausführen, der Lens Mapped -Shading unterstützt. (Weitere Informationen findest du in der NVIDIA-Dokumentation.)
- Du musst ein NVIDIA SDK verwenden, das die Funktion „Lens Mapped Shading“ des Grafikprozessors unterstützt. (Weitere Informationen findest du in der NVIDIA-Dokumentation.)
- Du musst Texturen im richtigen Format mit dem NVIDIA SDK generieren.
- Deine App muss
ovr_EnableExtension aufrufen, um die oktilineare Erweiterung von der Oculus Rift-Seite zu aktivieren. - Dann verarbeitet die Laufzeitumgebung deine speziell formatierten Bilder zur Laufzeit automatisch.
In manchen Fällen sollen Inhalte nur auf dem Headset angezeigt werden. Die Funktion „Geschützte Inhalte“ ist so konzipiert, dass sie jegliche Spiegelung des Compositors verhindert.
Um die Funktion für geschützte Inhalte zu nutzen, konfiguriere deine App so, dass ein oder mehrere ovrTextureSwapChain-Objekte mit dem angegebenen ovrTextureMisc_ProtectedContent-Flag erstellt werden. Jede Einreichung, die auf eine geschützte Swapchain verweist, wird als geschützter Frame betrachtet. Alle geschützten Frames werden zusammengesetzt und im HMD angezeigt, aber nicht auf Spiegel repliziert oder für die Capture-Buffer-API verfügbar gemacht.
Wenn das HMD nicht HDCP-konform ist, schlägt die API zur Erstellung der Textur-Swapchain mit ovrError_ContentProtectionNotAvailable fehl. Wenn die Texturen erstellt werden können (HDCP-konformes HMD), die Verknüpfung jedoch später unterbrochen wird, schlägt der nächste ovr_EndFrame-Aufruf, der auf geschützte Textur-Swapchain verweist, mit dem Fehler ovrError_ContentProtectionNotAvailable fehl. Konfiguriere deine App so, dass sie deinen Anforderungen entsprechend reagiert. Beispielsweise könntest du das nächste Bild ohne geschützte Swapchains senden, allerdings mit einer geringeren Qualität, die keinen Schutz erfordert. Oder du kannst die Wiedergabe anhalten und dem*der Nutzer*in einen Fehler oder eine Warnung anzeigen.
Hinweis: Da das Spiegelungsfenster von der App gesteuert wird, muss deine App, wenn sie die Spiegelungstextur nicht verwendet, etwas in das Vorschaufenster rendern. Stelle sicher, dass deine App keine geschützten Inhalte anzeigt. Da die Oberflächen nicht als vom Betriebssystem geschützt bekannt sind, werden sie in der App, mit der sie erstellt wurden, normal angezeigt.
Um geschützte Inhalte zu aktivieren, gib das ovrTextureMisc_ProtectedContent-Flag in etwa wie folgt an:
ovrTextureSwapChainDesc desc = {};
desc.Type = ovrTexture_2D;
desc.ArraySize = 1;
desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
desc.Width = sizeW;
desc.Height = sizeH;
desc.MipLevels = 1;
desc.SampleCount = 1;
desc.MiscFlags = ovrTextureMisc_DX_Typeless | ovrTextureMisc_ProtectedContent;
desc.BindFlags = ovrTextureBind_DX_RenderTarget;
desc.StaticImage = ovrFalse;
ovrResult result = ovr_CreateTextureSwapChainDX(session, Device, &desc, &TextureChain);