使用mipmap,用于解决 纹理过大 (屏幕像素对应到纹理的区域包含大量纹素,此时采样结果无法代表整体颜色)闪烁的问题
//ShaderResourceView.h
#pragma once
#include "Bindable.h"
#include <string>
#include <vector>
#include <d3dcompiler.h> //D3DReflect
class ShaderResourceView :public Bindable
{
protected:
vector<ComPtr<ID3D11ShaderResourceView>> pShaderViews;
UINT slot;
vector<wstring> FilesBeenUsed; // 第一个file对应的图片 放在 register(t slot), 第二个图片 放在 register(t slot+1)
//构造:输入 可变参数 - 文件名:
public:
template<typename ...Args>
ShaderResourceView(shared_ptr<Graphics> gfx, UINT slot, Args... FileNames);
private:
template<typename ...Args>
void DealWithMutiArgus(wstring fileName_BitMap, Args... FileNames);
void DealWithMutiArgus();
//构造:输入某个VSBlob或PSblob
public:
ShaderResourceView(shared_ptr<Graphics> gfx, UINT slot, ComPtr<ID3DBlob> blob);
UINT GetSRVNum();
void SetFileName(wstring fileName_BitMap, UINT fileArrayIndex);
public:
virtual void Load() override;
virtual void Bind() override = 0;
};
template<typename ...Args>
ShaderResourceView::ShaderResourceView(shared_ptr<Graphics> gfx, UINT slot, Args... FileNames)
:Bindable(gfx), slot{slot}
{
DealWithMutiArgus(FileNames...);
}
template<typename ...Args>
void ShaderResourceView::DealWithMutiArgus(wstring fileName_BitMap, Args... FileNames)
{
FilesBeenUsed.push_back(fileName_BitMap);
DealWithMutiArgus(FileNames...);
}
//子类***********
class VSShaderResourceView :public ShaderResourceView
{
public:
template<typename ...Args>
VSShaderResourceView(shared_ptr<Graphics> gfx, UINT slot, Args... FileNames);
VSShaderResourceView(shared_ptr<Graphics> gfx, UINT slot, ComPtr<ID3DBlob> blob);
virtual void Load() override;
virtual void Bind() override;
};
template<typename ...Args>
VSShaderResourceView::VSShaderResourceView(shared_ptr<Graphics> gfx, UINT slot, Args... FileNames)
:ShaderResourceView(gfx, slot, FileNames...)
{
}
class PSShaderResourceView :public ShaderResourceView
{
public:
template<typename ...Args>
PSShaderResourceView(shared_ptr<Graphics> gfx, UINT slot, Args... FileNames);
PSShaderResourceView(shared_ptr<Graphics> gfx, UINT slot, ComPtr<ID3DBlob> blob);
virtual void Load() override;
virtual void Bind() override;
};
template<typename ...Args>
PSShaderResourceView::PSShaderResourceView(shared_ptr<Graphics> gfx, UINT slot, Args... FileNames)
:ShaderResourceView(gfx, slot, FileNames...)
{
}
//ShaderResourceView.cpp
#include "ShaderResourceView.h"
#include <gdiplus.h>
void ShaderResourceView::DealWithMutiArgus()
{
return;
}
ShaderResourceView::ShaderResourceView(shared_ptr<Graphics> gfx, UINT slot, ComPtr<ID3DBlob> blob)
:Bindable(gfx), slot{slot}
{
UINT sourceViewNum; //Shader 用到的 SRV 的数量
ComPtr<ID3D11ShaderReflection> pShaderReflect;
D3DReflect(blob->GetBufferPointer(), blob->GetBufferSize(), __uuidof(ID3D11ShaderReflection), &pShaderReflect);
D3D11_SHADER_DESC shaderDesc;
pShaderReflect->GetDesc(&shaderDesc);
for (int i = 0; i < shaderDesc.BoundResources; i++)//获取到SRV的数量
{
FilesBeenUsed.push_back(wstring{});
}
}
UINT ShaderResourceView::GetSRVNum()
{
return FilesBeenUsed.size();
}
void ShaderResourceView::SetFileName(wstring fileName_BitMap, UINT fileArrayIndex)
{
if (fileArrayIndex > FilesBeenUsed.size())
return;
FilesBeenUsed[fileArrayIndex] = fileName_BitMap;
}
void ShaderResourceView::Load()
{
vector<ComPtr<ID3D11Texture2D> > texs;
for(auto i : FilesBeenUsed)
{
ULONG_PTR token;
Gdiplus::GdiplusStartupInput input{};
Gdiplus::GdiplusStartup(&token, &input, NULL);
Gdiplus::Bitmap tex{ i.c_str() };
struct mColor
{
unsigned char r, g, b, a;
};
std::vector<mColor> texPixelArray{ tex.GetWidth() * tex.GetHeight(),mColor{} };
Gdiplus::Color temp;
for (unsigned int i = 0; i < tex.GetHeight(); ++i)
{
for (unsigned int j = 0; j < tex.GetWidth(); ++j)
{
tex.GetPixel(j, i, &temp);
texPixelArray[tex.GetWidth() * i + j].r = temp.GetR();
texPixelArray[tex.GetWidth() * i + j].g = temp.GetG();
texPixelArray[tex.GetWidth() * i + j].b = temp.GetB();
texPixelArray[tex.GetWidth() * i + j].a = temp.GetA();
}
}
D3D11_TEXTURE2D_DESC t2dDesc{};
t2dDesc.Width = tex.GetWidth();
t2dDesc.Height = tex.GetHeight();
t2dDesc.MipLevels = 0u; //一整套mipmap
t2dDesc.ArraySize = 1u;
t2dDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
t2dDesc.SampleDesc.Count = 1u;
t2dDesc.SampleDesc.Quality = 0u;
t2dDesc.Usage = D3D11_USAGE::D3D11_USAGE_DEFAULT;
t2dDesc.BindFlags = D3D11_BIND_FLAG::D3D11_BIND_SHADER_RESOURCE|D3D11_BIND_RENDER_TARGET;
t2dDesc.MiscFlags = D3D11_RESOURCE_MISC_FLAG::D3D11_RESOURCE_MISC_GENERATE_MIPS; //使用 mipmap
t2dDesc.CPUAccessFlags = 0u;
//D3D11_SUBRESOURCE_DATA initiaTex{};
//initiaTex.pSysMem = texPixelArray.data();
//initiaTex.SysMemPitch = sizeof(mColor) * tex.GetWidth(); //在创建mipTex,不再使用SubresourceData初始化
ComPtr<ID3D11Texture2D> pTexture;
gfx->GetDevice()->CreateTexture2D(&t2dDesc, /*&initiaTex*/nullptr, &pTexture);
gfx->GetContext()->UpdateSubresource(pTexture.Get(), 0u, nullptr, texPixelArray.data(), sizeof(mColor)* tex.GetWidth(), 0u);//创建Tex2D后,再初始化
//Gdiplus::GdiplusShutdown(token);
texs.push_back(pTexture);
}
if (FilesBeenUsed.empty())
{
pShaderViews.clear();
}
else
{
for (auto i : texs)
{
ComPtr<ID3D11ShaderResourceView> temp;
D3D11_SHADER_RESOURCE_VIEW_DESC shaderViewDesc;
shaderViewDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
shaderViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
shaderViewDesc.Texture2D.MostDetailedMip = 0u; //要使用的最详细的map
shaderViewDesc.Texture2D.MipLevels = -1; //-1表示:从 MostDetailedMip到最大的mip级别的 map,都可以用。
gfx->GetDevice()->CreateShaderResourceView(i.Get(), &shaderViewDesc, &temp);
gfx->GetContext()->GenerateMips(temp.Get());
pShaderViews.push_back(temp);
}
}
}
VSShaderResourceView::VSShaderResourceView(shared_ptr<Graphics> gfx, UINT slot, ComPtr<ID3DBlob> blob)
:ShaderResourceView(gfx, slot, blob)
{
}
void VSShaderResourceView::Load()
{
ShaderResourceView::Load();
}
void VSShaderResourceView::Bind()
{
ID3D11ShaderResourceView** viewsArray = new ID3D11ShaderResourceView * [pShaderViews.size()];
for (int i = 0; i < pShaderViews.size(); i++)
{
viewsArray[i] = pShaderViews[i].Get();
}
gfx->GetContext()->VSSetShaderResources(slot, pShaderViews.size(), viewsArray);
delete[] viewsArray;
}
PSShaderResourceView::PSShaderResourceView(shared_ptr<Graphics> gfx, UINT slot, ComPtr<ID3DBlob> blob)
:ShaderResourceView(gfx, slot, blob)
{
}
void PSShaderResourceView::Load()
{
ShaderResourceView::Load();
}
void PSShaderResourceView::Bind()
{
ID3D11ShaderResourceView** viewsArray = new ID3D11ShaderResourceView * [pShaderViews.size()];
for (int i = 0; i < pShaderViews.size(); i++)
{
viewsArray[i] = pShaderViews[i].Get();
}
gfx->GetContext()->PSSetShaderResources(slot, pShaderViews.size(), viewsArray);
delete[] viewsArray;
}