Probleme mit Pointsprites (durch GeoShader)

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
Stephan Theisgen
Beiträge: 94
Registriert: 29.07.2003, 11:13

Probleme mit Pointsprites (durch GeoShader)

Beitrag von Stephan Theisgen »

Hi!

Ich benutze D3D10 und versuche gerade einfach nur ein paar Pointsprites zu rendern. Dazu benutze ich den GeoShader. Ich übergebe eine Pointliste mit den Punkten im WorldSpace, transformiere sie im VertexShader in den ViewSpace. Und erzeuge dann aus jedem Punkt 2 Dreiecke indem ich die Koordinaten aus der Pointliste um jeweils einen Pixel verschiebe:

Code: Alles auswählen

[maxvertexcount(4)]
void GS(point vs_output input[1], inout TriangleStream<vs_output> TriStream)
{
	vs_output output;

	output.Pos.x=input[0].Pos.x - 1 / SCREEN_WIDTH;
	output.Pos.y=input[0].Pos.y -  1 / SCREEN_HEIGHT;
	output.Pos.z=input[0].Pos.z;
	output.Pos.w=input[0].Pos.w;
	output.Color=input[0].Color;
	TriStream.Append(output);

	output.Pos.x=input[0].Pos.x - 1 / SCREEN_WIDTH;
	output.Pos.y=input[0].Pos.y +  1 / SCREEN_HEIGHT;
	output.Pos.z=input[0].Pos.z;
	output.Pos.w=input[0].Pos.w;
	output.Color=input[0].Color;
	TriStream.Append(output);
	
	output.Pos.x=input[0].Pos.x + 1 / SCREEN_WIDTH;
	output.Pos.y=input[0].Pos.y -  1 / SCREEN_HEIGHT;
	output.Pos.z=input[0].Pos.z;
	output.Pos.w=input[0].Pos.w;
	output.Color=input[0].Color;
	TriStream.Append(output);
	
	output.Pos.x=input[0].Pos.x + 1 / SCREEN_WIDTH;
	output.Pos.y=input[0].Pos.y +  1 / SCREEN_HEIGHT;
	output.Pos.z=input[0].Pos.z;
	output.Pos.w=input[0].Pos.w;
	output.Color=input[0].Color;
	TriStream.Append(output);
	
	TriStream.RestartStrip(); 
}
Eigentlich sollten jetzt die Pointsprites 3x3 Pixel groß sein. Das ist aber nicht immer der Fall je nach Blickrichtung sind sie auch nur 2x3 oder 3x2 oder 2x2 Pixel groß.
Hat jemand eine Idee, bzw. wie macht Ihr das, dass die Pointsprites immer genau 3x3 Pixel groß sind und nicht so hin und her "wabbern".

Vielen Dank!
Stephan
dronus
Establishment
Beiträge: 114
Registriert: 11.01.2010, 01:53

Re: Probleme mit Pointsprites (durch GeoShader)

Beitrag von dronus »

Benutzt du AntiAlias? Sonst ist das ganz normal, weil die Koordinaten keine glatten Zahlen sind, und die Kanten deiner Sprites dann so über die Pixel kriechen dass mal mehr, mal weniger Pixel sichtbar sind. Mit AntiAlias sollte es ganz gut aussehen.

Wenn es ohne AntiAlias gehen soll, musst du die Koordinaten im GeoShader runden. Dann wird es aber mit AntiAlias blöd, weil sich die Sprites nur noch um ganze Pixel bewegen können.
Stephan Theisgen
Beiträge: 94
Registriert: 29.07.2003, 11:13

Re: Probleme mit Pointsprites (durch GeoShader)

Beitrag von Stephan Theisgen »

Hi!

Danke für die Antwort! Das könnte sein, ich benutze zur Zeit kein AntiAliasing da ich HDR benutze und ein Fließkomma-Rendertarget habe. Ich könnte es natürlich einstellen, meine Grafikkarte unterstützt es.
Aber zunächst mal, wie kann ich denn im Geoshader richtig runden?

MfG
Stephan
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Probleme mit Pointsprites (durch GeoShader)

Beitrag von Krishty »

Keine Zeit für eine genaue Analyse, aber das hier stand in meinem Sternen-Shader:

Code: Alles auswählen

	// Bildschirmauflösung horizontal und vertikal / 2.0.
	float2				g_vHalfScreenResolution		:packoffset(c8);
	float				g_ZValue					:packoffset(c8.z);

[…]

	// Da wir direkt mit Pixeln rechnen müssen, wird die perspektivische Projektion im Weg stehen. Wir berechnen hier direkt die
	//	transformierte Position und werden dafür die Z- und W-Koordinate der erzeugten Vertices auf 1.0 setzen.
	const float2 l_vCurrScreenPosition	= l_vCurrScreenPositionUntransformed.xy / l_vCurrScreenPositionUntransformed.w;

	// Um das Höhen- und Breitenverhältnis des Bildschirms auszugleichen und weil die weiteren Operationen auf Pixelebene
	//	vorgenommen werden, werden diese Positionsdaten in Pixelpositionen umgerechnet.
	const float2 l_vCurrPixelPosition	= l_vCurrScreenPosition * g_vHalfScreenResolution;

[…]

	// Transformation vom Pixel- zurück in den Screen-Space.
	const float2 l_vRcpHalfScreenRes = 1.0f / g_vHalfScreenResolution;

	float4 l_MyOutput;
	l_MyOutput.vCurrScreenPosition.w	= 1.0f;
	l_MyOutput.vCurrScreenPosition.z	= g_ZValue;
	l_MyOutput.xy = …;
	p_TriangleOutputStream.Append(l_MyOutput);
Ich kann gerade nicht sagen, worauf ich g_ZValue gesetzt habe – das könnte 1.0 oder 0.5 oder 0.0 gewesen sein (in absteigender Wahrscheinlichkeit). Anti-Aliasing ist es nicht (wenn eine Sprite oben aus dem Sample-Raster rausfällt, fällt sie unten dafür wieder rein, da die Sprite-Größe ein genaues Vielfaches des Sampling-Rasters ist). Hoffe, das hilft.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Stephan Theisgen
Beiträge: 94
Registriert: 29.07.2003, 11:13

Re: Probleme mit Pointsprites (durch GeoShader)

Beitrag von Stephan Theisgen »

Hallo Krishty!

Vielen Dank für die Hilfe, hat wider Erwarten (fast) gleich funktioniert! Jetzt muß ich nur noch verstehen warum das mit der Perspektivischen Projektion so schwierig ist.

Übrigens versuche ich gerade genau Deinen Artikel nach zu machen. Ich muß sagen ein super Artikel. Natürlich muß man sich ohne Code mehr anstrengen, aber das ist auch gut so, immerhin muß man es ja sowieso an sein aktuelles Problem angepaßt implementieren. Aber die Tips sind wirklich spitze. Immerhin sehe ich jetzt schon einmal Sterne, die auch nicht mehr Flackern, HDR klappt auch, fehlt eigentlich nur noch die CubeMap (die kann ich allerdings gerade nicht so richtig finden, aber vielleicht bin ich auch nur blind).

Vielleicht hättest Du ja Lust, wenn ich soweit fertig bin, dass Ergebniss zu diskutieren. Du könntest mir wertvolle Tips zum Finetuning geben (meine HDR-Tonemapping mußte ich deutlich von dem Angegebenen abändern.) Aber ich verwende wahrscheinlich auch einen anderen Operator...

Vielen Danke und viele Grüße
Stephan
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Probleme mit Pointsprites (durch GeoShader)

Beitrag von Krishty »

Die Größe der Sprites wird bei der perspektivischen Projektion dadurch bestimmt, wie „tief“ sie im Bildschirm sind. Dabei ist wichtig, dass es tatsächlich um die Tiefe (entlang der Z-Achse in den Bildschirm hinein) geht und nicht um die Entfernung: Obwohl deine Sterne auf der Einheitskugel alle gleich weit vom Betrachter entfernt sind, sind die Sterne am Bildschirmrand weniger tief in der Bildschirmebene als die im Zentrum. Darum werden die Sterne in der Mitte kleiner.

Ich werde das im Artikel nachtragen – man soll zwar möglichst vieles selber programmieren können, das ist aber imo ein fieser Fallstrick, dessen Ursache über das Basiswissen hinausgeht … und eben vermeidbar.

Die Cubemap ist Abbildung 3 im Artikel. Ich benutze aber inzwischen eine andere (auch Aramis war unzufrieden), nächste Woche kann ich die nachliefern (WE ist verplant). Auch über Diskussionen würde ich mich freuen – dafür steht der Thread des Artikels offen :) Ich muss dich aber warnen … bin in letzter Zeit in der Programmierung ziemlich rumgekommen und habe deshalb seit bestimmt einem Jahr keinen Shader mehr angerührt.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Stephan Theisgen
Beiträge: 94
Registriert: 29.07.2003, 11:13

Re: Probleme mit Pointsprites (durch GeoShader)

Beitrag von Stephan Theisgen »

Ok, jetzt ist's mir klar.

Für die CubeMap wäre ich natürlich sehr dankbar. Ich hab auch einiges um die Ohren insofern eilt es nicht.

Shader sollten nicht das Problem werden, ich bin zwar ganz schön raus, aber das technische wird schon gehen. Wichtiger ist mir der ästhetische Blick. Man wird betriebsblind, wenn man so lange auf die selbe Szene schaut.

Viele Grüße
Stephan
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Probleme mit Pointsprites (durch GeoShader)

Beitrag von Krishty »

Machen wir mit allem, was nicht zu den Pointsprites gehört, hier weiter.

Achja, es gibt da noch ein Problem mit Point-Sprites: dass Sterne am Bildschirmrand kleiner werden, ist ja eigentlich durchaus konsistent. Wenn wir nurnoch im Screen-Space arbeiten und die perspektivische Projektion außen vor lassen, müssen wir die Verkleinerung dadurch ausgleichen, dass wir die Helligkeit der Sterne zur Mitte hin reduzieren, sonst ist ihre Leuchtdichte nicht mehr gleichmäßig. Einfach als Bild ausgedrückt: da die Sterne in der Mitte weder kleiner noch dunkler werden, bilden sich insbesondere bei Weitwinkelansichten Knubbel.
Fish.png
Das zu umgehen hängt streng mit einem anderen Problem zusammen, nämlich, dass die Sterne nicht auflösungsunabhängig gleich hell sind. Des Pudels Kern ist: Ich muss eine Möglichkeit finden, einem Stern eine Größe zuzuweisen und damit aus der Fläche, die seine Pointsprite abdeckt, die Helligkeit berechnen. Ich habe bisher kein wissenschaftlich gebräuchliches Maß für die scheinbare Größe eines Sterns gefunden … das wird also die nächste Hürde.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Stephan Theisgen
Beiträge: 94
Registriert: 29.07.2003, 11:13

Re: Probleme mit Pointsprites (durch GeoShader)

Beitrag von Stephan Theisgen »

Ok, entweder stehe ich jetzt auf der Leitung, oder?
Erstens sieht der Effekt bei mir gar nicht so stark aus und zweitens sind meine Sterne überall auf dem Bildschirm gleich groß. Ich habs ausprobiert mit Pointsprites der größe 20x20 Pixel und habs ausgemessen.
Also wo ist mein Denkfehler?

Viele Grüße
Stephan

P.S.: Danke für die CubeMap, ich habs jetzt fast vollständig implementiert. Ist schon beeindruckend...Es freut mich immer wieder die Sterne zu sehen. Ich muß sagen, diese Artikel wird noch zu 'ner richtigen Referenz. Schonmal an eine englische Übersetzung gedacht? Immerhin habe ich nirgendwo im Web (ich hba natürlich auch auf Englisch gesucht), so einen guten Artikel gefunden...
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Probleme mit Pointsprites (durch GeoShader)

Beitrag von Krishty »

Stephan Theisgen hat geschrieben:Erstens sieht der Effekt bei mir gar nicht so stark aus und zweitens sind meine Sterne überall auf dem Bildschirm gleich groß.
Der Screenshot ist bei fast 180 ° Blickfeld aufgenommen, also schon sehr überspitzt. Schaut man sich allerdings an, mit welchen Blickfeldern auf Multi-Monitor-Setups gearbeitet wird, ist der Effekt wichtig.

Zweitens ist, dass die Sterne gleich groß sind, ja gerade das Problem. Alle anderen Objekte werden zum Bildschirmrand her größer, nur unsere Sterne nicht. Das ist einerseits gerade der Trick, weil Sterne viel zu klein für einen konventionellen Rendering-Ansatz sind, aber andererseits muss ich mir jetzt den Kopf darüber zerbrechen, wie ich da solche Anomalien rauskriege.
Stephan Theisgen hat geschrieben:Ich muß sagen, diese Artikel wird noch zu 'ner richtigen Referenz. Schonmal an eine englische Übersetzung gedacht? Immerhin habe ich nirgendwo im Web (ich hba natürlich auch auf Englisch gesucht), so einen guten Artikel gefunden...
Lob hört man doch immer wieder gern :) Naja, die englische Version scheitert zum einen an der Zeit und zum anderen daran, dass ich als bekennender Rechtschreibextremist gewisse Anforderungen an die Übersetzung stelle, die ich selber weder einhalten noch überprüfen könnte. Zwar landet der Artikel in den englischen Suchlisten wahrscheinlich niemals auf den ersten Seiten, aber sollte sich doch mal ein englischsprachiger Leser dorthin verirren, kann er sich die Seite von Google provisorisch übersetzen lassen. Werden zwar viele dicke Hunde drin sein, aber verstehen sollte man ihn trotzdem können – und das ohne dass ich mir stundenlang den Kopf darüber zerbrochen habe, ob „Luminary“ oder „Star“ die bessere Übersetzung des Worts „Gestirn“ ist ;)
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Probleme mit Pointsprites (durch GeoShader)

Beitrag von Krishty »

Okay, mal ein paar Gedanken dazu gemacht:


Zuerst einmal ist es wirklich wichtig, dass wir die Helligkeit bei verschiedenen Auflösungen konstant kriegen. Nochmal eine (überspitzte!) Skizze zum Verständnis: Bei unterschiedlichen Auflösungen erscheint der Himmel unterschiedlich hell, man muss die Sterne zwingend an die Auflösung anpassen. Das ist schlecht.
Bild
Mein Problem ist nicht, dass ich auflösungsabhängige Effekte generell ablehne, sondern dass dieses Problem auch schon zu tragen kommt, wenn man das Blickfeld verstellt. Hat man ein großes Blickfeld eingestellt, knubbeln sich in der Bildschirmmitte viele Sterne auf wenigen Pixeln, werden aber fälschlicherweise nicht lichtschwächer (siehe Screenshot). Zoomt man an einen Stern heran, kann man so lange zoomen, wie man möchte – er erscheint ständig gleich hell, obwohl er eigentlich immer heller erscheinen müsste.

Da sich weder scheinbarer Durchmesser noch die Helligkeit von Sternen (durch Kataloge) feststellen, geschweige denn verarbeiten lassen (das eine zu klein, das andere zu groß), brauchen wir ein kombiniertes Maß für die Sternenhelligkeit, von dem wir die Helligkeit der Pointsprites für die aktuelle Auflösung ableiten können. Die Astronomie bietet das mit der Magnitude an, allerdings ist das eine logarithmische Klassifizierung und damit – zumindest für mich – schwer zu verwerten. Andere Informationen bieten Sternkataloge jedoch nicht an, also werde ich damit arbeiten müssen (ich poste hier natürlich alle Ergebnisse).


Der nächste Punkt ist, dass ich mit den Sprites gern wieder zur perspektivischen Transformation zurück möchte. Steuern wir die Helligkeit der Sterne nämlich korrekt, sorgt der Effekt, dass die Sprites am Bildschirmrand größer werden, automatisch für einen Helligkeitsausgleich über das Blickfeld. Sonst müssten wir auch das selber machen.
Außerdem ist mit die perspektivische Transformation schon im Vertex-Shader ein Dorn im Auge. Vortransformierte Koordinaten sind schwerer verständlich als es der Zweck erfordert und relativ umständlich zu implementieren. Lieber würde ich stattdessen die Berechnung der Sprites endlich mal richtig durchführen. Der Rechenweg ist hier skizzert, ich habe nur momentan weder Zeit noch technische Möglichkeit, das auszuprobieren:
Bild
Aus den Sprite-Achsen lässt sich dann eine ordentliche Sprite zwischen den beiden Sternkoordinaten aufspannen. Ich werde zusehen, dass ich das bis nächste Woche ausprobieren kann.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Probleme mit Pointsprites (durch GeoShader)

Beitrag von Krishty »

Perspektivische Sprites sind nun auch in einer kleinen Demo implementiert. Konsistente Leuchtdichte bei verschiedenen Auflösungen habe ich aber immernoch nicht auf die Kette gekriegt …
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Jörg
Establishment
Beiträge: 296
Registriert: 03.12.2005, 13:06
Wohnort: Trondheim
Kontaktdaten:

Re: Probleme mit Pointsprites (durch GeoShader)

Beitrag von Jörg »

Krishty hat geschrieben:... obwohl er eigentlich immer heller erscheinen müsste.
Wieso? Aus der Optik (Objektive/Teleskope) ist doch das Gegenteil bekannt...
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Probleme mit Pointsprites (durch GeoShader)

Beitrag von Krishty »

Also, der Stern an sich bleibt natürlich immer gleich hell. Zoomt man aber nun heran, wächst die Fläche des Sternabbilds auf dem Bildschirm.

Die Sterne sind nun aber so weit entfernt, dass die abgebildete Größe des Sterns bei jeder praktisch implementierten Zoomstufe noch unter 1×1 Pixel liegt. Die Größe des Sterns auf dem Ausgabegerät bleibt also bei jedem FoV 1×1 Pixel – ergo müssen wir die Helligkeit dieses einzelnen Pixels hochdrehen, um den Flächenzuwachs des projezierten Objekts zu simulieren.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Jörg
Establishment
Beiträge: 296
Registriert: 03.12.2005, 13:06
Wohnort: Trondheim
Kontaktdaten:

Re: Probleme mit Pointsprites (durch GeoShader)

Beitrag von Jörg »

Umgekehrt...durch den Zoom geht Licht verloren (daher ja auch die verlaengerten Belichtungszeiten in der Fotografie). Sterne bleiben (bis auf Beugungseffekte und Aberration) Punkte, das ist korrekt. Was sich beim realen Zoom vergroessert ist die Abbildung dieses Fehlerbildes. Wenn Du also "Punkte" beibehalten willst, dann wuesste ich nicht, wieso Du versuchst, sie simuliert zu vergroessern.
Worauf Du wohl abziehlst ist die Belichtungszeit mit einzurechnen. D.h. du willst beim "Zoomen" schwache Sterne erst richtig sichtbar machen, oder?

PS: Die punktförmige Abbildung meine ich bezogen auf Verwendung von Standard- (Amateur-)Ausrüstung. Oder hast Du soetwas vor?
Zuletzt geändert von Jörg am 16.04.2010, 14:46, insgesamt 2-mal geändert.
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Probleme mit Pointsprites (durch GeoShader)

Beitrag von Krishty »

Ja, genau das will ich.

Natürlich hast du mit der Belichtungszeit recht – darum haben Ferngläser und Teleskope eben auch größere Öffnungen als unsere Pupillen. Aber es ist noch viel klarer, dass das in der Computergrafik komplett ignoriert wird – da wird nichts dunkler, nur weil man das FoV verringert. Also hack damit nicht ausgerechnet auf mir rum sondern auf den Leuten, die angefangen haben, Geometrieprojektion von Pixel-Shading zu entkoppeln ;)

Edit:
Jörg hat geschrieben:PS: Die punktförmige Abbildung meine ich bezogen auf Verwendung von Standard- (Amateur-)Ausrüstung. Oder hast Du soetwas vor?
Neinein, keine Angst. Ich will bloß mit FoVs von 90 bis 5 ° arbeiten und kein Planetarium programmieren. Jedenfalls kein komplettes ;)
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Jörg
Establishment
Beiträge: 296
Registriert: 03.12.2005, 13:06
Wohnort: Trondheim
Kontaktdaten:

Re: Probleme mit Pointsprites (durch GeoShader)

Beitrag von Jörg »

Aber dann hast Du doch schon fast eine Loesung....
Die Helligkeit bei konstanter Oeffnung ist ~1/(f^2). Das es ja hier nicht dunkler wird, wird genau dieser Abfall "ausgeglichen". Fuer einen FOV von 5° kannst Du nun eine maximale Helligkeit definieren (beliebig, so dass es halt gut aussieht und du die Sterne erkennst , die man sehen soll). Dann interpolierst Du zwischen 1.0 beim groessten FOV und diesem Maximum basierend auf 1/f^2. f bekommst Du ja via f ~ cot(FOV/2).
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Probleme mit Pointsprites (durch GeoShader)

Beitrag von Krishty »

Kann man dich anmieten? Dass du mir das alles implentierst? ;) Wieder richtig, jedenfalls zum größten Teil: da muss noch die Auflösung mit rein, damit die Durchschnittshelligkeit nicht nur bei verschiedenen FoVs, sondern auch bei verschiedenen Auflösungen konstant bleibt.

Das eigentliche Problem ist aber das von dir angesprochene „beliebig, so dass es halt gut aussieht“ … ich kenne zwar die Magnitude der Sterne, aber der Algorithmus für die Umrechnung in die finale Helligkeit ist komplett aus der Luft gegriffen. Mein eigentliches Problem ist es, die *reale* Leuchtdichte eines Sternpixels aus dem Datensatz zu ermitteln. Astronomiker sind sonderbare Leute … die arbeiten mit zig voneinander unabhängigen, relativen Einheiten und Koordinatensystemen …

… es ist aber nicht so – als dass ich da jetzt Hilfe bräuchte: ich wollte es wenn, dann in der Gesamtheit richtig machen hatte schlicht noch keine Lust, mich durch die Datensätze zu wühlen. Mit der absoluten Helligkeit und einer Entfernungsangabe werde ich sicher schon weit kommen … mal gucken, ob ich die irgendwo herkriege.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Antworten