Image

    Image is a buffer with pixel data. I put information in separate struct. And added some usefull methods.

    
    enum class slImageFormat : uint32_t
    {
    	r8g8b8,
    	r8g8b8a8,
    	x1r5g5b5,
    	a4r4g4b4,
    	x4r4g4b4,
    	r5g6b5,
    	a1r5g5b5
    };
    
    struct slImageInfo
    {
    	uint32_t m_width = 0;
    	uint32_t m_height = 0;
    	uint32_t m_bits = 32;
    	uint32_t m_pitch = 0;
    	slImageFormat m_format = slImageFormat::r8g8b8a8;
    };
    
    class slImage
    {
    public:
    	slImage();
    	~slImage();
    
    	uint8_t* m_data = 0;
    	uint32_t m_dataSize = 0;
    	slImageInfo m_info;
    
    	// fast creating
    	void Create(uint32_t x, uint32_t y);
    	
    	// must be created
    	void FlipVertical();
    	// must be created
    	void FlipPixel();
    	// must be created
    	void Fill(const slColor& color);
    	
    	void ConvertTo(slImageFormat);
    };
    

    Image loader

    New library and new abstract class

    
    class slImageLoader
    {
    public:
    	slImageLoader() {}
    	virtual ~slImageLoader() {}
    
    	virtual uint32_t GetSupportedFilesCount() = 0;
    	virtual slString GetSupportedFileExtension(uint32_t) = 0;
    	virtual slString GetSupportedFileName(uint32_t) = 0;
    
    	virtual slImage* Load(const char* path) = 0;
    };
    

    Create the object in new library

    
    extern "C"
    {
    	slImageLoader* SL_CDECL slImageLoaderDefault_create()
    	{
    		slImageLoaderImpl* il = slCreate<slImageLoaderImpl>();
    		return il;
    	}
    }
    

    Image loader implementation class look almost the same with mesh loader.

    
    class slImageLoaderImpl : public slImageLoader{
    	slImage* LoadBMP(const char* path);
    public:
    	slImageLoaderImpl();
    	virtual ~slImageLoaderImpl();
    	virtual uint32_t GetSupportedFilesCount() final;
    	virtual slString GetSupportedFileExtension(uint32_t) final;
    	virtual slString GetSupportedFileName(uint32_t) final;
    	virtual slImage* Load(const char* path) final;
    };
    

    BMP

    Load 32, 24, 16 bits

    
    #pragma pack(push,2)
    struct BitmapHeader {
    	uint16_t		bfType;
    	uint32_t		bfSize;
    	uint16_t		bfReserved1;
    	uint16_t		bfReserved2;
    	uint32_t		bfOffBits;
    };
    #pragma pack(pop)
    
    struct ciexyzTriple {
    	int32_t		ciexyzRed[3];
    	int32_t		ciexyzGreen[3];
    	int32_t		ciexyzBlue[3];
    };
    struct BitmapInfoHeader_v5 {
    	uint32_t			bV5Size;		//	размер header в файле
    	int32_t		bV5Width;		//	ширина
    	int32_t		bV5Height;		//	высота
    	uint16_t	bV5Planes;		//	хз что это, всегда 1
    	uint16_t	bV5BitCount;	//	биты
    	uint32_t	bV5Compression;	//	1 - RLE 8bit, 2 - RLE 4bit, 3 или что-то, видимо, специальные обозначения у разработчиков 2D редакторов.
    	uint32_t	bV5SizeImage;	//	размер массива пикселей/индексов
    	int32_t		bV5XPelsPerMeter;// размер в чём-то, видимо для печати или вывода ещё кудато
    	int32_t		bV5YPelsPerMeter;//	для обычного использования в ПК не играет никакой роли
    	uint32_t	bV5ClrUsed;		//	обычно тут ноль
    	uint32_t	bV5ClrImportant;//	и тут ноль
    	uint32_t	bV5RedMask;		//	для определения позиции цветов
    	uint32_t	bV5GreenMask;	//	в форматах типа x1r5g5b5
    	uint32_t	bV5BlueMask;
    	uint32_t	bV5AlphaMask;
    	uint32_t	bV5CSType;		//	далее информация для более специализированного
    	ciexyzTriple bV5Endpoints;	//	использования.
    	uint32_t	bV5GammaRed;	//	для передачи простой картинки достаточно того
    	uint32_t	bV5GammaGreen;	//	что указано выше. А эта часть нужна для, например,
    	uint32_t	bV5GammaBlue;	//	тех кто делает видео плеер, видео редактор
    	uint32_t	bV5Intent;		//	что-то типа этого. Как бы универсальное решение
    	uint32_t	bV5ProfileData;	//	от Microsoft
    	uint32_t	bV5ProfileSize;
    	uint32_t	bV5Reserved;
    };
    
    slImage* slImageLoaderImpl::LoadBMP(const char* path)
    {
    	SL_ASSERT_ST(path);
    
    	FILE* file = 0;
    	fopen_s(&file, path, "rb");
    	if (!file)
    	{
    		slLog::PrintWarning("BMP: Image could not be opened\n");
    		return NULL;
    	}
    
    	BitmapHeader header;
    	BitmapInfoHeader_v5 info;
    
    	if (fread(&header, 1, sizeof(BitmapHeader), file) != sizeof(BitmapHeader))
    	{
    		slLog::PrintWarning("BMP: Not a correct BMP file\n");
    		fclose(file);
    		return 0;
    	}
    
    	if (header.bfType != 19778)
    	{
    		slLog::PrintWarning("BMP: Not a correct BMP file\n");
    		fclose(file);
    		return 0;
    	}
    
    	fread(&info, 1, sizeof(BitmapInfoHeader_v5), file);
    	if (info.bV5Size < 40U)
    	{
    		slLog::PrintWarning("BMP: Bad header size\n");
    		fclose(file);
    		return 0;
    	}
    
    	if (/*info.bV5BitCount != 1u &&
    		info.bV5BitCount != 4u &&
    		info.bV5BitCount != 8u &&*/
    		info.bV5BitCount != 16u &&
    		info.bV5BitCount != 24u &&
    		info.bV5BitCount != 32u)
    	{
    		slLog::PrintWarning("BMP: Bad bit count\n");
    		fclose(file);
    		return 0;
    	}
    
    	slImageInfo imageInfo;
    
    	slImage* image = NULL;
    	imageInfo.m_width = static_cast<uint32_t>(info.bV5Width);
    	imageInfo.m_height = static_cast<uint32_t>(info.bV5Height);
    	imageInfo.m_bits = info.bV5BitCount;
    	
    	bool flipPixel = false;
    
    	if (imageInfo.m_bits == 24u)
    	{
    		imageInfo.m_format = slImageFormat::r8g8b8;
    		imageInfo.m_pitch = imageInfo.m_width * 3;
    
    		image = slCreate<slImage>();
    		image->m_dataSize = imageInfo.m_pitch * imageInfo.m_height;
    		image->m_data = (uint8_t*)slMemory::malloc(image->m_dataSize);
    
    		fseek(file, 54, SEEK_SET);
    		fread(image->m_data, 1, image->m_dataSize, file);
    		flipPixel = true;
    	}
    	else if (imageInfo.m_bits == 32u)
    	{
    		imageInfo.m_pitch = imageInfo.m_width * 4;
    		uint32_t offset = header.bfOffBits;
    
    		if (info.bV5Compression == 3 || info.bV5Compression == 0) // BI_BITFIELDS
    		{
    			fseek(file, offset, SEEK_SET);
    			imageInfo.m_format = slImageFormat::r8g8b8a8;
    
    			image = slCreate<slImage>();
    			image->m_dataSize = imageInfo.m_pitch * imageInfo.m_height;
    			image->m_data = (uint8_t*)slMemory::malloc(image->m_dataSize);
    
    			fread(image->m_data, 1, image->m_dataSize, file);
    			image->FlipPixel();
    		}
    		else
    		{
    			slLog::PrintWarning("BMP: unsupported format\n");
    			fclose(file);
    			return 0;
    		}
    	}
    	else if (imageInfo.m_bits == 16u)
    	{
    		if (info.bV5Size != 40U && info.bV5Size != 56u)
    		{
    			slLog::PrintWarning("BMP: unsupported format\n");
    			fclose(file);
    			return 0;
    		}
    
    		imageInfo.m_pitch = imageInfo.m_width * 2;
    
    		if (info.bV5RedMask == 3840 &&
    			info.bV5GreenMask == 240 &&
    			info.bV5BlueMask == 15)
    		{
    			if (info.bV5AlphaMask)
    			{
    				imageInfo.m_format = slImageFormat::a4r4g4b4;
    			}
    			else
    			{
    				imageInfo.m_format = slImageFormat::x4r4g4b4;
    			}
    		}
    		else if (info.bV5RedMask == 63488 &&
    			info.bV5GreenMask == 2016 &&
    			info.bV5BlueMask == 31)
    		{
    			imageInfo.m_format = slImageFormat::r5g6b5;
    		}
    		else if (info.bV5RedMask == 31744 &&
    			info.bV5GreenMask == 992 &&
    			info.bV5BlueMask == 31)
    		{
    			if (info.bV5AlphaMask)
    				imageInfo.m_format = slImageFormat::a1r5g5b5;
    		}
    		else
    		{
    			imageInfo.m_format = slImageFormat::x1r5g5b5;
    		}
    		fseek(file, 70, SEEK_SET);
    		image = slCreate<slImage>();
    		image->m_dataSize = imageInfo.m_pitch * imageInfo.m_height;
    		image->m_data = (uint8_t*)slMemory::malloc(image->m_dataSize);
    
    		fread(image->m_data, 1, image->m_dataSize, file);
    	}
    
    	if (image)
    	{
    		image->m_info = imageInfo;
    		image->ConvertTo(slImageFormat::r8g8b8a8);
    		image->FlipVertical();
    		if (flipPixel)
    			image->FlipPixel();
    	}
    
    	return image;
    }
    

    Loading. Add methods in slFramework (I also renamed LoadMesh into SummonMesh)

    
    static uint32_t GetImageLoadersNum();
    static slImageLoader* GetImageLoader(uint32_t);
    static slImage* SummonImage(const char*);
    

    Implementation

    
    uint32_t slFramework::GetImageLoadersNum()
    {
    	return (uint32_t)g_framework->m_imageLoaders.size();
    }
    
    slImageLoader* slFramework::GetImageLoader(uint32_t i)
    {
    	SL_ASSERT_ST(i < g_framework->m_imageLoaders.size());
    	return g_framework->m_imageLoaders[i];
    }
    
    slImage* slFramework::SummonImage(const char* path)
    {
    	slStringA stra;
    	std::filesystem::path p = path;
    	auto e = p.extension();
    	uint32_t mln = GetImageLoadersNum();
    	for (uint32_t i = 0; i < mln; ++i)
    	{
    		auto il = GetImageLoader(i);
    		auto sfc = il->GetSupportedFilesCount();
    		for (uint32_t o = 0; o < sfc; ++o)
    		{
    			slString sfe = il->GetSupportedFileExtension(o);
    			sfe.insert(U".", 0);
    			sfe.to_lower();
    			sfe.to_utf8(stra);
    			auto stre = lowercase(e.generic_string());
    			if (strcmp((const char*)stra.m_data, stre.c_str()) == 0)
    			{
    				return il->Load(path);
    			}
    		}
    	}
    	return NULL;
    }
    

    Add function and link lib

    
    extern "C"
    {
    	slGS* SL_CDECL slGSD3D11_create();
    	slMeshLoader* SL_CDECL slMeshLoaderOBJ_create();
    	slImageLoader* SL_CDECL slImageLoaderDefault_create(); //new
    }
    SL_LINK_LIBRARY("slowlib.d3d11");
    SL_LINK_LIBRARY("slowlib.meshloader");
    SL_LINK_LIBRARY("slowlib.imageloader"); //new
    
    ...
    
    g_framework->m_imageLoaders.push_back(slImageLoaderDefault_create());
    

    Texture

    Add new abstract class and more other things

    
    enum class slTextureType : uint32_t
    {
    	Texture2D,
    	RTT
    };
    
    enum class slTextureComparisonFunc : uint32_t
    {
    	Never,
    	Less,
    	Equal,
    	LessEqual,
    	Greater,
    	NotEqual,
    	GreaterEqual,
    	Always
    };
    
    enum class slTextureAddressMode : uint32_t
    {
    	Wrap,
    	Mirror,
    	Clamp,
    	Border,
    	MirrorOnce
    };
    
    enum class slTextureFilter : uint32_t
    {
    	// min mag mip / point linear
    	PPP,
    	PPL,
    	PLP,
    	PLL,
    	LPP,
    	LPL,
    	LLP,
    	LLL,
    	ANISOTROPIC,
    	// comparison
    	CMP_PPP,
    	CMP_PPL,
    	CMP_PLP,
    	CMP_PLL,
    	CMP_LPP,
    	CMP_LPL,
    	CMP_LLP,
    	CMP_LLL,
    	CMP_ANISOTROPIC,
    };
    
    struct slTextureInfo
    {
    	slImageInfo m_info;
    	slTextureType m_type = slTextureType::Texture2D;
    	slTextureComparisonFunc m_cmpFnc = slTextureComparisonFunc::Always;
    	slTextureAddressMode m_adrMode = slTextureAddressMode::Wrap;
    	slTextureFilter m_filter = slTextureFilter::PPP;
    	uint32_t m_anisotropicLevel = 1;
    };
    
    class slTexture
    {
    protected:
    	slTextureInfo m_info;
    public:
    	slTexture() {}
    	virtual ~slTexture() {}
    
    	const slTextureInfo& GetInfo() { return m_info; }
    };
    

    GPU texture

    
    class slGSD3D11Texture : public slTexture
    {
    public:
    	slGSD3D11Texture();
    	virtual ~slGSD3D11Texture();
    
    	ID3D11Texture2D* m_texture = 0;
    	ID3D11ShaderResourceView* m_textureResView = 0;
    	ID3D11SamplerState* m_samplerState = 0;
    	ID3D11RenderTargetView* m_RTV = 0;
    
    	slTextureInfo m_textureInfo;
    };
    

    Destructor

    
    slGSD3D11Texture::~slGSD3D11Texture()
    {
    	SLD3DSAFE_RELEASE(m_RTV);
    	SLD3DSAFE_RELEASE(m_samplerState);
    	SLD3DSAFE_RELEASE(m_textureResView);
    	SLD3DSAFE_RELEASE(m_texture);
    }
    

    Texture creation. Add new method in GS

    
    virtual slTexture* SummonTexture(slImage*, const slTextureInfo&) = 0;
    

    Implementation

    
    slTexture* slGSD3D11::SummonTexture(slImage* img, const slTextureInfo& inf)
    {
    	SL_ASSERT_ST(img);
    	slGSD3D11Texture* newTexture = 0;
    
    	ID3D11Texture2D* _texture = 0;
    	ID3D11ShaderResourceView* _textureResView = 0;
    	ID3D11SamplerState* _samplerState = 0;
    	ID3D11RenderTargetView* _RTV = 0;
    	D3D11_FILTER filter;
    	slTextureFilter tf = inf.m_filter;
    	switch (tf)
    	{
    	case slTextureFilter::PPP:
    		filter = D3D11_FILTER::D3D11_FILTER_MIN_MAG_MIP_POINT;
    		break;
    	case slTextureFilter::PPL:
    		filter = D3D11_FILTER::D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
    		break;
    	case slTextureFilter::PLP:
    		filter = D3D11_FILTER::D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
    		break;
    	case slTextureFilter::PLL:
    		filter = D3D11_FILTER::D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR;
    		break;
    	case slTextureFilter::LPP:
    		filter = D3D11_FILTER::D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
    		break;
    	case slTextureFilter::LPL:
    		filter = D3D11_FILTER::D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
    		break;
    	case slTextureFilter::LLP:
    		filter = D3D11_FILTER::D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
    		break;
    	case slTextureFilter::LLL:
    		filter = D3D11_FILTER::D3D11_FILTER_MIN_MAG_MIP_LINEAR;
    		break;
    	case slTextureFilter::ANISOTROPIC:
    		filter = D3D11_FILTER::D3D11_FILTER_ANISOTROPIC;
    		break;
    	case slTextureFilter::CMP_PPP:
    		filter = D3D11_FILTER::D3D11_FILTER_COMPARISON_MIN_MAG_MIP_POINT;
    		break;
    	case slTextureFilter::CMP_PPL:
    		filter = D3D11_FILTER::D3D11_FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR;
    		break;
    	case slTextureFilter::CMP_PLP:
    		filter = D3D11_FILTER::D3D11_FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT;
    		break;
    	case slTextureFilter::CMP_PLL:
    		filter = D3D11_FILTER::D3D11_FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR;
    		break;
    	case slTextureFilter::CMP_LPP:
    		filter = D3D11_FILTER::D3D11_FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT;
    		break;
    	case slTextureFilter::CMP_LPL:
    		filter = D3D11_FILTER::D3D11_FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
    		break;
    	case slTextureFilter::CMP_LLP:
    		filter = D3D11_FILTER::D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT;
    		break;
    	case slTextureFilter::CMP_LLL:
    		filter = D3D11_FILTER::D3D11_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR;
    		break;
    	case slTextureFilter::CMP_ANISOTROPIC:
    		filter = D3D11_FILTER::D3D11_FILTER_COMPARISON_ANISOTROPIC;
    		break;
    	default:
    		break;
    	}
    
    	HRESULT hr = 0;
    	if (inf.m_type == slTextureType::Texture2D)
    	{
    		D3D11_TEXTURE2D_DESC desc;
    		ZeroMemory(&desc, sizeof(desc));
    		desc.Width = img->m_info.m_width;
    		desc.Height = img->m_info.m_height;
    		desc.SampleDesc.Count = 1;
    		desc.SampleDesc.Quality = 0;
    
    		bool isGenMips = inf.m_generateMipmaps;
    
    		switch (img->m_info.m_format)
    		{
    		case slImageFormat::r8g8b8a8:
    		{
    			desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    			desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
    			desc.MiscFlags = 0;
    			desc.MipLevels = 1;
    
    			desc.ArraySize = 1;
    			desc.Usage = D3D11_USAGE_DEFAULT;
    			desc.CPUAccessFlags = 0;
    
    			if (isGenMips)
    			{
    				desc.MipLevels = 0;
    				desc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;
    				hr = m_d3d11Device->CreateTexture2D(&desc, 0, &_texture);
    				if (FAILED(hr))
    				{
    					slLog::PrintError("Can't create 2D texture\n");
    					goto fail;
    				}
    				m_d3d11DevCon->UpdateSubresource(_texture, 0, NULL, img->m_data, img->m_info.m_pitch, 0);
    			}
    			else
    			{
    				D3D11_SUBRESOURCE_DATA initData;
    				ZeroMemory(&initData, sizeof(initData));
    				initData.pSysMem = img->m_data;
    				initData.SysMemPitch = img->m_info.m_pitch;
    				initData.SysMemSlicePitch = img->m_dataSize;
    				hr = m_d3d11Device->CreateTexture2D(&desc, &initData, &_texture);
    				if (FAILED(hr))
    				{
    					slLog::PrintError("Can't create 2D texture\n");
    					goto fail;
    				}
    			}
    
    
    			D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
    			ZeroMemory(&SRVDesc, sizeof(SRVDesc));
    			SRVDesc.Format = desc.Format;
    			SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
    			SRVDesc.Texture2D.MostDetailedMip = 0;
    			SRVDesc.Texture2D.MipLevels = 1;
    			if (isGenMips)
    				SRVDesc.Texture2D.MipLevels = -1;
    
    			hr = m_d3d11Device->CreateShaderResourceView(_texture,
    				&SRVDesc, &_textureResView);
    			if (FAILED(hr))
    			{
    				slLog::PrintError("Can't create shader resource view\n");
    				goto fail;
    			}
    		}break;
    		default:
    			slLog::PrintError("Unsupported texture format\n");
    			goto fail;
    		}
    		if (isGenMips)
    			m_d3d11DevCon->GenerateMips(_textureResView);
    	}
    	else
    	{
    		D3D11_TEXTURE2D_DESC desc;
    		ZeroMemory(&desc, sizeof(desc));
    		desc.Width = img->m_info.m_width;
    		desc.Height = img->m_info.m_height;
    		desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    		desc.SampleDesc.Count = 1;
    		desc.SampleDesc.Quality = 0;
    		desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
    		desc.MiscFlags = 0;
    		desc.ArraySize = 1;
    		desc.MipLevels = 1;
    		desc.Usage = D3D11_USAGE_DEFAULT;
    		desc.CPUAccessFlags = 0;
    
    		hr = m_d3d11Device->CreateTexture2D(&desc, NULL, &_texture);
    		if (FAILED(hr))
    		{
    			slLog::PrintError("Can't create render target texture\n");
    			goto fail;
    		}
    		D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
    		renderTargetViewDesc.Format = desc.Format;
    		renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
    		renderTargetViewDesc.Texture2D.MipSlice = 0;
    		hr = m_d3d11Device->CreateRenderTargetView(_texture, &renderTargetViewDesc, &_RTV);
    		if (FAILED(hr))
    		{
    			slLog::PrintError("Can't create render target view\n");
    			goto fail;
    		}
    
    
    
    		D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
    		ZeroMemory(&SRVDesc, sizeof(SRVDesc));
    		SRVDesc.Format = desc.Format;
    		SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
    		SRVDesc.Texture2D.MostDetailedMip = 0;
    		SRVDesc.Texture2D.MipLevels = 1;
    
    		hr = m_d3d11Device->CreateShaderResourceView(_texture,
    			&SRVDesc, &_textureResView);
    		if (FAILED(hr))
    		{
    			slLog::PrintError("Can't create shader resource view\n");
    			goto fail;
    		}
    
    		//goto success;
    	}
    
    	D3D11_TEXTURE_ADDRESS_MODE tam;
    	switch (inf.m_adrMode)
    	{
    	case slTextureAddressMode::Wrap:
    	default:
    		tam = D3D11_TEXTURE_ADDRESS_WRAP;
    		break;
    	case slTextureAddressMode::Mirror:
    		tam = D3D11_TEXTURE_ADDRESS_MIRROR;
    		break;
    	case slTextureAddressMode::Clamp:
    		tam = D3D11_TEXTURE_ADDRESS_CLAMP;
    		break;
    	case slTextureAddressMode::Border:
    		tam = D3D11_TEXTURE_ADDRESS_BORDER;
    		break;
    	case slTextureAddressMode::MirrorOnce:
    		tam = D3D11_TEXTURE_ADDRESS_MIRROR_ONCE;
    		break;
    	}
    
    	D3D11_COMPARISON_FUNC cmpFunc;
    	switch (inf.m_cmpFnc)
    	{
    	case slTextureComparisonFunc::Never:
    		cmpFunc = D3D11_COMPARISON_NEVER;
    		break;
    	case slTextureComparisonFunc::Less:
    		cmpFunc = D3D11_COMPARISON_LESS;
    		break;
    	case slTextureComparisonFunc::Equal:
    		cmpFunc = D3D11_COMPARISON_EQUAL;
    		break;
    	case slTextureComparisonFunc::LessEqual:
    		cmpFunc = D3D11_COMPARISON_LESS_EQUAL;
    		break;
    	case slTextureComparisonFunc::Greater:
    		cmpFunc = D3D11_COMPARISON_GREATER;
    		break;
    	case slTextureComparisonFunc::NotEqual:
    		cmpFunc = D3D11_COMPARISON_NOT_EQUAL;
    		break;
    	case slTextureComparisonFunc::GreaterEqual:
    		cmpFunc = D3D11_COMPARISON_GREATER_EQUAL;
    		break;
    	case slTextureComparisonFunc::Always:
    	default:
    		cmpFunc = D3D11_COMPARISON_ALWAYS;
    		break;
    	}
    
    	hr = createSamplerState(filter, tam, inf.m_anisotropicLevel,
    		&_samplerState, cmpFunc);
    	if (FAILED(hr))
    	{
    		slLog::PrintError("Can't create sampler state\n");
    		goto fail;
    	}
    
    	newTexture = slCreate<slGSD3D11Texture>();
    	newTexture->m_RTV = _RTV;
    	newTexture->m_samplerState = _samplerState;
    	newTexture->m_textureResView = _textureResView;
    	newTexture->m_texture = _texture;
    	newTexture->m_textureInfo = inf;
    	newTexture->m_textureInfo.m_imageInfo = img->m_info;
    	return newTexture;
    
    fail:;
    	SLD3DSAFE_RELEASE(_RTV);
    	SLD3DSAFE_RELEASE(_samplerState);
    	SLD3DSAFE_RELEASE(_textureResView);
    	SLD3DSAFE_RELEASE(_texture);
    	return NULL;
    }
    

    I don't want to think a lot so just use goto. And there is also Render Target Texture

    slGSD3D11::createSamplerState

    
    HRESULT	slGSD3D11::createSamplerState(D3D11_FILTER filter,
    	D3D11_TEXTURE_ADDRESS_MODE addressMode,
    	uint32_t anisotropic_level,
    	ID3D11SamplerState** samplerState,
    	D3D11_COMPARISON_FUNC cmpFunc)
    {
    	D3D11_SAMPLER_DESC samplerDesc;
    	ZeroMemory(&samplerDesc, sizeof(samplerDesc));
    	samplerDesc.Filter = filter;
    	samplerDesc.MipLODBias = 0.0f;
    
    	samplerDesc.AddressU = addressMode;
    	samplerDesc.AddressV = addressMode;
    	samplerDesc.AddressW = addressMode;
    
    	samplerDesc.ComparisonFunc = cmpFunc; //D3D11_COMPARISON_ALWAYS;
    	samplerDesc.MinLOD = 0;
    	samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
    
    	samplerDesc.MaxAnisotropy = anisotropic_level;
    	return m_d3d11Device->CreateSamplerState(&samplerDesc, samplerState);
    }
    

    Using in shader

    
    "Texture2D tex2d_1;\n"
    "SamplerState tex2D_sampler_1;\n"
    ...
    "   output.color = tex2d_1.Sample(tex2D_sampler_1, input.uv) * BaseColor;\n"
    
    
    if (material->m_maps[0].m_texture)
    {
    	slGSD3D11Texture* _t = (slGSD3D11Texture*)material->m_maps[0].m_texture;
    	m_gs->m_d3d11DevCon->PSSetShaderResources(0, 1, &_t->m_textureResView);
    	m_gs->m_d3d11DevCon->PSSetSamplers(0, 1, &_t->m_samplerState);
    }
    

    Using in app. Modify class from previous article

    
    bool Load(const char* p)
    {
    	m_cb.m_model = this;
    	slFramework::SummonMesh(p, &m_cb);
    
    	slImage* image = slFramework::SummonImage("D:\\moon_64.bmp");
    	if (image)
    	{
    		printf("Image %ix%i\n", image->m_info.m_width, image->m_info.m_height);
    		slTextureInfo ti;
    		m_texture = m_gs->SummonTexture(image, ti);
    		m_material.m_maps[0].m_texture = m_texture;
    		slDestroy(image);
    	}
    
    	return m_meshBuffers.m_size > 0;
    }
    
    void Draw(slCamera* camera)
    	{
    		m_WVP = camera->m_projectionMatrix * camera->m_viewMatrix * m_W;
    		m_material.m_sunPosition.set(0.f, 1.f, 0.f);
    
    		slFramework::SetMatrix(slMatrixType::World, &m_W);
    		slFramework::SetMatrix(slMatrixType::WorldViewProjection, &m_WVP);
    		for (size_t i = 0; i < m_meshBuffers.m_size; ++i)
    		{			
    			m_gs->SetMesh(m_meshBuffers.m_data[i]);
    			m_gs->SetMaterial(&m_material);
    			m_gs->Draw();
    		}
    	}
    
    Download