Files
directx-plane-game/Graphics2/SubMeshRenderer.cpp
iDunnoDev 7a57c73ac3 Added the camera class
Added the DDS Texture Loading for future use
Added the gamepad class for future use
Added first child method to the scenegraph
Added RGB to intensity and lerp methods to the shared methods class
Added the terrain node class with normals
Fixed issue with submeshnode not passing the world transform to the actual meshes
2022-04-18 22:33:15 +01:00

205 lines
7.7 KiB
C++

#include "SubMeshRenderer.h"
void SubMeshRenderer::SetSubMesh(shared_ptr<SubMesh> subMesh)
{
_subMesh = subMesh;
}
void SubMeshRenderer::SetWorldTransformation(FXMMATRIX worldTransformation)
{
XMStoreFloat4x4(&_worldTransformation, worldTransformation);
}
void SubMeshRenderer::SetAmbientLight(XMFLOAT4 ambientLight)
{
_ambientLight = ambientLight;
}
void SubMeshRenderer::SetDirectionalLight(FXMVECTOR lightVector, XMFLOAT4 lightColour)
{
_directionalLightColour = lightColour;
XMStoreFloat4(&_directionalLightVector, lightVector);
}
void SubMeshRenderer::SetCameraPosition(XMFLOAT4 cameraPosition)
{
_cameraPosition = cameraPosition;
}
bool SubMeshRenderer::Initialise()
{
_device = DirectXFramework::GetDXFramework()->GetDevice();
_deviceContext = DirectXFramework::GetDXFramework()->GetDeviceContext();
BuildShaders();
BuildVertexLayout();
BuildConstantBuffer();
BuildBlendState();
BuildRendererState();
return true;
}
void SubMeshRenderer::Render()
{
// Turn off back face culling while we render a mesh.
// We do this since ASSIMP does not appear to be setting the
// TWOSIDED property on materials correctly. Without turning off
// back face culling, some materials do not render correctly.
_deviceContext->RSSetState(_noCullRasteriserState.Get());
XMMATRIX projectionTransformation = DirectXFramework::GetDXFramework()->GetProjectionTransformation();
XMMATRIX viewTransformation = DirectXFramework::GetDXFramework()->GetCamera()->GetViewMatrix();
XMMATRIX completeTransformation = XMLoadFloat4x4(&_worldTransformation) * viewTransformation * projectionTransformation;
// Draw the first cube
CBUFFER cBuffer;
cBuffer.completeTransformation = completeTransformation;
cBuffer.worldTransformation = XMLoadFloat4x4(&_worldTransformation);
cBuffer.ambientColor = _ambientLight;
cBuffer.lightVector = XMVector4Normalize(XMLoadFloat4(&_directionalLightVector));
cBuffer.lightColor = _directionalLightColour;
cBuffer.cameraPosition = _cameraPosition;
_deviceContext->VSSetShader(_vertexShader.Get(), 0, 0);
_deviceContext->PSSetShader(_pixelShader.Get(), 0, 0);
_deviceContext->IASetInputLayout(_layout.Get());
// Set the blend state correctly to handle opacity
float blendFactors[] = { 0.0f, 0.0f, 0.0f, 0.0f };
_deviceContext->OMSetBlendState(_transparentBlendState.Get(), blendFactors, 0xffffffff);
shared_ptr<Material> material = _subMesh->GetMaterial();
float opacity = material->GetOpacity();
UINT stride = sizeof(VERTEX);
UINT offset = 0;
_vertexBuffer = _subMesh->GetVertexBuffer();
_deviceContext->IASetVertexBuffers(0, 1, _vertexBuffer.GetAddressOf(), &stride, &offset);
_indexBuffer = _subMesh->GetIndexBuffer();
_deviceContext->IASetIndexBuffer(_indexBuffer.Get(), DXGI_FORMAT_R32_UINT, 0);
cBuffer.diffuseCoefficient = material->GetDiffuseColour();
cBuffer.specularCoefficient = material->GetSpecularColour();
cBuffer.shininess = material->GetShininess();
cBuffer.opacity = opacity;
// Update the constant buffer
_deviceContext->VSSetConstantBuffers(0, 1, _constantBuffer.GetAddressOf());
_deviceContext->UpdateSubresource(_constantBuffer.Get(), 0, 0, &cBuffer, 0, 0);
_texture = material->GetTexture();
_deviceContext->PSSetShaderResources(0, 1, _texture.GetAddressOf());
_deviceContext->PSSetConstantBuffers(0, 1, _constantBuffer.GetAddressOf());
_deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
_deviceContext->DrawIndexed(static_cast<UINT>(_subMesh->GetIndexCount()), 0, 0);
// Turn back face culling back on in case another renderer
// relies on it
_deviceContext->RSSetState(_defaultRasteriserState.Get());
}
void SubMeshRenderer::Shutdown(void)
{
}
void SubMeshRenderer::BuildShaders()
{
DWORD shaderCompileFlags = 0;
#if defined( _DEBUG )
shaderCompileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
#endif
ComPtr<ID3DBlob> compilationMessages = nullptr;
//Compile vertex shader
HRESULT hr = D3DCompileFromFile(L"TexturedShaders.hlsl",
nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE,
"VShader", "vs_5_0",
shaderCompileFlags, 0,
_vertexShaderByteCode.GetAddressOf(),
compilationMessages.GetAddressOf());
if (compilationMessages.Get() != nullptr)
{
// If there were any compilation messages, display them
MessageBoxA(0, (char*)compilationMessages->GetBufferPointer(), 0, 0);
}
// Even if there are no compiler messages, check to make sure there were no other errors.
ThrowIfFailed(hr);
ThrowIfFailed(_device->CreateVertexShader(_vertexShaderByteCode->GetBufferPointer(), _vertexShaderByteCode->GetBufferSize(), NULL, _vertexShader.GetAddressOf()));
// Compile pixel shader
hr = D3DCompileFromFile(L"TexturedShaders.hlsl",
nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE,
"PShader", "ps_5_0",
shaderCompileFlags, 0,
_pixelShaderByteCode.GetAddressOf(),
compilationMessages.GetAddressOf());
if (compilationMessages.Get() != nullptr)
{
// If there were any compilation messages, display them
MessageBoxA(0, (char*)compilationMessages->GetBufferPointer(), 0, 0);
}
ThrowIfFailed(hr);
ThrowIfFailed(_device->CreatePixelShader(_pixelShaderByteCode->GetBufferPointer(), _pixelShaderByteCode->GetBufferSize(), NULL, _pixelShader.GetAddressOf()));
}
void SubMeshRenderer::BuildVertexLayout()
{
// Create the vertex input layout. This tells DirectX the format
// of each of the vertices we are sending to it.
D3D11_INPUT_ELEMENT_DESC vertexDesc[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT , D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT , D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
ThrowIfFailed(_device->CreateInputLayout(vertexDesc, ARRAYSIZE(vertexDesc), _vertexShaderByteCode->GetBufferPointer(), _vertexShaderByteCode->GetBufferSize(), _layout.GetAddressOf()));
}
void SubMeshRenderer::BuildConstantBuffer()
{
D3D11_BUFFER_DESC bufferDesc;
ZeroMemory(&bufferDesc, sizeof(bufferDesc));
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
bufferDesc.ByteWidth = sizeof(CBUFFER);
bufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
ThrowIfFailed(_device->CreateBuffer(&bufferDesc, NULL, _constantBuffer.GetAddressOf()));
}
void SubMeshRenderer::BuildBlendState()
{
D3D11_BLEND_DESC transparentDesc = { 0 };
transparentDesc.AlphaToCoverageEnable = false;
transparentDesc.IndependentBlendEnable = false;
transparentDesc.RenderTarget[0].BlendEnable = true;
transparentDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
transparentDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
transparentDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
transparentDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO;
transparentDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
transparentDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
transparentDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
ThrowIfFailed(_device->CreateBlendState(&transparentDesc, _transparentBlendState.GetAddressOf()));
}
void SubMeshRenderer::BuildRendererState()
{
// Set default and no cull rasteriser states
D3D11_RASTERIZER_DESC rasteriserDesc;
rasteriserDesc.FillMode = D3D11_FILL_SOLID;
rasteriserDesc.CullMode = D3D11_CULL_BACK;
rasteriserDesc.FrontCounterClockwise = false;
rasteriserDesc.DepthBias = 0;
rasteriserDesc.SlopeScaledDepthBias = 0.0f;
rasteriserDesc.DepthBiasClamp = 0.0f;
rasteriserDesc.DepthClipEnable = true;
rasteriserDesc.ScissorEnable = false;
rasteriserDesc.MultisampleEnable = false;
rasteriserDesc.AntialiasedLineEnable = false;
ThrowIfFailed(_device->CreateRasterizerState(&rasteriserDesc, _defaultRasteriserState.GetAddressOf()));
rasteriserDesc.CullMode = D3D11_CULL_NONE;
ThrowIfFailed(_device->CreateRasterizerState(&rasteriserDesc, _noCullRasteriserState.GetAddressOf()));
}