Isohypsen-Shader

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
IH82W8
Beiträge: 15
Registriert: 08.06.2009, 23:05

Isohypsen-Shader

Beitrag 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!
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: Isohypsen-Shader

Beitrag 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 ;)
Benutzeravatar
Schrompf
Moderator
Beiträge: 4854
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Isohypsen-Shader

Beitrag 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.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: Isohypsen-Shader

Beitrag 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: ;)
IH82W8
Beiträge: 15
Registriert: 08.06.2009, 23:05

Re: Isohypsen-Shader

Beitrag 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
Benutzeravatar
Krishty
Establishment
Beiträge: 8238
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Isohypsen-Shader

Beitrag 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
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Aramis
Moderator
Beiträge: 1458
Registriert: 25.02.2009, 19:50
Echter Name: Alexander Gessler
Wohnort: 2016
Kontaktdaten:

Re: Isohypsen-Shader

Beitrag 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.
IH82W8
Beiträge: 15
Registriert: 08.06.2009, 23:05

Re: Isohypsen-Shader

Beitrag von IH82W8 »

Clever, vielen Dank zusammen!
IH82W8
Beiträge: 15
Registriert: 08.06.2009, 23:05

Re: Isohypsen-Shader

Beitrag 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
Benutzeravatar
Krishty
Establishment
Beiträge: 8238
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Isohypsen-Shader

Beitrag 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.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
IH82W8
Beiträge: 15
Registriert: 08.06.2009, 23:05

Re: Isohypsen-Shader

Beitrag 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?
Benutzeravatar
Schrompf
Moderator
Beiträge: 4854
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Isohypsen-Shader

Beitrag 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.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
IH82W8
Beiträge: 15
Registriert: 08.06.2009, 23:05

Re: Isohypsen-Shader

Beitrag 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
IH82W8
Beiträge: 15
Registriert: 08.06.2009, 23:05

Re: Isohypsen-Shader

Beitrag 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ß!
Benutzeravatar
Schrompf
Moderator
Beiträge: 4854
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Isohypsen-Shader

Beitrag 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.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Krishty
Establishment
Beiträge: 8238
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Isohypsen-Shader

Beitrag von Krishty »

Ist Clamping (oder präziser, Saturating) nicht sowieso kostenlos?
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Richard Schubert
Moderator
Beiträge: 106
Registriert: 27.02.2009, 08:44
Wohnort: Hohen Neuendorf (b. Berlin)
Kontaktdaten:

Re: Isohypsen-Shader

Beitrag 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.
Produktivität über Performance - XNA Creators Club
Benutzeravatar
Schrompf
Moderator
Beiträge: 4854
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Isohypsen-Shader

Beitrag 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.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Krishty
Establishment
Beiträge: 8238
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Isohypsen-Shader

Beitrag 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.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Antworten