Wormbo
11.08.2011, 22:19
Machen wir uns nichts vor, die Unreal Engine 3 hängt die Unreal Engine 2 in Sachen Grafik deutlich ab. Trotzdem kann man sich dem UE3-Look zumindest annähern, indem man die Möglichkeiten der Unreal Engine 2 gründlich ausschöpft.
Zunächst eine sehr kurze Einführung in die UE3-Materials. Es gibt zwei Arten von Materials, die man auf BSP und StaticMeshes verwenden kann, Materials und Material Instances, wobei letztere nochmal in Material Instance Constant (kurz: MIC) und Material Instance Time Varying unterteilt werden. Von den variablen Material Instances wird nur selten Gebrauch gemacht, daher lasse ich sie mal unter den Tisch fallen. So richtig kann man sie in der Unreal Engine 2 eh nicht umsetzen, zumindest nicht ohne teilweise auf UnrealScript zurückzugreifen.
Material Instances kann man sich so vorstellen: In Materials kann man bestimmte Aspekte parametrierbar machen. Diese Parameter haben im Material voreingestellte Standardwerte, aber eine Material Instances kann davon abweichende Werte angeben, um dem Material einen anderen Look zu geben. Ein einfaches Beispiel sind Teamfarben auf CTF-Maps. Für rote und blaue Versionen eines Materials wird ein gemeinsames "Eltern"-Material erstellt, das einen Farbparameter definiert. Von diesem Material werden dann einfach zwei MICs abgeleitet, die als Farbparameter Werte für rot bzw. blau angeben. In einer farbenfrohen DM-Map könnte man von diesem Material auch einfach weitere MICs ableiten und andere Farben angeben.
Im Generic Browser sind Materials und MICs an der Rahmenfarbe unterscheidbar:
1381
Hier sind ein Material (hellgrüner Rahmen) und drei Material Instance Constants (dunkelgrüner Rahmen) aufgelistet.
Öffnet man nun den Editor für eine der MICs, so ist das ganze relativ unspektakulär:
1382
Es gibt eine Vorschau, eine Liste der verfügbaren Parameter, sowie die Info, von welchem Material die MIC abgeleitet ist. Dieses Eltern-Material kann man auch ändern und man kann MICs auch von anderen MICs ableiten. Die Checkboxen vor den einzelnen Parametern geben an, welche man eigentlich ändern will. Man kann auch den Standardwert übernehmen. Damit wird auch klar, warum man MICs von MICs ableiten kann - in übergeordneten MICs kann man Voreinstellungen grob unterteilen und in abgeleiteten dann präzisieren. Man könnte z.B. ein glänzendes Material definieren, als erste Ableitung die Teamfarbe vorgeben und in der zweiten Stufe den Glanz an die jeweilige Umgebung anpassen. (Oder umgekehrt, je nach dem was mehr Sinn ergibt.)
Dir Funktion von MICs kann man in der UE2 nicht wirklich nachbilden, man wird dafür immer einen Teil der Shaderkonstruktion duplizieren müssen.
Aber werfen wir doch erst einmal einen Blick auf die Materials:
1383
Oha, und das ist noch ein relativ einfaches Material! Nicht gleich Panik schieben, die Hälfte davon brauchen wir nicht. So gibt's z.B. keine Normalmaps in der UE2. Letzten Endes interessiert uns nur der mittlere Teil:
1384
In der Unreal Engine 2 können wir die Kanäle Diffuse (Farbe), Emissive (Licht), Specular (Reflexion/Glanz) und Opacity (Transparenz) halbwegs nachbilden, also richten wir unser Augenmerk darauf. Natürlich hat auch die Normalmap einen gewaltigen Einfluss auf den Look, aber das lässt sich einfach nicht ordentlich emulieren.
Wir haben also eine Texture Sample (also eine Textur), die quasi direkt auf den Diffuse-Kanal geht. Aus dem Alpha-Kanal (weißer Output-Knubbel :)) und einem Farbparameter wird der Emissive-Kanal generiert. Hier wird z.B. eine leuchtende Teamfarbe für das Fenster erzeugt. Ein zweites Texture Sample wird für den Specular-Kanal verwendet. Die gleiche Textur geht, nach Multiplikation mit einer Konstanten, noch in den "Specular Power"-Kanal. Der gibt an, wie stark der Glanz sein soll. Den Kanal gibt es indirekt auch in der UE2, nämlich in Form der SpecularityMask eines Shaders.
Also gut, jetzt brauchen wir erst einmal die Texturen, die in dem Material verwendet werden. Die bekommt man z.B. mit UModel direkt aus den .upk-Dateien oder man kann sie auch mit verschiedenen Programmen direkt aus dem Speicher ziehen, wenn UT3 läuft und man eine Map mit dem gewünschten Material geladen ist. Ich setze ienfach mal voraus, dass ihr euch den Umgang mit diesen Tools selbst aneignen könnt.
Wenn wir die Texturen haben, können wir sie schon mal in UnrealEd in ein neues Package oder myLevel importieren. Da wir ein komplexeres Material nachbilden wollen, werden wir wohl auch einen Shader brauchen, denn der kann Diffuse, Opacity, Specular und SelfIllumination (entspricht ungefähr Emissive) zusammenführen. Also im Texture-Browser-Menü File->New, dann MaterialClass=Shader und Name/Group/Package nach eurem Geschmack einstellen.
So, fangen wir mit dem Einfachsten an. Wir hatten ja festgestellt, dass der diffuse-Kanal praktisch direkt aus einem Texture Sample gespeist wird. Also verwenden wir diese Textur direkt als Diffuse in unserem Shader.
Das nächste ist der Emissive-Kanal. Hier werden die Farben der Textur mit ihrem eigenen Alphakanal und einem Farbparameter multipliziert. Multiplizieren kann die Unreal Engine 2 auch, und zwar mit dem Combiner. Es ist zwar nicht ohne weiteres möglich, die Farben einer Textur direkt mit ihrem eigenen Alphakanal (oder dem einer anderen Textur) zu multiplizieren, aber das brauchen wir auch nicht. Der SelfIlumination-kanal funktioniert nämlich etwas anders als der Emissive-Kanal. Emissive addiert eher drauf, während SelfIllumination erstmal den Diffuse-Kanal überdeckt. Um ein ähnliches Verhalten zu erzeugen, werden wir in unserem Beispiel nicht mit dem Alphakanal multiplizieren, sondern ihn in die SelfIlluminationMask geben.
Ein Combiner kann eigentlich zwei Sachen gleichzeitig erledigen, nämlich die RGB-Kanäle zweier Texturen kombinieren und die Alpha-Kanäle dieser Texturen auf andere Art kombinieren. Wir haben hier zwei Multiplikationen, also macht der Combiner für RGB- und Alpha-Kanäle das gleiche, nämlich CO_Multiply bzw. AO_Multiply. Als Ausgangsmaterials verwenden wir die Diffuse-Textur und eine ConstantColor, die die Rolle des Farbparameters übernimmt. Den fertigen Combiner verwenden wir dann sowohl für SelfIllumination als auch SelfIlluminationMask im Shader. Die Mask verwendet nur die Alpha-Informationen, während SelfIllumination nur die RGB-Infos nimmt.
Ein Wort noch zu Farbwerten in der UE3 und der UE2: Die UE3 verwendet Gleitkommazahlen im Bereich von 0 bis 1 für normale Farben und Werte größer als 1 für Farben, die ihre Umgebung überstrahlen. Selbst negative Werte sind möglich, ergeben in der Anzeige aber schwarz. Für einige Operationen sind sie dennoch interessant, z.B. um Texturkoordinaten zu manipulieren und somit das Material zu verschieben oder verzerren. Die UE2 verwendet dagegen ganzzahlige Werte von 0 bis 255. Für Combiner-Multiplikationen werden 0-255 aber wie 0-1 behandelt, 255*255 ergibt also 255, während 127*127 wie 0.5*0.5 gerechnet wird und damit 63 ergibt. Die Werte lassen sich nicht direkt ineinander umwandeln, da auch Werte > 1.0 in der UE3 durchaus eine Farbe ergeben. Die beste Strategie ist hier, sich an die Zahlenverhältnisse zu halten und einfach zu probieren.
Der Farbparameter in unserem Beispiel ist z.B. (2,1,0.4,1), also quasi R=512,G=255,B=102,A=255 - allerdings ist der Wert 512 für rot nicht möglich. Skaliert man die Werte entsprechend, so erhält man R=255,G=127,B=51,A=255 als möglichen Farbwert. Wichtig bei der Farbkonvertierung ist aber nicht das Jonglieren mit Zahlen, sondern das Endergebnis.
Ein Kanal unseres Shaders fehlt noch, und zwar Specular. Diese Textur kann man prinzipiell auch wieder direkt im Specular-Kanal des Shaders verwenden, aber auch hier impliziert die UE3 dein Alpha-Kanal, während die UE2 einfach alles verwendet. Um das Problem zu beheben, muss die gleiche Textur einfach auch als SpecularityMask verwendet werden. Das war's eigentlich schon.
Zunächst eine sehr kurze Einführung in die UE3-Materials. Es gibt zwei Arten von Materials, die man auf BSP und StaticMeshes verwenden kann, Materials und Material Instances, wobei letztere nochmal in Material Instance Constant (kurz: MIC) und Material Instance Time Varying unterteilt werden. Von den variablen Material Instances wird nur selten Gebrauch gemacht, daher lasse ich sie mal unter den Tisch fallen. So richtig kann man sie in der Unreal Engine 2 eh nicht umsetzen, zumindest nicht ohne teilweise auf UnrealScript zurückzugreifen.
Material Instances kann man sich so vorstellen: In Materials kann man bestimmte Aspekte parametrierbar machen. Diese Parameter haben im Material voreingestellte Standardwerte, aber eine Material Instances kann davon abweichende Werte angeben, um dem Material einen anderen Look zu geben. Ein einfaches Beispiel sind Teamfarben auf CTF-Maps. Für rote und blaue Versionen eines Materials wird ein gemeinsames "Eltern"-Material erstellt, das einen Farbparameter definiert. Von diesem Material werden dann einfach zwei MICs abgeleitet, die als Farbparameter Werte für rot bzw. blau angeben. In einer farbenfrohen DM-Map könnte man von diesem Material auch einfach weitere MICs ableiten und andere Farben angeben.
Im Generic Browser sind Materials und MICs an der Rahmenfarbe unterscheidbar:
1381
Hier sind ein Material (hellgrüner Rahmen) und drei Material Instance Constants (dunkelgrüner Rahmen) aufgelistet.
Öffnet man nun den Editor für eine der MICs, so ist das ganze relativ unspektakulär:
1382
Es gibt eine Vorschau, eine Liste der verfügbaren Parameter, sowie die Info, von welchem Material die MIC abgeleitet ist. Dieses Eltern-Material kann man auch ändern und man kann MICs auch von anderen MICs ableiten. Die Checkboxen vor den einzelnen Parametern geben an, welche man eigentlich ändern will. Man kann auch den Standardwert übernehmen. Damit wird auch klar, warum man MICs von MICs ableiten kann - in übergeordneten MICs kann man Voreinstellungen grob unterteilen und in abgeleiteten dann präzisieren. Man könnte z.B. ein glänzendes Material definieren, als erste Ableitung die Teamfarbe vorgeben und in der zweiten Stufe den Glanz an die jeweilige Umgebung anpassen. (Oder umgekehrt, je nach dem was mehr Sinn ergibt.)
Dir Funktion von MICs kann man in der UE2 nicht wirklich nachbilden, man wird dafür immer einen Teil der Shaderkonstruktion duplizieren müssen.
Aber werfen wir doch erst einmal einen Blick auf die Materials:
1383
Oha, und das ist noch ein relativ einfaches Material! Nicht gleich Panik schieben, die Hälfte davon brauchen wir nicht. So gibt's z.B. keine Normalmaps in der UE2. Letzten Endes interessiert uns nur der mittlere Teil:
1384
In der Unreal Engine 2 können wir die Kanäle Diffuse (Farbe), Emissive (Licht), Specular (Reflexion/Glanz) und Opacity (Transparenz) halbwegs nachbilden, also richten wir unser Augenmerk darauf. Natürlich hat auch die Normalmap einen gewaltigen Einfluss auf den Look, aber das lässt sich einfach nicht ordentlich emulieren.
Wir haben also eine Texture Sample (also eine Textur), die quasi direkt auf den Diffuse-Kanal geht. Aus dem Alpha-Kanal (weißer Output-Knubbel :)) und einem Farbparameter wird der Emissive-Kanal generiert. Hier wird z.B. eine leuchtende Teamfarbe für das Fenster erzeugt. Ein zweites Texture Sample wird für den Specular-Kanal verwendet. Die gleiche Textur geht, nach Multiplikation mit einer Konstanten, noch in den "Specular Power"-Kanal. Der gibt an, wie stark der Glanz sein soll. Den Kanal gibt es indirekt auch in der UE2, nämlich in Form der SpecularityMask eines Shaders.
Also gut, jetzt brauchen wir erst einmal die Texturen, die in dem Material verwendet werden. Die bekommt man z.B. mit UModel direkt aus den .upk-Dateien oder man kann sie auch mit verschiedenen Programmen direkt aus dem Speicher ziehen, wenn UT3 läuft und man eine Map mit dem gewünschten Material geladen ist. Ich setze ienfach mal voraus, dass ihr euch den Umgang mit diesen Tools selbst aneignen könnt.
Wenn wir die Texturen haben, können wir sie schon mal in UnrealEd in ein neues Package oder myLevel importieren. Da wir ein komplexeres Material nachbilden wollen, werden wir wohl auch einen Shader brauchen, denn der kann Diffuse, Opacity, Specular und SelfIllumination (entspricht ungefähr Emissive) zusammenführen. Also im Texture-Browser-Menü File->New, dann MaterialClass=Shader und Name/Group/Package nach eurem Geschmack einstellen.
So, fangen wir mit dem Einfachsten an. Wir hatten ja festgestellt, dass der diffuse-Kanal praktisch direkt aus einem Texture Sample gespeist wird. Also verwenden wir diese Textur direkt als Diffuse in unserem Shader.
Das nächste ist der Emissive-Kanal. Hier werden die Farben der Textur mit ihrem eigenen Alphakanal und einem Farbparameter multipliziert. Multiplizieren kann die Unreal Engine 2 auch, und zwar mit dem Combiner. Es ist zwar nicht ohne weiteres möglich, die Farben einer Textur direkt mit ihrem eigenen Alphakanal (oder dem einer anderen Textur) zu multiplizieren, aber das brauchen wir auch nicht. Der SelfIlumination-kanal funktioniert nämlich etwas anders als der Emissive-Kanal. Emissive addiert eher drauf, während SelfIllumination erstmal den Diffuse-Kanal überdeckt. Um ein ähnliches Verhalten zu erzeugen, werden wir in unserem Beispiel nicht mit dem Alphakanal multiplizieren, sondern ihn in die SelfIlluminationMask geben.
Ein Combiner kann eigentlich zwei Sachen gleichzeitig erledigen, nämlich die RGB-Kanäle zweier Texturen kombinieren und die Alpha-Kanäle dieser Texturen auf andere Art kombinieren. Wir haben hier zwei Multiplikationen, also macht der Combiner für RGB- und Alpha-Kanäle das gleiche, nämlich CO_Multiply bzw. AO_Multiply. Als Ausgangsmaterials verwenden wir die Diffuse-Textur und eine ConstantColor, die die Rolle des Farbparameters übernimmt. Den fertigen Combiner verwenden wir dann sowohl für SelfIllumination als auch SelfIlluminationMask im Shader. Die Mask verwendet nur die Alpha-Informationen, während SelfIllumination nur die RGB-Infos nimmt.
Ein Wort noch zu Farbwerten in der UE3 und der UE2: Die UE3 verwendet Gleitkommazahlen im Bereich von 0 bis 1 für normale Farben und Werte größer als 1 für Farben, die ihre Umgebung überstrahlen. Selbst negative Werte sind möglich, ergeben in der Anzeige aber schwarz. Für einige Operationen sind sie dennoch interessant, z.B. um Texturkoordinaten zu manipulieren und somit das Material zu verschieben oder verzerren. Die UE2 verwendet dagegen ganzzahlige Werte von 0 bis 255. Für Combiner-Multiplikationen werden 0-255 aber wie 0-1 behandelt, 255*255 ergibt also 255, während 127*127 wie 0.5*0.5 gerechnet wird und damit 63 ergibt. Die Werte lassen sich nicht direkt ineinander umwandeln, da auch Werte > 1.0 in der UE3 durchaus eine Farbe ergeben. Die beste Strategie ist hier, sich an die Zahlenverhältnisse zu halten und einfach zu probieren.
Der Farbparameter in unserem Beispiel ist z.B. (2,1,0.4,1), also quasi R=512,G=255,B=102,A=255 - allerdings ist der Wert 512 für rot nicht möglich. Skaliert man die Werte entsprechend, so erhält man R=255,G=127,B=51,A=255 als möglichen Farbwert. Wichtig bei der Farbkonvertierung ist aber nicht das Jonglieren mit Zahlen, sondern das Endergebnis.
Ein Kanal unseres Shaders fehlt noch, und zwar Specular. Diese Textur kann man prinzipiell auch wieder direkt im Specular-Kanal des Shaders verwenden, aber auch hier impliziert die UE3 dein Alpha-Kanal, während die UE2 einfach alles verwendet. Um das Problem zu beheben, muss die gleiche Textur einfach auch als SpecularityMask verwendet werden. Das war's eigentlich schon.