Detailprops sind Models vom Typ prop_detail, welche in Verhältniss zu anderen Modeltypen sehr wenig Performance benötigen. Dies liegt vor allem daran, dass sie weder Schatten werfen, noch solide sind. Darum eignen sie sich auch so sehr für Gras, Sträucher und ähnliches: Schatten wären bei Gräsern sowieso nicht besonders sinnvoll, da sie eine extrem kleine Lightmap benötigen bzw. die Mapfile unnötig aufblähen würden. Dass Detailprops nicht solide sind ist für Gras auch von Vorteil: Würde man an jedem Grashalm hängen bleiben, wären Maps mit Detailprops schnell unspielbar.
Detailsprites benötigen noch weniger Performance (~ 1/10) als Detailprops, sind dafür aber nur zweidimensional. Auch sie sind weder solide noch werfen sie Schatten.
Detailprops und Detailsprites werden vom Compiler auf der Textur verteilt, allerdings nach selbstbestimmten „Regeln“, welche vorher festgelegt werden müssen.
Der Einfachkeit halber werde ich zuerst das Einsetzen von Detailprops erklären. Zu Detailsprites komme ich danach nochmals. Im Prinzip funktioniert es zwar gleich, aber ein paar kleine Unterschiede gibt es eben doch.
Damit klar ist, wie eine Textur mit Detailsprites/ -props später aussehen kann, hier ein Bild (aus HL2):
Dazu wird eine *.vbsp Datei benötigt, welche sich im Modverzeichniss befindet. Beispielsweiße also in
...\SteamApps\<Accountname>\half-life 2\hl2
oder in
...\SteamApps\<Accountname>\counter-strike source\cstrike
Einige Sourcegames besitzen bereits eine Datei detail.vbsp. Ihr könnt dann einfach diese verwenden, also unterhalb der bereits existierenden Einträge weiterschreiben (allerdings vor der letzten schließenden geschweiften Klammer, siehe unten).
Es ist aber in jedem Fall auch möglich, eine neue, andere *.vbsp Datei zu verwenden. Erstellt dazu einfach eine Textdatei und ändert ihre Endung in .vbsp. Falls ihr das tut, müsst ihr diese Datei im Hammer Editor unter Map ⇒ Map properties ⇒ detail.vbsp file relativ zum Modordner angeben.
Liegt eure *.vbsp Datei also zum Beispiel im selbst erstellten Verzeichniss <mod>\detailfiles und heißt eigene_details.vbsp müsst ihr unter Map ⇒ Map properties ⇒ detail.vbsp file folgendes angeben: detailfiles/eigene_details.vbsp.
Der Einfachkeit halber würde ich euch aber raten, die Datei direkt ins Modverzeichniss zu legen, da ihr dann nur dateiname.vbsp angeben müsst.
Da die Detailprops schon während dem Compilen gesetzt werden, ist es nicht nötig, die *.vbsp Datei beim Veröffentlichen der Map mit zu liefern.
Es gibt ein paar allgemeingültige Regeln zur Syntax in *.vbsp Dateien.
⇒ Alle Eigenschaften und Werte stehen in eigenen Anführungszeichen und sind durch ein Leerzeichen getrennt. Also:
"Eigenschaft" "Wert"
zum Beispiel:
"alpha" "1.0"
⇒ Zudem gibt es verschiedene Befehle, welche nicht in Anführungszeichen stehen (detail, alle Zusammenstellungsnamen, Group[Nummer] und Model[Nummer]) und welche die *.vbsp Datei in Blöcke einteilen. Diese Blöcke werden durch geschweifte Klammern markiert.
Zum Beispiel:
detai
{
//Blockinhalt
}
⇒ In jedem Fall steht der gesamte Inhalt der *.vbsp Datei innerhalb des Blocks, welcher von detail erzeugt wird. Die Datei beginnt also mit detail { und endet mit der zugehörigen geschweiften Klammer }.
Mit "normaler Textur" ist hier eine Textur gemeint, die keine Blendtextur ist. Ich beginne mit "normalen" Texturen, da das erstellen der *.vbsp Datei für solche am einfachsten ist. Allerdings lassen sich einige Angaben an "normalen" Texturen nicht erklären. Zu diesen lest bitte den Abschnitt über *.vbsp Dateien für Blendtexturen.
Also los. Wie oben schon gesagt beginnt die Datei mit
detail
{
}
Darin wird nun ein Name für die nachfolgende Zusammenstellung von Detailprops festgelegt, über welchen diese später aufgerufen und mit einer Textur verknüpft werden kann. Dieser Zusammenstellungsname kann frei festgelegt werden, darf allerdings nur die auch in Mapnamen erlaubten Zeichen enthalten. Auch dieser Zusammenstellungsname erzeugt einen Block, innerhalb dessem die Eigenschaften der Zusammenstellung, definiert werden.
detail
{
details_normale_textur
{
}
}
Als Erstes muss die Dichte der Detailprops mit Hilfe der Eigenschaft density festgelegt werden. Je höher der Wert ist, desto mehr Detailprops werden gesetzt. Bei einem Wert von 100 und einer Fläche, die 512 x 512 Units groß ist, werden 26 Detailprops gesetzt. Wird der Wert verdoppelt, werden doppelt so viele Detailprops gesetzt usw., werden die Seitenlängen Fläche verdoppelt, werden viermal so viele Detailprops gesetzt usw. Welcher Wert angemessen ist, hängt ganz von der Größe der Detailprops und dem Anwendungsgebiet ab.
Mit der Eigenschaft density samt Wert sieht die *.vbsp Datei inzwischen also so aus:
detail
{
details_normale_textur
{
"density" "220"
}
}
Als nächstes wird mit Group1 die Gruppe 1 erzeugt. Jede Gruppe kommt bei einem anderen Alphawert der Textur zum Einsatz. Da "normale" Texturen aber prinzipiell einen Alphawert von 0 haben, werden Gruppen und der Alphawert erst im Abschnitt über Blendtexturen erklärt (Texturen mit Alphachannel haben zwar auch einen Alphawert, für Detailprops ist aber nur der per Paint Alpha im Displacement Tool erzeugte Wert relevant).
Da auch Group[Nummer] einen Block erzeugt, sieht die *.vbsp Datei inzwischen also wie folgt aus:
detail
{
details_normale_textur
{
"density" "220"
Group1
{
"alpha" "0.0"
}
}
}
Nun kommen die eigentlichen Detailprops an die Reihe. Sie werden jeweils in einem eigenen, durch Model[Nummer] Block, angegeben:
detail
{
details_normale_textur
{
"density" "220"
Group1
{
"alpha" "0.0"
Model1
{
"model" "models/props_foliage/cattails.mdl"
}
}
}
}
Auf die gleiche Art lassen sich noch weitere Models hinzufügen:
detail
{
details_normale_textur
{
"density" "200"
Group1
{
"alpha" "0.0"
Model1
{
"model" "models/props_foliage/cattails.mdl"
}
Model2
{
"model" "models/props_foliage/bramble001a.mdl"
}
}
}
}
Allerdings sind die Angaben zu den Models so noch nicht vollständig. Um der Engine mit zu teilen, von welchem Detailprop wie viele gesetzt werden sollen, gibt es die Eigenschft amount. Teilt man dem Model 1 nun einen amount-Wert von 0.7 zu, sind 70% der Detailprops vom Typ des Models 1, wenn man Model 2 einen amount-Wert von 0.3, also 30% zuweißt. Dies ist aber nicht zwingend notwendig. Gibt die Summe der amount-Werte mehr oder weniger als 1.0, so werden insgesamt auch mehr bzw. weniger Detailprops gesetzt als unter density festgelegt.
Mit amount-Angaben sieht die *.vbsp Datei so aus:
detail
{
details_normale_textur
{
"density" "220"
Group1
{
"alpha" "0.0"
Model1
{
"model" "models/props_foliage/cattails.mdl"
"amount" "0.7"
}
Model2
{
"model" "models/props_foliage/bramble001a.mdl"
"amount" "0.3"
}
}
}
}
Für eine "normale" Textur wars das schon. Unterhalb der schließenden geschweiften Klammer des Zusammenstellungsnamens können in der Datei noch beliebig viele andere Zusammenstellungen definiert werden. Diese müssen sich aber alle noch innerhalb des von detail erzeugten Blockes- also vor der letzten schließenden geschweiften Klammer- befinden.
Im Prinzip sieht die *.vbsp Datei für Blendtexturen genauso aus wie bei "normalen" Texturen. Einziger Unterschied ist, dass bei Blendtexturen der Wert von alpha variabel ist und also mehrere Gruppen verwendet werden können.
Wie sicher bekannt ist, kann man bei Blendtexturen mit Hilfe von Paint Alpha verschiedenen Stellen einer Textur verschiedene Alphawerte zuweißen, so dass etwa an einer Stelle nur die "obere" Textur zu sehen ist (Alphablendingwert 0), an einer anderen Stelle nur die "untere" Textur zu sehen ist (Alphablendingwert 255) und an einigen Stellen eine Mischung aus beiden. Jedem Zustand bzw. Alphablendingwert kann in der *.vbsp Datei eine andere Gruppe innerhalb der für dieses Material gültigen Zusammenstellung zugewießen werden- nämlich mit der Eigenschaft alpha.
Hat eine Gruppe den Wert 0.0 bei alpha, so werden die in ihr definierten Detailprops auf Stellen des Materials platziert, welche einen Alphablendingwert von 0 haben. Eine Gruppe, bei der alpha den Wert 1.0 hat, wird auf Stellen des Materials angewandt, welche einen Alphablendingwert von 255 haben.
Dabei ist zu beachten, dass beim Alphablending Werte von 0 bis 255 (und nicht bis 100) verwendet werden, während der Wert von alpha relativ dazu arbeitet. Ein Wert von 0.5 bei alpha gehört also nicht zu einem Alphablendingwert von 50 sondern zu 128 (255 / 2, gerundet).
Gibt es zu einem Alphablendingwert keine Gruppe mit einem entsprechenden Wert bei alpha, so wird eine Gruppe mit einem nahe liegenden Wert verwendet. Darum müssen, selbst wenn nur zwischen zwei Alphablendingwerten unterschieden werden und einer von den beiden Fällen völlig ohne Detailprops sein soll, zwei Gruppen definiert werden: eine, mit dem Wert bei alpha, bei dessen zugehörigem Alphablendingwert Detailprops angezeigt werden sollen inklusive den Detailprops, und eine zweite Gruppe, die nur alpha mit dem Wert enthält, bei dem keine Detailprops angezeigt werden sollen. Würde nur eine Gruppe existieren, so würde diese in jedem Fall benutzt, da sie unausweichlich die mit dem naheliegendsten Wert von alpha ist. Die zweite, leere Gruppe dient also nur dazu, der Engine eine "Ausweichmöglichkeit" zu geben.
Genug der reinen Theorie, hier ein Beipspiel, wie eine *.vbsp Datei für Blendtexturen aussehen kann:
details
{
tutorial_blendtextur
{
"density" "75"
Group1
{
"alpha" "0.0"
Model1
{
"model" "models/props_foliage/cattails.mdl"
"amount" "0.5"
}
Model2
{
"model" "models/props_foliage/bramble001a.mdl"
"amount" "0.5"
}
}
Group2
{
"alpha" "0.5"
Model1
{
"model" "models/props_foliage/cattails.mdl"
"amount" "0.4"
}
}
Group3
{
"alpha" "0.0"
}
}
}
Im Prinzip werden Detailsprites genauso verwendet wie Detailprops. Nur muss in der *.vbsp Datei anstatt eines Models ein Sprite angegeben werden sowie noch ein paar weitere Angaben.
Bei Detailsprites handelt es sich um Aussschnitte aus der Datei detailsprites.vtf. An welcher Stelle in der detailsprites.vtf sich die Sprites befinden, ist eine der Angaben, die für Sprites benötigt werden.
Wo sich diese detailsprites.vtf befindet, ist von Sourcegame zu Sourcegame unterschiedlich. Je nachdem liegt sie in der entsprechenden *.gcf und dort im Verzeichniss <modname>\materials\detail. Da sich die detailsprites.vtf Dateien der verschiedenen Sourcegames unterscheiden, können die unten stehenden Beispiele für Detailsprites so nicht in jedem Sourcegame angewandt werden.
Es ist auch möglich, eigene *.vtf Dateien als Ausgangsbasis für Detailsprites zu verwenden. In manchen Sourcegames ist es dabei egal, in welchem Unterverzeichniss des materials Ordners sich diese Datei befindet (z.B. bei CS:S). Bei anderen Sourcegames (z.B. HL2) muss sich diese Datei aber im Verzeichniss materials\detail befinden. Mit diesem Verzeichniss befindet man sich prinzipiell auf der sicheren Seite. Liegt die *.vtf Datei für die Detailsprites allerdings nicht dort, ist es nötig, sie unter Map ⇒ Map properties ⇒ Detail material file relativ zum materials Ordner an zu geben.
In jedem Fall muss eine eigene *.vtf Datei für Detailsprites mit der Map mitgeliefert werden, wenn diese an Dritte weitergegeben wird. Da es gut möglich ist, dass mehrere Mapper eine eigene detailsprites.vtf in den detail Ordner legen, ist es ratsam, diese in die *.bsp ein zu binden, damit sie keinesfalls überschrieben wird.
Nun ein Beispiel, wie Detailsprites in der *.vbsp Datei angegeben werden müssen:
...
Model1
{
"sprite" "518 0 238 245 1024"
"spritesize" "0.5 0.0 30 50"
"spriterandomscale" "0.2"
"detailOrientation" "2"
"amount" "0.8"
}
...
Die ersten beiden Zahlen der sprite-Zeile bestimmen die Position der linken oberen Ecke des Detaisprites in der *.vtf. Die erste der beiden Zahlen gibt dabei an, wie weit die linke obere Ecke des Detailsprites von der linken Seite der *.vtf entfernt ist und die zweite, wie weit sie von oben entfernt ist.
Dies lässt sich am leichtesten ermitteln, indem man alle Kanäle bis auf den Alphakanal ausblendet, die Datei als *.jpg speichert und anschließend in Paint öffnet. Bei der detailsprites.vtf von CS:S, welche ich hier verwende, da sie umfangreicher als die detailsprites.vtf von HL2 ist, sieht das dann so aus:
Unten rechts wird die aktuelle Position der Maus angezeigt.
Die dritte und vierte Zahl in der Spalte geben die Breite und Höhe des Sprites an, welche sich auf die gleiche Art wie die linke obere Ecke ermitteln lassen.
Der letzte Wert gibt die Seitenlänge der (quadratischen) detailsprites.vtf an.
In der spritesize-Zeile werden zwei verschiedene Dinge bestimmt:
Die ersten beiden Zahlen bestimmen den Drehpunkt des Sprites. Dabei definiert der erste Wert, wo der Drehpunkt in der Horizontalen liegt. 0 bedeutet dabei ganz rechts, 1 ganz links. Der zweite Wert bestimmt den Drehpunkt in der Vertikalen. Dabei steht 0 für unten, 1 für oben. Die Angabe 0.5 0.0 im Beispiel bedeutet also, dass sich der Drehpunkt in der Mitte unten befindet.
Die letzten beiden Zahlen der spritesize-Zeile geben die Größe des Sprites Ingame in Pixeln an, welche frei festgelegt werden kann.
Der Wert von spriterandomscale bestimmt, um wieviel Prozent die Größe der Sprites zufällig variiert. 0.0 bedeutet um 0%, 0.3 bedeutet um 30% usw.
Die Zeile detailOrientation bestimmt, ob bzw. wie sich die Detailsprites nach dem Spieler ausrichten. 0 bedeutet, dass sie sich überhaupt nicht drehen, 1, dass sie sich um alle Achsen drehen, um immer zum Spieler ausgerichtet zu sein (was in vielen Fällen nicht sinnvoll ist) und 2 bedeutet, dass die Sprites sich nur um die vertikale Achse drehen.
Bei Detail Shapes handelt es sich um eine Sonderform von Detailsprites. Sie bieten die Möglichkeit, Detailsprites nach zwei bestimmten Formen aus zu richten, sowie Detailsprites schwanken zu lassen. Bei diesen Formen handelt es sich um ein Dreieck und ein Kreuz.
Leider sind Detail Shapes in HL2 und HL2:DM nicht möglich. Laut developer.valvesoftware.com funktionieren sie sogar nur in CS:S und DoD:S.
Ausgangspunkt für Detail Shapes sind normale Detailsprites. Diese müssen nur um ein paar Zeilen ergänzt werden. Hier ein Beispiel für die Anordnung im Dreieck:
...
Model1
{
"sprite" "518 0 238 245 1024"
"spritesize" "0.5 0.0 30 50"
"spriterandomscale" "0.2"
"amount" "0.8"
"sprite_shape" "tri"
"shape_angle" "15"
"shape_size" "0.3"
}
...
Die Zeile detailOrientation wird unnötig, dafür kommen die untersten drei Zeilen neu dazu. Mit "sprite_shape" "tri" wird die dreieckige Anordnug bestimmt.
„shape_angle“ „15" macht, dass die Sprites nicht senkrecht stehen, sondern sich im Winkel von 15° vom Mittelpunkt des Dreiecks wegbeugen.
„shape_size“ „0.3“ bestimmt, wie weit die drei Sprites auseinander stehen.
Das oben angegebene Beispiel für ein Detail Shape mit tri sieht Ingame so aus:
Die kreuzförmige Anordnung ist noch leichter zu erzeugen. Dort sind die Angaben shape_angle und shape_size unnötig. Einzig "sprite_shape" "cross" wird benötigt.
Um Sprites schwanken zu lassen, wird die Angabe sway benötigt. Sie kann jedem Detailsprite angefügt werden, allerdings leider keinen Detailprops. Der Wert von sway muss zwischen 0 und 1 liegen. Er bestimmt den Prozentsatz des Konsolenbefehls cl_detail_max_sway. Standard ist dort ein Wert von 5, welcher aber bei bedarf natürlich per point_servercommand verändert werden kann.
Wird nur sway, aber nicht sprite_shape benutzt, dann funktioniert auch detailOrientation.
Nun noch ein Beispiel für ein Detail Shape mit cross, welches durch die Angabe sway schwankt (und zwar 30% so stark, wie durch cl_detail_max_sway vorgegeben wird):
...
Model1
{
"sprite" "518 0 238 245 1024"
"spritesize" "0.5 0.0 30 50"
"spriterandomscale" "0.2"
"amount" "1.0"
"sprite_shape" "cross"
"sway" "0.3"
}
...
Damit sich die in der *.vbsp Datei zusammengestellten Detailprops und -sprites auch auf eine Textur auswirken, muss in ihrer *.vmt auf einen Zusammenstellungsnamen aus der *.vbsp Datei verwießen werden. Dazu muss der *.vmt einfach folgende Zeile hinzugefügt werden:
"%detailtype" "[Gruppenname aus der *.vbsp Datei]"
Also zum Beispiel:
"%detailtype" "tutorial_normale_textur"
Das wars auch schon. Im Archiv befinden sich auch noch Beispieldateien. Ich hoffe, ihr habt euch beim Lesen nicht allzu sehr gelangweilt und alles verstanden.
Viel Erfolg mit dem „neuen Wissen“,
El Supremo
Dieses Tutorial als Offlineversion sowie die bereits erwähnten Beispieldaten gibt es zum Download:
tutorial_detailprops_und_detailsprites.zip (~1,3 MB)