Terrainindizierung und LODs

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
Gelöschter Benutzer
Beiträge: 92
Registriert: 26.02.2009, 22:09

Terrainindizierung und LODs

Beitrag von Gelöschter Benutzer »

Hallo Leute,

ich schreibe gerade an meiner Arbeit zur 5. Prüfungskomponente zum Abitur und habe wohl ein scheinbares einfaches Problem, dessen Lösung ich mir gerade wohl nicht bewusst bin. Erstmal beschreibe ich worum es geht: Es soll ein Brute-Force-Terrain (zu Demonstrationszwecken) mit LODs versehen werden.

Die Vertexgeneration ist relativ simpel mit einer heightmap welche 2^n als Größe besitzt. Also 2^n Samples pro Seite.
Es wird dann ein 2^n-Vertexbuffer erzeugt mit entsprechenden Höhendaten und skalierung. Klappt auch wie am Schnürrchen.

Der Indexbuffer wird je nach LOD-Step mit einer Vertexüberspringung von 1, 2, 4 etc. erstellt und funktioniert fast wie ich es will. Nun ja, fast. Als ich mir das Terrain bei einer hohen LOD-Stufe anzeigen lassen habe, fiel mir auf, dass pro Durchlauf ein Quad fehlt und die letzte Reihe auch. Dies ist auch bei einer niedrigen LOD-Stufe so.

Jetzt zum Problem: Meine Textur von Beispielsweise 512x512 samples kann mir im Indexbuffer nur 511 Quads anbieten, da das erste Sample ja ganz links benötigt wird. Entsprechend ist die Größe QuadSize*511 eins zu klein. Beziehungsweise lässt sich 511 bei LODs auch irgendwie im 2^n Schritt schlecht teilen. Bin ich jetzt gezwungen eine 513x513er-Textur zu verwenden oder gibt es auch eine andere Lösung? Bin schon fast am Verzweifeln vom diesem Problem und werde bald wahnsinnig.

Ich danke schonmal im Vorraus für die Hilfestellung.
Benutzeravatar
Aramis
Moderator
Beiträge: 1458
Registriert: 25.02.2009, 19:50
Echter Name: Alexander Gessler
Wohnort: 2016
Kontaktdaten:

Re: Terrainindizierung und LODs

Beitrag von Aramis »

Meine Textur von Beispielsweise 512x512 samples kann mir im Indexbuffer nur 511 Quads anbieten, da das erste Sample ja ganz links benötigt wird.
Du kannst einen Pixel auch als die Mitte eines Quads sehen. Die Vertexpositionen ergeben sich dann durch Interpolation der umliegenden Höhen (4, am Rand 2, in der Ecke 1). Dann kriegst du 512*512 Quads, 513*513 Vertices. Dann geht auch der LOD-Indexbuffer auf.
Gelöschter Benutzer
Beiträge: 92
Registriert: 26.02.2009, 22:09

Re: Terrainindizierung und LODs

Beitrag von Gelöschter Benutzer »

Aber macht dies nicht Probleme an den Rändern von Terrains wenn keine benachbarten Samples vorhandne sind?

Edit: Was mir noch einfallen würde wäre eine Texturskalierung, da ich ein eigenes Format benutze. Sprich: Die Textur wird seitens Devil im Importer um einen Pixel gestreckt. Dies würde einen Verlust einer Höheninformation bedeuten, aber wäre in dem Sinne akzeptabel. Ob der Weg auch praktisch ist?
Benutzeravatar
Schrompf
Moderator
Beiträge: 4859
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Terrainindizierung und LODs

Beitrag von Schrompf »

Du kannst auch die eine Randspalte und -zeile jeweils verdoppeln, dann kommst Du auch auf saubere Größen.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Gelöschter Benutzer
Beiträge: 92
Registriert: 26.02.2009, 22:09

Re: Terrainindizierung und LODs

Beitrag von Gelöschter Benutzer »

Jupp, ist mir auch schon eingefallen, allerdings gibt es dann eine gewisse Ungenauigkeit am Rand.

Das Problem habe ich weitestgehend schonmal gelöst. Per devIL habe ich die Textur von 512x512px auf 513x513px Bild skalieren lassen per B-Spline und das dann in mein eigenes Datenformat konvertiert. Nun funktionierts prima. Es ist zwar nicht ganz 100% aber wenistens fast ganz genau.

Hm, als nächstes werde ich mich mal um das Geometric Clipmapping kümmern - muss ja was für die Presentation her damits schnell in einer großen Szene läuft.
Benutzeravatar
Krishty
Establishment
Beiträge: 8250
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Terrainindizierung und LODs

Beitrag von Krishty »

Die Frage greift doch eigentlich viel tiefer … beispielsweise ist ein anderes Symptom des selben Problems die Frage: Wenn ich das Terrain durch Splines weiter verfeinere, was für Werte benutze ich dann an den Randpixeln? In diesem Fall braucht man nämlich für n Quads n + 3 Samples …

… egal, wie du dein Terrain auslegst, du hast konzeptbedingt immer Verschnitt.

Dasselbe Problem hat man übrigens auch bei Texturen, weil man dort für die lineare Filterung immer einen Randpixel mehr braucht, als die Textur zur Verfügung stellt, und löst es über Texture-Addressing-Modes. Ein tesseliertes Terrain mit einem Heightmap-Texel pro Vertex ist nichts anderes als eine linear gefilterte Textur (nur mit Positionen statt Farben), darum bietet es sich an, auch hier auf Texture-Addressing-Modes zurückzugreifen, um das Randproblem zu lösen. Eigentlich stehst du ja, sobald du das Terrain texturieren musst, nochmal vor exakt demselben Problem …

Schrompfs Vorschlag entspricht Clamping und ist für simple Fälle auch meine erste Wahl, sobald es komplexer wird (Splines) würde ich aber Wrapping oder Mirroring nutzen, damit an den Rändern nichts abflacht.

Die Heightmap einen Pixel zu strecken ist die eine Lösung, bei der du garantiert Qualität einbüßt. Und noch dazu das wunderschöne, vollkommene Speicher-Layout einer quadratischen Zweierpotenz-Textur ruinierst.

Gruß, Ky
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Gelöschter Benutzer
Beiträge: 92
Registriert: 26.02.2009, 22:09

Re: Terrainindizierung und LODs

Beitrag von Gelöschter Benutzer »

Werde ich mal weiter verfolgen. Danke.

Allerdings habe ich jetzt ein neues Problem (nicht das Terrain!): Es geht um Atmospheric Scattering. Ich hab mich mal im Netz schlau gemacht um irgendwie einen Einstieg zum Herumprobieren zu finden und bin auf http://www.gamedev.net/community/forums ... hichPage=1 gestoßen und bin dabei den Shader im Programm funktionstüchtig zu bekommen.

Schwarz ist ja nun ein schöner Kontrast, aber bitte doch nicht für den Himmel :). Irgendwie stimmen bei mir die Shaderkonstanden nicht, die ich als Defaultwerte übergebe. Zur Information: Über das Terrain wird ein Erdballgerundetes plane gezogen, dass 200km hoch ist und bis zu Horizont mit der Rundung reicht, wie ich es im Forum gelesen habe: http://www.basi.zugsimulationen.de/Inte ... 18_big.png . Dann habe ich die Koeffizienten ausprobiert und es blieb schwarz. Ich bin auch schon die ganzen Koeffizienten durchgegangen und es bleibt leider trotzdem Schwarz. Findet wer wo ich im Gedanken falsch liege (hier die Setzung der Defaultvalues):

Code: Alles auswählen

// Set default data:
	float3 Wavelengths = float3(0.650f, 0.570f, 0.475f);
	float3 Wavelengths4 = float3(powf(Wavelengths.x, 4.0f), powf(Wavelengths.y, 4.0f), powf(Wavelengths.z, 4.0f));
	float3 InvWavelengths4 = float3(1.0f/Wavelengths4.x, 1.0f/Wavelengths4.y, 1.0f/Wavelengths4.z);
	float2 Radien = float2(EarthRadius, EarthRadius+Height);
	float2 Radien2 = float2(Radien.x*Radien.x, Radien.y*Radien.y);
	float Scale = 1.0f / (Radien.y - Radien.x);
	float ScaleDepth = (Radien.y - Radien.x) / 2.0f;
	float ScaleOverScaleDepth = Scale / ScaleDepth;
	float2 CameraHeight = float2(EarthRadius, EarthRadius*EarthRadius);
	float3 LightDirection = float3(0.0f, 1.0f, 0.0f);
	float3 CameraPosition = float3(0.0f, 0.0f, 0.0f);
	float4 KRMs = float4(0.0225f, 0.0f, 0.0375f, 0.0f);
	KRMs.y = KRMs.x * 4.0f * 3.141592f;
	KRMs.w = KRMs.z * 4.0f * 3.141592f; 
	float2 g = float2(-0.991f, -0.991f*-0.991f);
	float2 Samples = float2(50.0f);

	_pLightDirection.Setf3(LightDirection);
	_pCameraPosition.Setf3(CameraPosition);
	_pLightWavelengths.Setf3(InvWavelengths4);
	_pCameraHeight.Setf1(CameraHeight.x);
	_pCameraHeight2.Setf1(CameraHeight.y);
	_pInnerRadius.Setf1(Radien.x);
	_pInnerRadius2.Setf1(Radien2.x);
	_pOuterRadius.Setf1(Radien.y);
	_pOuterRadius.Setf1(Radien2.y);
	_pKrESun.Setf1(KRMs.x);
	_pKmESun.Setf1(KRMs.y);
	_pKr4Pi.Setf1(KRMs.z);
	_pKm4Pi.Setf1(KRMs.w);
	_pg.Setf1(g.x);
	_pg2.Setf1(g.y);
	_pScale.Setf1(Scale);
	_pScaleDepth.Setf1(ScaleDepth);
	_pScaleOverScaleDepth.Setf1(ScaleOverScaleDepth);
	_pSkyDomeRadius.Setf1(EarthRadius + Height);
	_pExposure.Setf1(2.0f);
	_pNumSamples.Seti1(int(Samples.x));
	_pSamples.Setf1(Samples.y);
Es kann sein das ich mich irgendwie in einer Konstanten geirrt habe (was auch ärgerlich wäre), aber ich finde einfach den fehlerhaften Parameter nicht nicht (und die Werte werden gesetzt). EarthRadius ist überraschenderweise der Erdradius (6378km) und Height die Höhe der Atmosphere (200km). Der Rest wird derzeit im Shader gesetzt.

Wem der Ausschnitt nicht reicht, kann sich hier die volle Version (Im Ordner "Demo Brute-Force-Terrain-Indexed") anschauen: http://bsgameengine.svn.sourceforge.net ... n-Indexed/.

Ich danke schonmal :).

Edit: MOMENT... Ist hier ein Sphere (Kreisfläche) oder eine Hemisphäre zu verwenden?

Edit 2: Problem hat sich erledigt! Ich verwende stattdessen nun diesen Shader: http://www.gamedev.net/community/forums ... _id=510928 . Dort werde ich mich dann mal langsam einarbeiten, wie die Routine im Detail abläuft und was es zu beachten gibt.

Bild
Antworten