Delen via


Textuurbronnen maken (Direct3D 10)

Een textuur bron is een gestructureerde verzameling gegevens. Normaal gesproken worden kleurwaarden opgeslagen in patronen en gebruikt tijdens het weergeven door de pijplijn in verschillende fasen voor zowel invoer als uitvoer. Het maken van patronen en het definiëren van hoe ze worden gebruikt, is een belangrijk onderdeel van het weergeven van interessante scènes in Direct3D 10.

Hoewel patronen doorgaans kleurinformatie bevatten, kunnen ze verschillende soorten gegevens opslaan door patronen te maken met verschillende DXGI_FORMAT. Deze gegevens kunnen vervolgens op niet-traditionele manieren worden gebruikt door de Direct3D 10-pijplijn.

Alle texturen hebben limieten voor hoeveel geheugen ze verbruiken en hoeveel texels ze bevatten. Deze limieten worden opgegeven door resource-constanten.

Een patroon maken op basis van een bestand

Notitie

De D3DX-hulpprogrammabibliotheek is afgeschaft voor Windows 8 en wordt niet ondersteund voor Windows Store-apps.

 

Wanneer u een textuur maakt in Direct3D 10, moet u ook een weergave maken. Een weergave is een object dat aangeeft hoe een textuur moet worden benaderd tijdens rendering. De meest voorkomende manier om toegang te krijgen tot een textuur is door een shaderte gebruiken om ervan te lezen. Een arceringsresourceweergave vertelt een shader hoe te lezen van een textuur tijdens het renderen. Het type weergave dat een patroon gebruikt, moet worden opgegeven wanneer u het maakt.

Het maken van een bitmappatroon en het laden van de initiële gegevens kan op twee verschillende manieren worden uitgevoerd: een patroon en weergave afzonderlijk maken, of het patroon en de weergave tegelijkertijd maken. De API biedt beide technieken, zodat u kunt kiezen welke beter aansluit bij uw behoeften.

Textuur en weergave los van elkaar maken

De eenvoudigste manier om een bitmappatroon te maken, is door het te laden vanuit een afbeeldingsbestand. Om de textuur te maken, vult u één structuur in en geeft u de naam van de textuur op aan D3DX10CreateTextureFromFile.

ID3D10Device *pDevice = NULL;
// Initialize D3D10 device...

D3DX10_IMAGE_LOAD_INFO loadInfo;
ZeroMemory( &loadInfo, sizeof(D3DX10_IMAGE_LOAD_INFO) );
loadInfo.BindFlags = D3D10_BIND_SHADER_RESOURCE;

ID3D10Resource *pTexture = NULL;
D3DX10CreateTextureFromFile( pDevice, L"sample.bmp", &loadInfo, NULL, &pTexture, NULL );

De functie D3DX D3DX10CreateTextureFromFile doet drie dingen: eerst wordt er een Direct3D 10-patroonobject gemaakt; ten tweede wordt het invoerafbeeldingsbestand gelezen; ten derde worden de afbeeldingsgegevens opgeslagen in het bitmapobject. In het bovenstaande voorbeeld wordt een BMP-bestand geladen, maar de functie kan verschillende bestandstypen laden.

De bind-vlag geeft aan dat de textuur wordt gemaakt als een shader-resource, zodat een shader-fase tijdens het weergeven van de textuur kan worden gelezen.

In het bovenstaande voorbeeld worden niet alle laadparameters opgegeven. Het is zelfs handig om eenvoudigweg de laadparameters uit te schakelen, omdat D3DX hierdoor de juiste waarden kan kiezen op basis van de invoerafbeelding. Als u wilt dat de invoerafbeelding alle parameters bepaalt waarmee het patroon wordt gemaakt, geeft u NULL- op voor de parameter loadInfo als volgt:

D3DX10CreateTextureFromFile( pDevice, L"sample.bmp", NULL, NULL, &pTexture, NULL );

Het opgeven van NULL voor de laadinformatie is een eenvoudige maar krachtige snelkoppeling.

Nu er een textuur is gemaakt, moet u een shader-resourceweergave maken, zodat de textuur als invoer voor een shader kan worden gebruikt. Aangezien D3DX10CreateTextureFromFile een aanwijzer retourneert naar een resource en niet naar een bitmappatroon, moet u het exacte type resource bepalen dat is geladen. Vervolgens kunt u een shader-resourceweergave maken met behulp van CreateShaderResourceView-.

D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc;
D3D10_RESOURCE_DIMENSION type;
pTexture->GetType( &type );
switch( type )
{
    case D3D10_RESOURCE_DIMENSION_BUFFER:
    //...
    break;
    case D3D10_RESOURCE_DIMENSION_TEXTURE1D:
    //...
    break;
    case D3D10_RESOURCE_DIMENSION_TEXTURE2D:
    {
        D3D10_TEXTURE2D_DESC desc;
        ID3D10Texture2D *pTexture2D = (ID3D10Texture2D*)pTexture;
        pTexture2D->GetDesc( &desc );
        
        srvDesc.Format = desc.Format;
        srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
        srvDesc.Texture2D.MipLevels = desc.MipLevels;
        srvDesc.Texture2D.MostDetailedMip = desc.MipLevels -1;

    }
    break;
    case D3D10_RESOURCE_DIMENSION_TEXTURE3D:
    //...
    break;
    default:
    //...
    break;
}

ID3D10ShaderResourceView *pSRView = NULL;
pDevice->CreateShaderResourceView( pTexture, &srvDesc, &pSRView );

Hoewel in het bovenstaande voorbeeld een 2D-shader-resourceweergave wordt gemaakt, is de code voor het maken van andere typen shader-resourceweergaven vergelijkbaar. Elke shader-fase kan dit patroon nu gebruiken als invoer.

Het gebruik van D3DX10CreateTextureFromFile en CreateShaderResourceView om een textuur en de bijbehorende weergave te maken, is een manier om een textuur voor te bereiden om aan een shaderfase te worden gekoppeld. Een andere manier om dit te doen, is door zowel het patroon als de weergave ervan tegelijkertijd te maken, wat in de volgende sectie wordt besproken.

Textuur en weergave gelijktijdig maken

Direct3D 10 vereist zowel een textuur als een shader-resourceview om tijdens runtime een textuur te lezen. Omdat het maken van een texture en een shader-resource view een dergelijke algemene taak is, biedt D3DX de D3DX10CreateShaderResourceViewFromFile om dit voor je te doen.

D3DX10_IMAGE_LOAD_INFO loadInfo;
ZeroMemory( &loadInfo, sizeof(D3DX10_IMAGE_LOAD_INFO) );
loadInfo.BindFlags = D3D10_BIND_SHADER_RESOURCE;
loadInfo.Format = DXGI_FORMAT_BC1_UNORM;

ID3D10ShaderResourceView *pSRView = NULL;
D3DX10CreateShaderResourceViewFromFile( pDevice, L"sample.bmp", &loadInfo, NULL, &pSRView, NULL );

Met één D3DX-aanroep worden zowel de textuur- als de shader-resourceweergave gemaakt. De functionaliteit van de parameter loadInfo is ongewijzigd; u kunt het gebruiken om aan te passen hoe het patroon wordt gemaakt of om de benodigde parameters van het invoerbestand af te leiden door NULL- op te geven voor de parameter loadInfo.

De ID3D10ShaderResourceView object dat wordt geretourneerd door de D3DX10CreateShaderResourceViewFromFile functie kan later worden gebruikt om de oorspronkelijke ID3D10Resource interface op te halen als dit nodig is. U kunt dit doen door de methode GetResource aan te roepen.

D3DX biedt één functie om een textuur en een weergave van shader-resources te maken als een gemak; het is aan u om te bepalen welke methode voor het maken van een textuur en weergave het beste past bij de behoeften van uw toepassing.

Nu u weet hoe u een textuur en de shader-resourceweergave kunt maken, ziet u in de volgende sectie hoe u een shader kunt gebruiken om van deze textuur een voorbeeld te nemen (aflezen).

Lege patronen maken

Soms willen toepassingen een patroon maken en de gegevens berekenen die in het patroon moeten worden opgeslagen, of de grafische pijplijn gebruiken om deze textuur weer te geven en later de resultaten in andere verwerkingen te gebruiken. Deze texturen kunnen worden bijgewerkt door de grafische pijplijn of door de toepassing zelf, afhankelijk van het type gebruik dat is opgegeven voor de textuur toen deze werd gemaakt.

Weergeven naar een textuur

Het meest voorkomende geval van het maken van een leeg patroon dat tijdens runtime met gegevens moet worden gevuld, is het geval waarin een toepassing een patroon wil weergeven en vervolgens de resultaten van de renderingbewerking in een volgende keer wil gebruiken. Patronen die met dit doel zijn gemaakt, moeten het standaardgebruik van specificeren.

In het volgende codevoorbeeld wordt een lege textuur aangemaakt waarop de pijplijn kan renderen en die vervolgens kan dienen als invoer voor een shader.

// Create the render target texture
D3D10_TEXTURE2D_DESC desc;
ZeroMemory( &desc, sizeof(desc) );
desc.Width = 256;
desc.Height = 256;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
desc.SampleDesc.Count = 1;
desc.Usage = D3D10_USAGE_DEFAULT;
desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;

ID3D10Texture2D *pRenderTarget = NULL;
pDevice->CreateTexture2D( &desc, NULL, &pRenderTarget );

Voor het maken van het patroon moet de toepassing informatie opgeven over de eigenschappen die het patroon heeft. De breedte en hoogte van de textuur in Texels is ingesteld op 256. Voor dit renderdoel is één mipmapniveau alles wat we nodig hebben. Er is slechts één renderdoel vereist, zodat de matrixgrootte is ingesteld op 1. Elke texel bevat vier 32-bits drijvendekommawaarden, die kunnen worden gebruikt om zeer nauwkeurige informatie op te slaan (zie DXGI_FORMAT). Eén voorbeeld per pixel is alles wat u nodig hebt. Het gebruik is standaard ingesteld omdat dit de meest efficiënte plaatsing van het renderdoel in het geheugen mogelijk maakt. Ten slotte wordt opgegeven dat de textuur op verschillende tijdstippen als een renderdoel en als een shader-resource zal worden gebruikt.

Texturen kunnen niet rechtstreeks aan de pijplijn worden gekoppeld; gebruik een render-doelweergave, zoals wordt weergegeven in het volgende codevoorbeeld.

D3D10_RENDER_TARGET_VIEW_DESC rtDesc;
rtDesc.Format = desc.Format;
rtDesc.ViewDimension = D3D10_RTV_DIMENSION_TEXTURE2D;
rtDesc.Texture2D.MipSlice = 0;

ID3D10RenderTargetView *pRenderTargetView = NULL;
pDevice->CreateRenderTargetView( pRenderTarget, &rtDesc, &pRenderTargetView );

De indeling van de render-doelweergave is gewoon ingesteld op de indeling van het oorspronkelijke patroon. De informatie in de resource moet worden geïnterpreteerd als een 2D-patroon en we willen alleen het eerste mipmapniveau van het renderdoel gebruiken.

Net als bij de manier waarop een render-doelweergave moet worden gemaakt, zodat het renderdoel kan worden gebonden aan uitvoer naar de pijplijn, moet er een shader-resourceweergave worden gemaakt, zodat het renderdoel als invoer aan de pijplijn kan worden gebonden. In het volgende codevoorbeeld ziet u dit.

// Create the shader-resource view
D3D10_SHADER_RESOURCE_VIEW_DESC srDesc;
srDesc.Format = desc.Format;
srDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
srDesc.Texture2D.MostDetailedMip = 0;
srDesc.Texture2D.MipLevels = 1;

ID3D10ShaderResourceView *pShaderResView = NULL;
pDevice->CreateShaderResourceView( pRenderTarget, &srDesc, &pShaderResView );

De parameters van shader-resourceweergavebeschrijvingen zijn erg vergelijkbaar met die van renderdoelweergavebeschrijvingen en zijn om dezelfde redenen gekozen.

Texturen handmatig vullen

Soms willen toepassingen tijdens runtime waarden berekenen, ze handmatig in een patroon plaatsen en vervolgens de graphics pijplijn dit patroon gebruiken in latere renderingbewerkingen. Hiervoor moet de toepassing een leeg patroon maken op een zodanige manier dat de CPU toegang heeft tot het onderliggende geheugen. Dit wordt gedaan door een dynamisch patroon te maken en toegang te krijgen tot het onderliggende geheugen door een bepaalde methode aan te roepen. In het volgende codevoorbeeld ziet u hoe u dit doet.

D3D10_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 = D3D10_USAGE_DYNAMIC;
desc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
ID3D10Texture2D *pTexture = NULL;
pd3dDevice->CreateTexture2D( &desc, NULL, &pTexture );

Houd er rekening mee dat de indeling is ingesteld op een 32 bits per pixel, waarbij elk onderdeel wordt gedefinieerd door 8 bits. De gebruiksparameter is ingesteld op dynamisch, terwijl de bindingsvlaggen zijn ingesteld om aan te geven dat de textuur toegankelijk zal zijn door een shader. De rest van de textuurbeschrijving is vergelijkbaar met het maken van een render target.

Door kaart aan te roepen kan de toepassing toegang krijgen tot het onderliggende geheugen van het patroon. De opgehaalde aanwijzer wordt vervolgens gebruikt om het patroon te vullen met gegevens. Dit is te zien in het volgende codevoorbeeld.

D3D10_MAPPED_TEXTURE2D mappedTex;
pTexture->Map( D3D10CalcSubresource(0, 0, 1), D3D10_MAP_WRITE_DISCARD, 0, &mappedTex );

UCHAR* pTexels = (UCHAR*)mappedTex.pData;
for( UINT row = 0; row < desc.Height; row++ )
{
    UINT rowStart = row * mappedTex.RowPitch;
    for( UINT col = 0; col < desc.Width; col++ )
    {
        UINT colStart = col * 4;
        pTexels[rowStart + colStart + 0] = 255; // Red
        pTexels[rowStart + colStart + 1] = 128; // Green
        pTexels[rowStart + colStart + 2] = 64;  // Blue
        pTexels[rowStart + colStart + 3] = 32;  // Alpha
    }
}

pTexture->Unmap( D3D10CalcSubresource(0, 0, 1) );

Meerdere rendertargets

Maximaal acht rendertarget-weergaven kunnen tegelijkertijd aan de pijplijn worden gebonden (met OMSetRenderTargets). Voor elke pixel (of elk voorbeeld als multisampling is ingeschakeld), wordt het combineren onafhankelijk uitgevoerd voor elke render-doelweergave. Twee van de blend-statusvariabelen - BlendEnable en RenderTargetWriteMask - zijn matrices van acht, elk matrixlid komt overeen met een render-doelweergave. Wanneer u meerdere renderdoelen gebruikt, moet elk renderdoel hetzelfde zijn resourcetype (buffer, 1D-patroon, matrix met 2D-patronen, enzovoort) en moet deze dezelfde dimensie hebben (breedte, hoogte, diepte voor 3D-patronen en matrixgrootte voor patroonmatrices). Als de renderdoelen multisampled zijn, moeten ze allemaal hetzelfde aantal steekproeven per pixel hebben.

Er kan slechts één dieptestencilbuffer actief zijn, ongeacht hoeveel renderdoelen actief zijn. Wanneer u patroonmatrices gebruikt als renderdoelen, moeten alle weergavedimensies overeenkomen. De renderdoelen hoeven niet dezelfde structuurindeling te hebben.

Resources (Direct3D 10)