Sdílet prostřednictvím


Vytváření prostředků textury (Direct3D 10)

textury zdroj je strukturovaná kolekce dat. Hodnoty barev se obvykle ukládají v texturách a při vykreslování kanálem v různých fázích pro vstup i výstup. Vytváření textur a definování způsobu jejich použití je důležitou součástí vykreslování zajímavých scén v Direct3D 10.

I když textury obvykle obsahují informace o barvě, vytváření textur pomocí různých DXGI_FORMAT jim umožňuje ukládat různé druhy dat. Tato data pak může kanál Direct3D 10 využívat jiným než tradičním způsobem.

Všechny textury mají omezení, kolik paměti spotřebovávají, a kolik texelů obsahují. Tato omezení jsou určena konstantami prostředků .

Vytvoření textury ze souboru

Poznámka

Knihovna nástrojů D3DX je pro Windows 8 zastaralá a nepodporuje se pro aplikace pro Windows Store.

 

Při vytváření textury v Direct3D 10 je také nutné vytvořit zobrazení. Zobrazení je objekt, který zařízení říká, jak má být textura při vykreslování přístupná. Nejběžnějším způsobem, jak získat přístup k textuře, je její čtení pomocí shaderu. Zobrazení prostředků shaderu určí shaderu, jak během vykreslování číst z textury. Typ zobrazení, které bude textura používat, musí být zadán při jeho vytvoření.

Vytvoření textury a načtení počátečních dat lze provést dvěma různými způsoby: vytvořit texturu a zobrazení samostatně, nebo vytvořit texturu i zobrazení najednou. Rozhraní API poskytuje obě techniky, abyste si mohli vybrat, které lépe vyhovuje vašim potřebám.

Vytvoření textury a zobrazení samostatně

Nejjednodušší způsob, jak vytvořit texturu, je načíst ji ze souboru obrázku. Pokud chcete vytvořit texturu, stačí vyplnit jednu strukturu a zadat název textury 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 );

Funkce D3DX D3DX10CreateTextureFromFile dělá tři věci: nejprve vytvoří objekt textury Direct3D 10; za druhé, přečte vstupní soubor obrázku; za třetí uloží data obrázku do objektu textury. V ukázce výše se načte soubor BMP, ale funkce může načíst různé typy souborů.

Příznak vazby označuje, že textura bude vytvořena jako zdroj shaderu, což umožňuje stupni shaderu číst z textury během vykreslování.

Výše uvedený příklad nespecifikuje všechny parametry načítání. Ve skutečnosti je často výhodné jednoduše vynulovat parametry načítání, protože to umožňuje D3DX zvolit vhodné hodnoty na základě vstupního obrázku. Pokud chcete, aby vstupní obrázek určil všechny parametry, se kterými se textura vytvoří, jednoduše zadejte NULL pro parametr loadInfo takto:

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

Zadání NULL pro informace o načítání je jednoduchá, ale výkonná zkratka.

Nyní, když byla vytvořena textura, je třeba vytvořit zobrazení shaderového zdroje, aby textura mohla být vázána jako vstup do shaderu. Vzhledem k tomu, že D3DX10CreateTextureFromFile vrací ukazatel na zdroj, a nikoli ukazatel na texturu, je potřeba určit přesný typ načteného zdroje, a poté můžete vytvořit zobrazení shader- prostředku pomocí 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 );

I když výše uvedená ukázka vytvoří zobrazení 2D shader-resource, kód pro vytvoření dalších typů zobrazení shader-resource je velmi podobný. Každá fáze shaderu teď může tuto texturu použít jako vstup.

Použití D3DX10CreateTextureFromFile a CreateShaderResourceView k vytvoření textury a jeho přidruženého zobrazení je jedním ze způsobů, jak připravit texturu, která se má svázat s fází shaderu. Dalším způsobem, jak to udělat, je vytvořit texturu i jeho zobrazení současně, což je popsáno v další části.

Vytvoření textury a zobrazení současně

Direct3D 10 vyžaduje texturu i zobrazení prostředků shaderu ke čtení z textury během běhu. Vzhledem k tomu, že vytvoření textury a zobrazení zdroje shaderu je takový běžný úkol, D3DX poskytuje D3DX10CreateShaderResourceViewFromFile, aby to udělal za vás.

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 );

Při jednom volání D3DX se vytvoří zobrazení textury i zobrazení zdrojů shaderu. Funkce parametru loadInfo se nezmění; Můžete ho použít k přizpůsobení způsobu vytvoření textury nebo odvození nezbytných parametrů ze vstupního souboru zadáním NULL pro parametr loadInfo.

ID3D10ShaderResourceView objekt vrácený funkcí D3DX10CreateShaderResourceViewFromFile lze později použít k načtení původního ID3D10Resource rozhraní, pokud je potřeba. To lze provést voláním metody GetResource.

D3DX poskytuje jedinou funkci pro vytvoření textury a zobrazení prostředků shaderu jako pohodlí; je na vás, abyste se rozhodli, která metoda vytvoření textury a zobrazení nejlépe vyhovuje potřebám vaší aplikace.

Teď, když víte, jak vytvořit texturu a její zobrazení v podobě zdroje shaderu, v další části se dozvíte, jak můžete z této textury vzorkovat, tedy číst, pomocí shaderu.

Vytváření prázdných textur

Aplikace někdy budou chtít vytvořit texturu a vypočítat data, která mají být uložena v texturě, nebo použít grafické kanál k vykreslení této textury a později použít výsledky při jiném zpracování. Tyto textury mohou být aktualizovány grafickým kanálem nebo samotnou aplikací v závislosti na tom, jaký druh použití byl zadán pro texturu při jeho vytvoření.

Vykreslení na texturu

Nejběžnějším případem vytvoření prázdné textury, která se má vyplnit daty během běhu, je případ, kdy aplikace chce vykreslit texturu a následně použít výsledky operace vykreslování v následném průchodu. Textury vytvořené pro tento účel by měly určovat výchozí využití.

Následující ukázka kódu vytvoří prázdnou texturu, kterou kanál může vykreslit a následně použít jako vstup 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 );

Vytvoření textury vyžaduje, aby aplikace zadala určité informace o vlastnostech textury. Šířka a výška textury v texelech je nastavena na 256. Pro tento cílový renderovací povrch potřebujeme pouze jednu úroveň mipmap. Vyžaduje se jenom jeden cíl vykreslení, takže velikost pole je nastavená na 1. Každý texel obsahuje čtyři 32bitové hodnoty s plovoucí desetinou čárkou, které lze použít k ukládání velmi přesných informací (viz DXGI_FORMAT). Jeden vzorek na pixel je vše, co bude potřeba. Použití je nastavené na výchozí, protože to umožňuje nejúčinnější umístění cíle vykreslení v paměti. Nakonec je specifikováno, že textura bude v různých časových bodech vázaná jako cíl vykreslení a zdroj shaderu.

Textury nelze svázat přímo pro vykreslování v renderovacím kanálu; použijte zobrazení cílového objektu vykreslování, jak je znázorněno v následující ukázce kódu.

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 );

Formát zobrazení cíle vykreslování je jednoduše nastaven na formát původní textury. Informace v prostředku by se měly interpretovat jako 2D textura, a chceme použít pouze první úroveň mipmapy renderovacího cíle.

Podobně jako je třeba vytvořit zobrazení cíle vykreslování, aby mohl být cíl vykreslování svázán jako výstup na potrubí, musí být vytvořeno zobrazení prostředků shaderu, aby mohl být cíl vykreslování svázán jako vstup do potrubí. Následující ukázka kódu to ukazuje.

// 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 );

Parametry popisů zobrazení zdrojových shaderů jsou velmi podobné parametrům popisů zobrazení cílů vykreslení, a popisy byly vybrány ze stejných důvodů.

Ruční vyplňování textur

Někdy by aplikace chtěly vypočítat hodnoty za běhu, umístit je do textury ručně a pak mají grafické kanál tuto texturu použít v pozdějších operacích vykreslování. Aby to bylo možné, musí aplikace vytvořit prázdnou texturu takovým způsobem, aby procesor mohl přistupovat k podkladové paměti. To se provádí vytvořením dynamické textury a získáním přístupu k podkladové paměti voláním konkrétní metody. Následující ukázka kódu ukazuje, jak to provést.

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 );

Všimněte si, že formát je nastaven na 32 bitů na pixel, kde každá komponenta je definována 8 bity. Parametr použití je nastaven na dynamický a příznaky vazby jsou nastaveny tak, aby specifikovaly, že k textuře bude přistupováno pomocí shaderu. Zbytek popisu textury je podobný vytváření vykreslovacího cíle.

Volání Map umožňuje aplikaci přistupovat k podkladové paměti textury. Načítaný ukazatel se pak použije k vyplnění textury daty. To je vidět v následující ukázce kódu.

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) );

Několik objektů Rendertarget

Až osm zobrazení cíle vykreslování lze svázat s potrubím najednou (s OMSetRenderTargets). Pro každý pixel (nebo každý vzorek, pokud je povoleno vícevzorkování) se míchání provádí nezávisle pro každý vykreslovací cíl. Dvě proměnné stavu blendu – BlendEnable a RenderTargetWriteMask – jsou pole o osmi prvcích, každý člen pole odpovídá pohledu na cíl vykreslování. Při použití více cílů vykreslení musí být každý cíl vykreslení stejného typu prostředku (buffer, 1D textura, 2D textura pole atd.) a musí mít stejné rozměry (šířku, výšku a hloubku u 3D textur a velikost pole u texturových polí). Pokud jsou cíle vykreslování vícevzorkové, musí mít všechny stejný počet vzorků na pixel.

Může být aktivní pouze jeden hloubkový a šablonový buffer, bez ohledu na počet aktivních cílů vykreslování. Při použití texturových polí jako cílů vykreslení se musí shodovat všechny dimenze zobrazení. Cíle vykreslování nemusí mít stejný formát textury.

Zdroje (Direct3D 10)