Files
2025-12-03 15:50:25 +01:00

195 lines
6.2 KiB
C++

#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<MatrixBuffer*>(bufferData.pData);
XMStoreFloat4x4(static_cast<XMFLOAT4X4*>(&matrixBuffer->WorldViewProjectionMatrix), XMMatrixTranspose(wvp));
XMStoreFloat4x4(static_cast<XMFLOAT4X4*>(&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;
}