1
votes

I am new to Direct3D11 and I am currently trying to create a texture programatically within my code using this code I found online:

// Some Constants
int w = 256;
int h = 256;
int bpp = 4;
int *buf = new int[w*h];

//declarations
ID3D11Texture2D* tex;
D3D11_TEXTURE2D_DESC sTexDesc;
D3D11_SUBRESOURCE_DATA tbsd;

// filling the image
for (int i = 0; i<h; i++)
    for (int j = 0; j<w; j++)
    {
        if ((i & 32) == (j & 32))
            buf[i*w + j] = 0x00000000;
        else
            buf[i*w + j] = 0xffffffff;
    }

// setting up D3D11_SUBRESOURCE_DATA 
tbsd.pSysMem = (void *)buf;
tbsd.SysMemPitch = w*bpp;
tbsd.SysMemSlicePitch = w*h*bpp; // Not needed since this is a 2d texture

// initializing sTexDesc
sTexDesc.Width = w;
sTexDesc.Height = h;
sTexDesc.MipLevels = 1;
sTexDesc.ArraySize = 1;
sTexDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sTexDesc.SampleDesc.Count = 1;
sTexDesc.SampleDesc.Quality = 0;
sTexDesc.Usage = D3D11_USAGE_DEFAULT;
sTexDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
sTexDesc.CPUAccessFlags = 0;
sTexDesc.MiscFlags = 0;

hr = m_pd3dDevice->CreateTexture2D(&sTexDesc, &tbsd, &tex);

and that' all fine and dandy, but I am a bit confused about how to actually load this into the shader. Below I initialized this ID3D11ShaderResourceView:

        ID3D11ShaderResourceView*           m_pTextureRV = nullptr;

I found on the Microsoft tutorials I need to use the CreateShaderResourceView. But how exactly do I use it? I tried this:

        hr = m_pd3dDevice->CreateShaderResourceView(tex, NULL , m_pTextureRV);

but it gives me an error, telling me that m_pTextureRV is not a valid argument for the function. What am I doing wrong here?

1

1 Answers

0
votes

The correct way to call that function is:

hr = m_pd3dDevice->CreateShaderResourceView(tex, nullptr, &m_pTextureRV);

Remember that ID3D11ShaderResourceView* is a pointer to an interface. You need a pointer-to-a-pointer to get a new instance of one back.

You should really consider using a COM smart-pointer like Microsoft::WRL::ComPtr instead of raw pointers for these interfaces.

Once you have created the shader resource view for your texture object, then you need to associate it with whatever slot the HLSL expects to find it in. So, for example, if you were to write an HLSL source file as:

Texture2D texture : register( t0 );
SamplerState sampler: register( s0 );

float4 PS(float2 tex : TEXCOORD0) : SV_Target
{
    return texture.Sample( sampler, tex );
}

Then compile it as a Pixel Shader, and bind it to the render pipeline via PSSetShader. Then you'd need to call:

ID3D11ShaderResourceView* srv[1] = { m_pTextureRV };
m_pImmediateContext->PSSetShaderResources( 0, 1, srv );

Of course you also need a ID3D11SamplerState* sampler bound as well:

ID3D11SamplerState* m_pSamplerLinear = nullptr;

D3D11_SAMPLER_DESC sampDesc = {};
sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
sampDesc.MinLOD = 0;
sampDesc.MaxLOD = D3D11_FLOAT32_MAX;
hr = m_pd3dDevice->CreateSamplerState( &sampDesc, &m_pSamplerLinear );

Then when you are about to draw:

m_pImmediateContext->PSSetSamplers( 0, 1, &m_pSamplerLinear );

I strongly recommend you check out the DirectX Tool Kit and the tutorials there.