[D3D9] "Pixelperfekte" Textur im world space

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
zfxacc32
Beiträge: 27
Registriert: 05.03.2013, 15:24

[D3D9] "Pixelperfekte" Textur im world space

Beitrag von zfxacc32 »

Hallo,

ich möchte ein älteres Spiel (kein Source vorhanden) um ein paar Funktionen erweitern. Dazu verwende ich hooks.
Momentan bin ich dabei, Multisampling zu aktivieren. Das Problem dabei: Das Spiel lockt den backbuffer, um das Hauptmenü zu zeichnen. Ein multisampled backbuffer ist aber nicht lockbar.
Meine Idee: GetBackBuffer() hooken, statt dem backbuffer eine Textur zurückgeben (die ist lockbar), das Spiel zeichnet rein und am Ende rendere ich die Textur manuell über den ganzen Bildschirm.
Das funktioniert soweit, jedoch ist die Textur etwas "verwaschen", also nicht "pixelperfekt".
Wäre die Textur im screen space, könnte ich die vertices um 0.5f verschieben, dann sieht es perfekt aus, den Trick kenne ich.
Wie mache ich das jedoch im world space?

Ich habe es nicht geschafft, die Textur im screen space zu zeichnen, denn:
Das Spiel zeichnet das Menü in den backbuffer (vermutlich mit GDI) und rendert dann noch ein paar 3D Objekte drauf.
Zeige ich nun meine Textur im screen space an (D3DXMatrixOrthoLH), sind diese 3D Objekte nicht sichtbar (keine Ahnung warum, ich kenne mich da nicht so aus. Vermutlich verdeckt die Textur die Objekte. z-position der vertices hatte keinen Effekt).

Bin für jeden Tipp dankbar!
MfG
Benutzeravatar
Krishty
Establishment
Beiträge: 8238
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [D3D9] "Pixelperfekte" Textur im world space

Beitrag von Krishty »

In den Screen Space zeichnest du nicht via D3DXMatrixOrthoLH, sondern mit pretransformed Vertices (D3DFVF_XYZRHW ist das Stichwort). Dort kannst du den Vertices direkt einen Tiefenwert mitgeben. Du kannst also damit das Hauptmenü im Screen Space rendern, und im Depth Buffer sieht es unendlich weit entfernt aus und alle 3D-Objekte darüber bleiben sichtbar.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
zfxacc32
Beiträge: 27
Registriert: 05.03.2013, 15:24

Re: [D3D9] "Pixelperfekte" Textur im world space

Beitrag von zfxacc32 »

Danke erstmal. Achso, orthogonal ist ja für model->screen, denke ich.
Nunja, mit RHW habe ich es schon versucht. Doch sobald der z-Wert 1.0f erreicht, ist die Textur nicht mehr sichtbar (0.0f bis 0.9f geht).
Vielleicht hilft der Code weiter.

Code: Alles auswählen

// define

struct Vertex
{
	float x, y, z, rhw;
	float tu, tv;
};

#define D3DT_CUSTOMVERTEX (D3DFVF_XYZRHW | D3DFVF_TEX1)

// init

float z = 0.9f; // ab 1.0f Textur nicht mehr sichtbar, 3D Objekte nie sichtbar

		Vertex vertices[] =
		{
			{ 0.0f, height, z, 1.0f, 0.0f, 1.0f },
			{ 0.0f, 0.0f, z, 1.0f, 0.0f, 0.0f },
			{ width, height, z, 1.0f, 1.0f, 1.0f },
			{ width, 0.0f, z, 1.0f, 1.0f, 0.0f }
		};

		for(int i = 0; i < 4; ++i)
		{
			vertices[i].x -= 0.5f;
			vertices[i].y -= 0.5f;
		}

// render

Clear()
HookGetBackBuffer(): *ppBackBuffer = myTexture;
HookBeginScene():

long result = dev->BeginScene();

	dev->CreateStateBlock(D3DSBT_ALL, &currentStates);

	defaultStates->Apply();

dev->SetFVF(D3DT_CUSTOMVERTEX);
	dev->SetStreamSource(0, vb, 0, sizeof(Vertex));
	dev->SetTexture(0, myTexture);

	dev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);

	currentStates->Apply();
	currentStates->Release();

return result;

EndScene()
Present()
zfxacc32
Beiträge: 27
Registriert: 05.03.2013, 15:24

Re: [D3D9] "Pixelperfekte" Textur im world space

Beitrag von zfxacc32 »

Ahaaa, wenn ich z auf 0.999f setze, sind die Objekte sichtbar, die Textur also dahinter.

Ich verstehe es bloß noch nicht so genau.
Wer entscheidet eigentlich, welchen z Wert ein Objekt im z-buffer bekommt? Direct3D anhand der far/near plane?
Das bedeutet also, dass das Spiel diese Objekte schon sehr weit hinten zeichnet, und deshalb 0.9 nicht ausreichte, also scheinbar immer noch vor den Objekten lag?

Danke jedenfalls!
Benutzeravatar
Krishty
Establishment
Beiträge: 8238
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [D3D9] "Pixelperfekte" Textur im world space

Beitrag von Krishty »

Ja genau. Z ist nicht linear verteilt, sondern logarithmisch zwischen Near und Far Plane. Es ist also (je nach Transformationsmatrix) gut möglich, dass sich die Tiefenwerte der Modelle zwischen 0,999 und 1 ballen. Vielleicht hilft es in diesem Fall, den Z-Buffer-Test von lower auf lowerequal zu stellen, dann funktioniert auch die glatte 1 … jedenfalls bestimmt sauberer als World Space-Projektion :)
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
zfxacc32
Beiträge: 27
Registriert: 05.03.2013, 15:24

Re: [D3D9] "Pixelperfekte" Textur im world space

Beitrag von zfxacc32 »

Ah okay.
Das setzen von D3DRS_ZFUNC auf D3DCMP_LESSEQUAL (übrigens der default-Wert) lässt die Textur bei 1.0f weiterhin nicht erscheinen.

Ein weiteres Problem:
Das Spiel hat eine Konsole, die auf Tastendruck aufgeht. Leider erscheint diese aber hinter meiner Textur.
Ich habe schon herausgefunden, dass die Konsole ebenfalls mit D3DFVF_XYZRHW dargestellt wird, und zwar mit z gleich 0.0f.
Deshalb verstehe ich nicht, warum die Konsole durch meine 0.999f vertices verdeckt wird..

Komischer Effekt: Die Objekte liegen ja nun vor meiner Textur, die Konsole scheinbar dahinter, jedoch nehmen die Objekte die Farbe der Konsole an, wenn diese geöffnet ist (sie liegt also scheinbar vor den Objekten, aber hinter meiner Textur, kann irgendwie nicht sein..).

:?:
Benutzeravatar
Krishty
Establishment
Beiträge: 8238
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [D3D9] "Pixelperfekte" Textur im world space

Beitrag von Krishty »

Versuch mal, an W zu drehen (transformierte Vertices haben schließlich vier Koordinaten) :)
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
zfxacc32
Beiträge: 27
Registriert: 05.03.2013, 15:24

Re: [D3D9] "Pixelperfekte" Textur im world space

Beitrag von zfxacc32 »

Hmm, du meinst den Wert nach Z, also "RHW"? Ich dachte, der soll immer auf 1.0f gesetzt sein.
Hat leider nichts verändert (außer die Textur verzerrt, wenn nicht alle Werte gleich waren).

(Ich zeichne jetzt übrigens direkt vor Present(), aber das sollte ja keinen Unterschied machen)

// EDIT:
Oh, ich dachte es wäre egal, in welcher Reihenfolge gezeichnet wird, da ja endgültig der z-buffer entscheiden sollte.
Zum Test habe ich also versucht, eine Textur mit z gleich 0.5f vor meine Menütextur mit z gleich 0.999f zu zeichnen. Diese ist aber nur sichtbar, wenn sie nach der Menütextur gezeichnet wird.

// EDIT 2:
D3DRS_ZWRITEENABLE war nicht aktiv :roll:
Das Spiel aktiviert es scheinbar auch nicht, also muss ich wohl versuchen, es beim zeichnen des Konsolenfensters zu aktivieren..
Antworten