Sie wird das Objekt zweimal an einem gewissen Punkt machen müssen. Sie können mit Rendering nur die Gesichter vor der Kamera einmal und die Gesichter mit Blick weg weg einmal von der Kamera, aber es hat seine Kompromisse.
Die einfachste gängige Lösung besteht darin, das Objekt in einem Durchgang zweimal zu rendern:
- Sie verwenden einen Vertex-Shader, um die Normalen des Objekts umzukehren und um die Größe des Umrisses zu "sprengen", und einen Fragment-Shader, um es in der Umrissfarbe zu rendern
- Über diesem Umriss rendern Sie das Objekt normal. Die Z-Reihenfolge ist in der Regel mehr oder weniger automatisch richtig, da der Umriss durch die Gesichter auf der "Rückseite" des Objekts erstellt wird, während die Figur selbst aus Gesichtern besteht, die der Kamera zugewandt sind.
Dies ist einfach genug zu erstellen und zu implementieren und vermeidet Tricks beim Rendern von Texturen, weist jedoch einige auffällige Nachteile auf:
- Die Umrissgröße variiert, wenn Sie sie nicht anhand des Abstands von der Kamera skalieren. Weiter entfernte Objekte haben einen kleineren Umriss als die in der Nähe befindlichen. Dies könnte natürlich das sein, was Sie tatsächlich wollen .
- Der Vertex-Shader "Aufblasen" funktioniert bei komplexen Objekten wie dem in Ihrem Beispiel gezeigten Skelett nicht besonders gut, da Z-Fighting-Artefakte problemlos in das Rendering eingefügt werden können. Wenn Sie das Problem beheben möchten, müssen Sie das Objekt in zwei Durchgängen rendern, können jedoch die Normalen nicht umkehren.
- Der Umriss und das Objekt funktionieren möglicherweise nicht sehr gut, wenn andere Objekte denselben Raum belegen und es im Allgemeinen schwierig ist, in Kombination mit Reflexions- und Brechungsshadern die richtigen Ergebnisse zu erzielen.
Die Grundidee für einen solchen Shader sieht wie folgt aus (Cg, for Unity - der Code ist ein leicht modifizierter Toon-Shader, den ich irgendwo gefunden habe und der die Quelle nicht notiert hat. zu verwendender Shader):
Shader "Basic Outline" {
Properties {
_Color ("Main Color", Color) = (.5,.5,.5,1)
_OutlineColor ("Outline Color", Color) = (1,0.5,0,1)
_Outline ("Outline width", Range (0.0, 0.1)) = .05
_MainTex ("Base (RGB)", 2D) = "white" { }
}
SubShader {
Tags { "RenderType"="Opaque" }
Pass {
Name "OUTLINE"
Tags { "LightMode" = "Always" }
CGPROGRAM
#pragma exclude_renderers gles
#pragma exclude_renderers xbox360
#pragma vertex vert
struct appdata {
float4 vertex;
float3 normal;
};
struct v2f
{
float4 pos : POSITION;
float4 color : COLOR;
float fog : FOGC;
};
float _Outline;
float4 _OutlineColor;
v2f vert(appdata v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
float3 norm = mul ((float3x3)UNITY_MATRIX_MV, v.normal);
norm.x *= UNITY_MATRIX_P[0][0];
norm.y *= UNITY_MATRIX_P[1][1];
o.pos.xy += norm.xy * _Outline;
o.fog = o.pos.z;
o.color = _OutlineColor;
return o;
}
ENDCG
Cull Front
ZWrite On
ColorMask RGB
Blend SrcAlpha OneMinusSrcAlpha
SetTexture [_MainTex] { combine primary }
}
Pass {
Name "BASE"
Tags {"LightMode" = "Always"}
CGPROGRAM
#pragma fragment frag
#pragma vertex vert
#pragma fragmentoption ARB_fog_exp2
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
struct v2f {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float3 viewDir : TEXCOORD1;
float3 normal : TEXCOORD2;
};
v2f vert (appdata_base v)
{
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
o.normal = v.normal;
o.uv = TRANSFORM_UV(0);
o.viewDir = ObjSpaceViewDir( v.vertex );
return o;
}
uniform float4 _Color;
uniform sampler2D _MainTex;
float4 frag (v2f i) : COLOR
{
half4 texcol = tex2D( _MainTex, i.uv );
half3 ambient = texcol.rgb * (UNITY_LIGHTMODEL_AMBIENT.rgb);
return float4( ambient, texcol.a * _Color.a );
}
ENDCG
}
}
FallBack "Diffuse"
}
Die andere gebräuchliche Methode rendert das Objekt ebenfalls zweimal, vermeidet jedoch den Vertex-Shader vollständig. Auf der anderen Seite ist dies nicht einfach in einem Durchgang möglich und erfordert das Rendern in eine Textur: Rendern Sie das Objekt einmal mit einem "flachen", konturfarbenen Fragment-Shader und verwenden Sie eine (gewichtete) Unschärfe für dieses Rendern Platz auf dem Bildschirm , und rendern Sie das Objekt wie gewohnt darüber.
Es gibt auch eine dritte und möglicherweise am einfachsten zu implementierende Methode, die jedoch die GPU ein wenig belastet und Ihre Künstler dazu bringt, Sie im Schlaf zu ermorden, es sei denn, Sie erleichtern ihnen das Generieren: Lassen Sie die Objekte die Gliederung als separate haben Masche die ganze Zeit, nur vollständig transparent oder an einen Ort verschoben, an dem sie nicht zu sehen ist (wie tief im Untergrund), bis Sie sie brauchen