Im Zuge eines aktuellen Projektes habe ich mich das erste Mal etwas näher mit Shadern beschäftigt und muss immer wieder fasziniert feststellen, was für Effekte damit eigentlich möglich sind. In den meisten Fällen reichen für erste Ergebnisse oder Prototypen die Unity Standard-Shader aus. Jedoch sobald man etwas speziellere Anforderungen hat oder besondere Effekte erzielen möchte stößt man hier schnell an die Grenzen.

Eine solche Grenze, auf die die meisten VR-Entwickler in den Anfängen vermutlich irgendwann stoßen werden, ist das Rendern von Objekten "von Innen". Warum von Innen? Nun, wenn man beispielsweise eine 360°-Bild oder -Video betrachten will, dann wird dieses Bild in den meisten Fällen auf das Innere einer Kugel oder eines Würfels projiziert (texturiert) und in der Mitte der Kugel befindet sich die VR-Kamera, die den jeweiligen Bildausschnitt entsprechend der Kopfbewegung des Nutzers abfilmt.

Standardmäßig sind Shader in Unity allerdings so optimiert, dass "Innereien" durch aktiviertes Culling nicht gerendert werden, um Performance einzusparen. Wer also eine Sphere (für Equirect Panos) oder auch einen Cube (für Cubemaps) von Innen rendern möchte, um darin eine VR-Kamera zu platzieren, der kann in fast jedem Shader die Zeile "Cull Front" hinzufügen, damit nur die Innenseiten anstatt der Außenseiten gerendert werden.

Die in Unity integrierten Shader kann man zur eigenen Bearbeitung im offiziellen Download-Archiv herunterladen. Dort bei der jeweiligen Unity-Version auf das Dropdown-Feld der Plattform klicken und "Integrierte Shader" auswählen.

Beispiel
Der folgende Unlit-Shader wird in Zeile 9 um den Parameter "Cull Front" erweitert.

Shader "Unlit/Texture" {
Properties {
    _MainTex ("Base (RGB)", 2D) = "white" {}
}

SubShader {
    Tags { "RenderType"="Opaque" }
    LOD 100
    Cull Front

    Pass {  
        CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma target 2.0
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            struct appdata_t {
                float4 vertex : POSITION;
                float2 texcoord : TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct v2f {
                float4 vertex : SV_POSITION;
                float2 texcoord : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                UNITY_VERTEX_OUTPUT_STEREO
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert (appdata_t v)
            {
                v2f o;
                UNITY_SETUP_INSTANCE_ID(v);
                UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.texcoord);
                UNITY_APPLY_FOG(i.fogCoord, col);
                UNITY_OPAQUE_ALPHA(col.a);
                return col;
            }
        ENDCG
    }
}

}

Erklärung
Durch diese einfache Ergänzung wird erreicht, dass das Culling sich nur auf die Front beschränkt, aber die Backfaces, also der Innenteil, gerendert wird. Culling ist eine der einfachsten Grafik-Optimierungsmöglichkeiten, da mit dessen Hilfe nur die Dinge gerendert werden, die auch sichtbar sind. Alles andere wird verworfen. In unserem Fall (360-Viewer) möchten wir allerdings die Kugel nicht wie sonst von Außen, sondern von Innen betrachten und können somit das Rendering der Frontfaces verwerfen. Das Culling lässt sich durch "Cull Off" auch komplett abschalten, sodass Innen- und Außenseiten gerendert werden. In unserem Fall ist dies jedoch nicht nötig und würde die Performance unnötig belasten.

Noch ein Tipp: Die standard Unity Sphere hat keine so grandiose Auflösung (zu wenig Polygone) sodass gegebenenfalls Bildfehler, wie z.B. hässliche Kanten, sichtbar werden. In diesem Fall hilft es eine höher aufgelöste Sphere herunterzuladen (oder selbst mit einem 3D-Programm zu erstellen) oder statt einer Sphere Cubemaps zu verwenden, die ohnehin eine höhere Auflösung erzielen können.