Seite 1 von 1

[D3D11] DepthStencilView mit TextureCube

Verfasst: 04.11.2012, 20:45
von RazorX
Servus,
für meine ShadowMap Generierung von Punktlichtquellen möchte ich eine Textur verwenden, die ich mit dem Flag D3D11_RESOURCE_MISC_TEXTURECUBE erstelle. Davon erstelle ich mir 6 DepthStencilView für jeden Face, 6 SRV für je ein Face sowie ein SRV für das binden als TextureCube. Die Erstellung funktioniert ohne Fehler, jedoch bleibt der Inhalt der Textur leer beim Zeichnen. Hat einer eine Idee ob bei der Erstellung semantisch etwas schief geht?

Code: Alles auswählen

// Create texture object
D3D11_TEXTURE2D_DESC tex2DDesc = {0};
tex2DDesc.Width				= width;
tex2DDesc.Height			= height;
tex2DDesc.Format			= DXGI_FORMAT_R32_TYPELESS;
tex2DDesc.BindFlags			= D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
tex2DDesc.MiscFlags			= D3D11_RESOURCE_MISC_TEXTURECUBE;
tex2DDesc.ArraySize			= 6;
tex2DDesc.MipLevels			= 1;
tex2DDesc.Usage				= D3D11_USAGE_DEFAULT;
tex2DDesc.SampleDesc.Count	= 1;

HRESULT hr = device->CreateTexture2D(&tex2DDesc, nullptr, cubeTexture.rebind());
assert(hr == S_OK);

// Create cube shader resource view
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
ZeroMemory(&srvDesc, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));
srvDesc.Format = DXGI_FORMAT_R32_FLOAT;
srvDesc.TextureCube.MipLevels = 1;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;

hr = device->CreateShaderResourceView(cubeTexture, &srvDesc, srv[6].rebind());
assert(hr == S_OK);

// Create face shader resource views
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
srvDesc.Texture2DArray.MipLevels = 1;
srvDesc.Texture2DArray.ArraySize = 1;

for(unsigned i = 0; i < 6; ++i) {
	srvDesc.Texture2DArray.FirstArraySlice = i;
				
	hr = device->CreateShaderResourceView(cubeTexture, &srvDesc, srv[i].rebind());
	assert(hr == S_OK);
}

// Create depth stencil views
D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
ZeroMemory(&dsvDesc, sizeof(D3D11_RENDER_TARGET_VIEW_DESC));
dsvDesc.Format = DXGI_FORMAT_D32_FLOAT;
dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
dsvDesc.Texture2DArray.ArraySize = 1;
			
for(unsigned i = 0; i < 6; ++i) {
	dsvDesc.Texture2DArray.FirstArraySlice = i;

	hr = device->CreateDepthStencilView(cubeTexture, &dsvDesc, dsvFace[i].rebind());
	assert(hr == S_OK);
}
Bin mir halt unsicher ob ein DepthStencilView auf eine solche Art von Textur zugreifen kann, wenn ihr die Erstellung semantisch verifizieren könnt muss ich wohl tiefer schürfen.

MfG
RazorX

Re: [D3D11] DepthStencilView mit TextureCube

Verfasst: 04.11.2012, 22:38
von RazorX
Nach weiterem forschen hab ich nun rausgefunden, dass in der Textur etwas drin steht und über die Face-SRV auch ausgelesen werden kann. Wenn ich jedoch den Cube-SRV nehme, wird mir immer 0 zurückgeliefert, obwohl der auf die selben Daten zugreifen sollte.

Re: [D3D11] DepthStencilView mit TextureCube

Verfasst: 04.11.2012, 22:41
von dot
Sagt die Debug Runtime vielleicht was?

Re: [D3D11] DepthStencilView mit TextureCube

Verfasst: 04.11.2012, 22:43
von RazorX
Leider nein

Re: [D3D11] DepthStencilView mit TextureCube

Verfasst: 04.11.2012, 22:52
von dot
Nachdem ich mal etwas genauer drübergeschaut hab: Du hast srvDesc.TextureCube.MostDetailedMip nicht gesetzt. Ansonsten wär vielleicht mal interessant, wie genau du im Shader auf den Cube zugreifst...

Re: [D3D11] DepthStencilView mit TextureCube

Verfasst: 04.11.2012, 22:55
von RazorX
Da ich die SRV Desc Struktur nulle und es nur ein Mip-Level gibt, hat sich das Zuweisen erledigt (Most-Detailed ist ja eben die 0).

Der Zugriff im Shader erfolgt so:

Code: Alles auswählen

float3 l = input.lightPos - viewspacePosition;
...
l = normalize(l);
...
output = float4(computeLinearDepth(texShadowCube.Sample(pointClampSampler, l), g_zNear, g_zFar), 0, 0, 1.f);

Re: [D3D11] DepthStencilView mit TextureCube

Verfasst: 04.11.2012, 22:59
von dot
Und l liefert auch sinnvolle Werte? Und das SRV wurde auch am richtigen Slot gebunden?

Re: [D3D11] DepthStencilView mit TextureCube

Verfasst: 04.11.2012, 23:04
von RazorX
l liefert richtige Werte, da dies der Vektor ist den ich auch für Beleuchtung benutze. Der TextureCube ist auch auf dem richtigen Slot gebunden, eine weitere Texture2D hab ich auf dem selben und im Programm tausch ich dann schonmal Zeilen aus. So konnte ich auch sagen, dass definitiv etwas in der Textur drin steht.

Edit: Kein Plan was ich geändert habe, aber es funktioniert jetzt oO

Re: [D3D11] DepthStencilView mit TextureCube

Verfasst: 05.11.2012, 16:58
von RazorX
Leider hab ich noch immer Probleme mit dem TextureCube. Heute im Laufe des Tages habe ich mich die ganze Zeit damit rumgeschlagen, dass beim auslesen des TextureCubes mir seltsame Artefakte auftauchen. Der Vektor wird ganz normal berechnet und wird auch zur Beleuchtung verwendet. Die Projektionsmatrix für die einzelnen CubeFaces hat: FoV = PI / 2, Aspect = 1, Near = .1f, Far = Radius. Ich hätte angenommen, dass wenn ich nun mit einem Vektor auf dem Einheitskreis daraus sample das ich auch eine sphärische Verzerrung erhalte. Leider bekomme ich aber Samples, denen man deutlich ansehen kann das sie in einer Box liegen. (Auf dem Bild wird ein Point Clamp Filter benutzt und ich bin mit der Kamera sehr nah auf den Boden runter, da so der Effekt sehr stark sichtbar wird; Rot ist der Beleuchtungsanteil berechnet durch N dot L; Grün ist der Tiefenwert der Shadowmaps).
screenshot_2012-11-05_16-35-40.png
Wenn ich nun mit diesen Tiefeninformationen gegen die Entfernung des Pixels von der Punktlichtquelle einen Schattentest mache, erhalte ich folgende seltsame Strukturen.
screenshot_2012-11-05_14-04-56.png
Muss ich eine zusätzliche sphärische Verzerrung anwenden um keine Boxergebnisse zu bekommen?

MfG
RazorX

Re: [D3D11] DepthStencilView mit TextureCube

Verfasst: 05.11.2012, 17:05
von dot
Beim Samplen aus einer Cubemap zählt nur die Richtung, ob der Vektor normalisiert ist (ich nehme mal an das meinst du mit "auf dem Einheitskreis") oder nicht, macht keinen Unterschied...

Wenn ich das richtig verstanden hab, enthalten deine Maps die nichtlineare Tiefe, aus der du die lineare Viewspace Tiefe aus Sicht der Lichtquelle rekonstruierst!? Ich nehme an, du verwendest für den Schattentest dann die euklidische Entfernung ("die Entfernung des Pixels von der Punktlichtquelle")!? Das ist natürlich falsch, du musst natürlich ebenso die lineare Viewspace Tiefe aus Sicht der Lichtquelle verwenden...

Re: [D3D11] DepthStencilView mit TextureCube

Verfasst: 05.11.2012, 17:29
von RazorX
Fängt langsam an Sinn zu ergeben. Also den Punkt aus meinem Viewspace in den Viewspace der Punktlichtquelle (dem Viewspace in dem der CubeFace gerendert wurde) transformieren und dann die z-Komponente gegen die gespeicherte Tiefe testen? Ich geh mal davon aus, dass es in HLSL keine Möglichkeit gibt zu erkennen aus welchem Face der Sample stammt!?

Re: [D3D11] DepthStencilView mit TextureCube

Verfasst: 01.01.2013, 22:33
von Niki
RazorX, hast du das Problem mittlerweile gelöst? Wenn nicht, dann will ich mal versuchen zu helfen. Auf grund der Benutzung von "computeLinearDepth" gehe im folgenden davon aus, dass du einen Renderer mit Deferred Lighting hast.

Was ich mache ist folgendes:

(1) Zuerst einmal bestimme ich welches pixel im GBuffer ich beleuchten will. Dieses transformiere ich zurück in den View Space des Spielers. Ich nenne diese position mal posVS.

(2) Als nächstes transformiere ich posVS in das Koordinatensystem des Point Lights. Nennen wir das mal posLS (LS für Light Space)

(3) Dann sample ich die shadow cube map mit Texturekoordinaten posLS.xyz. Normalisieren brauchst man da nichts. Den resultierenden nicht-linearen depth-Wert wandle ich in einen linearen depth-Wert um. Nennen wir den mal shadowLinearDepth.

(4) Nun musst du rausfinden ob der Punkt posLS von shadowLinearDepth verdeckt wird. Wie "dot" bereits erwähnte benutzt du anscheinend die Euklidische Distanz length(posLS) und vergleichst die mit shadowLinearDepth. Wie Du bereits gemerkt hast kommen daher diese komischen kurvigen Resultate in Deinen Screenshots. Damit Du das korrigieren kannst fragst Du, wie Du rausfinden kannst aus welchem Face das Sample stammt. Willst Du gar nicht wissen, denn das bedeutet jede Menge if/else im Pixel Shader. Stattdessen etwas Pseudo-Code (der Trick steckt in abs() und max()):

Code: Alles auswählen

float3 absPosLS = abs(posLS.xyz);
float pixelLinearDepth = max(absPosLS.x, max(absPosLS.y, absPosLS.z));

if (pixelLinearDepth > g_lightFarPlane)
    return float4(0, 0, 0, 0); // in shadow

if (shadowLinearDepth <= pixelLinearDepth * 0.96) // 0.96 = shadow bias
{
    return float4(0, 0, 0, 0); // in shadow
}
else
{
    return Lighting(...);
}

Re: [D3D11] DepthStencilView mit TextureCube

Verfasst: 05.01.2013, 14:07
von RazorX
Dank dir für die ausführliche Antwort, hatte das aber selber schon vor geraumer Zeit gelöst. Habs letztlich auch über den max/abs Ansatz gemacht und funktionierte relativ gut. Was mich etwas gestört hatte war, dass man auf TextureCubes kein PCF anwenden kann und das Resultat nicht ganz so schön aussah. Muss das ganze mal zu einem Texturatlas umbauen.

Re: [D3D11] DepthStencilView mit TextureCube

Verfasst: 05.01.2013, 15:30
von Niki
Ich bin mir auch noch nicht sicher ob ich die cube maps für diesen Zweck mag. Das war mir aber vorerst wurscht, da ich das shadow mapping nur testweise implementiert habe um für später zu wissen wie ich das ganze in meine deferred shading pipeline reinbaue. Wenn's dann soweit ist werde ich auch andere Methoden ausprobieren, wie zum Beispiel über 6 spot lights mit einer einzigen shadow map.