Search code examples
c++graphicstexturesgame-enginedirectx-11

Texture shows as black


I am trying to make a texture to cover a triangle instead of color, but it looks like there is something wrong with the Texture Initialization...

Texture loading is fine, I tried it with Opengl and It worked perfectly however it isn't working in Directx 11.

    void DX11Texture2D::Create(Texture_Data Data, Texture_Desc Desc)
        {
            D3D11_TEXTURE2D_DESC texDesc;
            ZeroMemory(&texDesc, sizeof(texDesc));

            texDesc.Width = Data.width;
            texDesc.Height = Data.height;
            texDesc.MipLevels = 0;
            texDesc.ArraySize = 1;
            texDesc.Format = GetDXTextureFormat(Desc.Format);
            texDesc.SampleDesc.Count = 1;
            texDesc.SampleDesc.Quality = 0;
            texDesc.Usage = D3D11_USAGE_DEFAULT;
            texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
            texDesc.CPUAccessFlags = 0;
            texDesc.MiscFlags = 0;

            D3D11_SUBRESOURCE_DATA subData;


            subData.pSysMem = Data.databuf;
            subData.SysMemPitch = Data.width * 4;
            subData.SysMemSlicePitch = Data.width * Data.height * 4;


            Core::Internals::DX11Renderer::GetDevice()->CreateTexture2D(&texDesc, &subData, &textureID);

            //TODO: Add a way to disable and enable mip map
            Core::Internals::DX11Renderer::GetDevice()->CreateShaderResourceView(textureID, 0, &resourceView);

            D3D11_SAMPLER_DESC samplerDesc;
            ZeroMemory(&samplerDesc, sizeof(D3D11_SAMPLER_DESC));

            samplerDesc.AddressU = GetDXTextureWrap(Desc.Wrap);
            samplerDesc.AddressV = GetDXTextureWrap(Desc.Wrap);
            samplerDesc.AddressW = GetDXTextureWrap(Desc.Wrap);
            samplerDesc.Filter = GetDXTextureFilter(Desc.Filter);
            samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
            samplerDesc.MinLOD = 0;
            samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;

            Core::Internals::DX11Renderer::GetDevice()->CreateSamplerState(&samplerDesc, &samplerState);


        }
        void DX11Texture2D::Bind(unsigned int index)
        {
            Core::Internals::DX11Renderer::GetContext()->PSSetShaderResources(index, 1, &resourceView);
            Core::Internals::DX11Renderer::GetContext()->PSSetSamplers(index, 1, &samplerState);

        }
        DXGI_FORMAT DX11Texture2D::GetDXTextureFormat(API::TextureFormat format)
        {
            switch (format)
            {
            case API::TextureFormat::R8: return DXGI_FORMAT_R8_UNORM;
            case API::TextureFormat::R8G8: return DXGI_FORMAT_R8G8_UNORM;
            case API::TextureFormat::R8G8B8: return DXGI_FORMAT_R8G8B8A8_UNORM;
            case API::TextureFormat::R8G8B8A8: return DXGI_FORMAT_R8G8B8A8_UNORM;
            default: return DXGI_FORMAT_R8G8B8A8_UNORM;
            }
        }
        D3D11_TEXTURE_ADDRESS_MODE DX11Texture2D::GetDXTextureWrap(API::TextureWrap textureWrap)
        {
            switch (textureWrap)
            {
            case API::TextureWrap::Repeat: return D3D11_TEXTURE_ADDRESS_WRAP;
            case API::TextureWrap::MirroredReapeat: return D3D11_TEXTURE_ADDRESS_MIRROR;
            case API::TextureWrap::ClampToEdge: return D3D11_TEXTURE_ADDRESS_CLAMP;
            case API::TextureWrap::ClampToBorder: return D3D11_TEXTURE_ADDRESS_BORDER;
            default: return D3D11_TEXTURE_ADDRESS_WRAP;
            }
        }
        D3D11_FILTER DX11Texture2D::GetDXTextureFilter(API::TextureFilter textureFilter)
        {
            //TODO: Add more texture filter types to control both min and mag
            switch (textureFilter)
            {
            case API::TextureFilter::Nearest: return D3D11_FILTER_MIN_MAG_MIP_POINT;
            case API::TextureFilter::Linear: return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
            default: return D3D11_FILTER_MIN_MAG_MIP_POINT;
            }
        }

Also my shaders

Triangle.vs:

    struct VertexInputType
{
    float3 position : POSITION;
    float3 color : COLOR;
    float2 tex : TEXCOORD;

};

struct PixelInputType
{
    float4 position : SV_POSITION;
    float2 tex : TEXCOORD;
};

PixelInputType main(VertexInputType input)
{
    PixelInputType output;


    // Calculate the position of the vertex against the world, view, and projection matrices.
    output.position = float4(input.position,  1);


    // Store the input texture for the pixel shader to use.
    output.tex = input.tex;

    return output;
}

Triangle.ps

    struct PixelInputType
{
    float4 position : SV_POSITION;
    float2 tex : TEXCOORD;
};

Texture2D shaderTexture : register(t0);;
SamplerState SampleType : register(s0);;

float4 main(PixelInputType input) : SV_TARGET
{
    return shaderTexture.Sample(SampleType, input.tex);
}

Cheers, Zlixine.


Solution

  • It seems you are creating a texture with a full mip map chain, but looking at initial data it looks like you provide only one slice (if your sampler tries to access another slice, since no data was provided, it will be black)

    In that case you should enforce single mip by using :

    texDesc.MipLevels = 1;
    

    The line:

    subData.SysMemSlicePitch = Data.width * Data.height * 4;
    

    is not needed, as this parameter is ignored in case of 2d texture (you can leave it to 0 or any value).

    Also, you should check result codes when creating resources eg:

    HRESULT hr = Core::Internals::DX11Renderer::GetDevice()->CreateTexture2D(&texDesc, &subData, &textureID);
    if FAILED(hr)
    {
        //Handle issue if texture creation did fail
    }
    

    And make sure to use D3D11CreateDevice with D3D11_CREATE_DEVICE_DEBUG, so when debugging, you will have meaningful error messages in your visual studio output window (if creation fails, you will have an explanation instead of getting only INVALIDARG hresult, which is not really useful)