PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [Direct3D] 2D-Textur von Hand erstellen mit ungerader Länge/Breite?


Nasenbaer
2010-03-25, 14:06:43
Gibt es eine Möglichkeit eine 2D-Textur zu erstellen dessen MipMap-Payramide z.B. die Form 257*257, 129*129, 65*65, ... hat? In der Doku steht, dass beim Filtern jeder MipLevel (bis auf den höchsten) automatisch so gefiltert wird, dass Länge/Breite danach gerade sind.

Außerdem finde ich nichts im SDK, dass man beispielhaft die Erstellung einer Textur von Hand erklärt - ausschließlich mit D3DX-Funktionen um sie aus'ner Datei zu lesen was mir nicht weiterhilft, weil ich OpenEXR als Dateiformat nehmen wollte (wegen IEEE-Float pro Kanal). Und außerdem möchte ich die eigentlichen MipLevel auch gern von Hand angeben und nicht, dass D3D dort irgendwas selbst filtert.

Kann mir da jemand helfen, der sich mit Direct3D auskennt?

Coda
2010-03-25, 14:10:29
Welche Direct3D-Version?

Nasenbaer
2010-03-25, 14:17:11
Welche Direct3D-Version?
Stimmt ja seit D3D9 hat sich ja einiges verändert. Ich nutze 11. :)

Nasenbaer
2010-03-26, 09:56:14
Hmm ich hab schon das Problem, dass der Beispiel-Code aus dem SDK nicht will:


D3D11_TEXTURE2D_DESC desc;
desc.Width = 256;
desc.Height = 256;
desc.MipLevels = desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;

V_RETURN (pd3dDevice->CreateTexture2D( &desc, NULL, &gimTexture ));


CreateTexture2D() liefert E_INVALIDARG zurück. Warum weiß ich nicht. Da aber gimTexture ein Pointer auf ID3D11Texture2D ist und Ausgabeparameter der Funktion, vermute ich ein Problem bei der D3D11_TEXTURE2D_DESC. :/

Jemand ne Idee?

Demirug
2010-03-26, 10:03:16
Da ist MiscFlags und SampleDesc.Quality nicht gesetzt. Sollte beides 0 sein.

Ansonsten Debug runtime einschalten. Dann steht im output window des debuggers was nicht stimmt.

Nasenbaer
2010-03-26, 10:10:57
Da ist MiscFlags und SampleDesc.Quality nicht gesetzt. Sollte beides 0 sein.

Ansonsten Debug runtime einschalten. Dann steht im output window des debuggers was nicht stimmt.
Ja lag genau an den beiden Sachen - die Debug-Runtime hats mir dann auch verraten. Weil die MiscFlags nicht ordentlich initialisiert waren dachte D3D ich will ne CubeMap erzeugen und dann hätte ein paar andere Parameter nicht gestimmt.

Danke für den Tipp.

Nasenbaer
2010-03-26, 10:14:01
Jetzt hab ich ne weitere Frage:

Ich nutze die Shader derzeit ohne das Effects-System. Wie kann ich die erzeugte Textur nun an einen Shader weiterreichen? Ich finde nur Beispiele mit dem Effects-System. :/
Achso die Textur hab ich schon mittels Map/UnMap mit Daten gefüllt.

Nasenbaer
2010-03-26, 10:22:05
Ich glaub ich habs schon:

Erst mittels CreateShaderResourceView() ne Resource anlegen und dann mit PSSetShaderResources() diese an den Shader übergeben.

Demirug
2010-03-26, 11:31:55
Ich glaub ich habs schon:

Erst mittels CreateShaderResourceView() ne Resource anlegen und dann mit PSSetShaderResources() diese an den Shader übergeben.

Genau. Den Resourceview aber wie die Textur selbst bitte ausserhalb des Renderloops erzeugen.

Nasenbaer
2010-03-26, 12:35:10
So eine einfache Textur kann ich nun im VertexShader auslesen aber nur wenn ich sie per initialData und nicht mittels Map/Unmap fülle:


D3D11_TEXTURE2D_DESC texDesc;
texDesc.Width = 17;
texDesc.Height = 17;
texDesc.MipLevels = texDesc.ArraySize = 1;
texDesc.Format = DXGI_FORMAT_R32G32B32_FLOAT;
texDesc.SampleDesc.Count = 1;
texDesc.SampleDesc.Quality = 0;
texDesc.Usage = D3D11_USAGE_DYNAMIC;
texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
texDesc.MiscFlags = 0;

//Testdaten
float data[867];
for (int i=0; i < 866; ++i)
{
data[i] = 0.5 * i;
}

//
// Variante 1 = funktioniert
//
D3D11_SUBRESOURCE_DATA subData;
subData.pSysMem = data;
subData.SysMemPitch = sizeof(float)*3*17;
V_RETURN (pd3dDevice->CreateTexture2D( &texDesc, &subData, &gimTexture ));


//
// Variante 2 = funktioniert nicht
//
V_RETURN (pd3dDevice->CreateTexture2D( &texDesc, NULL, &gimTexture ));
D3D11_MAPPED_SUBRESOURCE texResource;
V( d3dContext->Map( gimTexture, 0, D3D11_MAP_WRITE_DISCARD, 0, &texResource ) );
texResource.pData = data;
texResource.RowPitch = sizeof(float)*3*17;
d3dContext->Unmap(gimTexture, 0);

Was mache ich bei Variante 2 falsch?
Also bei beiden gibts keine Bemerkungen der Debug-Runtime aber bei der zweiten liefert Load() im Vertex-Shader immer (0, 0, 0) zurück, bei Variante 1 die gewünschten Daten.

Demirug
2010-03-26, 12:49:24
Map/Unmap funktioniert anders.

Die Map Methode gibt dir einen Zeiger (und den Pitch) auf den Speicher in den du deine Daten kopieren sollst.

Die Methode die das macht was du willst ist UpdateSubresource. Die funktioniert allerdings nicht mit dynamischen Resourcen.

Die richtige Wahl hängt davon ab wie oft man die Resource aktualisiert.

Nasenbaer
2010-03-26, 13:03:35
Map/Unmap funktioniert anders.

Die Map Methode gibt dir einen Zeiger (und den Pitch) auf den Speicher in den du deine Daten kopieren sollst.

Die Methode die das macht was du willst ist UpdateSubresource. Die funktioniert allerdings nicht mit dynamischen Resourcen.

Die richtige Wahl hängt davon ab wie oft man die Resource aktualisiert.
Ahh ok. Ich hab mir das meiste aus den Beispielen entnommen und wenns nicht ging den Code immer 1:1 übernommen. Ich brauch eigentlich nur 2 Texturen, die ein einziges mal geladen und dann nicht verändert werden. Aber da weiß ich schon wo ich gucken muss.

Naja und später brauche ich noch eine Textur in die ich vom VS aus reinschreibe und wieder draus lesen kann. Allerdings weiß ich nicht ob da so funktioniert. Da ich ein DrawIndexedInstance() machen möchte und die geschrieben Daten von Instance i benötige ich beim Rendern von Instance i+1. Ich glaube aber nicht, dass die Instanzen sequentiell von der GPU verarbeitet werden oder irre ich mich da?