Seite 1 von 1

Isohypsen-Shader

Verfasst: 09.06.2009, 16:38
von IH82W8
Hallo zusammen,

ich versuche derzeit, per Shader Höhenlinien in Terrains zu realisieren bzw. Bereiche oberhalb einer bestimmten Höhe farblich hervorzuheben.

Mein erster Ansatz war es, in einem VertexShader die Farbwerte ab einer bestimmten Position zu manipulieren:
Bild

Dies führt nur zu dem abgebildeten "Sägezahn" Effekt - wie kann man nun die Höheninformation auf Pixelbasis bestimmen und somit eine schärfere Kontur zeichnen bzw. gar Linien darauf realisieren?

Cheers!

Re: Isohypsen-Shader

Verfasst: 09.06.2009, 17:13
von eXile
Wie du an die Weltkoordinate eines Pixels kommst:

Wenn du nicht schon Deferred Shading benutzt, die z-Werte erstmal in einem Pass in eine Textur schreiben. Dann ein Fullscreen-Quad mit Texturkoordinaten von 0 bis 1 über den Bildschrim legen, und beim VS fürs Rendern dann mit diesen Texturkoordinaten die z-Textur samplen (=z), und x- und y-Koordinaten (=x,y) aus den Texturkoordinaten berechnen. Diesen Vektor (x,y,z,1) dann mit der inversen Projektionsmatrix multiplizieren, und noch durch die w-Koordinate teilen.

Ich glaube zwar, es gibt schnellere Ansätze, das müsste aber so funktionieren :oops:

Wenn du dann die Weltkoordinaten erst einmal hast, kannst du damit auch die Höhe bestimmen und deine schönen Höhenlinien zeichnen ;)

Re: Isohypsen-Shader

Verfasst: 09.06.2009, 17:20
von Schrompf
Nimm doch einfach die Höhe in Weltkoordinaten und reiche die in den PixelShader rein. Dort nimmst Du die dann, um aus einer 1D-Textur zu samplen. Fertig.

Re: Isohypsen-Shader

Verfasst: 09.06.2009, 17:22
von eXile
Schrompf hat geschrieben:Nimm doch einfach die Höhe in Weltkoordinaten und reiche die in den PixelShader rein. Dort nimmst Du die dann, um aus einer 1D-Textur zu samplen. Fertig.
-.- ... mir fallen anscheinend immer die umständlichsten Lösungen ein :oops: ;)

Re: Isohypsen-Shader

Verfasst: 09.06.2009, 17:33
von IH82W8
Hallo eXile, hallo Schrompf,

vielen Dank für die Antworten, wobei mir noch nicht ganz klar ist, wie ich aus der Höheninformation eines Vertex im PixelShader 1D-Texturen samplen kann? Wie würde denn eine solche 1D-Textur aussehen?

Viele Grüße,
IH82W8

Re: Isohypsen-Shader

Verfasst: 09.06.2009, 17:46
von Krishty
Hi,

n Pixel in der Breite und nur ein Pixel in der Höhe. Möchtest du in der Mitte deines Terrains eine Höhenlinie, setzt du einen Punkt in die Mitte der Textur. Im Vertex-Shader nimmst du dann die Höhe des Terrains, bringst sie durch Division durch die Maximalhöhe, die in der Textur verzeichnet ist, in den Bereich [0, 1] und benutzt das als X-Texturkoordinate.

Gruß, Ky

Re: Isohypsen-Shader

Verfasst: 09.06.2009, 17:51
von Aramis
Die Textur dient nur zur Beschleunigung des Ganzen, im Prinzip kannst du auch einfach mit if()'s arbeiten.

Code: Alles auswählen


struct vout {
   // [...]
   float height : TEXCOORD0;
};

[...]

vout vshader (vin in) {

   vout out =0;
   [....]
   out.height = mul(in.position,world).z;
}

float4 pshader (pin in) : COLOR {
   if (in.height >= quak) {
       ... Farbe 1
   }
   else if ( ... )
      .. weitere Farben
}
Solche if's sind aber ziemlich lahm. Ein Lookup in einer ungefilterten 1D-Textur beschleunigt das ganze - du verwendest einfach die Höhe als Texturkoordinate.

Code: Alles auswählen

float4 pshader (pin in) : COLOR {
  ...
  float4 col = tex1D(mytex,in.height)
}

Damit du die Textur nicht zu groß machen musst, einfach den Höhenwert noch skalieren - beträgt die Maximalhöhe 100, und hast du alle 10 Höheneinheiten eine andere Farbe, so bräuchtest du eine 1x10-Textur, Lookup mit floor((in.height/100)/10).
Und da war schon wieder jemand schneller als ich.

Re: Isohypsen-Shader

Verfasst: 09.06.2009, 17:54
von IH82W8
Clever, vielen Dank zusammen!

Re: Isohypsen-Shader

Verfasst: 10.06.2009, 14:25
von IH82W8
Hallo nochmal,

Euer Konzept der Färbung nach Höhenstufe im PS per 1D Textur funktioniert (nicht dass ich daran gezweifelt hätte ;)).

Nun möchte ich noch eine weitere Restriktion in das Färben mit einbeziehen, sprich: Es sollen nur jene Pixel eingefärbt werden, deren Weltposition sich in einem gewissen Höhenbereich befinden und einen variablen Radius um die Kameraposition unterschreiten.

Vllt. verdeutlicht diese Grafik die Idee:
Bild

Bisher ermittle ich (wieder im eingänglicheren Vertex Shader) die Entfernung Kamera - Vertex und liefere dann wie empfohlen entsprechende Höheneinstellungen an den PS.
Da diese Abgrenzung wieder auf Basis von Vertices erfolgt, ähnelt die Region eher einem Zahnrad denn einem hübschen Kreis um die Kameraposition. Habt ihr eine Idee, wie man dies schöner lösen kann?

Danke & Grüße,
IH82W8

Re: Isohypsen-Shader

Verfasst: 10.06.2009, 14:38
von Krishty
Verschieb die Berechnung in den Pixel-Shader – z.B., indem du die relative Position (Weltposition - Betrachterposition) in einem Texturregister übergibst.

Wenn der Wert auf per-Pixel-Basis berechnet wird, wird der Kreis (und damit auch das Geländefolgeradar) schön sauber.

Re: Isohypsen-Shader

Verfasst: 10.06.2009, 14:44
von IH82W8
Wird diese relative Position (Vertex - Kamera) dann auf die Pixelposition (in Richtung des folgenden Vertex) transformiert, wenn ich diese einfach in ein Texturregister stecke?

Re: Isohypsen-Shader

Verfasst: 10.06.2009, 14:49
von Schrompf
Ja. Du berechnest ja im Vertex die Relativposition (VPos - KameraPos). Wenn die Grafikkarte dann Deinen PixelShader laufen lässt, interpoliert sie vorher zwischen den ProVertex-Datensätzen den für den Pixel passenden ProPixel-Datensatz. Den bekommt dann Dein PixelShader als Eingabewerte. Eine Relativposition ist problemlos linear interpolierbar. Problematischer wird es erst, wenn Du die Entfernung im VertexShader ausrechnen und in den PixelShader reinreichen willst - die Entfernungsberechnung ist ja nichtlinear (weil quadratisch und wurzelisch), daher wird die nicht sauber interpoliert. Daher auch die Empfehlung, die Positionsdifferenz in den PixelShader runterzureichen und erst im PixelShader die Entfernung auszurechnen.

Re: Isohypsen-Shader

Verfasst: 10.06.2009, 14:55
von IH82W8
Danke, so langsam bekomme ich eine vage Vorstellung von der fundamentalen Funktionsweise der PS.

P.S.: Hat genauso funktioniert, wie gewünscht, endlich "hübsche" Übergänge...
Bild

Re: Isohypsen-Shader

Verfasst: 26.06.2009, 16:37
von IH82W8
Hallo,

eine (vorerst) letzte Frage zu dem Shader Thema bleibt... Wie auf obigen Screens zu sehen sind die Trennlinien auf obigen Screens noch sehr scharf - um diese aufzuweichen wurde ein distanzbasierter "Färbungsfaktor" eingeführt:

Bild

Kann es bei anderen Grafikkarten zu Problemen kommen, wenn die gesetzten Farbwerte (hier bspw. der Rotanteil) auf einen Wert > 1.0 gesetzt wird? Ich würde gerne die Normalisierung des Wertes einsparen, möchte aber sicher gehen, dass dies nicht zu Komplikationen führt.


Danke & Gruß!

Re: Isohypsen-Shader

Verfasst: 26.06.2009, 17:30
von Schrompf
IH82W8 hat geschrieben: Kann es bei anderen Grafikkarten zu Problemen kommen, wenn die gesetzten Farbwerte (hier bspw. der Rotanteil) auf einen Wert > 1.0 gesetzt wird? Ich würde gerne die Normalisierung des Wertes einsparen, möchte aber sicher gehen, dass dies nicht zu Komplikationen führt.
Nö, kein Problem. Wenn die Grafikkarte oder das Ziel-Rendertarget das nicht kann, wird die Grafikkarte automatisch clamp()en.

Re: Isohypsen-Shader

Verfasst: 26.06.2009, 17:44
von Krishty
Ist Clamping (oder präziser, Saturating) nicht sowieso kostenlos?

Re: Isohypsen-Shader

Verfasst: 27.06.2009, 09:46
von Richard Schubert
Ab Shader Model 2.0 oder 3.0 leider nicht mehr (weiß es nicht mehr genau). Das _sat Suffix für die ASM codierung wurde zu der Zeit abgeschaft.

Re: Isohypsen-Shader

Verfasst: 27.06.2009, 10:44
von Schrompf
Ich *glaube*, saturate ist immernoch kostenlos. Ich habe jetzt gerade nichts da, um das nachzuprüfen, aber wenn ich mich recht erinnere, hatte fxc selbst bei Target PS3_0 noch ASM-Anweisungen mit dem _sat -Postfix produziert. Du kannst ja mal fxc auf einen Deiner Shader loslassen, wenn Du magst. Kann aber auch sein, dass die Grakas intern noch den Saturate-Modifikator unterstützen und daher der Treiber die entsprechenden Codes im Shader findet und ersetzt. Ganz am Ende würde es wahrscheinlich nur was bringen, wenn man einen PixelShader mal mit einem Rudel saturates und mal ohne bildschirmfüllend anwendet und die Framerate misst.

Re: Isohypsen-Shader

Verfasst: 27.06.2009, 14:04
von Krishty
AMD GPU Shader Analyzer zeigt an, dass der interne Assembler-Code auf einer HD 4850 mit allen Shader-Models auf gleich viele Anweisungen hinausläuft – egal ob mit Saturation oder ohne.

Ich wollte noch andere (PS-3.0-)GPUs testen, da kam dann aber ein Absturz dazwischen :/

Edit: Also, die D3D-Assembly generiert auch bei PS 3.0, 4.0 und 4.1 noch mov_sat und mul_sat. Auf allen AMD-Karten von X800 über X1900 bis HD 4870 sind die Befehlszahlen mit und ohne Saturation gleich. Wäre schön, wenn das auch jemand für Nvidia-Karten prüfen könnte.