#include "Material.h" #include "Utilities.h" #include "WICTextureLoader11.h" using namespace DirectX; UINT Material::init(ID3D11Device* pD3DDevice, LPCTSTR textureFileName) { UINT error = 0; error = createVertexShader(pD3DDevice); CheckError(error); error = createPixelShader(pD3DDevice); CheckError(error); error = createMatrixBuffer(pD3DDevice); CheckError(error); error = createTextureAndSamplerState(pD3DDevice, textureFileName); CheckError(error); return 0; } void Material::render(ID3D11DeviceContext* pD3DDeviceContext) { // set shader stages pD3DDeviceContext->VSSetShader(_pVertexShader, nullptr, 0); pD3DDeviceContext->PSSetShader(_pPixelShader, nullptr, 0); // set input layout pD3DDeviceContext->IASetInputLayout(_pInputLayout); // set shader resources pD3DDeviceContext->VSSetConstantBuffers(0, 1, &_pMatrixBuffer); // set texture pD3DDeviceContext->PSSetShaderResources(0, 1, &_pTexture); // set sampler state pD3DDeviceContext->PSSetSamplers(0, 1, &_pSamplerState); } void Material::deInit() { safeRelease(_pSamplerState); safeRelease(_pTexture); safeRelease(_pMatrixBuffer); safeRelease(_pInputLayout); safeRelease(_pPixelShader); safeRelease(_pVertexShader); } void Material::setMatrixBuffer(ID3D11DeviceContext* pD3DDeviceContext, const XMFLOAT4X4& worldMatrix, const XMFLOAT4X4& viewMatrix, const XMFLOAT4X4& projectionMatrix) { // unpack matrix data XMMATRIX w = XMLoadFloat4x4(&worldMatrix); XMMATRIX v = XMLoadFloat4x4(&viewMatrix); XMMATRIX p = XMLoadFloat4x4(&projectionMatrix); XMMATRIX wvp = w * v * p; // set matrix data D3D11_MAPPED_SUBRESOURCE bufferData = {}; HRESULT hr = pD3DDeviceContext->Map(_pMatrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &bufferData); if (FAILED(hr)) return; MatrixBuffer* matrixBuffer = static_cast(bufferData.pData); XMStoreFloat4x4(static_cast(&matrixBuffer->WorldViewProjectionMatrix), XMMatrixTranspose(wvp)); XMStoreFloat4x4(static_cast(&matrixBuffer->WorldMatrix), XMMatrixTranspose(w)); pD3DDeviceContext->Unmap(_pMatrixBuffer, 0); } UINT Material::createVertexShader(ID3D11Device* pD3DDevice) { HRESULT hr = {}; ID3DBlob* pCompiledShaderCode = nullptr; // part 1 get compiled shader code // option 1: load high level shader code & compile //hr = D3DCompileFromFile( // L"ColorVertexShader.hlsl", // shader file name // nullptr, // optional macro defines // nullptr, // pre compiled included shader code // "main", // shader entry point (start function) // "vs_4_0", // shader type & version // 0, 0, // optional flags // &pCompiledShaderCode, // compiled shader code memory // nullptr // error messages //); // option 2: load compiled shader code hr = D3DReadFileToBlob(L"ColorVertexShader.cso", &pCompiledShaderCode); //hr = D3DReadFileToBlob(L"TextureVertexShader.cso", &pCompiledShaderCode); //hr = D3DReadFileToBlob(L"LightingVertexShader.cso", &pCompiledShaderCode); CheckFailed(hr, 60); // part 2 create vertex shader object hr = pD3DDevice->CreateVertexShader(pCompiledShaderCode->GetBufferPointer(), pCompiledShaderCode->GetBufferSize(), nullptr, &_pVertexShader); CheckFailed(hr, 62); UINT error = createInputLayout(pD3DDevice, pCompiledShaderCode); CheckError(error); safeRelease(pCompiledShaderCode); return 0; } UINT Material::createPixelShader(ID3D11Device* pD3DDevice) { HRESULT hr = {}; ID3DBlob* pCompiledShaderCode = nullptr; hr = D3DReadFileToBlob(L"ColorPixelShader.cso", &pCompiledShaderCode); //hr = D3DReadFileToBlob(L"TexturePixelShader.cso", &pCompiledShaderCode); //hr = D3DReadFileToBlob(L"LightingPixelShader.cso", &pCompiledShaderCode); CheckFailed(hr, 64); hr = pD3DDevice->CreatePixelShader(pCompiledShaderCode->GetBufferPointer(), pCompiledShaderCode->GetBufferSize(), nullptr, &_pPixelShader); CheckFailed(hr, 66); safeRelease(pCompiledShaderCode); return 0; } UINT Material::createInputLayout(ID3D11Device* pD3DDevice, ID3DBlob* pCompiledVertexShaderCode) { // https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-semantics D3D11_INPUT_ELEMENT_DESC elements[4] = {}; // position elements[0].SemanticName = "POSITION"; elements[0].Format = DXGI_FORMAT_R32G32B32_FLOAT; // normal elements[1].SemanticName = "NORMAL"; elements[1].Format = DXGI_FORMAT_R32G32B32_FLOAT; elements[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; // uv elements[2].SemanticName = "TEXCOORD"; elements[2].Format = DXGI_FORMAT_R32G32_FLOAT; elements[2].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; // color elements[3].SemanticName = "COLOR"; elements[3].Format = DXGI_FORMAT_R32G32B32A32_FLOAT; elements[3].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; HRESULT hr = pD3DDevice->CreateInputLayout(elements, std::size(elements), pCompiledVertexShaderCode->GetBufferPointer(), pCompiledVertexShaderCode->GetBufferSize(), &_pInputLayout); CheckFailed(hr, 68); return 0; } UINT Material::createMatrixBuffer(ID3D11Device* pD3DDevice) { D3D11_BUFFER_DESC desc = {}; desc.ByteWidth = sizeof(MatrixBuffer); desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; desc.Usage = D3D11_USAGE_DYNAMIC; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; HRESULT hr = pD3DDevice->CreateBuffer(&desc, nullptr, &_pMatrixBuffer); CheckFailed(hr, 61); return 0; } UINT Material::createTextureAndSamplerState(ID3D11Device* pD3DDevice, LPCTSTR textureFileName) { // load texture HRESULT hr = CreateWICTextureFromFile(pD3DDevice, textureFileName, nullptr, &_pTexture); CheckFailed(hr, 63); // create sampler state D3D11_SAMPLER_DESC samplerDesc = {}; samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; // CAUTION: has to be set always samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; hr = pD3DDevice->CreateSamplerState(&samplerDesc, &_pSamplerState); CheckFailed(hr, 65); return 0; }