这个类是用来创建着色器并设置输入布局的。
这个类比较特殊,它创建的着色器与Effect文件有关,effect文件是用高级着色语言(hlsl)编写的。
shadersclass.h
1 #pragma once 2 #include <d3d11.h> 3 #include <d3dcompiler.h> 4 #include <D3DX11.h> 5 #include <xnamath.h> 6 7 #pragma comment(lib,"d3dx11.lib") 8 #pragma comment(lib,"d3d11.lib") 9 #pragma comment(lib,"d3dcompiler.lib") 10 class shaderclass 11 { 12 public: 13 shaderclass(); 14 ~shaderclass(); 15 bool Initialize(ID3D11Device *device, ID3D11DeviceContext* context); 16 void Shutdown(); 17 private: 18 bool CompileShaderFromFile(WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut); 19 private: 20 ID3DBlob* m_vsblob,*m_psblob; 21 ID3D11PixelShader *m_pixelshader; 22 ID3D11VertexShader *m_vertexshader; 23 ID3D11InputLayout *m_layout; 24 public: 25 void GetShaders(ID3D11VertexShader*& vs, ID3D11PixelShader*& ps); 26 };
这个着色器类比较简单,只创建了顶点着色器和像素着色器,还设置了一个简单的输入布局,这些工作都由Initialize()函数来做,私有函数CompileShaderFromFile()函数则是用来将effect文件编译成二进制文件的,GetShaders()则是用来获取创建好的着色器对象的。
shaderclass.cpp
1 #include "shaderclass.h" 2 3 4 shaderclass::shaderclass() 5 { 6 } 7 8 9 shaderclass::~shaderclass() 10 { 11 } 12 13 bool shaderclass::Initialize(ID3D11Device *device,ID3D11DeviceContext* context) 14 { 15 HRESULT hr = S_OK; 16 bool result = CompileShaderFromFile(L"shader.fx", "VS", "vs_4_0", &m_vsblob); 17 if (!result) 18 { 19 MessageBox(NULL, 20 L"The FX file cannot be compiled. Please run this executable from the directory that contains the FX file.", L"Error", MB_OK); 21 return false; 22 } 23 24 hr = device->CreateVertexShader(m_vsblob->GetBufferPointer(), m_vsblob->GetBufferSize(), NULL, &m_vertexshader); 25 if (FAILED(hr)) 26 { 27 return false; 28 } 29 30 result = CompileShaderFromFile(L"shader.fx", "PS", "ps_4_0", &m_psblob); 31 if (!result) 32 { 33 MessageBox(NULL, 34 L"The FX file cannot be compiled. Please run this executable from the directory that contains the FX file.", L"Error", MB_OK); 35 return false; 36 } 37 38 hr = device->CreatePixelShader(m_psblob->GetBufferPointer(), m_psblob->GetBufferSize(), NULL, &m_pixelshader); 39 if (FAILED(hr)) 40 { 41 return false; 42 } 43 D3D11_INPUT_ELEMENT_DESC layout[] = 44 { 45 { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 46 { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 47 };///////////////// 48 UINT numElements = ARRAYSIZE(layout); 49 50 hr = device->CreateInputLayout(layout, numElements, m_vsblob->GetBufferPointer(),m_vsblob->GetBufferSize(), &m_layout); 51 if (FAILED(hr)) 52 { 53 return false; 54 } 55 context->IASetInputLayout(m_layout); 56 57 return true; 58 } 59 void shaderclass::Shutdown() 60 { 61 if (m_layout) 62 { 63 m_layout->Release(); 64 } 65 if (m_pixelshader) 66 { 67 m_pixelshader->Release(); 68 } 69 if (m_psblob) 70 { 71 m_psblob->Release(); 72 } 73 if (m_vertexshader) 74 { 75 m_vertexshader->Release(); 76 } 77 if (m_vsblob) 78 { 79 m_vsblob->Release(); 80 } 81 } 82 83 bool shaderclass::CompileShaderFromFile(WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut) 84 { 85 HRESULT hr = S_OK; 86 87 DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS; 88 #if defined( DEBUG ) || defined( _DEBUG ) 89 dwShaderFlags |= D3DCOMPILE_DEBUG; 90 #endif 91 92 ID3DBlob* pErrorBlob=0; 93 hr = D3DX11CompileFromFile(szFileName, NULL, NULL, szEntryPoint, szShaderModel, 94 dwShaderFlags, 0, NULL, ppBlobOut, &pErrorBlob, NULL); 95 96 if (FAILED(hr)) 97 { 98 if (pErrorBlob != NULL) 99 OutputDebugStringA((char*)pErrorBlob->GetBufferPointer()); 100 if (pErrorBlob) pErrorBlob->Release(); 101 return false; 102 } 103 if (pErrorBlob) 104 pErrorBlob->Release(); 105 106 return true; 107 } 108 109 void shaderclass::GetShaders(ID3D11VertexShader*& vs,ID3D11PixelShader*& ps) 110 { 111 vs = m_vertexshader; 112 ps = m_pixelshader; 113 }
Initialize():
- 调用CompileShaderFromFile()函数编译effect文件里的顶点处理函数,得到二进制文件,根据二进制文件创建顶点着色器,CompileShaderFromFile()函数的第一个参数“shader.fx”就是effect文件
- 编译effect文件里的像素处理函数,得到二进制文件并创建像素着色器
- 填充输入布局描述数据结构,并创建输入布局,成功后设置输入布局
CompileShaderFromFile(): 里面只是单纯的调用dx11API D3DX11CompileFromFile()函数
整个类的编写非常简单,这只是因为我很简单的创建了两个着色器。如果要创建更复杂的着色器,还要学习很多。
另附上effect文件
shader.fx
1 Texture2D txDiffuse : register(t0); 2 SamplerState samLinear : register(s0); 3 4 cbuffer ConstantBuffer : register(b0) 5 { 6 matrix World; 7 matrix View; 8 matrix Projection; 9 } 10 11 12 struct VS_INPUT 13 { 14 float4 Pos : POSITION; 15 float4 Tex : TEXCOORD0; 16 }; 17 struct PS_INPUT 18 { 19 float4 Pos : SV_POSITION; 20 float2 Tex : TEXCOORD0; 21 }; 22 //-------------------------------------------------------------------------------------- 23 // Vertex Shader 24 //-------------------------------------------------------------------------------------- 25 PS_INPUT VS(VS_INPUT input) 26 { 27 PS_INPUT output = (PS_INPUT)0; 28 output.Pos = mul(input.Pos, World); 29 output.Pos = mul(output.Pos, View); 30 output.Pos = mul(output.Pos, Projection); 31 output.Tex = input.Tex; 32 33 return output; 34 } 35 //-------------------------------------------------------------------------------------- 36 // Pixel Shader 37 //-------------------------------------------------------------------------------------- 38 float4 PS(PS_INPUT input) : SV_Target 39 { 40 return txDiffuse.Sample(samLinear, input.Tex); 41 }