2020.5
This commit is contained in:
parent
ca36fcc02e
commit
ee5afaab96
112 changed files with 5752 additions and 1241 deletions
BIN
Bin/PAKBuilder.exe
Normal file
BIN
Bin/PAKBuilder.exe
Normal file
Binary file not shown.
BIN
Bin/TextureTool.exe
Normal file
BIN
Bin/TextureTool.exe
Normal file
Binary file not shown.
|
@ -39,10 +39,8 @@ std::queue<FileEntry> g_fileEntries;
|
|||
|
||||
void TraverseDirectory(CWSZ parentDir, CWSZ foundDir, IO::RFile pakFile);
|
||||
|
||||
int main(VERUS_MAIN_DEFAULT_ARGS)
|
||||
void Run()
|
||||
{
|
||||
try
|
||||
{
|
||||
std::wcout << _T("PACK Builder 1.2.1") << std::endl;
|
||||
std::wcout << _T("Copyright (c) 2006-2020 Dmitry Maluev") << std::endl;
|
||||
std::wcout << _T("Arguments: [PAK/folder name] [input directory] [PAK output directory]") << std::endl;
|
||||
|
@ -126,13 +124,6 @@ int main(VERUS_MAIN_DEFAULT_ARGS)
|
|||
pakFile.Close();
|
||||
if (argCount < 2)
|
||||
system("pause");
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
system("pause");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT64 WriteData(CWSZ name, RcString password, IO::RFile pakFile, const BYTE* p, INT64 size)
|
||||
|
@ -332,3 +323,17 @@ void TraverseDirectory(CWSZ parentDir, CWSZ foundDir, IO::RFile pakFile)
|
|||
}
|
||||
g_depth--;
|
||||
}
|
||||
|
||||
int main(VERUS_MAIN_DEFAULT_ARGS)
|
||||
{
|
||||
try
|
||||
{
|
||||
Run();
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::wcerr << _T("EXCEPTION: ") << e.what() << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -1,2 +1,8 @@
|
|||
# verus
|
||||
Game Engine
|
||||
|
||||
# Release
|
||||
undef VERUS_RELEASE_DEBUG
|
||||
UseFullPaths=false
|
||||
DebugInformationFormat=None
|
||||
GenerateDebugInformation=false (Link)
|
||||
|
|
|
@ -48,7 +48,7 @@ void CommandBufferD3D12::End()
|
|||
throw VERUS_RUNTIME_ERROR << "Close(), hr=" << VERUS_HR(hr);
|
||||
}
|
||||
|
||||
void CommandBufferD3D12::BeginRenderPass(int renderPassHandle, int framebufferHandle, std::initializer_list<Vector4> ilClearValues, bool setViewportAndScissor)
|
||||
void CommandBufferD3D12::BeginRenderPass(RPHandle renderPassHandle, FBHandle framebufferHandle, std::initializer_list<Vector4> ilClearValues, bool setViewportAndScissor)
|
||||
{
|
||||
VERUS_QREF_RENDERER_D3D12;
|
||||
|
||||
|
@ -99,7 +99,7 @@ void CommandBufferD3D12::EndRenderPass()
|
|||
if (_vAttachmentStates[index] != attachment._finalState)
|
||||
{
|
||||
const auto& resources = _pFramebuffer->_vResources[index];
|
||||
barriers[barrierCount++] = CD3DX12_RESOURCE_BARRIER::Transition(resources, _vAttachmentStates[index], attachment._finalState);
|
||||
barriers[barrierCount++] = CD3DX12_RESOURCE_BARRIER::Transition(resources, _vAttachmentStates[index], attachment._finalState, 0);
|
||||
}
|
||||
index++;
|
||||
if (VERUS_MAX_RT == barrierCount)
|
||||
|
@ -157,6 +157,13 @@ void CommandBufferD3D12::BindPipeline(PipelinePtr pipe)
|
|||
|
||||
void CommandBufferD3D12::SetViewport(std::initializer_list<Vector4> il, float minDepth, float maxDepth)
|
||||
{
|
||||
if (il.size() > 0)
|
||||
{
|
||||
const float w = il.begin()->Width();
|
||||
const float h = il.begin()->Height();
|
||||
_viewportSize = Vector4(w, h, 1 / w, 1 / h);
|
||||
}
|
||||
|
||||
CD3DX12_VIEWPORT vpD3D12[VERUS_MAX_RT];
|
||||
int count = 0;
|
||||
for (const auto& rc : il)
|
||||
|
@ -182,7 +189,7 @@ void CommandBufferD3D12::SetBlendConstants(const float* p)
|
|||
GetD3DGraphicsCommandList()->OMSetBlendFactor(p);
|
||||
}
|
||||
|
||||
bool CommandBufferD3D12::BindDescriptors(ShaderPtr shader, int setNumber, int complexSetHandle)
|
||||
bool CommandBufferD3D12::BindDescriptors(ShaderPtr shader, int setNumber, CSHandle complexSetHandle)
|
||||
{
|
||||
bool copyDescOnly = false;
|
||||
if (setNumber < 0)
|
||||
|
@ -197,7 +204,7 @@ bool CommandBufferD3D12::BindDescriptors(ShaderPtr shader, int setNumber, int co
|
|||
if (shaderD3D12.TryRootConstants(setNumber, *this))
|
||||
return true;
|
||||
|
||||
const D3D12_GPU_DESCRIPTOR_HANDLE hGPU = shaderD3D12.UpdateUniformBuffer(setNumber, complexSetHandle, copyDescOnly);
|
||||
const D3D12_GPU_DESCRIPTOR_HANDLE hGPU = shaderD3D12.UpdateUniformBuffer(setNumber, complexSetHandle.Get(), copyDescOnly);
|
||||
if (!hGPU.ptr)
|
||||
return false;
|
||||
|
||||
|
@ -208,9 +215,9 @@ bool CommandBufferD3D12::BindDescriptors(ShaderPtr shader, int setNumber, int co
|
|||
else
|
||||
pCmdList->SetGraphicsRootDescriptorTable(rootParameterIndex, hGPU);
|
||||
|
||||
if (complexSetHandle >= 0 && !shaderD3D12.IsCompute())
|
||||
if (complexSetHandle.IsSet() && !shaderD3D12.IsCompute())
|
||||
{
|
||||
const D3D12_GPU_DESCRIPTOR_HANDLE hGPU = shaderD3D12.UpdateSamplers(setNumber, complexSetHandle);
|
||||
const D3D12_GPU_DESCRIPTOR_HANDLE hGPU = shaderD3D12.UpdateSamplers(setNumber, complexSetHandle.Get());
|
||||
if (hGPU.ptr)
|
||||
{
|
||||
const UINT rootParameterIndex = shaderD3D12.GetDescriptorSetCount();
|
||||
|
@ -283,7 +290,7 @@ void CommandBufferD3D12::PrepareSubpass()
|
|||
if (_vAttachmentStates[ref._index] != ref._state)
|
||||
{
|
||||
const auto& resources = fs._vResources[resIndex];
|
||||
barriers[barrierCount++] = CD3DX12_RESOURCE_BARRIER::Transition(resources, _vAttachmentStates[ref._index], ref._state);
|
||||
barriers[barrierCount++] = CD3DX12_RESOURCE_BARRIER::Transition(resources, _vAttachmentStates[ref._index], ref._state, 0);
|
||||
_vAttachmentStates[ref._index] = ref._state;
|
||||
}
|
||||
resIndex++;
|
||||
|
@ -294,7 +301,7 @@ void CommandBufferD3D12::PrepareSubpass()
|
|||
if (_vAttachmentStates[ref._index] != ref._state)
|
||||
{
|
||||
const auto& resources = fs._vResources[resIndex];
|
||||
barriers[barrierCount++] = CD3DX12_RESOURCE_BARRIER::Transition(resources, _vAttachmentStates[ref._index], ref._state);
|
||||
barriers[barrierCount++] = CD3DX12_RESOURCE_BARRIER::Transition(resources, _vAttachmentStates[ref._index], ref._state, 0);
|
||||
_vAttachmentStates[ref._index] = ref._state;
|
||||
}
|
||||
resIndex++;
|
||||
|
@ -304,7 +311,7 @@ void CommandBufferD3D12::PrepareSubpass()
|
|||
const auto& ref = subpass._depthStencil;
|
||||
if (_vAttachmentStates[ref._index] != ref._state)
|
||||
{
|
||||
barriers[barrierCount++] = CD3DX12_RESOURCE_BARRIER::Transition(fs._vResources.back(), _vAttachmentStates[ref._index], ref._state);
|
||||
barriers[barrierCount++] = CD3DX12_RESOURCE_BARRIER::Transition(fs._vResources.back(), _vAttachmentStates[ref._index], ref._state, 0);
|
||||
_vAttachmentStates[ref._index] = ref._state;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace verus
|
|||
virtual void Begin() override;
|
||||
virtual void End() override;
|
||||
|
||||
virtual void BeginRenderPass(int renderPassHandle, int framebufferHandle, std::initializer_list<Vector4> ilClearValues, bool setViewportAndScissor) override;
|
||||
virtual void BeginRenderPass(RPHandle renderPassHandle, FBHandle framebufferHandle, std::initializer_list<Vector4> ilClearValues, bool setViewportAndScissor) override;
|
||||
virtual void NextSubpass() override;
|
||||
virtual void EndRenderPass() override;
|
||||
|
||||
|
@ -35,7 +35,7 @@ namespace verus
|
|||
virtual void SetScissor(std::initializer_list<Vector4> il) override;
|
||||
virtual void SetBlendConstants(const float* p) override;
|
||||
|
||||
virtual bool BindDescriptors(ShaderPtr shader, int setNumber, int complexSetHandle) override;
|
||||
virtual bool BindDescriptors(ShaderPtr shader, int setNumber, CSHandle complexSetHandle) override;
|
||||
virtual void PushConstants(ShaderPtr shader, int offset, int size, const void* p, ShaderStageFlags stageFlags) override;
|
||||
|
||||
virtual void PipelineImageMemoryBarrier(TexturePtr tex, ImageLayout oldLayout, ImageLayout newLayout, Range<int> mipLevels, int arrayLayer) override;
|
||||
|
|
|
@ -20,11 +20,11 @@ void GeometryD3D12::Init(RcGeometryDesc desc)
|
|||
_dynBindingsMask = desc._dynBindingsMask;
|
||||
_32BitIndices = desc._32BitIndices;
|
||||
|
||||
_vInputElementDesc.reserve(GetInputElementDescCount(desc._pInputElementDesc));
|
||||
_vInputElementDesc.reserve(GetVertexInputAttrDescCount(desc._pVertexInputAttrDesc));
|
||||
int i = 0;
|
||||
while (desc._pInputElementDesc[i]._offset >= 0)
|
||||
while (desc._pVertexInputAttrDesc[i]._offset >= 0)
|
||||
{
|
||||
int binding = desc._pInputElementDesc[i]._binding;
|
||||
int binding = desc._pVertexInputAttrDesc[i]._binding;
|
||||
D3D12_INPUT_CLASSIFICATION inputClassification = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
|
||||
UINT instanceDataStepRate = 0;
|
||||
if (binding < 0)
|
||||
|
@ -36,11 +36,11 @@ void GeometryD3D12::Init(RcGeometryDesc desc)
|
|||
}
|
||||
D3D12_INPUT_ELEMENT_DESC ieDesc =
|
||||
{
|
||||
ToNativeSemanticName(desc._pInputElementDesc[i]._usage),
|
||||
static_cast<UINT>(desc._pInputElementDesc[i]._usageIndex),
|
||||
ToNativeFormat(desc._pInputElementDesc[i]._usage, desc._pInputElementDesc[i]._type, desc._pInputElementDesc[i]._components),
|
||||
ToNativeSemanticName(desc._pVertexInputAttrDesc[i]._usage),
|
||||
static_cast<UINT>(desc._pVertexInputAttrDesc[i]._usageIndex),
|
||||
ToNativeFormat(desc._pVertexInputAttrDesc[i]._usage, desc._pVertexInputAttrDesc[i]._type, desc._pVertexInputAttrDesc[i]._components),
|
||||
static_cast<UINT>(binding),
|
||||
static_cast<UINT>(desc._pInputElementDesc[i]._offset),
|
||||
static_cast<UINT>(desc._pVertexInputAttrDesc[i]._offset),
|
||||
inputClassification,
|
||||
instanceDataStepRate
|
||||
};
|
||||
|
@ -48,7 +48,7 @@ void GeometryD3D12::Init(RcGeometryDesc desc)
|
|||
i++;
|
||||
}
|
||||
|
||||
_vStrides.reserve(GetBindingCount(desc._pInputElementDesc));
|
||||
_vStrides.reserve(GetBindingCount(desc._pVertexInputAttrDesc));
|
||||
i = 0;
|
||||
while (desc._pStrides[i] > 0)
|
||||
{
|
||||
|
|
|
@ -103,6 +103,8 @@ D3D_PRIMITIVE_TOPOLOGY CGI::ToNativePrimitiveTopology(PrimitiveTopology primitiv
|
|||
case PrimitiveTopology::lineStrip: return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
|
||||
case PrimitiveTopology::triangleList: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
|
||||
case PrimitiveTopology::triangleStrip: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
|
||||
case PrimitiveTopology::patchList3: return D3D_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST;
|
||||
case PrimitiveTopology::patchList4: return D3D_PRIMITIVE_TOPOLOGY_4_CONTROL_POINT_PATCHLIST;
|
||||
default: throw VERUS_RECOVERABLE << "ToNativePrimitiveTopology()";
|
||||
}
|
||||
}
|
||||
|
@ -116,6 +118,8 @@ D3D12_PRIMITIVE_TOPOLOGY_TYPE CGI::ToNativePrimitiveTopologyType(PrimitiveTopolo
|
|||
case PrimitiveTopology::lineStrip: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
|
||||
case PrimitiveTopology::triangleList: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
|
||||
case PrimitiveTopology::triangleStrip: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
|
||||
case PrimitiveTopology::patchList3: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH;
|
||||
case PrimitiveTopology::patchList4: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH;
|
||||
default: throw VERUS_RECOVERABLE << "ToNativePrimitiveTopologyType()";
|
||||
}
|
||||
}
|
||||
|
@ -141,14 +145,16 @@ CSZ CGI::ToNativeSemanticName(IeUsage usage)
|
|||
static const CSZ names[] =
|
||||
{
|
||||
"POSITION", // IeUsage::position
|
||||
"BLENDWEIGHT", // IeUsage::blendWeight
|
||||
"BLENDWEIGHTS", // IeUsage::blendWeights
|
||||
"BLENDINDICES", // IeUsage::blendIndices
|
||||
"NORMAL", // IeUsage::normal
|
||||
"TANGENT", // IeUsage::tangent
|
||||
"BINORMAL", // IeUsage::binormal
|
||||
"COLOR", // IeUsage::color
|
||||
"PSIZE", // IeUsage::psize
|
||||
"TEXCOORD", // IeUsage::texCoord
|
||||
"TEXCOORD", // IeUsage::tangent
|
||||
"TEXCOORD", // IeUsage::binormal
|
||||
"COLOR" // IeUsage::color
|
||||
"INSTDATA", // IeUsage::instData
|
||||
"ATTR" // IeUsage::attr
|
||||
};
|
||||
return names[+usage];
|
||||
}
|
||||
|
|
|
@ -51,11 +51,12 @@ void PipelineD3D12::Init(RcPipelineDesc desc)
|
|||
|
||||
D3D12_GRAPHICS_PIPELINE_STATE_DESC gpsDesc = {};
|
||||
gpsDesc.pRootSignature = _pRootSignature;
|
||||
gpsDesc.VS = ToBytecode(shader.GetD3DBlob(desc._shaderBranch, BaseShader::Stage::vs));
|
||||
gpsDesc.PS = ToBytecode(shader.GetD3DBlob(desc._shaderBranch, BaseShader::Stage::fs));
|
||||
gpsDesc.DS = ToBytecode(shader.GetD3DBlob(desc._shaderBranch, BaseShader::Stage::ds));
|
||||
gpsDesc.HS = ToBytecode(shader.GetD3DBlob(desc._shaderBranch, BaseShader::Stage::hs));
|
||||
gpsDesc.GS = ToBytecode(shader.GetD3DBlob(desc._shaderBranch, BaseShader::Stage::gs));
|
||||
ShaderD3D12::RcCompiled compiled = shader.GetCompiled(desc._shaderBranch);
|
||||
gpsDesc.VS = ToBytecode(compiled._pBlobs[+BaseShader::Stage::vs].Get());
|
||||
gpsDesc.PS = ToBytecode(compiled._pBlobs[+BaseShader::Stage::fs].Get());
|
||||
gpsDesc.DS = ToBytecode(compiled._pBlobs[+BaseShader::Stage::ds].Get());
|
||||
gpsDesc.HS = ToBytecode(compiled._pBlobs[+BaseShader::Stage::hs].Get());
|
||||
gpsDesc.GS = ToBytecode(compiled._pBlobs[+BaseShader::Stage::gs].Get());
|
||||
gpsDesc.StreamOutput = {};
|
||||
|
||||
gpsDesc.BlendState = {};
|
||||
|
@ -141,7 +142,7 @@ void PipelineD3D12::Init(RcPipelineDesc desc)
|
|||
gpsDesc.RasterizerState.SlopeScaledDepthBias = desc._rasterizationState._depthBiasSlopeFactor;
|
||||
gpsDesc.RasterizerState.DepthClipEnable = desc._rasterizationState._depthClampEnable;
|
||||
gpsDesc.RasterizerState.MultisampleEnable = FALSE;
|
||||
gpsDesc.RasterizerState.AntialiasedLineEnable = TRUE;
|
||||
gpsDesc.RasterizerState.AntialiasedLineEnable = (desc._colorAttachBlendEqs[0] == VERUS_COLOR_BLEND_ALPHA) ? TRUE : FALSE;
|
||||
gpsDesc.RasterizerState.ForcedSampleCount = 0;
|
||||
gpsDesc.RasterizerState.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
|
||||
|
||||
|
@ -200,7 +201,8 @@ void PipelineD3D12::InitCompute(RcPipelineDesc desc)
|
|||
|
||||
D3D12_COMPUTE_PIPELINE_STATE_DESC cpsDesc = {};
|
||||
cpsDesc.pRootSignature = _pRootSignature;
|
||||
cpsDesc.CS = ToBytecode(shader.GetD3DBlob(desc._shaderBranch, BaseShader::Stage::cs));
|
||||
ShaderD3D12::RcCompiled compiled = shader.GetCompiled(desc._shaderBranch);
|
||||
cpsDesc.CS = ToBytecode(compiled._pBlobs[+BaseShader::Stage::cs].Get());
|
||||
cpsDesc.NodeMask = 0;
|
||||
cpsDesc.CachedPSO = { nullptr, 0 };
|
||||
cpsDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
|
||||
|
|
|
@ -40,13 +40,13 @@ void RendererD3D12::Done()
|
|||
Renderer::I().ImGuiSetCurrentContext(nullptr);
|
||||
}
|
||||
|
||||
DeleteFramebuffer(-1);
|
||||
DeleteRenderPass(-1);
|
||||
DeleteFramebuffer(FBHandle::Make(-2));
|
||||
DeleteRenderPass(RPHandle::Make(-2));
|
||||
|
||||
_vSamplers.clear();
|
||||
|
||||
_dhSamplers.Reset();
|
||||
_dhCbvSrvUav.Reset();
|
||||
_dhViews.Reset();
|
||||
|
||||
if (_hFence != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
|
@ -210,7 +210,7 @@ void RendererD3D12::InitD3D()
|
|||
_pFence = CreateFence();
|
||||
_hFence = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||
|
||||
_dhCbvSrvUav.Create(_pDevice.Get(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, settings.GetLimits()._d3d12_dhCbvSrvUavCapacity, 16, true);
|
||||
_dhViews.Create(_pDevice.Get(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, settings.GetLimits()._d3d12_dhViewsCapacity, 16, true);
|
||||
_dhSamplers.Create(_pDevice.Get(), D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, settings.GetLimits()._d3d12_dhSamplersCapacity, 0, true);
|
||||
|
||||
CreateSamplers();
|
||||
|
@ -326,40 +326,40 @@ void RendererD3D12::CreateSamplers()
|
|||
|
||||
// <Wrap>
|
||||
desc = init;
|
||||
_vSamplers[+Sampler::linear3D] = desc;
|
||||
_vSamplers[+Sampler::linearMipL] = desc;
|
||||
|
||||
desc = init;
|
||||
desc.Filter = ApplyTrilinearFilter(D3D12_FILTER_MIN_MAG_MIP_POINT);
|
||||
_vSamplers[+Sampler::nearest3D] = desc;
|
||||
_vSamplers[+Sampler::nearestMipL] = desc;
|
||||
|
||||
desc = init;
|
||||
desc.Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT;
|
||||
_vSamplers[+Sampler::linear2D] = desc;
|
||||
_vSamplers[+Sampler::linearMipN] = desc;
|
||||
|
||||
desc = init;
|
||||
desc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
|
||||
_vSamplers[+Sampler::nearest2D] = desc;
|
||||
_vSamplers[+Sampler::nearestMipN] = desc;
|
||||
// </Wrap>
|
||||
|
||||
// <Clamp>
|
||||
desc = init;
|
||||
desc.AddressU = desc.AddressV = desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||
_vSamplers[+Sampler::linearClamp3D] = desc;
|
||||
_vSamplers[+Sampler::linearClampMipL] = desc;
|
||||
|
||||
desc = init;
|
||||
desc.Filter = ApplyTrilinearFilter(D3D12_FILTER_MIN_MAG_MIP_POINT);
|
||||
desc.AddressU = desc.AddressV = desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||
_vSamplers[+Sampler::nearestClamp3D] = desc;
|
||||
_vSamplers[+Sampler::nearestClampMipL] = desc;
|
||||
|
||||
desc = init;
|
||||
desc.Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT;
|
||||
desc.AddressU = desc.AddressV = desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||
_vSamplers[+Sampler::linearClamp2D] = desc;
|
||||
_vSamplers[+Sampler::linearClampMipN] = desc;
|
||||
|
||||
desc = init;
|
||||
desc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
|
||||
desc.AddressU = desc.AddressV = desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||
_vSamplers[+Sampler::nearestClamp2D] = desc;
|
||||
_vSamplers[+Sampler::nearestClampMipN] = desc;
|
||||
// </Clamp>
|
||||
}
|
||||
|
||||
|
@ -368,7 +368,7 @@ D3D12_STATIC_SAMPLER_DESC RendererD3D12::GetStaticSamplerDesc(Sampler s) const
|
|||
return _vSamplers[+s];
|
||||
}
|
||||
|
||||
void RendererD3D12::ImGuiInit(int renderPassHandle)
|
||||
void RendererD3D12::ImGuiInit(RPHandle renderPassHandle)
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
VERUS_QREF_CONST_SETTINGS;
|
||||
|
@ -392,12 +392,12 @@ void RendererD3D12::ImGuiInit(int renderPassHandle)
|
|||
ImGui::StyleColorsDark();
|
||||
|
||||
ImGui_ImplSDL2_InitForD3D(renderer.GetMainWindow()->GetSDL());
|
||||
auto hp = _dhCbvSrvUav.GetStaticHandlePair(0);
|
||||
auto hp = _dhViews.GetStaticHandlePair(0);
|
||||
ImGui_ImplDX12_Init(
|
||||
_pDevice.Get(),
|
||||
s_ringBufferSize,
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,
|
||||
_dhCbvSrvUav.GetD3DDescriptorHeap(),
|
||||
_dhViews.GetD3DDescriptorHeap(),
|
||||
hp._hCPU,
|
||||
hp._hGPU);
|
||||
}
|
||||
|
@ -450,7 +450,7 @@ void RendererD3D12::BeginFrame(bool present)
|
|||
|
||||
renderer.GetCommandBuffer()->Begin();
|
||||
|
||||
ID3D12DescriptorHeap* ppHeaps[] = { _dhCbvSrvUav.GetD3DDescriptorHeap(), _dhSamplers.GetD3DDescriptorHeap() };
|
||||
ID3D12DescriptorHeap* ppHeaps[] = { _dhViews.GetD3DDescriptorHeap(), _dhSamplers.GetD3DDescriptorHeap() };
|
||||
static_cast<CommandBufferD3D12*>(&(*renderer.GetCommandBuffer()))->GetD3DGraphicsCommandList()->SetDescriptorHeaps(2, ppHeaps);
|
||||
}
|
||||
|
||||
|
@ -552,7 +552,7 @@ void RendererD3D12::DeleteTexture(PBaseTexture p)
|
|||
TStoreTextures::Delete(static_cast<PTextureD3D12>(p));
|
||||
}
|
||||
|
||||
int RendererD3D12::CreateRenderPass(std::initializer_list<RP::Attachment> ilA, std::initializer_list<RP::Subpass> ilS, std::initializer_list<RP::Dependency> ilD)
|
||||
RPHandle RendererD3D12::CreateRenderPass(std::initializer_list<RP::Attachment> ilA, std::initializer_list<RP::Subpass> ilS, std::initializer_list<RP::Dependency> ilD)
|
||||
{
|
||||
RP::D3DRenderPass renderPass;
|
||||
|
||||
|
@ -627,16 +627,16 @@ int RendererD3D12::CreateRenderPass(std::initializer_list<RP::Attachment> ilA, s
|
|||
renderPass._vSubpasses.push_back(std::move(d3dSubpass));
|
||||
}
|
||||
|
||||
const int handle = GetNextRenderPassHandle();
|
||||
if (handle >= _vRenderPasses.size())
|
||||
const int nextIndex = GetNextRenderPassIndex();
|
||||
if (nextIndex >= _vRenderPasses.size())
|
||||
_vRenderPasses.push_back(std::move(renderPass));
|
||||
else
|
||||
_vRenderPasses[handle] = renderPass;
|
||||
_vRenderPasses[nextIndex] = renderPass;
|
||||
|
||||
return handle;
|
||||
return RPHandle::Make(nextIndex);
|
||||
}
|
||||
|
||||
int RendererD3D12::CreateFramebuffer(int renderPassHandle, std::initializer_list<TexturePtr> il, int w, int h, int swapChainBufferIndex)
|
||||
FBHandle RendererD3D12::CreateFramebuffer(RPHandle renderPassHandle, std::initializer_list<TexturePtr> il, int w, int h, int swapChainBufferIndex)
|
||||
{
|
||||
RP::RcD3DRenderPass renderPass = GetRenderPass(renderPassHandle);
|
||||
RP::D3DFramebuffer framebuffer;
|
||||
|
@ -746,32 +746,32 @@ int RendererD3D12::CreateFramebuffer(int renderPassHandle, std::initializer_list
|
|||
framebuffer._vSubpasses.push_back(std::move(fs));
|
||||
}
|
||||
|
||||
const int handle = GetNextFramebufferHandle();
|
||||
if (handle >= _vFramebuffers.size())
|
||||
const int nextIndex = GetNextFramebufferIndex();
|
||||
if (nextIndex >= _vFramebuffers.size())
|
||||
_vFramebuffers.push_back(std::move(framebuffer));
|
||||
else
|
||||
_vFramebuffers[handle] = framebuffer;
|
||||
_vFramebuffers[nextIndex] = framebuffer;
|
||||
|
||||
return handle;
|
||||
return FBHandle::Make(nextIndex);
|
||||
}
|
||||
|
||||
void RendererD3D12::DeleteRenderPass(int handle)
|
||||
void RendererD3D12::DeleteRenderPass(RPHandle handle)
|
||||
{
|
||||
if (handle >= 0)
|
||||
_vRenderPasses[handle] = RP::D3DRenderPass();
|
||||
else
|
||||
if (handle.IsSet())
|
||||
_vRenderPasses[handle.Get()] = RP::D3DRenderPass();
|
||||
else if (-2 == handle.Get())
|
||||
_vRenderPasses.clear();
|
||||
}
|
||||
|
||||
void RendererD3D12::DeleteFramebuffer(int handle)
|
||||
void RendererD3D12::DeleteFramebuffer(FBHandle handle)
|
||||
{
|
||||
if (handle >= 0)
|
||||
_vFramebuffers[handle] = RP::D3DFramebuffer();
|
||||
else
|
||||
if (handle.IsSet())
|
||||
_vFramebuffers[handle.Get()] = RP::D3DFramebuffer();
|
||||
else if (-2 == handle.Get())
|
||||
_vFramebuffers.clear();
|
||||
}
|
||||
|
||||
int RendererD3D12::GetNextRenderPassHandle() const
|
||||
int RendererD3D12::GetNextRenderPassIndex() const
|
||||
{
|
||||
const int count = Utils::Cast32(_vRenderPasses.size());
|
||||
VERUS_FOR(i, count)
|
||||
|
@ -782,7 +782,7 @@ int RendererD3D12::GetNextRenderPassHandle() const
|
|||
return count;
|
||||
}
|
||||
|
||||
int RendererD3D12::GetNextFramebufferHandle() const
|
||||
int RendererD3D12::GetNextFramebufferIndex() const
|
||||
{
|
||||
const int count = Utils::Cast32(_vFramebuffers.size());
|
||||
VERUS_FOR(i, count)
|
||||
|
@ -793,12 +793,12 @@ int RendererD3D12::GetNextFramebufferHandle() const
|
|||
return count;
|
||||
}
|
||||
|
||||
RP::RcD3DRenderPass RendererD3D12::GetRenderPass(int handle) const
|
||||
RP::RcD3DRenderPass RendererD3D12::GetRenderPass(RPHandle handle) const
|
||||
{
|
||||
return _vRenderPasses[handle];
|
||||
return _vRenderPasses[handle.Get()];
|
||||
}
|
||||
|
||||
RP::RcD3DFramebuffer RendererD3D12::GetFramebuffer(int handle) const
|
||||
RP::RcD3DFramebuffer RendererD3D12::GetFramebuffer(FBHandle handle) const
|
||||
{
|
||||
return _vFramebuffers[handle];
|
||||
return _vFramebuffers[handle.Get()];
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace verus
|
|||
ComPtr<IDXGISwapChain4> _pSwapChain;
|
||||
Vector<ComPtr<ID3D12Resource>> _vSwapChainBuffers;
|
||||
DescriptorHeap _dhSwapChainBuffersRTVs;
|
||||
DynamicDescriptorHeap _dhCbvSrvUav;
|
||||
DynamicDescriptorHeap _dhViews;
|
||||
DynamicDescriptorHeap _dhSamplers;
|
||||
TMapCommandAllocators _mapCommandAllocators[s_ringBufferSize];
|
||||
ComPtr<ID3D12Fence> _pFence;
|
||||
|
@ -64,7 +64,7 @@ namespace verus
|
|||
ID3D12CommandAllocator* GetD3DCommandAllocator(int ringBufferIndex) const { return _mapCommandAllocators[ringBufferIndex].at(std::this_thread::get_id()).Get(); }
|
||||
D3D12_STATIC_SAMPLER_DESC GetStaticSamplerDesc(Sampler s) const;
|
||||
|
||||
virtual void ImGuiInit(int renderPassHandle) override;
|
||||
virtual void ImGuiInit(RPHandle renderPassHandle) override;
|
||||
virtual void ImGuiRenderDrawData() override;
|
||||
|
||||
virtual void ResizeSwapChain() override;
|
||||
|
@ -91,17 +91,17 @@ namespace verus
|
|||
virtual void DeleteShader(PBaseShader p) override;
|
||||
virtual void DeleteTexture(PBaseTexture p) override;
|
||||
|
||||
virtual int CreateRenderPass(std::initializer_list<RP::Attachment> ilA, std::initializer_list<RP::Subpass> ilS, std::initializer_list<RP::Dependency> ilD) override;
|
||||
virtual int CreateFramebuffer(int renderPassHandle, std::initializer_list<TexturePtr> il, int w, int h, int swapChainBufferIndex = -1) override;
|
||||
virtual void DeleteRenderPass(int handle) override;
|
||||
virtual void DeleteFramebuffer(int handle) override;
|
||||
int GetNextRenderPassHandle() const;
|
||||
int GetNextFramebufferHandle() const;
|
||||
RP::RcD3DRenderPass GetRenderPass(int handle) const;
|
||||
RP::RcD3DFramebuffer GetFramebuffer(int handle) const;
|
||||
virtual RPHandle CreateRenderPass(std::initializer_list<RP::Attachment> ilA, std::initializer_list<RP::Subpass> ilS, std::initializer_list<RP::Dependency> ilD) override;
|
||||
virtual FBHandle CreateFramebuffer(RPHandle renderPassHandle, std::initializer_list<TexturePtr> il, int w, int h, int swapChainBufferIndex = -1) override;
|
||||
virtual void DeleteRenderPass(RPHandle handle) override;
|
||||
virtual void DeleteFramebuffer(FBHandle handle) override;
|
||||
int GetNextRenderPassIndex() const;
|
||||
int GetNextFramebufferIndex() const;
|
||||
RP::RcD3DRenderPass GetRenderPass(RPHandle handle) const;
|
||||
RP::RcD3DFramebuffer GetFramebuffer(FBHandle handle) const;
|
||||
|
||||
RDynamicDescriptorHeap GetHeapCbvSrvUav() { return _dhCbvSrvUav; }
|
||||
RDynamicDescriptorHeap GetHeapSampler() { return _dhSamplers; }
|
||||
RDynamicDescriptorHeap GetViewHeap() { return _dhViews; }
|
||||
RDynamicDescriptorHeap GetSamplerHeap() { return _dhSamplers; }
|
||||
};
|
||||
VERUS_TYPEDEFS(RendererD3D12);
|
||||
}
|
||||
|
|
|
@ -66,12 +66,12 @@ void ShaderD3D12::Init(CSZ source, CSZ sourceName, CSZ* branches)
|
|||
|
||||
while (*branches)
|
||||
{
|
||||
String entryVS, entryHS, entryDS, entryGS, entryFS, entryCS, stages;
|
||||
String entry, stageEntries[+Stage::count], stages;
|
||||
Vector<String> vMacroName;
|
||||
Vector<String> vMacroValue;
|
||||
const String entry = Parse(*branches, entryVS, entryHS, entryDS, entryGS, entryFS, entryCS, stages, vMacroName, vMacroValue, "DEF_");
|
||||
const String branch = Parse(*branches, entry, stageEntries, stages, vMacroName, vMacroValue, "DEF_");
|
||||
|
||||
if (IsInIgnoreList(_C(entry)))
|
||||
if (IsInIgnoreList(_C(branch)))
|
||||
{
|
||||
branches++;
|
||||
continue;
|
||||
|
@ -118,12 +118,13 @@ void ShaderD3D12::Init(CSZ source, CSZ sourceName, CSZ* branches)
|
|||
// </System defines>
|
||||
|
||||
Compiled compiled;
|
||||
compiled._entry = entry;
|
||||
|
||||
if (strchr(_C(stages), 'V'))
|
||||
{
|
||||
compiled._stageCount++;
|
||||
vDefines[typeIndex].Name = "_VS";
|
||||
hr = D3DCompile(source, len, sourceName, vDefines.data(), &inc, _C(entryVS), _C("vs_" + version), flags, 0, &compiled._pBlobs[+Stage::vs], &pErrorMsgs);
|
||||
hr = D3DCompile(source, len, sourceName, vDefines.data(), &inc, _C(stageEntries[+Stage::vs]), _C("vs_" + version), flags, 0, &compiled._pBlobs[+Stage::vs], &pErrorMsgs);
|
||||
CheckErrorMsgs(pErrorMsgs);
|
||||
}
|
||||
|
||||
|
@ -131,7 +132,7 @@ void ShaderD3D12::Init(CSZ source, CSZ sourceName, CSZ* branches)
|
|||
{
|
||||
compiled._stageCount++;
|
||||
vDefines[typeIndex].Name = "_HS";
|
||||
hr = D3DCompile(source, len, sourceName, vDefines.data(), &inc, _C(entryHS), _C("hs_" + version), flags, 0, &compiled._pBlobs[+Stage::hs], &pErrorMsgs);
|
||||
hr = D3DCompile(source, len, sourceName, vDefines.data(), &inc, _C(stageEntries[+Stage::hs]), _C("hs_" + version), flags, 0, &compiled._pBlobs[+Stage::hs], &pErrorMsgs);
|
||||
CheckErrorMsgs(pErrorMsgs);
|
||||
}
|
||||
|
||||
|
@ -139,7 +140,7 @@ void ShaderD3D12::Init(CSZ source, CSZ sourceName, CSZ* branches)
|
|||
{
|
||||
compiled._stageCount++;
|
||||
vDefines[typeIndex].Name = "_DS";
|
||||
hr = D3DCompile(source, len, sourceName, vDefines.data(), &inc, _C(entryDS), _C("ds_" + version), flags, 0, &compiled._pBlobs[+Stage::ds], &pErrorMsgs);
|
||||
hr = D3DCompile(source, len, sourceName, vDefines.data(), &inc, _C(stageEntries[+Stage::ds]), _C("ds_" + version), flags, 0, &compiled._pBlobs[+Stage::ds], &pErrorMsgs);
|
||||
CheckErrorMsgs(pErrorMsgs);
|
||||
}
|
||||
|
||||
|
@ -147,7 +148,7 @@ void ShaderD3D12::Init(CSZ source, CSZ sourceName, CSZ* branches)
|
|||
{
|
||||
compiled._stageCount++;
|
||||
vDefines[typeIndex].Name = "_GS";
|
||||
hr = D3DCompile(source, len, sourceName, vDefines.data(), &inc, _C(entryGS), _C("gs_" + version), flags, 0, &compiled._pBlobs[+Stage::gs], &pErrorMsgs);
|
||||
hr = D3DCompile(source, len, sourceName, vDefines.data(), &inc, _C(stageEntries[+Stage::gs]), _C("gs_" + version), flags, 0, &compiled._pBlobs[+Stage::gs], &pErrorMsgs);
|
||||
CheckErrorMsgs(pErrorMsgs);
|
||||
}
|
||||
|
||||
|
@ -155,7 +156,7 @@ void ShaderD3D12::Init(CSZ source, CSZ sourceName, CSZ* branches)
|
|||
{
|
||||
compiled._stageCount++;
|
||||
vDefines[typeIndex].Name = "_FS";
|
||||
hr = D3DCompile(source, len, sourceName, vDefines.data(), &inc, _C(entryFS), _C("ps_" + version), flags, 0, &compiled._pBlobs[+Stage::fs], &pErrorMsgs);
|
||||
hr = D3DCompile(source, len, sourceName, vDefines.data(), &inc, _C(stageEntries[+Stage::fs]), _C("ps_" + version), flags, 0, &compiled._pBlobs[+Stage::fs], &pErrorMsgs);
|
||||
CheckErrorMsgs(pErrorMsgs);
|
||||
}
|
||||
|
||||
|
@ -163,12 +164,12 @@ void ShaderD3D12::Init(CSZ source, CSZ sourceName, CSZ* branches)
|
|||
{
|
||||
compiled._stageCount++;
|
||||
vDefines[typeIndex].Name = "_CS";
|
||||
hr = D3DCompile(source, len, sourceName, vDefines.data(), &inc, _C(entryCS), _C("cs_" + version), flags, 0, &compiled._pBlobs[+Stage::cs], &pErrorMsgs);
|
||||
hr = D3DCompile(source, len, sourceName, vDefines.data(), &inc, _C(stageEntries[+Stage::cs]), _C("cs_" + version), flags, 0, &compiled._pBlobs[+Stage::cs], &pErrorMsgs);
|
||||
CheckErrorMsgs(pErrorMsgs);
|
||||
_compute = true;
|
||||
}
|
||||
|
||||
_mapCompiled[entry] = compiled;
|
||||
_mapCompiled[branch] = compiled;
|
||||
|
||||
branches++;
|
||||
}
|
||||
|
@ -284,6 +285,16 @@ void ShaderD3D12::CreatePipelineLayout()
|
|||
stageFlags |= dsd._stageFlags;
|
||||
if (dsd._capacity > 0)
|
||||
{
|
||||
D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
switch (dsd._stageFlags)
|
||||
{
|
||||
case ShaderStageFlags::vs: visibility = D3D12_SHADER_VISIBILITY_VERTEX; break;
|
||||
case ShaderStageFlags::hs: visibility = D3D12_SHADER_VISIBILITY_HULL; break;
|
||||
case ShaderStageFlags::ds: visibility = D3D12_SHADER_VISIBILITY_DOMAIN; break;
|
||||
case ShaderStageFlags::gs: visibility = D3D12_SHADER_VISIBILITY_GEOMETRY; break;
|
||||
case ShaderStageFlags::fs: visibility = D3D12_SHADER_VISIBILITY_PIXEL; break;
|
||||
}
|
||||
|
||||
CD3DX12_DESCRIPTOR_RANGE1 descRange;
|
||||
descRange.Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0, space);
|
||||
vDescRanges.push_back(descRange);
|
||||
|
@ -313,18 +324,15 @@ void ShaderD3D12::CreatePipelineLayout()
|
|||
{
|
||||
Sampler s = dsd._vSamplers[i];
|
||||
if (Sampler::input == s)
|
||||
s = Sampler::nearest2D;
|
||||
s = Sampler::nearestMipN;
|
||||
D3D12_STATIC_SAMPLER_DESC samplerDesc = pRendererD3D12->GetStaticSamplerDesc(s);
|
||||
samplerDesc.ShaderRegister = i + 1;
|
||||
samplerDesc.RegisterSpace = space;
|
||||
samplerDesc.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
samplerDesc.ShaderVisibility = visibility;
|
||||
vStaticSamplers.push_back(samplerDesc);
|
||||
}
|
||||
}
|
||||
}
|
||||
D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
if (ShaderStageFlags::fs == dsd._stageFlags)
|
||||
visibility = D3D12_SHADER_VISIBILITY_PIXEL;
|
||||
CD3DX12_ROOT_PARAMETER1 rootParam;
|
||||
rootParam.InitAsDescriptorTable(1 + textureCount, pDescriptorRanges, visibility);
|
||||
vRootParams.push_back(rootParam);
|
||||
|
@ -359,6 +367,8 @@ void ShaderD3D12::CreatePipelineLayout()
|
|||
rootSignatureFlags |= D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS;
|
||||
}
|
||||
|
||||
UpdateDebugInfo(vRootParams, vStaticSamplers, rootSignatureFlags);
|
||||
|
||||
CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC rootSignatureDesc;
|
||||
rootSignatureDesc.Init_1_1(
|
||||
Utils::Cast32(vRootParams.size()), vRootParams.data(),
|
||||
|
@ -376,7 +386,7 @@ void ShaderD3D12::CreatePipelineLayout()
|
|||
throw VERUS_RUNTIME_ERROR << "CreateRootSignature(), hr=" << VERUS_HR(hr);
|
||||
}
|
||||
|
||||
int ShaderD3D12::BindDescriptorSetTextures(int setNumber, std::initializer_list<TexturePtr> il, const int* pMips)
|
||||
CSHandle ShaderD3D12::BindDescriptorSetTextures(int setNumber, std::initializer_list<TexturePtr> il, const int* pMips)
|
||||
{
|
||||
VERUS_QREF_RENDERER_D3D12;
|
||||
|
||||
|
@ -400,7 +410,7 @@ int ShaderD3D12::BindDescriptorSetTextures(int setNumber, std::initializer_list<
|
|||
|
||||
RComplexSet complexSet = _vComplexSets[complexSetHandle];
|
||||
complexSet._vTextures.reserve(il.size());
|
||||
complexSet._dhSrvUav.Create(pRendererD3D12->GetD3DDevice(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, Utils::Cast32(il.size()));
|
||||
complexSet._dhViews.Create(pRendererD3D12->GetD3DDevice(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, Utils::Cast32(il.size()));
|
||||
if (!dsd._staticSamplersOnly)
|
||||
complexSet._dhSamplers.Create(pRendererD3D12->GetD3DDevice(), D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, Utils::Cast32(il.size()));
|
||||
int index = 0;
|
||||
|
@ -412,14 +422,14 @@ int ShaderD3D12::BindDescriptorSetTextures(int setNumber, std::initializer_list<
|
|||
if (Sampler::storage == dsd._vSamplers[index])
|
||||
{
|
||||
pRendererD3D12->GetD3DDevice()->CopyDescriptorsSimple(1,
|
||||
complexSet._dhSrvUav.AtCPU(index),
|
||||
complexSet._dhViews.AtCPU(index),
|
||||
texD3D12.GetDescriptorHeapUAV().AtCPU(mip),
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
||||
}
|
||||
else
|
||||
{
|
||||
pRendererD3D12->GetD3DDevice()->CopyDescriptorsSimple(1,
|
||||
complexSet._dhSrvUav.AtCPU(index),
|
||||
complexSet._dhViews.AtCPU(index),
|
||||
texD3D12.GetDescriptorHeapSRV().AtCPU(mip),
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
||||
if (Sampler::custom == dsd._vSamplers[index])
|
||||
|
@ -433,18 +443,18 @@ int ShaderD3D12::BindDescriptorSetTextures(int setNumber, std::initializer_list<
|
|||
index++;
|
||||
}
|
||||
|
||||
return complexSetHandle;
|
||||
return CSHandle::Make(complexSetHandle);
|
||||
}
|
||||
|
||||
void ShaderD3D12::FreeDescriptorSet(int& complexSetHandle)
|
||||
void ShaderD3D12::FreeDescriptorSet(CSHandle& complexSetHandle)
|
||||
{
|
||||
if (complexSetHandle >= 0 && complexSetHandle < _vComplexSets.size())
|
||||
if (complexSetHandle.IsSet() && complexSetHandle.Get() < _vComplexSets.size())
|
||||
{
|
||||
_vComplexSets[complexSetHandle]._vTextures.clear();
|
||||
_vComplexSets[complexSetHandle]._dhSrvUav.Reset();
|
||||
_vComplexSets[complexSetHandle]._dhSamplers.Reset();
|
||||
_vComplexSets[complexSetHandle.Get()]._vTextures.clear();
|
||||
_vComplexSets[complexSetHandle.Get()]._dhViews.Reset();
|
||||
_vComplexSets[complexSetHandle.Get()]._dhSamplers.Reset();
|
||||
}
|
||||
complexSetHandle = -1;
|
||||
complexSetHandle = CSHandle();
|
||||
}
|
||||
|
||||
void ShaderD3D12::BeginBindDescriptors()
|
||||
|
@ -532,7 +542,7 @@ CD3DX12_GPU_DESCRIPTOR_HANDLE ShaderD3D12::UpdateUniformBuffer(int setNumber, in
|
|||
dsd._index++;
|
||||
}
|
||||
|
||||
auto hpBase = pRendererD3D12->GetHeapCbvSrvUav().GetNextHandlePair();
|
||||
auto hpBase = pRendererD3D12->GetViewHeap().GetNextHandlePair();
|
||||
|
||||
// Copy CBV:
|
||||
pRendererD3D12->GetD3DDevice()->CopyDescriptorsSimple(1,
|
||||
|
@ -545,8 +555,8 @@ CD3DX12_GPU_DESCRIPTOR_HANDLE ShaderD3D12::UpdateUniformBuffer(int setNumber, in
|
|||
const auto& complexSet = _vComplexSets[complexSetHandle];
|
||||
const int count = Utils::Cast32(complexSet._vTextures.size());
|
||||
pRendererD3D12->GetD3DDevice()->CopyDescriptorsSimple(count,
|
||||
pRendererD3D12->GetHeapCbvSrvUav().GetNextHandlePair(count)._hCPU,
|
||||
complexSet._dhSrvUav.AtCPU(0),
|
||||
pRendererD3D12->GetViewHeap().GetNextHandlePair(count)._hCPU,
|
||||
complexSet._dhViews.AtCPU(0),
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
||||
}
|
||||
|
||||
|
@ -562,15 +572,24 @@ CD3DX12_GPU_DESCRIPTOR_HANDLE ShaderD3D12::UpdateSamplers(int setNumber, int com
|
|||
if (dsd._staticSamplersOnly)
|
||||
return CD3DX12_GPU_DESCRIPTOR_HANDLE();
|
||||
|
||||
CD3DX12_GPU_DESCRIPTOR_HANDLE hOffset = CD3DX12_GPU_DESCRIPTOR_HANDLE();
|
||||
const auto& complexSet = _vComplexSets[complexSetHandle];
|
||||
const int count = Utils::Cast32(complexSet._vTextures.size());
|
||||
auto hpSampler = pRendererD3D12->GetHeapSampler().GetNextHandlePair(count);
|
||||
pRendererD3D12->GetD3DDevice()->CopyDescriptorsSimple(count,
|
||||
const int maxCount = Utils::Cast32(complexSet._vTextures.size());
|
||||
VERUS_FOR(i, maxCount)
|
||||
{
|
||||
if (Sampler::custom == dsd._vSamplers[i])
|
||||
{
|
||||
auto hpSampler = pRendererD3D12->GetSamplerHeap().GetNextHandlePair(1);
|
||||
if (!hOffset.ptr)
|
||||
hOffset = hpSampler._hGPU;
|
||||
pRendererD3D12->GetD3DDevice()->CopyDescriptorsSimple(1,
|
||||
hpSampler._hCPU,
|
||||
complexSet._dhSamplers.AtCPU(0),
|
||||
complexSet._dhSamplers.AtCPU(i),
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
|
||||
}
|
||||
}
|
||||
|
||||
return hpSampler._hGPU;
|
||||
return hOffset;
|
||||
}
|
||||
|
||||
void ShaderD3D12::OnError(CSZ s)
|
||||
|
@ -587,3 +606,112 @@ void ShaderD3D12::OnError(CSZ s)
|
|||
else
|
||||
renderer.OnShaderWarning(s);
|
||||
}
|
||||
|
||||
void ShaderD3D12::UpdateDebugInfo(
|
||||
const Vector<CD3DX12_ROOT_PARAMETER1>& vRootParams,
|
||||
const Vector<D3D12_STATIC_SAMPLER_DESC>& vStaticSamplers,
|
||||
D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags)
|
||||
{
|
||||
StringStream ss;
|
||||
|
||||
auto PrintShaderVisibility = [&ss](D3D12_SHADER_VISIBILITY shaderVisibility)
|
||||
{
|
||||
switch (shaderVisibility)
|
||||
{
|
||||
case D3D12_SHADER_VISIBILITY_ALL: ss << "All"; break;
|
||||
case D3D12_SHADER_VISIBILITY_VERTEX: ss << "V"; break;
|
||||
case D3D12_SHADER_VISIBILITY_HULL: ss << "H"; break;
|
||||
case D3D12_SHADER_VISIBILITY_DOMAIN: ss << "D"; break;
|
||||
case D3D12_SHADER_VISIBILITY_GEOMETRY: ss << "G"; break;
|
||||
case D3D12_SHADER_VISIBILITY_PIXEL: ss << "P"; break;
|
||||
}
|
||||
};
|
||||
|
||||
int totalSize = 0;
|
||||
int index = 0;
|
||||
for (const auto& rootParam : vRootParams)
|
||||
{
|
||||
ss << "Index=" << index;
|
||||
ss << ", Type=";
|
||||
switch (rootParam.ParameterType)
|
||||
{
|
||||
case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE: ss << "Table"; totalSize += 4; break;
|
||||
case D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS: ss << "Const"; totalSize += 4 * rootParam.Constants.Num32BitValues; break;
|
||||
case D3D12_ROOT_PARAMETER_TYPE_CBV: ss << "CBV"; totalSize += 8; break;
|
||||
case D3D12_ROOT_PARAMETER_TYPE_SRV: ss << "SRV"; totalSize += 8; break;
|
||||
case D3D12_ROOT_PARAMETER_TYPE_UAV: ss << "UAV"; totalSize += 8; break;
|
||||
}
|
||||
ss << ", Visibility=";
|
||||
PrintShaderVisibility(rootParam.ShaderVisibility);
|
||||
if (totalSize > 64)
|
||||
ss << " (spilled)";
|
||||
ss << std::endl;
|
||||
switch (rootParam.ParameterType)
|
||||
{
|
||||
case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE:
|
||||
{
|
||||
VERUS_FOR(i, rootParam.DescriptorTable.NumDescriptorRanges)
|
||||
{
|
||||
auto& descRange = rootParam.DescriptorTable.pDescriptorRanges[i];
|
||||
ss << " Type=";
|
||||
switch (descRange.RangeType)
|
||||
{
|
||||
case D3D12_DESCRIPTOR_RANGE_TYPE_SRV: ss << "SRV"; break;
|
||||
case D3D12_DESCRIPTOR_RANGE_TYPE_UAV: ss << "UAV"; break;
|
||||
case D3D12_DESCRIPTOR_RANGE_TYPE_CBV: ss << "CBV"; break;
|
||||
case D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER: ss << "Sampler"; break;
|
||||
}
|
||||
ss << ", Count=" << descRange.NumDescriptors;
|
||||
ss << ", Register=" << descRange.BaseShaderRegister;
|
||||
ss << ", Space=" << descRange.RegisterSpace;
|
||||
ss << ", Flags=" << descRange.Flags;
|
||||
ss << ", Offset=" << static_cast<int>(descRange.OffsetInDescriptorsFromTableStart);
|
||||
ss << std::endl;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS:
|
||||
{
|
||||
ss << " ";
|
||||
ss << "Register=" << rootParam.Constants.ShaderRegister;
|
||||
ss << ", Space=" << rootParam.Constants.RegisterSpace;
|
||||
ss << ", Count=" << rootParam.Constants.Num32BitValues << "x4 bytes";
|
||||
ss << std::endl;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
}
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
for (const auto& sampler : vStaticSamplers)
|
||||
{
|
||||
ss << "StaticSampler Register=" << sampler.ShaderRegister;
|
||||
ss << ", Space=" << sampler.RegisterSpace;
|
||||
ss << ", Visibility=";
|
||||
PrintShaderVisibility(sampler.ShaderVisibility);
|
||||
ss << std::endl;
|
||||
}
|
||||
ss << "TotalSize=" << totalSize << " bytes (256 max)";
|
||||
ss << ", Flags=";
|
||||
if (rootSignatureFlags & D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT)
|
||||
ss << "[AIAIL]";
|
||||
if (rootSignatureFlags & D3D12_ROOT_SIGNATURE_FLAG_DENY_VERTEX_SHADER_ROOT_ACCESS)
|
||||
ss << "[DVSRA]";
|
||||
if (rootSignatureFlags & D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS)
|
||||
ss << "[DHSRA]";
|
||||
if (rootSignatureFlags & D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS)
|
||||
ss << "[DDSRA]";
|
||||
if (rootSignatureFlags & D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS)
|
||||
ss << "[DGSRA]";
|
||||
if (rootSignatureFlags & D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS)
|
||||
ss << "[DPSRA]";
|
||||
if (rootSignatureFlags & D3D12_ROOT_SIGNATURE_FLAG_ALLOW_STREAM_OUTPUT)
|
||||
ss << "[ASO]";
|
||||
if (rootSignatureFlags & D3D12_ROOT_SIGNATURE_FLAG_LOCAL_ROOT_SIGNATURE)
|
||||
ss << "[LRS]";
|
||||
|
||||
_debugInfo = ss.str();
|
||||
}
|
||||
|
|
|
@ -19,11 +19,16 @@ namespace verus
|
|||
|
||||
class ShaderD3D12 : public BaseShader
|
||||
{
|
||||
public:
|
||||
struct Compiled
|
||||
{
|
||||
ComPtr<ID3DBlob> _pBlobs[+Stage::count];
|
||||
String _entry;
|
||||
int _stageCount = 0;
|
||||
};
|
||||
VERUS_TYPEDEFS(Compiled);
|
||||
|
||||
private:
|
||||
typedef Map<String, Compiled> TMapCompiled;
|
||||
|
||||
struct DescriptorSetDesc
|
||||
|
@ -48,7 +53,7 @@ namespace verus
|
|||
struct ComplexSet
|
||||
{
|
||||
Vector<TexturePtr> _vTextures;
|
||||
DescriptorHeap _dhSrvUav;
|
||||
DescriptorHeap _dhViews;
|
||||
DescriptorHeap _dhSamplers;
|
||||
};
|
||||
VERUS_TYPEDEFS(ComplexSet);
|
||||
|
@ -57,6 +62,7 @@ namespace verus
|
|||
Vector<DescriptorSetDesc> _vDescriptorSetDesc;
|
||||
Vector<ComplexSet> _vComplexSets;
|
||||
ComPtr<ID3D12RootSignature> _pRootSignature;
|
||||
String _debugInfo;
|
||||
UINT64 _currentFrame = UINT64_MAX;
|
||||
bool _compute = false;
|
||||
|
||||
|
@ -69,8 +75,8 @@ namespace verus
|
|||
|
||||
virtual void CreateDescriptorSet(int setNumber, const void* pSrc, int size, int capacity, std::initializer_list<Sampler> il, ShaderStageFlags stageFlags) override;
|
||||
virtual void CreatePipelineLayout() override;
|
||||
virtual int BindDescriptorSetTextures(int setNumber, std::initializer_list<TexturePtr> il, const int* pMips) override;
|
||||
virtual void FreeDescriptorSet(int& complexSetHandle) override;
|
||||
virtual CSHandle BindDescriptorSetTextures(int setNumber, std::initializer_list<TexturePtr> il, const int* pMips) override;
|
||||
virtual void FreeDescriptorSet(CSHandle& complexSetHandle) override;
|
||||
|
||||
virtual void BeginBindDescriptors() override;
|
||||
virtual void EndBindDescriptors() override;
|
||||
|
@ -79,8 +85,7 @@ namespace verus
|
|||
// D3D12
|
||||
//
|
||||
|
||||
ID3DBlob* GetD3DBlob(CSZ branch, Stage stage) const { return _mapCompiled.at(branch)._pBlobs[+stage].Get(); }
|
||||
int GetStageCount(CSZ branch) const { return _mapCompiled.at(branch)._stageCount; }
|
||||
RcCompiled GetCompiled(CSZ branch) const { return _mapCompiled.at(branch); }
|
||||
|
||||
ID3D12RootSignature* GetD3DRootSignature() const { return _pRootSignature.Get(); }
|
||||
|
||||
|
@ -92,6 +97,11 @@ namespace verus
|
|||
bool IsCompute() const { return _compute; }
|
||||
|
||||
void OnError(CSZ s);
|
||||
|
||||
void UpdateDebugInfo(
|
||||
const Vector<CD3DX12_ROOT_PARAMETER1>& vRootParams,
|
||||
const Vector<D3D12_STATIC_SAMPLER_DESC>& vStaticSamplers,
|
||||
D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags);
|
||||
};
|
||||
VERUS_TYPEDEFS(ShaderD3D12);
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ void TextureD3D12::Init(RcTextureDesc desc)
|
|||
_bytesPerPixel = FormatToBytesPerPixel(desc._format);
|
||||
const bool renderTarget = (_desc._flags & TextureDesc::Flags::colorAttachment);
|
||||
const bool depthFormat = IsDepthFormat(desc._format);
|
||||
const bool depthSampled = _desc._flags & TextureDesc::Flags::depthSampled;
|
||||
const bool depthSampled = _desc._flags & (TextureDesc::Flags::depthSampledR | TextureDesc::Flags::depthSampledW);
|
||||
if (_desc._flags & TextureDesc::Flags::anyShaderResource)
|
||||
_mainLayout = ImageLayout::xsReadOnly;
|
||||
|
||||
|
@ -50,17 +50,13 @@ void TextureD3D12::Init(RcTextureDesc desc)
|
|||
D3D12_RESOURCE_STATES initialResourceState = ToNativeImageLayout(_mainLayout);
|
||||
D3D12_CLEAR_VALUE clearValue = {};
|
||||
clearValue.Format = ToNativeFormat(_desc._format, false);
|
||||
if (renderTarget)
|
||||
{
|
||||
initialResourceState = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
|
||||
memcpy(clearValue.Color, _desc._clearValue.ToPointer(), sizeof(clearValue.Color));
|
||||
}
|
||||
if (depthFormat)
|
||||
{
|
||||
initialResourceState = D3D12_RESOURCE_STATE_DEPTH_WRITE;
|
||||
clearValue.DepthStencil.Depth = _desc._clearValue.getX();
|
||||
clearValue.DepthStencil.Stencil = static_cast<UINT8>(_desc._clearValue.getY());
|
||||
if (depthSampled)
|
||||
if (_desc._flags & TextureDesc::Flags::depthSampledR)
|
||||
initialResourceState = D3D12_RESOURCE_STATE_DEPTH_READ | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
|
||||
}
|
||||
D3D12MA::ALLOCATION_DESC allocDesc = {};
|
||||
|
@ -83,6 +79,12 @@ void TextureD3D12::Init(RcTextureDesc desc)
|
|||
resDescUAV.Height = Math::Max(1, _desc._height >> 1);
|
||||
resDescUAV.MipLevels = uavMipLevels;
|
||||
resDescUAV.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
|
||||
// sRGB cannot be used with UAV:
|
||||
switch (resDescUAV.Format)
|
||||
{
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: resDescUAV.Format = DXGI_FORMAT_R8G8B8A8_UNORM; break;
|
||||
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: resDescUAV.Format = DXGI_FORMAT_B8G8R8A8_UNORM; break;
|
||||
}
|
||||
|
||||
D3D12MA::ALLOCATION_DESC allocDesc = {};
|
||||
allocDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;
|
||||
|
@ -91,18 +93,18 @@ void TextureD3D12::Init(RcTextureDesc desc)
|
|||
&resDescUAV,
|
||||
D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE,
|
||||
nullptr,
|
||||
&_uavResource._pMaAllocation,
|
||||
IID_PPV_ARGS(&_uavResource._pResource))))
|
||||
&_uaResource._pMaAllocation,
|
||||
IID_PPV_ARGS(&_uaResource._pResource))))
|
||||
throw VERUS_RUNTIME_ERROR << "CreateResource(D3D12_HEAP_TYPE_DEFAULT), hr=" << VERUS_HR(hr);
|
||||
|
||||
_dhUAV.Create(pRendererD3D12->GetD3DDevice(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, uavMipLevels);
|
||||
VERUS_FOR(i, uavMipLevels)
|
||||
{
|
||||
D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
|
||||
uavDesc.Format = resDesc.Format;
|
||||
uavDesc.Format = resDescUAV.Format;
|
||||
uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D;
|
||||
uavDesc.Texture2D.MipSlice = i;
|
||||
pRendererD3D12->GetD3DDevice()->CreateUnorderedAccessView(_uavResource._pResource.Get(), nullptr, &uavDesc, _dhUAV.AtCPU(i));
|
||||
pRendererD3D12->GetD3DDevice()->CreateUnorderedAccessView(_uaResource._pResource.Get(), nullptr, &uavDesc, _dhUAV.AtCPU(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,9 +154,9 @@ void TextureD3D12::Done()
|
|||
_dhDSV.Reset();
|
||||
_dhRTV.Reset();
|
||||
_dhSRV.Reset();
|
||||
VERUS_SMART_RELEASE(_uavResource._pMaAllocation);
|
||||
VERUS_COM_RELEASE_CHECK(_uavResource._pResource.Get());
|
||||
_uavResource._pResource.Reset();
|
||||
VERUS_SMART_RELEASE(_uaResource._pMaAllocation);
|
||||
VERUS_COM_RELEASE_CHECK(_uaResource._pResource.Get());
|
||||
_uaResource._pResource.Reset();
|
||||
VERUS_SMART_RELEASE(_resource._pMaAllocation);
|
||||
VERUS_COM_RELEASE_CHECK(_resource._pResource.Get());
|
||||
_resource._pResource.Reset();
|
||||
|
@ -258,7 +260,7 @@ void TextureD3D12::GenerateMips(PBaseCommandBuffer pCB)
|
|||
ub._srcMipLevel = srcMip;
|
||||
ub._mipLevelCount = dispatchMipCount;
|
||||
ub._srcDimensionCase = (srcHeight & 1) << 1 | (srcWidth & 1);
|
||||
ub._srgb = false;
|
||||
ub._srgb = IsSRGBFormat(_desc._format);
|
||||
ub._texelSize.x = 1.f / dstWidth;
|
||||
ub._texelSize.y = 1.f / dstHeight;
|
||||
|
||||
|
@ -267,7 +269,7 @@ void TextureD3D12::GenerateMips(PBaseCommandBuffer pCB)
|
|||
int mips[5] = {}; // For input texture (always mip 0) and 4 UAV mips.
|
||||
VERUS_FOR(mip, dispatchMipCount)
|
||||
mips[mip + 1] = srcMip + mip;
|
||||
const int complexSetHandle = shader->BindDescriptorSetTextures(0, { tex, tex, tex, tex, tex }, mips);
|
||||
const CSHandle complexSetHandle = shader->BindDescriptorSetTextures(0, { tex, tex, tex, tex, tex }, mips);
|
||||
_vCshGenerateMips.push_back(complexSetHandle);
|
||||
pCB->BindDescriptors(shader, 0, complexSetHandle);
|
||||
}
|
||||
|
@ -278,7 +280,7 @@ void TextureD3D12::GenerateMips(PBaseCommandBuffer pCB)
|
|||
|
||||
pCB->Dispatch(Math::DivideByMultiple(dstWidth, 8), Math::DivideByMultiple(dstHeight, 8));
|
||||
|
||||
auto rb = CD3DX12_RESOURCE_BARRIER::UAV(_uavResource._pResource.Get());
|
||||
auto rb = CD3DX12_RESOURCE_BARRIER::UAV(_uaResource._pResource.Get());
|
||||
pCmdList->ResourceBarrier(1, &rb);
|
||||
|
||||
// Transition state for upcoming CopyTextureRegion():
|
||||
|
@ -288,7 +290,8 @@ void TextureD3D12::GenerateMips(PBaseCommandBuffer pCB)
|
|||
VERUS_FOR(mip, dispatchMipCount)
|
||||
{
|
||||
const int subUAV = srcMip + mip;
|
||||
barriers[barrierCount++] = CD3DX12_RESOURCE_BARRIER::Transition(_uavResource._pResource.Get(), D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_COPY_SOURCE, subUAV);
|
||||
barriers[barrierCount++] = CD3DX12_RESOURCE_BARRIER::Transition(_uaResource._pResource.Get(),
|
||||
D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_COPY_SOURCE, subUAV);
|
||||
}
|
||||
pCmdList->ResourceBarrier(barrierCount, barriers);
|
||||
|
||||
|
@ -301,7 +304,7 @@ void TextureD3D12::GenerateMips(PBaseCommandBuffer pCB)
|
|||
pCmdList->CopyTextureRegion(
|
||||
&CD3DX12_TEXTURE_COPY_LOCATION(_resource._pResource.Get(), subSRV),
|
||||
0, 0, 0,
|
||||
&CD3DX12_TEXTURE_COPY_LOCATION(_uavResource._pResource.Get(), subUAV),
|
||||
&CD3DX12_TEXTURE_COPY_LOCATION(_uaResource._pResource.Get(), subUAV),
|
||||
nullptr);
|
||||
}
|
||||
// Transition state for next Dispatch():
|
||||
|
@ -311,7 +314,8 @@ void TextureD3D12::GenerateMips(PBaseCommandBuffer pCB)
|
|||
VERUS_FOR(mip, dispatchMipCount)
|
||||
{
|
||||
const int subUAV = srcMip + mip;
|
||||
barriers[barrierCount++] = CD3DX12_RESOURCE_BARRIER::Transition(_uavResource._pResource.Get(), D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, subUAV);
|
||||
barriers[barrierCount++] = CD3DX12_RESOURCE_BARRIER::Transition(_uaResource._pResource.Get(),
|
||||
D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, subUAV);
|
||||
}
|
||||
pCmdList->ResourceBarrier(barrierCount, barriers);
|
||||
|
||||
|
@ -348,7 +352,7 @@ Continue TextureD3D12::Scheduled_Update()
|
|||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
auto shader = renderer.GetShaderGenerateMips();
|
||||
for (int csh : _vCshGenerateMips)
|
||||
for (auto& csh : _vCshGenerateMips)
|
||||
shader->FreeDescriptorSet(csh);
|
||||
_vCshGenerateMips.clear();
|
||||
}
|
||||
|
|
|
@ -13,9 +13,9 @@ namespace verus
|
|||
};
|
||||
|
||||
ResourceEx _resource;
|
||||
ResourceEx _uavResource;
|
||||
ResourceEx _uaResource;
|
||||
Vector<ResourceEx> _vStagingBuffers;
|
||||
Vector<int> _vCshGenerateMips;
|
||||
Vector<CSHandle> _vCshGenerateMips;
|
||||
DescriptorHeap _dhSRV;
|
||||
DescriptorHeap _dhUAV;
|
||||
DescriptorHeap _dhRTV;
|
||||
|
|
|
@ -44,7 +44,7 @@ void CommandBufferVulkan::End()
|
|||
throw VERUS_RUNTIME_ERROR << "vkEndCommandBuffer(), res=" << res;
|
||||
}
|
||||
|
||||
void CommandBufferVulkan::BeginRenderPass(int renderPassHandle, int framebufferHandle, std::initializer_list<Vector4> ilClearValues, bool setViewportAndScissor)
|
||||
void CommandBufferVulkan::BeginRenderPass(RPHandle renderPassHandle, FBHandle framebufferHandle, std::initializer_list<Vector4> ilClearValues, bool setViewportAndScissor)
|
||||
{
|
||||
VERUS_QREF_RENDERER_VULKAN;
|
||||
VERUS_QREF_CONST_SETTINGS;
|
||||
|
@ -120,6 +120,13 @@ void CommandBufferVulkan::BindPipeline(PipelinePtr pipe)
|
|||
|
||||
void CommandBufferVulkan::SetViewport(std::initializer_list<Vector4> il, float minDepth, float maxDepth)
|
||||
{
|
||||
if (il.size() > 0)
|
||||
{
|
||||
const float w = il.begin()->Width();
|
||||
const float h = il.begin()->Height();
|
||||
_viewportSize = Vector4(w, h, 1 / w, 1 / h);
|
||||
}
|
||||
|
||||
VkViewport vpVulkan[VERUS_MAX_RT];
|
||||
int count = 0;
|
||||
for (const auto& rc : il)
|
||||
|
@ -155,7 +162,7 @@ void CommandBufferVulkan::SetBlendConstants(const float* p)
|
|||
vkCmdSetBlendConstants(GetVkCommandBuffer(), p);
|
||||
}
|
||||
|
||||
bool CommandBufferVulkan::BindDescriptors(ShaderPtr shader, int setNumber, int complexSetHandle)
|
||||
bool CommandBufferVulkan::BindDescriptors(ShaderPtr shader, int setNumber, CSHandle complexSetHandle)
|
||||
{
|
||||
if (setNumber < 0)
|
||||
return true;
|
||||
|
@ -167,7 +174,7 @@ bool CommandBufferVulkan::BindDescriptors(ShaderPtr shader, int setNumber, int c
|
|||
if (offset < 0)
|
||||
return false;
|
||||
|
||||
const VkDescriptorSet descriptorSet = (complexSetHandle >= 0) ?
|
||||
const VkDescriptorSet descriptorSet = complexSetHandle.IsSet() ?
|
||||
shaderVulkan.GetComplexVkDescriptorSet(complexSetHandle) : shaderVulkan.GetVkDescriptorSet(setNumber);
|
||||
const uint32_t dynamicOffset = offset;
|
||||
const uint32_t dynamicOffsetCount = 1;
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace verus
|
|||
virtual void Begin() override;
|
||||
virtual void End() override;
|
||||
|
||||
virtual void BeginRenderPass(int renderPassHandle, int framebufferHandle, std::initializer_list<Vector4> ilClearValues, bool setViewportAndScissor) override;
|
||||
virtual void BeginRenderPass(RPHandle renderPassHandle, FBHandle framebufferHandle, std::initializer_list<Vector4> ilClearValues, bool setViewportAndScissor) override;
|
||||
virtual void NextSubpass() override;
|
||||
virtual void EndRenderPass() override;
|
||||
|
||||
|
@ -31,7 +31,7 @@ namespace verus
|
|||
virtual void SetScissor(std::initializer_list<Vector4> il) override;
|
||||
virtual void SetBlendConstants(const float* p) override;
|
||||
|
||||
virtual bool BindDescriptors(ShaderPtr shader, int setNumber, int complexSetHandle) override;
|
||||
virtual bool BindDescriptors(ShaderPtr shader, int setNumber, CSHandle complexSetHandle) override;
|
||||
virtual void PushConstants(ShaderPtr shader, int offset, int size, const void* p, ShaderStageFlags stageFlags) override;
|
||||
|
||||
virtual void PipelineImageMemoryBarrier(TexturePtr tex, ImageLayout oldLayout, ImageLayout newLayout, Range<int> mipLevels, int arrayLayer) override;
|
||||
|
|
|
@ -19,13 +19,13 @@ void GeometryVulkan::Init(RcGeometryDesc desc)
|
|||
_dynBindingsMask = desc._dynBindingsMask;
|
||||
_32BitIndices = desc._32BitIndices;
|
||||
|
||||
const int bindingCount = GetBindingCount(desc._pInputElementDesc);
|
||||
const int bindingCount = GetBindingCount(desc._pVertexInputAttrDesc);
|
||||
_vVertexInputBindingDesc.reserve(bindingCount);
|
||||
_vVertexInputAttributeDesc.reserve(GetInputElementDescCount(desc._pInputElementDesc));
|
||||
_vVertexInputAttributeDesc.reserve(GetVertexInputAttrDescCount(desc._pVertexInputAttrDesc));
|
||||
int i = 0;
|
||||
while (desc._pInputElementDesc[i]._offset >= 0)
|
||||
while (desc._pVertexInputAttrDesc[i]._offset >= 0)
|
||||
{
|
||||
int binding = desc._pInputElementDesc[i]._binding;
|
||||
int binding = desc._pVertexInputAttrDesc[i]._binding;
|
||||
VkVertexInputRate inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||
if (binding < 0)
|
||||
{
|
||||
|
@ -53,10 +53,10 @@ void GeometryVulkan::Init(RcGeometryDesc desc)
|
|||
}
|
||||
|
||||
VkVertexInputAttributeDescription vkviad = {};
|
||||
vkviad.location = ToNativeLocation(desc._pInputElementDesc[i]._usage, desc._pInputElementDesc[i]._usageIndex);
|
||||
vkviad.location = ToNativeLocation(desc._pVertexInputAttrDesc[i]._usage, desc._pVertexInputAttrDesc[i]._usageIndex);
|
||||
vkviad.binding = binding;
|
||||
vkviad.format = ToNativeFormat(desc._pInputElementDesc[i]._usage, desc._pInputElementDesc[i]._type, desc._pInputElementDesc[i]._components);
|
||||
vkviad.offset = desc._pInputElementDesc[i]._offset;
|
||||
vkviad.format = ToNativeFormat(desc._pVertexInputAttrDesc[i]._usage, desc._pVertexInputAttrDesc[i]._type, desc._pVertexInputAttrDesc[i]._components);
|
||||
vkviad.offset = desc._pVertexInputAttrDesc[i]._offset;
|
||||
_vVertexInputAttributeDesc.push_back(vkviad);
|
||||
i++;
|
||||
}
|
||||
|
|
|
@ -90,6 +90,8 @@ VkPrimitiveTopology CGI::ToNativePrimitiveTopology(PrimitiveTopology primitiveTo
|
|||
case PrimitiveTopology::lineStrip: return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
|
||||
case PrimitiveTopology::triangleList: return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||
case PrimitiveTopology::triangleStrip: return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
|
||||
case PrimitiveTopology::patchList3: return VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
|
||||
case PrimitiveTopology::patchList4: return VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
|
||||
default: throw VERUS_RECOVERABLE << "ToNativePrimitiveTopology()";
|
||||
}
|
||||
}
|
||||
|
@ -148,14 +150,16 @@ int CGI::ToNativeLocation(IeUsage usage, int usageIndex)
|
|||
switch (usage)
|
||||
{
|
||||
case IeUsage::position: return 0;
|
||||
case IeUsage::blendWeight: return 1;
|
||||
case IeUsage::blendWeights: return 1;
|
||||
case IeUsage::blendIndices: return 6;
|
||||
case IeUsage::normal: return 2;
|
||||
case IeUsage::psize: return 7;
|
||||
case IeUsage::texCoord: return 8 + usageIndex;
|
||||
case IeUsage::tangent: return 14;
|
||||
case IeUsage::binormal: return 15;
|
||||
case IeUsage::color: return 3 + usageIndex;
|
||||
case IeUsage::psize: return 7;
|
||||
case IeUsage::texCoord: return 8 + usageIndex;
|
||||
case IeUsage::instData: return 16 + usageIndex;
|
||||
case IeUsage::attr: return usageIndex;
|
||||
default: throw VERUS_RECOVERABLE << "ToNativeLocation()";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,27 +38,31 @@ void PipelineVulkan::Init(RcPipelineDesc desc)
|
|||
attachmentCount++;
|
||||
}
|
||||
|
||||
const bool tess = desc._topology >= PrimitiveTopology::patchList3 && desc._topology <= PrimitiveTopology::patchList4;
|
||||
|
||||
ShaderVulkan::RcCompiled compiled = shader.GetCompiled(desc._shaderBranch);
|
||||
Vector<String> entryNames(+BaseShader::Stage::count);
|
||||
Vector<VkPipelineShaderStageCreateInfo> vShaderStages;
|
||||
vShaderStages.reserve(shader.GetStageCount(desc._shaderBranch));
|
||||
auto PushShaderStage = [&vShaderStages, &shader, &desc](CSZ name, BaseShader::Stage stage, VkShaderStageFlagBits shaderStageFlagBits)
|
||||
vShaderStages.reserve(compiled._stageCount);
|
||||
auto PushShaderStage = [&vShaderStages, &compiled, &entryNames](CSZ suffix, BaseShader::Stage stage, VkShaderStageFlagBits shaderStageFlagBits)
|
||||
{
|
||||
const VkShaderModule shaderModule = shader.GetVkShaderModule(desc._shaderBranch, stage);
|
||||
const VkShaderModule shaderModule = compiled._shaderModules[+stage];
|
||||
entryNames[+stage] = compiled._entry + suffix;
|
||||
if (shaderModule != VK_NULL_HANDLE)
|
||||
{
|
||||
VkPipelineShaderStageCreateInfo vkpssci = {};
|
||||
vkpssci.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
vkpssci.stage = shaderStageFlagBits;
|
||||
vkpssci.module = shaderModule;
|
||||
vkpssci.pName = name;
|
||||
vkpssci.pName = _C(entryNames[+stage]);
|
||||
vShaderStages.push_back(vkpssci);
|
||||
}
|
||||
};
|
||||
|
||||
PushShaderStage("mainVS", BaseShader::Stage::vs, VK_SHADER_STAGE_VERTEX_BIT);
|
||||
PushShaderStage("mainHS", BaseShader::Stage::hs, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
|
||||
PushShaderStage("mainDS", BaseShader::Stage::ds, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
|
||||
PushShaderStage("mainGS", BaseShader::Stage::gs, VK_SHADER_STAGE_GEOMETRY_BIT);
|
||||
PushShaderStage("mainFS", BaseShader::Stage::fs, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
PushShaderStage("VS", BaseShader::Stage::vs, VK_SHADER_STAGE_VERTEX_BIT);
|
||||
PushShaderStage("HS", BaseShader::Stage::hs, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
|
||||
PushShaderStage("DS", BaseShader::Stage::ds, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
|
||||
PushShaderStage("GS", BaseShader::Stage::gs, VK_SHADER_STAGE_GEOMETRY_BIT);
|
||||
PushShaderStage("FS", BaseShader::Stage::fs, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
|
||||
Vector<VkVertexInputBindingDescription> vVertexInputBindingDesc;
|
||||
Vector<VkVertexInputAttributeDescription> vVertexInputAttributeDesc;
|
||||
|
@ -70,6 +74,14 @@ void PipelineVulkan::Init(RcPipelineDesc desc)
|
|||
inputAssemblyState.topology = ToNativePrimitiveTopology(desc._topology);
|
||||
inputAssemblyState.primitiveRestartEnable = desc._primitiveRestartEnable;
|
||||
|
||||
VkPipelineTessellationStateCreateInfo tessellationState = {};
|
||||
tessellationState.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
|
||||
tessellationState.patchControlPoints = 3;
|
||||
switch (desc._topology)
|
||||
{
|
||||
case PrimitiveTopology::patchList4: tessellationState.patchControlPoints = 4; break;
|
||||
}
|
||||
|
||||
VkPipelineViewportStateCreateInfo viewportState = {};
|
||||
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
||||
viewportState.viewportCount = desc._multiViewport;
|
||||
|
@ -77,6 +89,8 @@ void PipelineVulkan::Init(RcPipelineDesc desc)
|
|||
|
||||
VkPipelineRasterizationLineStateCreateInfoEXT rasterizationLineState = {};
|
||||
rasterizationLineState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT;
|
||||
rasterizationLineState.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT;
|
||||
if (desc._colorAttachBlendEqs[0] == VERUS_COLOR_BLEND_ALPHA)
|
||||
rasterizationLineState.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT;
|
||||
VkPipelineRasterizationStateCreateInfo rasterizationState = {};
|
||||
rasterizationState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
||||
|
@ -94,7 +108,6 @@ void PipelineVulkan::Init(RcPipelineDesc desc)
|
|||
|
||||
VkPipelineMultisampleStateCreateInfo multisampleState = {};
|
||||
multisampleState.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||||
multisampleState.sampleShadingEnable = VK_FALSE;
|
||||
multisampleState.rasterizationSamples = ToNativeSampleCount(desc._sampleCount);
|
||||
|
||||
VkPipelineDepthStencilStateCreateInfo depthStencilState = {};
|
||||
|
@ -196,6 +209,7 @@ void PipelineVulkan::Init(RcPipelineDesc desc)
|
|||
vkgpci.pStages = vShaderStages.data();
|
||||
vkgpci.pVertexInputState = &vertexInputState;
|
||||
vkgpci.pInputAssemblyState = &inputAssemblyState;
|
||||
vkgpci.pTessellationState = tess ? &tessellationState : nullptr;
|
||||
vkgpci.pViewportState = &viewportState;
|
||||
vkgpci.pRasterizationState = &rasterizationState;
|
||||
vkgpci.pMultisampleState = &multisampleState;
|
||||
|
@ -225,14 +239,17 @@ void PipelineVulkan::InitCompute(RcPipelineDesc desc)
|
|||
VkResult res = VK_SUCCESS;
|
||||
|
||||
RcShaderVulkan shader = static_cast<RcShaderVulkan>(*desc._shader);
|
||||
const VkShaderModule shaderModule = shader.GetVkShaderModule(desc._shaderBranch, BaseShader::Stage::cs);
|
||||
|
||||
ShaderVulkan::RcCompiled compiled = shader.GetCompiled(desc._shaderBranch);
|
||||
const VkShaderModule shaderModule = compiled._shaderModules[+BaseShader::Stage::cs];
|
||||
String entryName = compiled._entry + "CS";
|
||||
|
||||
VkComputePipelineCreateInfo vkcpci = {};
|
||||
vkcpci.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
|
||||
vkcpci.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
vkcpci.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT;
|
||||
vkcpci.stage.module = shaderModule;
|
||||
vkcpci.stage.pName = "mainCS";
|
||||
vkcpci.stage.pName = _C(entryName);
|
||||
vkcpci.layout = shader.GetVkPipelineLayout();
|
||||
if (VK_SUCCESS != (res = vkCreateComputePipelines(pRendererVulkan->GetVkDevice(), VK_NULL_HANDLE, 1, &vkcpci, pRendererVulkan->GetAllocator(), &_pipeline)))
|
||||
throw VERUS_RUNTIME_ERROR << "vkCreateComputePipelines(), res=" << res;
|
||||
|
|
|
@ -100,8 +100,8 @@ void RendererVulkan::Done()
|
|||
Renderer::I().ImGuiSetCurrentContext(nullptr);
|
||||
}
|
||||
|
||||
DeleteFramebuffer(-1);
|
||||
DeleteRenderPass(-1);
|
||||
DeleteFramebuffer(FBHandle::Make(-2));
|
||||
DeleteRenderPass(RPHandle::Make(-2));
|
||||
|
||||
for (auto sampler : _vSamplers)
|
||||
VERUS_VULKAN_DESTROY(sampler, vkDestroySampler(_device, sampler, GetAllocator()));
|
||||
|
@ -189,6 +189,7 @@ VKAPI_ATTR VkBool32 VKAPI_CALL RendererVulkan::DebugUtilsMessengerCallback(
|
|||
severity = D::Log::Severity::warning;
|
||||
if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
|
||||
severity = D::Log::Severity::error;
|
||||
if (!strstr(pCallbackData->pMessage, "ptr to input arr[1] of struct of"))
|
||||
D::Log::I().Write(pCallbackData->pMessage, std::this_thread::get_id(), __FILE__, __LINE__, severity);
|
||||
return VK_FALSE;
|
||||
}
|
||||
|
@ -394,10 +395,12 @@ void RendererVulkan::PickPhysicalDevice()
|
|||
|
||||
void RendererVulkan::CreateDevice()
|
||||
{
|
||||
VERUS_QREF_CONST_SETTINGS;
|
||||
VkResult res = VK_SUCCESS;
|
||||
|
||||
VkPhysicalDeviceLineRasterizationFeaturesEXT lineRasterizationFeatures = {};
|
||||
lineRasterizationFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT;
|
||||
lineRasterizationFeatures.bresenhamLines = VK_TRUE;
|
||||
lineRasterizationFeatures.smoothLines = VK_TRUE;
|
||||
|
||||
_queueFamilyIndices = FindQueueFamilyIndices(_physicalDevice);
|
||||
|
@ -416,6 +419,8 @@ void RendererVulkan::CreateDevice()
|
|||
vDeviceQueueCreateInfos.push_back(vkdqci);
|
||||
}
|
||||
VkPhysicalDeviceFeatures physicalDeviceFeatures = {};
|
||||
physicalDeviceFeatures.geometryShader = VK_TRUE;
|
||||
physicalDeviceFeatures.tessellationShader = settings._gpuTessellation ? VK_TRUE : VK_FALSE;
|
||||
physicalDeviceFeatures.fillModeNonSolid = VK_TRUE;
|
||||
physicalDeviceFeatures.multiViewport = VK_TRUE;
|
||||
physicalDeviceFeatures.samplerAnisotropy = VK_TRUE;
|
||||
|
@ -624,46 +629,46 @@ void RendererVulkan::CreateSamplers()
|
|||
|
||||
// <Repeat>
|
||||
vksci = init;
|
||||
_vSamplers[+Sampler::linear3D] = Create(vksci);
|
||||
_vSamplers[+Sampler::linearMipL] = Create(vksci);
|
||||
|
||||
vksci = init;
|
||||
vksci.magFilter = VK_FILTER_NEAREST;
|
||||
vksci.minFilter = VK_FILTER_NEAREST;
|
||||
_vSamplers[+Sampler::nearest3D] = Create(vksci);
|
||||
_vSamplers[+Sampler::nearestMipL] = Create(vksci);
|
||||
|
||||
vksci = init;
|
||||
vksci.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
_vSamplers[+Sampler::linear2D] = Create(vksci);
|
||||
_vSamplers[+Sampler::linearMipN] = Create(vksci);
|
||||
|
||||
vksci = init;
|
||||
vksci.magFilter = VK_FILTER_NEAREST;
|
||||
vksci.minFilter = VK_FILTER_NEAREST;
|
||||
vksci.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
_vSamplers[+Sampler::nearest2D] = Create(vksci);
|
||||
_vSamplers[+Sampler::nearestMipN] = Create(vksci);
|
||||
// </Repeat>
|
||||
|
||||
// <Clamp>
|
||||
vksci = init;
|
||||
vksci.addressModeU = vksci.addressModeV = vksci.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
_vSamplers[+Sampler::linearClamp3D] = Create(vksci);
|
||||
_vSamplers[+Sampler::linearClampMipL] = Create(vksci);
|
||||
|
||||
vksci = init;
|
||||
vksci.magFilter = VK_FILTER_NEAREST;
|
||||
vksci.minFilter = VK_FILTER_NEAREST;
|
||||
vksci.addressModeU = vksci.addressModeV = vksci.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
_vSamplers[+Sampler::nearestClamp3D] = Create(vksci);
|
||||
_vSamplers[+Sampler::nearestClampMipL] = Create(vksci);
|
||||
|
||||
vksci = init;
|
||||
vksci.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
vksci.addressModeU = vksci.addressModeV = vksci.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
_vSamplers[+Sampler::linearClamp2D] = Create(vksci);
|
||||
_vSamplers[+Sampler::linearClampMipN] = Create(vksci);
|
||||
|
||||
vksci = init;
|
||||
vksci.magFilter = VK_FILTER_NEAREST;
|
||||
vksci.minFilter = VK_FILTER_NEAREST;
|
||||
vksci.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
vksci.addressModeU = vksci.addressModeV = vksci.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
_vSamplers[+Sampler::nearestClamp2D] = Create(vksci);
|
||||
_vSamplers[+Sampler::nearestClampMipN] = Create(vksci);
|
||||
// </Clamp>
|
||||
}
|
||||
|
||||
|
@ -692,7 +697,7 @@ void RendererVulkan::ImGuiCheckVkResultFn(VkResult res)
|
|||
throw VERUS_RUNTIME_ERROR << "ImGuiCheckVkResultFn(), res=" << res;
|
||||
}
|
||||
|
||||
void RendererVulkan::ImGuiInit(int renderPassHandle)
|
||||
void RendererVulkan::ImGuiInit(RPHandle renderPassHandle)
|
||||
{
|
||||
VkResult res = VK_SUCCESS;
|
||||
VkDescriptorPoolSize vkdps = { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1 };
|
||||
|
@ -720,7 +725,7 @@ void RendererVulkan::ImGuiInit(int renderPassHandle)
|
|||
IO::FileSystem::LoadResource(_C(settings._imguiFont), vData);
|
||||
void* pFontData = IM_ALLOC(vData.size());
|
||||
memcpy(pFontData, vData.data(), vData.size());
|
||||
io.Fonts->AddFontFromMemoryTTF(pFontData, Utils::Cast32(vData.size()), settings.GetFontSize(), nullptr, io.Fonts->GetGlyphRangesCyrillic());
|
||||
io.Fonts->AddFontFromMemoryTTF(pFontData, Utils::Cast32(vData.size()), static_cast<float>(settings.GetFontSize()), nullptr, io.Fonts->GetGlyphRangesCyrillic());
|
||||
}
|
||||
|
||||
ImGui::StyleColorsDark();
|
||||
|
@ -738,7 +743,7 @@ void RendererVulkan::ImGuiInit(int renderPassHandle)
|
|||
info.MinImageCount = settings._screenVSync ? 3 : 2;;
|
||||
info.ImageCount = s_ringBufferSize;
|
||||
info.CheckVkResultFn = ImGuiCheckVkResultFn;
|
||||
ImGui_ImplVulkan_Init(&info, _vRenderPasses[renderPassHandle]);
|
||||
ImGui_ImplVulkan_Init(&info, _vRenderPasses[renderPassHandle.Get()]);
|
||||
|
||||
CommandBufferVulkan commandBuffer;
|
||||
commandBuffer.InitOneTimeSubmit();
|
||||
|
@ -912,7 +917,7 @@ void RendererVulkan::DeleteTexture(PBaseTexture p)
|
|||
TStoreTextures::Delete(static_cast<PTextureVulkan>(p));
|
||||
}
|
||||
|
||||
int RendererVulkan::CreateRenderPass(std::initializer_list<RP::Attachment> ilA, std::initializer_list<RP::Subpass> ilS, std::initializer_list<RP::Dependency> ilD)
|
||||
RPHandle RendererVulkan::CreateRenderPass(std::initializer_list<RP::Attachment> ilA, std::initializer_list<RP::Subpass> ilS, std::initializer_list<RP::Dependency> ilD)
|
||||
{
|
||||
VkResult res = VK_SUCCESS;
|
||||
|
||||
|
@ -1111,16 +1116,16 @@ int RendererVulkan::CreateRenderPass(std::initializer_list<RP::Attachment> ilA,
|
|||
if (VK_SUCCESS != (res = vkCreateRenderPass(_device, &vkrpci, GetAllocator(), &renderPass)))
|
||||
throw VERUS_RUNTIME_ERROR << "vkCreateRenderPass(), res=" << res;
|
||||
|
||||
const int handle = GetNextRenderPassHandle();
|
||||
if (handle >= _vRenderPasses.size())
|
||||
const int nextIndex = GetNextRenderPassIndex();
|
||||
if (nextIndex >= _vRenderPasses.size())
|
||||
_vRenderPasses.push_back(renderPass);
|
||||
else
|
||||
_vRenderPasses[handle] = renderPass;
|
||||
_vRenderPasses[nextIndex] = renderPass;
|
||||
|
||||
return handle;
|
||||
return RPHandle::Make(nextIndex);
|
||||
}
|
||||
|
||||
int RendererVulkan::CreateFramebuffer(int renderPassHandle, std::initializer_list<TexturePtr> il, int w, int h, int swapChainBufferIndex)
|
||||
FBHandle RendererVulkan::CreateFramebuffer(RPHandle renderPassHandle, std::initializer_list<TexturePtr> il, int w, int h, int swapChainBufferIndex)
|
||||
{
|
||||
VkResult res = VK_SUCCESS;
|
||||
|
||||
|
@ -1138,7 +1143,7 @@ int RendererVulkan::CreateFramebuffer(int renderPassHandle, std::initializer_lis
|
|||
for (const auto& x : il)
|
||||
{
|
||||
auto& texVulkan = static_cast<RTextureVulkan>(*x);
|
||||
imageViews[count] = texVulkan.GetVkImageView();
|
||||
imageViews[count] = texVulkan.GetVkImageViewForFramebuffer();
|
||||
count++;
|
||||
}
|
||||
vkfci.attachmentCount = count;
|
||||
|
@ -1149,27 +1154,27 @@ int RendererVulkan::CreateFramebuffer(int renderPassHandle, std::initializer_lis
|
|||
if (VK_SUCCESS != (res = vkCreateFramebuffer(_device, &vkfci, GetAllocator(), &framebuffer)))
|
||||
throw VERUS_RUNTIME_ERROR << "vkCreateFramebuffer(), res=" << res;
|
||||
|
||||
const int handle = GetNextFramebufferHandle();
|
||||
const int nextIndex = GetNextFramebufferIndex();
|
||||
Framebuffer fb;
|
||||
fb._framebuffer = framebuffer;
|
||||
fb._width = w;
|
||||
fb._height = h;
|
||||
if (handle >= _vFramebuffers.size())
|
||||
if (nextIndex >= _vFramebuffers.size())
|
||||
_vFramebuffers.push_back(fb);
|
||||
else
|
||||
_vFramebuffers[handle] = fb;
|
||||
_vFramebuffers[nextIndex] = fb;
|
||||
|
||||
return handle;
|
||||
return FBHandle::Make(nextIndex);
|
||||
}
|
||||
|
||||
void RendererVulkan::DeleteRenderPass(int handle)
|
||||
void RendererVulkan::DeleteRenderPass(RPHandle handle)
|
||||
{
|
||||
if (handle >= 0)
|
||||
if (handle.IsSet())
|
||||
{
|
||||
vkDestroyRenderPass(_device, _vRenderPasses[handle], GetAllocator());
|
||||
_vRenderPasses[handle] = VK_NULL_HANDLE;
|
||||
vkDestroyRenderPass(_device, _vRenderPasses[handle.Get()], GetAllocator());
|
||||
_vRenderPasses[handle.Get()] = VK_NULL_HANDLE;
|
||||
}
|
||||
else
|
||||
else if (-2 == handle.Get())
|
||||
{
|
||||
for (auto renderPass : _vRenderPasses)
|
||||
vkDestroyRenderPass(_device, renderPass, GetAllocator());
|
||||
|
@ -1177,14 +1182,14 @@ void RendererVulkan::DeleteRenderPass(int handle)
|
|||
}
|
||||
}
|
||||
|
||||
void RendererVulkan::DeleteFramebuffer(int handle)
|
||||
void RendererVulkan::DeleteFramebuffer(FBHandle handle)
|
||||
{
|
||||
if (handle >= 0)
|
||||
if (handle.IsSet())
|
||||
{
|
||||
vkDestroyFramebuffer(_device, _vFramebuffers[handle]._framebuffer, GetAllocator());
|
||||
_vFramebuffers[handle]._framebuffer = VK_NULL_HANDLE;
|
||||
vkDestroyFramebuffer(_device, _vFramebuffers[handle.Get()]._framebuffer, GetAllocator());
|
||||
_vFramebuffers[handle.Get()]._framebuffer = VK_NULL_HANDLE;
|
||||
}
|
||||
else
|
||||
else if (-2 == handle.Get())
|
||||
{
|
||||
for (auto framebuffer : _vFramebuffers)
|
||||
vkDestroyFramebuffer(_device, framebuffer._framebuffer, GetAllocator());
|
||||
|
@ -1192,7 +1197,7 @@ void RendererVulkan::DeleteFramebuffer(int handle)
|
|||
}
|
||||
}
|
||||
|
||||
int RendererVulkan::GetNextRenderPassHandle() const
|
||||
int RendererVulkan::GetNextRenderPassIndex() const
|
||||
{
|
||||
const int count = Utils::Cast32(_vRenderPasses.size());
|
||||
VERUS_FOR(i, count)
|
||||
|
@ -1203,7 +1208,7 @@ int RendererVulkan::GetNextRenderPassHandle() const
|
|||
return count;
|
||||
}
|
||||
|
||||
int RendererVulkan::GetNextFramebufferHandle() const
|
||||
int RendererVulkan::GetNextFramebufferIndex() const
|
||||
{
|
||||
const int count = Utils::Cast32(_vFramebuffers.size());
|
||||
VERUS_FOR(i, count)
|
||||
|
@ -1214,14 +1219,14 @@ int RendererVulkan::GetNextFramebufferHandle() const
|
|||
return count;
|
||||
}
|
||||
|
||||
VkRenderPass RendererVulkan::GetRenderPass(int handle) const
|
||||
VkRenderPass RendererVulkan::GetRenderPass(RPHandle handle) const
|
||||
{
|
||||
return _vRenderPasses[handle];
|
||||
return _vRenderPasses[handle.Get()];
|
||||
}
|
||||
|
||||
RendererVulkan::RcFramebuffer RendererVulkan::GetFramebuffer(int handle) const
|
||||
RendererVulkan::RcFramebuffer RendererVulkan::GetFramebuffer(FBHandle handle) const
|
||||
{
|
||||
return _vFramebuffers[handle];
|
||||
return _vFramebuffers[handle.Get()];
|
||||
}
|
||||
|
||||
void RendererVulkan::CreateBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VmaMemoryUsage vmaUsage, VkBuffer& buffer, VmaAllocation& vmaAllocation)
|
||||
|
|
|
@ -127,7 +127,7 @@ namespace verus
|
|||
const VkSampler* GetImmutableSampler(Sampler s) const;
|
||||
|
||||
static void ImGuiCheckVkResultFn(VkResult res);
|
||||
virtual void ImGuiInit(int renderPassHandle) override;
|
||||
virtual void ImGuiInit(RPHandle renderPassHandle) override;
|
||||
virtual void ImGuiRenderDrawData() override;
|
||||
|
||||
virtual void ResizeSwapChain() override;
|
||||
|
@ -154,14 +154,14 @@ namespace verus
|
|||
virtual void DeleteShader(PBaseShader p) override;
|
||||
virtual void DeleteTexture(PBaseTexture p) override;
|
||||
|
||||
virtual int CreateRenderPass(std::initializer_list<RP::Attachment> ilA, std::initializer_list<RP::Subpass> ilS, std::initializer_list<RP::Dependency> ilD) override;
|
||||
virtual int CreateFramebuffer(int renderPassHandle, std::initializer_list<TexturePtr> il, int w, int h, int swapChainBufferIndex) override;
|
||||
virtual void DeleteRenderPass(int handle) override;
|
||||
virtual void DeleteFramebuffer(int handle) override;
|
||||
int GetNextRenderPassHandle() const;
|
||||
int GetNextFramebufferHandle() const;
|
||||
VkRenderPass GetRenderPass(int handle) const;
|
||||
RcFramebuffer GetFramebuffer(int handle) const;
|
||||
virtual RPHandle CreateRenderPass(std::initializer_list<RP::Attachment> ilA, std::initializer_list<RP::Subpass> ilS, std::initializer_list<RP::Dependency> ilD) override;
|
||||
virtual FBHandle CreateFramebuffer(RPHandle renderPassHandle, std::initializer_list<TexturePtr> il, int w, int h, int swapChainBufferIndex) override;
|
||||
virtual void DeleteRenderPass(RPHandle handle) override;
|
||||
virtual void DeleteFramebuffer(FBHandle handle) override;
|
||||
int GetNextRenderPassIndex() const;
|
||||
int GetNextFramebufferIndex() const;
|
||||
VkRenderPass GetRenderPass(RPHandle handle) const;
|
||||
RcFramebuffer GetFramebuffer(FBHandle handle) const;
|
||||
|
||||
void CreateBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VmaMemoryUsage vmaUsage, VkBuffer& buffer, VmaAllocation& vmaAllocation);
|
||||
void CopyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size, PBaseCommandBuffer pCB = nullptr);
|
||||
|
|
|
@ -70,12 +70,12 @@ void ShaderVulkan::Init(CSZ source, CSZ sourceName, CSZ* branches)
|
|||
|
||||
while (*branches)
|
||||
{
|
||||
String entryVS, entryHS, entryDS, entryGS, entryFS, entryCS, stages;
|
||||
String entry, stageEntries[+Stage::count], stages;
|
||||
Vector<String> vMacroName;
|
||||
Vector<String> vMacroValue;
|
||||
const String entry = Parse(*branches, entryVS, entryHS, entryDS, entryGS, entryFS, entryCS, stages, vMacroName, vMacroValue, "DEF_");
|
||||
const String branch = Parse(*branches, entry, stageEntries, stages, vMacroName, vMacroValue, "DEF_");
|
||||
|
||||
if (IsInIgnoreList(_C(entry)))
|
||||
if (IsInIgnoreList(_C(branch)))
|
||||
{
|
||||
branches++;
|
||||
continue;
|
||||
|
@ -126,12 +126,13 @@ void ShaderVulkan::Init(CSZ source, CSZ sourceName, CSZ* branches)
|
|||
// </System defines>
|
||||
|
||||
Compiled compiled;
|
||||
compiled._entry = entry;
|
||||
|
||||
if (strchr(_C(stages), 'V'))
|
||||
{
|
||||
compiled._stageCount++;
|
||||
vDefines[typeIndex] = "_VS";
|
||||
if (!RendererVulkan::VulkanCompile(source, sourceName, vDefines.data(), &inc, _C(entryVS), "vs", flags, &pCode, &size, &pErrorMsgs))
|
||||
if (!RendererVulkan::VulkanCompile(source, sourceName, vDefines.data(), &inc, _C(stageEntries[+Stage::vs]), "vs", flags, &pCode, &size, &pErrorMsgs))
|
||||
CheckErrorMsgs(pErrorMsgs);
|
||||
CreateShaderModule(pCode, size, compiled._shaderModules[+Stage::vs]);
|
||||
}
|
||||
|
@ -140,7 +141,7 @@ void ShaderVulkan::Init(CSZ source, CSZ sourceName, CSZ* branches)
|
|||
{
|
||||
compiled._stageCount++;
|
||||
vDefines[typeIndex] = "_HS";
|
||||
if (!RendererVulkan::VulkanCompile(source, sourceName, vDefines.data(), &inc, _C(entryHS), "hs", flags, &pCode, &size, &pErrorMsgs))
|
||||
if (!RendererVulkan::VulkanCompile(source, sourceName, vDefines.data(), &inc, _C(stageEntries[+Stage::hs]), "hs", flags, &pCode, &size, &pErrorMsgs))
|
||||
CheckErrorMsgs(pErrorMsgs);
|
||||
CreateShaderModule(pCode, size, compiled._shaderModules[+Stage::hs]);
|
||||
}
|
||||
|
@ -149,7 +150,7 @@ void ShaderVulkan::Init(CSZ source, CSZ sourceName, CSZ* branches)
|
|||
{
|
||||
compiled._stageCount++;
|
||||
vDefines[typeIndex] = "_DS";
|
||||
if (!RendererVulkan::VulkanCompile(source, sourceName, vDefines.data(), &inc, _C(entryDS), "ds", flags, &pCode, &size, &pErrorMsgs))
|
||||
if (!RendererVulkan::VulkanCompile(source, sourceName, vDefines.data(), &inc, _C(stageEntries[+Stage::ds]), "ds", flags, &pCode, &size, &pErrorMsgs))
|
||||
CheckErrorMsgs(pErrorMsgs);
|
||||
CreateShaderModule(pCode, size, compiled._shaderModules[+Stage::ds]);
|
||||
}
|
||||
|
@ -158,7 +159,7 @@ void ShaderVulkan::Init(CSZ source, CSZ sourceName, CSZ* branches)
|
|||
{
|
||||
compiled._stageCount++;
|
||||
vDefines[typeIndex] = "_GS";
|
||||
if (!RendererVulkan::VulkanCompile(source, sourceName, vDefines.data(), &inc, _C(entryGS), "gs", flags, &pCode, &size, &pErrorMsgs))
|
||||
if (!RendererVulkan::VulkanCompile(source, sourceName, vDefines.data(), &inc, _C(stageEntries[+Stage::gs]), "gs", flags, &pCode, &size, &pErrorMsgs))
|
||||
CheckErrorMsgs(pErrorMsgs);
|
||||
CreateShaderModule(pCode, size, compiled._shaderModules[+Stage::gs]);
|
||||
}
|
||||
|
@ -167,7 +168,7 @@ void ShaderVulkan::Init(CSZ source, CSZ sourceName, CSZ* branches)
|
|||
{
|
||||
compiled._stageCount++;
|
||||
vDefines[typeIndex] = "_FS";
|
||||
if (!RendererVulkan::VulkanCompile(source, sourceName, vDefines.data(), &inc, _C(entryFS), "fs", flags, &pCode, &size, &pErrorMsgs))
|
||||
if (!RendererVulkan::VulkanCompile(source, sourceName, vDefines.data(), &inc, _C(stageEntries[+Stage::fs]), "fs", flags, &pCode, &size, &pErrorMsgs))
|
||||
CheckErrorMsgs(pErrorMsgs);
|
||||
CreateShaderModule(pCode, size, compiled._shaderModules[+Stage::fs]);
|
||||
}
|
||||
|
@ -176,13 +177,13 @@ void ShaderVulkan::Init(CSZ source, CSZ sourceName, CSZ* branches)
|
|||
{
|
||||
compiled._stageCount++;
|
||||
vDefines[typeIndex] = "_CS";
|
||||
if (!RendererVulkan::VulkanCompile(source, sourceName, vDefines.data(), &inc, _C(entryCS), "cs", flags, &pCode, &size, &pErrorMsgs))
|
||||
if (!RendererVulkan::VulkanCompile(source, sourceName, vDefines.data(), &inc, _C(stageEntries[+Stage::cs]), "cs", flags, &pCode, &size, &pErrorMsgs))
|
||||
CheckErrorMsgs(pErrorMsgs);
|
||||
CreateShaderModule(pCode, size, compiled._shaderModules[+Stage::cs]);
|
||||
_compute = true;
|
||||
}
|
||||
|
||||
_mapCompiled[entry] = compiled;
|
||||
_mapCompiled[branch] = compiled;
|
||||
|
||||
branches++;
|
||||
}
|
||||
|
@ -248,6 +249,24 @@ void ShaderVulkan::CreatePipelineLayout()
|
|||
VERUS_QREF_RENDERER_VULKAN;
|
||||
VkResult res = VK_SUCCESS;
|
||||
|
||||
StringStream ss;
|
||||
|
||||
auto PrintStageFlags = [&ss](VkShaderStageFlags stageFlags)
|
||||
{
|
||||
if (stageFlags & VK_SHADER_STAGE_VERTEX_BIT)
|
||||
ss << "[V]";
|
||||
if (stageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
|
||||
ss << "[TC]";
|
||||
if (stageFlags & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
|
||||
ss << "[TE]";
|
||||
if (stageFlags & VK_SHADER_STAGE_GEOMETRY_BIT)
|
||||
ss << "[G]";
|
||||
if (stageFlags & VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||
ss << "[F]";
|
||||
if (stageFlags & VK_SHADER_STAGE_COMPUTE_BIT)
|
||||
ss << "[C]";
|
||||
};
|
||||
|
||||
VkPushConstantRange vkpcr = {};
|
||||
VkPipelineLayoutCreateInfo vkplci = {};
|
||||
vkplci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||
|
@ -307,6 +326,34 @@ void ShaderVulkan::CreatePipelineLayout()
|
|||
vkdslci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
vkdslci.bindingCount = Utils::Cast32(vBindings.size());
|
||||
vkdslci.pBindings = vBindings.data();
|
||||
|
||||
ss << "Set=" << _vDescriptorSetLayouts.size();
|
||||
ss << std::endl;
|
||||
for (const auto& binding : vBindings)
|
||||
{
|
||||
ss << " binding=" << binding.binding;
|
||||
ss << ", type=";
|
||||
switch (binding.descriptorType)
|
||||
{
|
||||
case VK_DESCRIPTOR_TYPE_SAMPLER: ss << "SAMPLER"; break;
|
||||
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: ss << "COMBINED_IMAGE_SAMPLER"; break;
|
||||
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: ss << "SAMPLED_IMAGE"; break;
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: ss << "STORAGE_IMAGE"; break;
|
||||
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: ss << "UNIFORM_TEXEL_BUFFER"; break;
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: ss << "STORAGE_TEXEL_BUFFER"; break;
|
||||
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: ss << "UNIFORM_BUFFER"; break;
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: ss << "STORAGE_BUFFER"; break;
|
||||
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: ss << "UNIFORM_BUFFER_DYNAMIC"; break;
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: ss << "STORAGE_BUFFER_DYNAMIC"; break;
|
||||
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: ss << "INPUT_ATTACHMENT"; break;
|
||||
}
|
||||
ss << ", count=" << binding.descriptorCount;
|
||||
ss << ", flags=";
|
||||
PrintStageFlags(binding.stageFlags);
|
||||
ss << ", immutableSampler=" << binding.pImmutableSamplers;
|
||||
ss << std::endl;
|
||||
}
|
||||
|
||||
VkDescriptorSetLayout descriptorSetLayout = VK_NULL_HANDLE;
|
||||
if (VK_SUCCESS != (res = vkCreateDescriptorSetLayout(pRendererVulkan->GetVkDevice(), &vkdslci, pRendererVulkan->GetAllocator(), &descriptorSetLayout)))
|
||||
throw VERUS_RUNTIME_ERROR << "vkCreateDescriptorSetLayout(), res=" << res;
|
||||
|
@ -321,6 +368,14 @@ void ShaderVulkan::CreatePipelineLayout()
|
|||
vkpcr.size = dsd._size;
|
||||
vkplci.pushConstantRangeCount = 1;
|
||||
vkplci.pPushConstantRanges = &vkpcr;
|
||||
|
||||
ss << "Set=PushConst";
|
||||
ss << std::endl;
|
||||
ss << " flags=";
|
||||
PrintStageFlags(vkpcr.stageFlags);
|
||||
ss << ", offset=" << vkpcr.offset;
|
||||
ss << ", size=" << vkpcr.size;
|
||||
ss << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -328,6 +383,8 @@ void ShaderVulkan::CreatePipelineLayout()
|
|||
vkplci.pSetLayouts = _vDescriptorSetLayouts.data();
|
||||
}
|
||||
|
||||
_debugInfo = ss.str();
|
||||
|
||||
if (VK_SUCCESS != (res = vkCreatePipelineLayout(pRendererVulkan->GetVkDevice(), &vkplci, pRendererVulkan->GetAllocator(), &_pipelineLayout)))
|
||||
throw VERUS_RUNTIME_ERROR << "vkCreatePipelineLayout(), res=" << res;
|
||||
|
||||
|
@ -340,7 +397,7 @@ void ShaderVulkan::CreatePipelineLayout()
|
|||
}
|
||||
}
|
||||
|
||||
int ShaderVulkan::BindDescriptorSetTextures(int setNumber, std::initializer_list<TexturePtr> il, const int* pMips)
|
||||
CSHandle ShaderVulkan::BindDescriptorSetTextures(int setNumber, std::initializer_list<TexturePtr> il, const int* pMips)
|
||||
{
|
||||
VERUS_QREF_RENDERER_VULKAN;
|
||||
VkResult res = VK_SUCCESS;
|
||||
|
@ -448,21 +505,21 @@ int ShaderVulkan::BindDescriptorSetTextures(int setNumber, std::initializer_list
|
|||
|
||||
vkUpdateDescriptorSets(pRendererVulkan->GetVkDevice(), Utils::Cast32(vWriteDescriptorSet.size()), vWriteDescriptorSet.data(), 0, nullptr);
|
||||
|
||||
return complexSetHandle;
|
||||
return CSHandle::Make(complexSetHandle);
|
||||
}
|
||||
|
||||
void ShaderVulkan::FreeDescriptorSet(int& complexSetHandle)
|
||||
void ShaderVulkan::FreeDescriptorSet(CSHandle& complexSetHandle)
|
||||
{
|
||||
VERUS_QREF_RENDERER_VULKAN;
|
||||
VkResult res = VK_SUCCESS;
|
||||
|
||||
if (complexSetHandle >= 0 && complexSetHandle < _vComplexDescriptorSets.size() && _vComplexDescriptorSets[complexSetHandle] != VK_NULL_HANDLE)
|
||||
if (complexSetHandle.IsSet() && complexSetHandle.Get() < _vComplexDescriptorSets.size() && _vComplexDescriptorSets[complexSetHandle.Get()] != VK_NULL_HANDLE)
|
||||
{
|
||||
if (VK_SUCCESS != (res = vkFreeDescriptorSets(pRendererVulkan->GetVkDevice(), _descriptorPool, 1, &_vComplexDescriptorSets[complexSetHandle])))
|
||||
if (VK_SUCCESS != (res = vkFreeDescriptorSets(pRendererVulkan->GetVkDevice(), _descriptorPool, 1, &_vComplexDescriptorSets[complexSetHandle.Get()])))
|
||||
throw VERUS_RUNTIME_ERROR << "vkFreeDescriptorSets(), res=" << res;
|
||||
_vComplexDescriptorSets[complexSetHandle] = VK_NULL_HANDLE;
|
||||
_vComplexDescriptorSets[complexSetHandle.Get()] = VK_NULL_HANDLE;
|
||||
}
|
||||
complexSetHandle = -1;
|
||||
complexSetHandle = CSHandle();
|
||||
}
|
||||
|
||||
void ShaderVulkan::BeginBindDescriptors()
|
||||
|
@ -582,9 +639,9 @@ VkDescriptorSet ShaderVulkan::GetVkDescriptorSet(int setNumber)
|
|||
return _vDescriptorSetDesc[setNumber]._descriptorSet;
|
||||
}
|
||||
|
||||
VkDescriptorSet ShaderVulkan::GetComplexVkDescriptorSet(int descSetID)
|
||||
VkDescriptorSet ShaderVulkan::GetComplexVkDescriptorSet(CSHandle descSetID)
|
||||
{
|
||||
return _vComplexDescriptorSets[descSetID];
|
||||
return _vComplexDescriptorSets[descSetID.Get()];
|
||||
}
|
||||
|
||||
bool ShaderVulkan::TryPushConstants(int setNumber, RBaseCommandBuffer cb)
|
||||
|
@ -621,7 +678,7 @@ int ShaderVulkan::UpdateUniformBuffer(int setNumber)
|
|||
void ShaderVulkan::OnError(CSZ s)
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
if (strstr(s, ": error "))
|
||||
if (strstr(s, " ERROR: "))
|
||||
renderer.OnShaderError(s);
|
||||
else
|
||||
renderer.OnShaderWarning(s);
|
||||
|
|
|
@ -6,11 +6,16 @@ namespace verus
|
|||
{
|
||||
class ShaderVulkan : public BaseShader
|
||||
{
|
||||
public:
|
||||
struct Compiled
|
||||
{
|
||||
VkShaderModule _shaderModules[+Stage::count] = {};
|
||||
String _entry;
|
||||
int _stageCount = 0;
|
||||
};
|
||||
VERUS_TYPEDEFS(Compiled);
|
||||
|
||||
private:
|
||||
typedef Map<String, Compiled> TMapCompiled;
|
||||
|
||||
struct DescriptorSetDesc
|
||||
|
@ -36,6 +41,7 @@ namespace verus
|
|||
Vector<VkDescriptorSet> _vComplexDescriptorSets;
|
||||
VkDescriptorPool _descriptorPool = VK_NULL_HANDLE;
|
||||
VkPipelineLayout _pipelineLayout = VK_NULL_HANDLE;
|
||||
String _debugInfo;
|
||||
UINT64 _currentFrame = UINT64_MAX;
|
||||
uint32_t _poolComplexUniformBuffers = 0;
|
||||
uint32_t _poolComplexImageSamplers = 0;
|
||||
|
@ -52,8 +58,8 @@ namespace verus
|
|||
|
||||
virtual void CreateDescriptorSet(int setNumber, const void* pSrc, int size, int capacity, std::initializer_list<Sampler> il, ShaderStageFlags stageFlags) override;
|
||||
virtual void CreatePipelineLayout() override;
|
||||
virtual int BindDescriptorSetTextures(int setNumber, std::initializer_list<TexturePtr> il, const int* pMips) override;
|
||||
virtual void FreeDescriptorSet(int& complexSetHandle) override;
|
||||
virtual CSHandle BindDescriptorSetTextures(int setNumber, std::initializer_list<TexturePtr> il, const int* pMips) override;
|
||||
virtual void FreeDescriptorSet(CSHandle& complexSetHandle) override;
|
||||
|
||||
virtual void BeginBindDescriptors() override;
|
||||
virtual void EndBindDescriptors() override;
|
||||
|
@ -65,10 +71,9 @@ namespace verus
|
|||
void CreateDescriptorPool();
|
||||
void CreateDescriptorSets();
|
||||
VkDescriptorSet GetVkDescriptorSet(int setNumber);
|
||||
VkDescriptorSet GetComplexVkDescriptorSet(int descSetID);
|
||||
VkDescriptorSet GetComplexVkDescriptorSet(CSHandle descSetID);
|
||||
|
||||
VkShaderModule GetVkShaderModule(CSZ branch, Stage stage) const { return _mapCompiled.at(branch)._shaderModules[+stage]; }
|
||||
int GetStageCount(CSZ branch) const { return _mapCompiled.at(branch)._stageCount; }
|
||||
RcCompiled GetCompiled(CSZ branch) const { return _mapCompiled.at(branch); }
|
||||
|
||||
VkPipelineLayout GetVkPipelineLayout() const { return _pipelineLayout; }
|
||||
|
||||
|
|
|
@ -28,9 +28,8 @@ void TextureVulkan::Init(RcTextureDesc desc)
|
|||
_desc._mipLevels = desc._mipLevels ? desc._mipLevels : Math::ComputeMipLevels(desc._width, desc._height, desc._depth);
|
||||
_bytesPerPixel = FormatToBytesPerPixel(desc._format);
|
||||
const bool renderTarget = (_desc._flags & TextureDesc::Flags::colorAttachment);
|
||||
const bool inputAttach = (_desc._flags & TextureDesc::Flags::inputAttachment);
|
||||
const bool depthFormat = IsDepthFormat(desc._format);
|
||||
const bool depthSampled = _desc._flags & TextureDesc::Flags::depthSampled;
|
||||
const bool depthSampled = _desc._flags & (TextureDesc::Flags::depthSampledR | TextureDesc::Flags::depthSampledW);
|
||||
if (_desc._flags & TextureDesc::Flags::anyShaderResource)
|
||||
_mainLayout = ImageLayout::xsReadOnly;
|
||||
|
||||
|
@ -50,14 +49,16 @@ void TextureVulkan::Init(RcTextureDesc desc)
|
|||
vkici.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
if (renderTarget)
|
||||
vkici.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
if (inputAttach)
|
||||
vkici.usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
|
||||
if (_desc._flags & TextureDesc::Flags::generateMips)
|
||||
vkici.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
if (depthFormat)
|
||||
{
|
||||
vkici.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
if (depthSampled)
|
||||
vkici.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
}
|
||||
if (_desc._flags & TextureDesc::Flags::inputAttachment)
|
||||
vkici.usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
|
||||
pRendererVulkan->CreateImage(&vkici, VMA_MEMORY_USAGE_GPU_ONLY, _image, _vmaAllocation);
|
||||
|
||||
if (_desc._flags & TextureDesc::Flags::generateMips)
|
||||
|
@ -68,6 +69,12 @@ void TextureVulkan::Init(RcTextureDesc desc)
|
|||
vkiciStorage.extent.height = Math::Max(1, _desc._height >> 1);
|
||||
vkiciStorage.mipLevels = Math::Max(1, _desc._mipLevels - 1);
|
||||
vkiciStorage.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
|
||||
// sRGB cannot be used with storage image:
|
||||
switch (vkiciStorage.format)
|
||||
{
|
||||
case VK_FORMAT_R8G8B8A8_SRGB: vkiciStorage.format = VK_FORMAT_R8G8B8A8_UNORM; break;
|
||||
case VK_FORMAT_B8G8R8A8_SRGB: vkiciStorage.format = VK_FORMAT_B8G8R8A8_UNORM; break;
|
||||
}
|
||||
pRendererVulkan->CreateImage(&vkiciStorage, VMA_MEMORY_USAGE_GPU_ONLY, _storageImage, _storageVmaAllocation);
|
||||
|
||||
_vCshGenerateMips.reserve((_desc._mipLevels + 3) / 4);
|
||||
|
@ -78,7 +85,7 @@ void TextureVulkan::Init(RcTextureDesc desc)
|
|||
vkivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
vkivci.image = _storageImage;
|
||||
vkivci.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
vkivci.format = vkici.format;
|
||||
vkivci.format = vkiciStorage.format;
|
||||
vkivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
vkivci.subresourceRange.baseMipLevel = mip;
|
||||
vkivci.subresourceRange.levelCount = 1;
|
||||
|
@ -103,6 +110,12 @@ void TextureVulkan::Init(RcTextureDesc desc)
|
|||
vkivci.subresourceRange.layerCount = vkici.arrayLayers;
|
||||
if (VK_SUCCESS != (res = vkCreateImageView(pRendererVulkan->GetVkDevice(), &vkivci, pRendererVulkan->GetAllocator(), &_imageView)))
|
||||
throw VERUS_RUNTIME_ERROR << "vkCreateImageView(), res=" << res;
|
||||
if (renderTarget)
|
||||
{
|
||||
vkivci.subresourceRange.levelCount = 1;
|
||||
if (VK_SUCCESS != (res = vkCreateImageView(pRendererVulkan->GetVkDevice(), &vkivci, pRendererVulkan->GetAllocator(), &_imageViewLevelZero)))
|
||||
throw VERUS_RUNTIME_ERROR << "vkCreateImageView(LevelZero), res=" << res;
|
||||
}
|
||||
|
||||
if (_desc._pSamplerDesc)
|
||||
CreateSampler();
|
||||
|
@ -116,7 +129,7 @@ void TextureVulkan::Init(RcTextureDesc desc)
|
|||
}
|
||||
if (depthFormat)
|
||||
{
|
||||
const ImageLayout layout = depthSampled ? ImageLayout::depthStencilReadOnly : ImageLayout::depthStencilAttachment;
|
||||
const ImageLayout layout = (_desc._flags & TextureDesc::Flags::depthSampledR) ? ImageLayout::depthStencilReadOnly : ImageLayout::depthStencilAttachment;
|
||||
CommandBufferVulkan commandBuffer;
|
||||
commandBuffer.InitOneTimeSubmit();
|
||||
commandBuffer.PipelineImageMemoryBarrier(TexturePtr::From(this), ImageLayout::undefined, layout, 0, 0);
|
||||
|
@ -134,6 +147,7 @@ void TextureVulkan::Done()
|
|||
ForceScheduled();
|
||||
|
||||
VERUS_VULKAN_DESTROY(_sampler, vkDestroySampler(pRendererVulkan->GetVkDevice(), _sampler, pRendererVulkan->GetAllocator()));
|
||||
VERUS_VULKAN_DESTROY(_imageViewLevelZero, vkDestroyImageView(pRendererVulkan->GetVkDevice(), _imageViewLevelZero, pRendererVulkan->GetAllocator()));
|
||||
VERUS_VULKAN_DESTROY(_imageView, vkDestroyImageView(pRendererVulkan->GetVkDevice(), _imageView, pRendererVulkan->GetAllocator()));
|
||||
for (auto view : _vStorageImageViews)
|
||||
VERUS_VULKAN_DESTROY(view, vkDestroyImageView(pRendererVulkan->GetVkDevice(), view, pRendererVulkan->GetAllocator()));
|
||||
|
@ -237,7 +251,7 @@ void TextureVulkan::GenerateMips(PBaseCommandBuffer pCB)
|
|||
ub._srcMipLevel = srcMip;
|
||||
ub._mipLevelCount = dispatchMipCount;
|
||||
ub._srcDimensionCase = (srcHeight & 1) << 1 | (srcWidth & 1);
|
||||
ub._srgb = false;
|
||||
ub._srgb = IsSRGBFormat(_desc._format);
|
||||
ub._texelSize.x = 1.f / dstWidth;
|
||||
ub._texelSize.y = 1.f / dstHeight;
|
||||
|
||||
|
@ -246,7 +260,7 @@ void TextureVulkan::GenerateMips(PBaseCommandBuffer pCB)
|
|||
int mips[5] = {}; // For input texture (always mip 0) and 4 storage mips.
|
||||
VERUS_FOR(mip, dispatchMipCount)
|
||||
mips[mip + 1] = srcMip + mip;
|
||||
const int complexSetHandle = shader->BindDescriptorSetTextures(0, { tex, tex, tex, tex, tex }, mips);
|
||||
const CSHandle complexSetHandle = shader->BindDescriptorSetTextures(0, { tex, tex, tex, tex, tex }, mips);
|
||||
_vCshGenerateMips.push_back(complexSetHandle);
|
||||
pCB->BindDescriptors(shader, 0, complexSetHandle);
|
||||
}
|
||||
|
@ -312,7 +326,7 @@ Continue TextureVulkan::Scheduled_Update()
|
|||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
auto shader = renderer.GetShaderGenerateMips();
|
||||
for (int csh : _vCshGenerateMips)
|
||||
for (auto& csh : _vCshGenerateMips)
|
||||
shader->FreeDescriptorSet(csh);
|
||||
_vCshGenerateMips.clear();
|
||||
}
|
||||
|
|
|
@ -17,11 +17,12 @@ namespace verus
|
|||
VkImage _storageImage = VK_NULL_HANDLE;
|
||||
VmaAllocation _storageVmaAllocation = VK_NULL_HANDLE;
|
||||
VkImageView _imageView = VK_NULL_HANDLE;
|
||||
VkImageView _imageViewLevelZero = VK_NULL_HANDLE;
|
||||
VkSampler _sampler = VK_NULL_HANDLE;
|
||||
Vector<UINT32> _vDefinedSubresources;
|
||||
Vector<VkImageView> _vStorageImageViews;
|
||||
Vector<VkBufferEx> _vStagingBuffers;
|
||||
Vector<int> _vCshGenerateMips;
|
||||
Vector<CSHandle> _vCshGenerateMips;
|
||||
bool _definedStorage = false;
|
||||
|
||||
public:
|
||||
|
@ -45,6 +46,7 @@ namespace verus
|
|||
|
||||
VkImage GetVkImage() const { return _image; }
|
||||
VkImageView GetVkImageView() const { return _imageView; }
|
||||
VkImageView GetVkImageViewForFramebuffer() const { return _imageViewLevelZero ? _imageViewLevelZero : _imageView; }
|
||||
VkImageView GetStorageVkImageView(int mip) const { return _vStorageImageViews[mip]; }
|
||||
VkSampler GetVkSampler() const { return _sampler; }
|
||||
ImageLayout GetSubresourceMainLayout(int mipLevel, int arrayLayer) const;
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
"C:\Home\nvidia-texture-tools-2.1.1-win64\bin64\nvcompress.exe" -bc1a %1
|
|
@ -1 +0,0 @@
|
|||
"C:\Home\nvidia-texture-tools-2.1.1-win64\bin64\nvcompress.exe" -bc3 %1
|
|
@ -1 +0,0 @@
|
|||
"C:\Home\nvidia-texture-tools-2.1.1-win64\bin64\nvcompress.exe" -bc7 %1
|
1
Scripts/Compress Colors (BC7).bat
Normal file
1
Scripts/Compress Colors (BC7).bat
Normal file
|
@ -0,0 +1 @@
|
|||
"C:\Home\Projects\Verus\verus\Bin\TextureTool.exe" %1
|
1
Scripts/Compress Non-Color Data (BC7).bat
Normal file
1
Scripts/Compress Non-Color Data (BC7).bat
Normal file
|
@ -0,0 +1 @@
|
|||
"C:\Home\Projects\Verus\verus\Bin\TextureTool.exe" --non-color-data %1
|
1
Scripts/Compress Normals (BC7).bat
Normal file
1
Scripts/Compress Normals (BC7).bat
Normal file
|
@ -0,0 +1 @@
|
|||
"C:\Home\Projects\Verus\verus\Bin\TextureTool.exe" --normal-map %1
|
97
TextureTool/TextureTool.vcxproj
Normal file
97
TextureTool/TextureTool.vcxproj
Normal file
|
@ -0,0 +1,97 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<ProjectGuid>{5A1A3E76-7F69-48B6-B1E3-F6BB281B7E73}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>TextureTool</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\Verus\Verus.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\Verus\Verus.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Verus\Verus.vcxproj">
|
||||
<Project>{b154d670-e4b1-4d8a-885c-69546a5bd833}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
22
TextureTool/TextureTool.vcxproj.filters
Normal file
22
TextureTool/TextureTool.vcxproj.filters
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
363
TextureTool/main.cpp
Normal file
363
TextureTool/main.cpp
Normal file
|
@ -0,0 +1,363 @@
|
|||
#define VERUS_INCLUDE_COMPRESSONATOR
|
||||
#include <verus.h>
|
||||
|
||||
using namespace verus;
|
||||
|
||||
void DeleteMipmap(CWSZ pathname);
|
||||
|
||||
CMP_BOOL CompressionCallback(CMP_FLOAT progress, CMP_DWORD_PTR pUser1, CMP_DWORD_PTR pUser2)
|
||||
{
|
||||
std::wcout << _T("ProcessTexture progress = ") << static_cast<int>(progress) << _T("%") << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
void Run()
|
||||
{
|
||||
int argCount = 0;
|
||||
LPWSTR* argArray = CommandLineToArgvW(GetCommandLine(), &argCount);
|
||||
WideString pathNameW;
|
||||
std::wcout << _T("TextureTool") << std::endl;
|
||||
std::wcout << _T("Copyright (c) 2016-2020 Dmitry Maluev") << std::endl;
|
||||
if (argCount < 2)
|
||||
{
|
||||
std::wcout << _T("Enter file name: ");
|
||||
std::wcin >> pathNameW;
|
||||
}
|
||||
else
|
||||
pathNameW = argArray[argCount - 1];
|
||||
String pathname = Str::WideToUtf8(pathNameW);
|
||||
bool argDeleteMipmap = false;
|
||||
bool argFade = false;
|
||||
bool argNormalMap = false;
|
||||
bool argColorData = true;
|
||||
VERUS_FOR(i, argCount)
|
||||
{
|
||||
if (!_wcsicmp(argArray[i], L"--delete-mipmap"))
|
||||
argDeleteMipmap = true;
|
||||
if (!_wcsicmp(argArray[i], L"--fade"))
|
||||
argFade = true;
|
||||
if (!_wcsicmp(argArray[i], L"--normal-map"))
|
||||
argNormalMap = true;
|
||||
if (!_wcsicmp(argArray[i], L"--non-color-data"))
|
||||
argColorData = false;
|
||||
}
|
||||
LocalFree(argArray);
|
||||
|
||||
if (argDeleteMipmap)
|
||||
{
|
||||
DeleteMipmap(_C(pathNameW));
|
||||
return;
|
||||
}
|
||||
|
||||
CMP_ERROR cmpError = CMP_OK;
|
||||
|
||||
CMP_MipSet srcMipSet = {};
|
||||
cmpError = CMP_LoadTexture(_C(pathname), &srcMipSet);
|
||||
if (CMP_OK != cmpError)
|
||||
{
|
||||
std::wcerr << _T("ERROR: CMP_LoadTexture(), ") << cmpError << std::endl;
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
// FX image with extra info:
|
||||
Vector<UINT32> vMipFX[2];
|
||||
String pathnameFX(pathname);
|
||||
Str::ReplaceExtension(pathnameFX, ".FX.png");
|
||||
if (argNormalMap && IO::FileSystem::FileExist(_C(pathnameFX)))
|
||||
{
|
||||
std::wcout << _T("FX file: ") << Str::Utf8ToWide(pathnameFX) << std::endl;
|
||||
IO::Image imageFX;
|
||||
imageFX.Init(_C(pathnameFX));
|
||||
if (imageFX._width == srcMipSet.m_nWidth && imageFX._height == srcMipSet.m_nHeight)
|
||||
{
|
||||
const int pixelCount = imageFX._width * imageFX._height;
|
||||
vMipFX[0].resize(pixelCount);
|
||||
vMipFX[1].resize(pixelCount);
|
||||
VERUS_FOR(i, pixelCount)
|
||||
memcpy(&vMipFX[0][i], imageFX._p + imageFX._bytesPerPixel * i, imageFX._bytesPerPixel);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::wcerr << _T("ERROR: FX image has different dimensions: ") << imageFX._width << _T("x") << imageFX._height << std::endl;
|
||||
throw std::exception();
|
||||
}
|
||||
}
|
||||
|
||||
if (srcMipSet.m_nMipLevels <= 1)
|
||||
CMP_GenerateMIPLevels(&srcMipSet, 0);
|
||||
|
||||
CMP_MipLevel* pMipLevel = srcMipSet.m_pMipLevelTable[0];
|
||||
const BYTE* pData = pMipLevel->m_pbData;
|
||||
const int pixelCount = srcMipSet.m_nWidth * srcMipSet.m_nHeight;
|
||||
|
||||
Vector<UINT32> vMip[2];
|
||||
vMip[0].resize(pixelCount);
|
||||
vMip[1].resize(pixelCount);
|
||||
|
||||
const float fadePerMip = pow(0.02f, 1.f / srcMipSet.m_nMipLevels);
|
||||
|
||||
int mip = 0;
|
||||
|
||||
bool finish = false;
|
||||
do
|
||||
{
|
||||
std::wcout << _T("Processing mipmap ") << mip << std::endl;
|
||||
|
||||
const int mipW = Math::Max(1, srcMipSet.m_nWidth >> mip);
|
||||
const int mipH = Math::Max(1, srcMipSet.m_nHeight >> mip);
|
||||
|
||||
// Switch between in and out:
|
||||
const int inIndex = (mip & 0x1);
|
||||
const int outIndex = ((mip + 1) & 0x1);
|
||||
|
||||
VERUS_FOR(i, mipH)
|
||||
{
|
||||
VERUS_FOR(j, mipW)
|
||||
{
|
||||
int offset = 0;
|
||||
UINT32 color = 0;
|
||||
UINT32 colorFX = 0;
|
||||
|
||||
if (mip) // Generate mipmap level 1+:
|
||||
{
|
||||
offset = i * mipW + j;
|
||||
|
||||
const int aboveMipW = mipW << 1;
|
||||
const int aboveMipH = mipH << 1;
|
||||
const int aboveMipEdgeW = aboveMipW - 1;
|
||||
const int aboveMipEdgeH = aboveMipH - 1;
|
||||
|
||||
const int sampleA[2] = { Math::Clamp((j << 1) + 0, 0, aboveMipEdgeW), Math::Clamp((i << 1) + 0, 0, aboveMipEdgeH) };
|
||||
const int sampleB[2] = { Math::Clamp((j << 1) + 1, 0, aboveMipEdgeW), Math::Clamp((i << 1) + 0, 0, aboveMipEdgeH) };
|
||||
const int sampleC[2] = { Math::Clamp((j << 1) + 0, 0, aboveMipEdgeW), Math::Clamp((i << 1) + 1, 0, aboveMipEdgeH) };
|
||||
const int sampleD[2] = { Math::Clamp((j << 1) + 1, 0, aboveMipEdgeW), Math::Clamp((i << 1) + 1, 0, aboveMipEdgeH) };
|
||||
|
||||
const int offsetA = sampleA[1] * aboveMipW + sampleA[0];
|
||||
const int offsetB = sampleB[1] * aboveMipW + sampleB[0];
|
||||
const int offsetC = sampleC[1] * aboveMipW + sampleC[0];
|
||||
const int offsetD = sampleD[1] * aboveMipW + sampleD[0];
|
||||
|
||||
if (argNormalMap)
|
||||
{
|
||||
Vector4 data[4];
|
||||
float raw[4];
|
||||
Convert::ColorInt32ToFloat(vMip[inIndex][offsetA], raw, false); data[0] = Vector4::MakeFromPointer(raw);
|
||||
Convert::ColorInt32ToFloat(vMip[inIndex][offsetB], raw, false); data[1] = Vector4::MakeFromPointer(raw);
|
||||
Convert::ColorInt32ToFloat(vMip[inIndex][offsetC], raw, false); data[2] = Vector4::MakeFromPointer(raw);
|
||||
Convert::ColorInt32ToFloat(vMip[inIndex][offsetD], raw, false); data[3] = Vector4::MakeFromPointer(raw);
|
||||
|
||||
// Generate FX mipmap:
|
||||
if (!vMipFX[inIndex].empty())
|
||||
{
|
||||
const BYTE* rgbaA = reinterpret_cast<BYTE*>(&vMipFX[inIndex][offsetA]);
|
||||
const BYTE* rgbaB = reinterpret_cast<BYTE*>(&vMipFX[inIndex][offsetB]);
|
||||
const BYTE* rgbaC = reinterpret_cast<BYTE*>(&vMipFX[inIndex][offsetC]);
|
||||
const BYTE* rgbaD = reinterpret_cast<BYTE*>(&vMipFX[inIndex][offsetD]);
|
||||
BYTE rgbaOut[4] =
|
||||
{
|
||||
static_cast<BYTE>((rgbaA[0] + rgbaB[0] + rgbaC[0] + rgbaD[0]) >> 2),
|
||||
static_cast<BYTE>((rgbaA[1] + rgbaB[1] + rgbaC[1] + rgbaD[1]) >> 2),
|
||||
static_cast<BYTE>((rgbaA[2] + rgbaB[2] + rgbaC[2] + rgbaD[2]) >> 2),
|
||||
static_cast<BYTE>((rgbaA[3] + rgbaB[3] + rgbaC[3] + rgbaD[3]) >> 2)
|
||||
};
|
||||
memcpy(&colorFX, rgbaOut, 4);
|
||||
}
|
||||
|
||||
const float prevAvgLength[4] =
|
||||
{
|
||||
data[0].getW(),
|
||||
data[1].getW(),
|
||||
data[2].getW(),
|
||||
data[3].getW()
|
||||
};
|
||||
data[0].setW(0);
|
||||
data[1].setW(0);
|
||||
data[2].setW(0);
|
||||
data[3].setW(0);
|
||||
|
||||
float minAvgLength = 1;
|
||||
VERUS_FOR(i, 4) // To [-1 to 1]:
|
||||
{
|
||||
data[i] = data[i] * 2.f - Vector4(1, 1, 1, 0);
|
||||
minAvgLength = Math::Min(minAvgLength, prevAvgLength[i]);
|
||||
}
|
||||
|
||||
Vector4 avg = (
|
||||
data[0] * prevAvgLength[0] +
|
||||
data[1] * prevAvgLength[1] +
|
||||
data[2] * prevAvgLength[2] +
|
||||
data[3] * prevAvgLength[3]) * 0.25f;
|
||||
float len = VMath::length(avg);
|
||||
|
||||
if (len > minAvgLength) // Don't make it too smooth.
|
||||
len = (len + minAvgLength) * 0.5f;
|
||||
|
||||
Vector4 dataOut = VMath::normalize(data[0] + data[1] + data[2] + data[3]);
|
||||
if (argFade)
|
||||
dataOut = VMath::normalize(VMath::lerp(fadePerMip, Vector4(0, 0, 1, 0), dataOut));
|
||||
dataOut = dataOut * 0.5f + Vector4(0.5f, 0.5f, 0.5f, 0); // To [0 to 1]:
|
||||
dataOut.setW(len);
|
||||
color = Convert::ColorFloatToInt32(dataOut.ToPointer(), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector4 data[4];
|
||||
float raw[4];
|
||||
Convert::ColorInt32ToFloat(vMip[inIndex][offsetA], raw, argColorData); data[0] = Vector4::MakeFromPointer(raw);
|
||||
Convert::ColorInt32ToFloat(vMip[inIndex][offsetB], raw, argColorData); data[1] = Vector4::MakeFromPointer(raw);
|
||||
Convert::ColorInt32ToFloat(vMip[inIndex][offsetC], raw, argColorData); data[2] = Vector4::MakeFromPointer(raw);
|
||||
Convert::ColorInt32ToFloat(vMip[inIndex][offsetD], raw, argColorData); data[3] = Vector4::MakeFromPointer(raw);
|
||||
Vector4 dataOut = (data[0] + data[1] + data[2] + data[3]) * 0.25f;
|
||||
color = Convert::ColorFloatToInt32(dataOut.ToPointer(), argColorData);
|
||||
}
|
||||
}
|
||||
else // Handle topmost mipmap level:
|
||||
{
|
||||
if (argNormalMap)
|
||||
{
|
||||
const bool upsideDownBGRA = false;
|
||||
if (upsideDownBGRA)
|
||||
{
|
||||
// Input image is upside down BGRA (?):
|
||||
offset = (mipH - i - 1) * mipW + j;
|
||||
UINT32 input = 0;
|
||||
memcpy(&input, &pData[offset * 4], 4);
|
||||
reinterpret_cast<BYTE*>(&input)[3] >>= 2; // Divide alpha by 4.
|
||||
color = VERUS_COLOR_TO_D3D(input);
|
||||
offset = i * mipW + j;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = i * mipW + j;
|
||||
UINT32 input = 0;
|
||||
memcpy(&input, &pData[offset * 4], 4);
|
||||
reinterpret_cast<BYTE*>(&input)[3] = 0xFF;
|
||||
color = input;
|
||||
|
||||
if (!vMipFX[inIndex].empty())
|
||||
{
|
||||
colorFX = vMipFX[inIndex][offset];
|
||||
BYTE* rgbaFX = reinterpret_cast<BYTE*>(&colorFX);
|
||||
rgbaFX[0] /= 4;
|
||||
rgbaFX[1] /= 4;
|
||||
rgbaFX[2] /= 4;
|
||||
rgbaFX[3] /= 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Simple copy for color:
|
||||
{
|
||||
offset = i * mipW + j;
|
||||
UINT32 input = 0;
|
||||
memcpy(&input, &pData[offset * 4], 4);
|
||||
color = input;
|
||||
}
|
||||
}
|
||||
vMip[outIndex][offset] = color;
|
||||
if (!vMipFX[outIndex].empty())
|
||||
vMipFX[outIndex][offset] = colorFX;
|
||||
}
|
||||
}
|
||||
|
||||
if (argNormalMap)
|
||||
{
|
||||
// Shuffle channels, read from outIndex, write to inIndex:
|
||||
const int pixelCount = mipW * mipH;
|
||||
VERUS_FOR(i, pixelCount)
|
||||
{
|
||||
BYTE* rgbaFX = vMipFX[outIndex].empty() ? nullptr : reinterpret_cast<BYTE*>(&vMipFX[outIndex][i]);
|
||||
BYTE* rgba = reinterpret_cast<BYTE*>(&vMip[outIndex][i]);
|
||||
const int len = Math::Clamp(rgba[3] - 128, 0, 0xFF);
|
||||
vMip[inIndex][i] = VERUS_COLOR_RGBA(rgbaFX ? rgbaFX[0] : 0, rgba[1], len, rgba[0]);
|
||||
}
|
||||
|
||||
// Save shuffled mip level, read from inIndex:
|
||||
CMP_MipLevel* pDstMipLevel = srcMipSet.m_pMipLevelTable[mip];
|
||||
memcpy(pDstMipLevel->m_pbData, vMip[inIndex].data(), mipW * mipH * sizeof(UINT32));
|
||||
}
|
||||
else
|
||||
{
|
||||
CMP_MipLevel* pDstMipLevel = srcMipSet.m_pMipLevelTable[mip];
|
||||
memcpy(pDstMipLevel->m_pbData, vMip[outIndex].data(), mipW * mipH * sizeof(UINT32));
|
||||
}
|
||||
|
||||
finish = (mipW == 1) && (mipH == 1);
|
||||
mip++; // Next level, switch between in and out.
|
||||
} while (!finish);
|
||||
|
||||
CMP_MipSet dstMipSet = {};
|
||||
|
||||
KernelOptions kernelOptions = {};
|
||||
kernelOptions.format = CMP_FORMAT_BC7;
|
||||
kernelOptions.fquality = 0.51f; // Tests show that 51% is production quality.
|
||||
|
||||
cmpError = CMP_ProcessTexture(&srcMipSet, &dstMipSet, kernelOptions, CompressionCallback);
|
||||
if (CMP_OK != cmpError)
|
||||
{
|
||||
std::wcerr << _T("ERROR: CMP_ProcessTexture(), ") << cmpError << std::endl;
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
Str::ReplaceExtension(pathname, ".dds");
|
||||
cmpError = CMP_SaveTexture(_C(pathname), &dstMipSet);
|
||||
if (CMP_OK != cmpError)
|
||||
{
|
||||
std::wcerr << _T("ERROR: CMP_SaveTexture(), ") << cmpError << std::endl;
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
CMP_FreeMipSet(&srcMipSet);
|
||||
CMP_FreeMipSet(&dstMipSet);
|
||||
}
|
||||
|
||||
void DeleteMipmap(CWSZ pathname)
|
||||
{
|
||||
const String pathnameIn = Str::WideToUtf8(pathname);
|
||||
const String pathnameOut = pathnameIn + "-del-mip.dds";
|
||||
IO::File file, fileOut;
|
||||
if (file.Open(_C(pathnameIn)) && file.GetSize() > sizeof(IO::DDSHeader) && fileOut.Open(_C(pathnameOut), "wb"))
|
||||
{
|
||||
IO::DDSHeader header;
|
||||
file >> header;
|
||||
if (!header.Validate())
|
||||
{
|
||||
std::wcerr << _T("ERROR: Invalid DDS header: ") << Str::Utf8ToWide(pathnameIn) << std::endl;
|
||||
throw std::exception();
|
||||
}
|
||||
if (header.IsBC1() && header._mipMapCount > 1)
|
||||
{
|
||||
const int levelSize = IO::DDSHeader::ComputeBcLevelSize(header._width, header._height, true);
|
||||
|
||||
header._mipMapCount--;
|
||||
header._width >>= 1;
|
||||
header._height >>= 1;
|
||||
header._pitchOrLinearSize = IO::DDSHeader::ComputeBcLevelSize(header._width, header._height, true);
|
||||
|
||||
fileOut << header;
|
||||
file.Seek(sizeof(IO::DDSHeader) + levelSize, SEEK_SET);
|
||||
Vector<BYTE> vData;
|
||||
vData.resize(file.GetSize() - levelSize - sizeof(IO::DDSHeader));
|
||||
file.Read(vData.data(), vData.size());
|
||||
fileOut.Write(vData.data(), vData.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::wcerr << _T("ERROR: Must be DXT1 with mipmaps") << std::endl;
|
||||
throw std::exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(VERUS_MAIN_DEFAULT_ARGS)
|
||||
{
|
||||
try
|
||||
{
|
||||
Run();
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::wcerr << _T("EXCEPTION: ") << e.what() << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -15,6 +15,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VulkanShaderCompiler", "Vul
|
|||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PAKBuilder", "PAKBuilder\PAKBuilder.vcxproj", "{EBF1E2F9-65AA-419D-A3D3-AD66EB086E57}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TextureTool", "TextureTool\TextureTool.vcxproj", "{5A1A3E76-7F69-48B6-B1E3-F6BB281B7E73}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
|
@ -45,6 +47,10 @@ Global
|
|||
{EBF1E2F9-65AA-419D-A3D3-AD66EB086E57}.Debug|x64.Build.0 = Debug|x64
|
||||
{EBF1E2F9-65AA-419D-A3D3-AD66EB086E57}.Release|x64.ActiveCfg = Release|x64
|
||||
{EBF1E2F9-65AA-419D-A3D3-AD66EB086E57}.Release|x64.Build.0 = Release|x64
|
||||
{5A1A3E76-7F69-48B6-B1E3-F6BB281B7E73}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{5A1A3E76-7F69-48B6-B1E3-F6BB281B7E73}.Debug|x64.Build.0 = Debug|x64
|
||||
{5A1A3E76-7F69-48B6-B1E3-F6BB281B7E73}.Release|x64.ActiveCfg = Release|x64
|
||||
{5A1A3E76-7F69-48B6-B1E3-F6BB281B7E73}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
<ImportGroup Label="PropertySheets" />
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<IncludePath>C:\Home\Projects\Verus\verus\Verus\src;C:\Home\Middleware\AMD Tootle 2.3\include;C:\Home\Middleware\bullet3-2.88\src;C:\Home\Middleware\bullet3-2.88\Extras;C:\Home\Middleware\DevIL-Windows-SDK-1.8.0\include;C:\Home\Middleware\libogg-1.3.4\include;C:\Home\Middleware\libvorbis-1.3.6\include;C:\Home\Middleware\SDL2-2.0.10\include;C:\Program Files %28x86%29\OpenAL 1.1 SDK\include;C:\VulkanSDK\1.2.131.2\Include;C:\VulkanSDK\1.2.131.2\glslang;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>C:\Home\Middleware\bullet3-2.88\bin;C:\Home\Middleware\AMD Tootle 2.3\lib;C:\Home\Middleware\DevIL-Windows-SDK-1.8.0\lib\x64\Release;C:\Home\Middleware\libogg-1.3.4\lib;C:\Home\Middleware\libvorbis-1.3.6\lib2;C:\Home\Middleware\SDL2-2.0.10\lib\x64;C:\Program Files %28x86%29\OpenAL 1.1 SDK\libs\Win64;C:\VulkanSDK\1.2.131.2\Lib;$(LibraryPath)</LibraryPath>
|
||||
<IncludePath>C:\Compressonator_3.2.4691\include;C:\Home\Projects\Verus\verus\Verus\src;C:\Home\Middleware\AMD Tootle 2.3\include;C:\Home\Middleware\bullet3-2.88\src;C:\Home\Middleware\bullet3-2.88\Extras;C:\Home\Middleware\DevIL-Windows-SDK-1.8.0\include;C:\Home\Middleware\libogg-1.3.4\include;C:\Home\Middleware\libvorbis-1.3.6\include;C:\Home\Middleware\SDL2-2.0.10\include;C:\Program Files %28x86%29\OpenAL 1.1 SDK\include;C:\VulkanSDK\1.2.131.2\Include;C:\VulkanSDK\1.2.131.2\glslang;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>C:\Compressonator_3.2.4691\lib\VS2017\x64;C:\Home\Middleware\bullet3-2.88\bin;C:\Home\Middleware\AMD Tootle 2.3\lib;C:\Home\Middleware\DevIL-Windows-SDK-1.8.0\lib\x64\Release;C:\Home\Middleware\libogg-1.3.4\lib;C:\Home\Middleware\libvorbis-1.3.6\lib2;C:\Home\Middleware\SDL2-2.0.10\lib\x64;C:\Program Files %28x86%29\OpenAL 1.1 SDK\libs\Win64;C:\VulkanSDK\1.2.131.2\Lib;$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup />
|
||||
<ItemGroup />
|
||||
|
|
|
@ -117,6 +117,7 @@
|
|||
<ClInclude Include="src\CGI\DeferredShading.h" />
|
||||
<ClInclude Include="src\CGI\RendererParser.h" />
|
||||
<ClInclude Include="src\CGI\Scheduled.h" />
|
||||
<ClInclude Include="src\CGI\TextureRAM.h" />
|
||||
<ClInclude Include="src\CGI\Types.h" />
|
||||
<ClInclude Include="src\CGI\Formats.h" />
|
||||
<ClInclude Include="src\CGI\Renderer.h" />
|
||||
|
@ -202,6 +203,7 @@
|
|||
<ClInclude Include="src\Scene\Camera.h" />
|
||||
<ClInclude Include="src\Scene\CameraOrbit.h" />
|
||||
<ClInclude Include="src\Scene\EditorTerrain.h" />
|
||||
<ClInclude Include="src\Scene\Grass.h" />
|
||||
<ClInclude Include="src\Scene\Helpers.h" />
|
||||
<ClInclude Include="src\Scene\MaterialManager.h" />
|
||||
<ClInclude Include="src\Scene\Mesh.h" />
|
||||
|
@ -209,6 +211,7 @@
|
|||
<ClInclude Include="src\Scene\SceneManager.h" />
|
||||
<ClInclude Include="src\Scene\ShadowMap.h" />
|
||||
<ClInclude Include="src\Scene\Terrain.h" />
|
||||
<ClInclude Include="src\Scene\Water.h" />
|
||||
<ClInclude Include="src\Security\CipherRC4.h" />
|
||||
<ClInclude Include="src\Security\Security.h" />
|
||||
<ClInclude Include="src\ThirdParty\imgui\imconfig.h" />
|
||||
|
@ -274,6 +277,7 @@
|
|||
<ClCompile Include="src\CGI\RendererParser.cpp" />
|
||||
<ClCompile Include="src\CGI\RenderPass.cpp" />
|
||||
<ClCompile Include="src\CGI\Scheduled.cpp" />
|
||||
<ClCompile Include="src\CGI\TextureRAM.cpp" />
|
||||
<ClCompile Include="src\D\D.cpp" />
|
||||
<ClCompile Include="src\D\Log.cpp" />
|
||||
<ClCompile Include="src\Extra\Extra.cpp" />
|
||||
|
@ -333,6 +337,7 @@
|
|||
<ClCompile Include="src\Scene\Camera.cpp" />
|
||||
<ClCompile Include="src\Scene\CameraOrbit.cpp" />
|
||||
<ClCompile Include="src\Scene\EditorTerrain.cpp" />
|
||||
<ClCompile Include="src\Scene\Grass.cpp" />
|
||||
<ClCompile Include="src\Scene\Helpers.cpp" />
|
||||
<ClCompile Include="src\Scene\MaterialManager.cpp" />
|
||||
<ClCompile Include="src\Scene\Mesh.cpp" />
|
||||
|
@ -340,6 +345,7 @@
|
|||
<ClCompile Include="src\Scene\SceneManager.cpp" />
|
||||
<ClCompile Include="src\Scene\ShadowMap.cpp" />
|
||||
<ClCompile Include="src\Scene\Terrain.cpp" />
|
||||
<ClCompile Include="src\Scene\Water.cpp" />
|
||||
<ClCompile Include="src\ThirdParty\fast_atof.c">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||
|
@ -578,6 +584,56 @@
|
|||
<FileType>Document</FileType>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="src\Shaders\LibSurface.hlsl">
|
||||
<FileType>Document</FileType>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="src\Shaders\LibTessellation.hlsl">
|
||||
<FileType>Document</FileType>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="src\Shaders\DS_Grass.hlsl">
|
||||
<FileType>Document</FileType>
|
||||
</None>
|
||||
<None Include="src\Shaders\DS_Grass.inc.hlsl">
|
||||
<FileType>Document</FileType>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="src\Shaders\Sky.hlsl">
|
||||
<FileType>Document</FileType>
|
||||
</None>
|
||||
<None Include="src\Shaders\Sky.inc.hlsl">
|
||||
<FileType>Document</FileType>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="src\Shaders\Water.hlsl">
|
||||
<FileType>Document</FileType>
|
||||
</None>
|
||||
<None Include="src\Shaders\Water.inc.hlsl">
|
||||
<FileType>Document</FileType>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="src\Shaders\WaterGen.hlsl">
|
||||
<FileType>Document</FileType>
|
||||
</None>
|
||||
<None Include="src\Shaders\WaterGen.inc.hlsl">
|
||||
<FileType>Document</FileType>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="src\Shaders\SimpleTerrain.hlsl">
|
||||
<FileType>Document</FileType>
|
||||
</None>
|
||||
<None Include="src\Shaders\SimpleTerrain.inc.hlsl">
|
||||
<FileType>Document</FileType>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -552,6 +552,15 @@
|
|||
<ClInclude Include="src\IO\Xxx.h">
|
||||
<Filter>src\IO</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\Scene\Grass.h">
|
||||
<Filter>src\Scene</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\CGI\TextureRAM.h">
|
||||
<Filter>src\CGI</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\Scene\Water.h">
|
||||
<Filter>src\Scene</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\CGI\BaseGeometry.cpp">
|
||||
|
@ -917,6 +926,15 @@
|
|||
<ClCompile Include="src\IO\Xxx.cpp">
|
||||
<Filter>src\IO</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Scene\Grass.cpp">
|
||||
<Filter>src\Scene</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\CGI\TextureRAM.cpp">
|
||||
<Filter>src\CGI</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Scene\Water.cpp">
|
||||
<Filter>src\Scene</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="src\Shaders\Lib.hlsl">
|
||||
|
@ -979,6 +997,42 @@
|
|||
<None Include="src\Shaders\DebugDraw.inc.hlsl">
|
||||
<Filter>src\Shaders</Filter>
|
||||
</None>
|
||||
<None Include="src\Shaders\LibSurface.hlsl">
|
||||
<Filter>src\Shaders</Filter>
|
||||
</None>
|
||||
<None Include="src\Shaders\LibTessellation.hlsl">
|
||||
<Filter>src\Shaders</Filter>
|
||||
</None>
|
||||
<None Include="src\Shaders\Sky.hlsl">
|
||||
<Filter>src\Shaders</Filter>
|
||||
</None>
|
||||
<None Include="src\Shaders\Sky.inc.hlsl">
|
||||
<Filter>src\Shaders</Filter>
|
||||
</None>
|
||||
<None Include="src\Shaders\DS_Grass.hlsl">
|
||||
<Filter>src\Shaders</Filter>
|
||||
</None>
|
||||
<None Include="src\Shaders\DS_Grass.inc.hlsl">
|
||||
<Filter>src\Shaders</Filter>
|
||||
</None>
|
||||
<None Include="src\Shaders\Water.hlsl">
|
||||
<Filter>src\Shaders</Filter>
|
||||
</None>
|
||||
<None Include="src\Shaders\Water.inc.hlsl">
|
||||
<Filter>src\Shaders</Filter>
|
||||
</None>
|
||||
<None Include="src\Shaders\WaterGen.inc.hlsl">
|
||||
<Filter>src\Shaders</Filter>
|
||||
</None>
|
||||
<None Include="src\Shaders\WaterGen.hlsl">
|
||||
<Filter>src\Shaders</Filter>
|
||||
</None>
|
||||
<None Include="src\Shaders\SimpleTerrain.hlsl">
|
||||
<Filter>src\Shaders</Filter>
|
||||
</None>
|
||||
<None Include="src\Shaders\SimpleTerrain.inc.hlsl">
|
||||
<Filter>src\Shaders</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="src\ThirdParty\pugixml-1.10\pugixml.natvis">
|
||||
|
|
|
@ -25,6 +25,7 @@ void Settings::Load()
|
|||
_gapi = GetI("gapi", _gapi);
|
||||
_gpuAnisotropyLevel = GetI("gpuAnisotropyLevel", _gpuAnisotropyLevel);
|
||||
_gpuAntialiasingLevel = GetI("gpuAntialiasingLevel", _gpuAntialiasingLevel);
|
||||
_gpuTessellation = GetB("gpuTessellation", _gpuTessellation);
|
||||
_gpuTextureLodLevel = GetI("gpuTextureLodLevel", _gpuTextureLodLevel);
|
||||
_gpuTrilinearFilter = GetB("gpuTrilinearFilter", _gpuTrilinearFilter);
|
||||
_inputMouseSensitivity = GetF("inputMouseSensitivity", _inputMouseSensitivity);
|
||||
|
@ -67,6 +68,7 @@ void Settings::Save()
|
|||
Set("gapi", _gapi);
|
||||
Set("gpuAnisotropyLevel", _gpuAnisotropyLevel);
|
||||
Set("gpuAntialiasingLevel", _gpuAntialiasingLevel);
|
||||
Set("gpuTessellation", _gpuTessellation);
|
||||
Set("gpuTextureLodLevel", _gpuTextureLodLevel);
|
||||
Set("gpuTrilinearFilter", _gpuTrilinearFilter);
|
||||
Set("inputMouseSensitivity", _inputMouseSensitivity);
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace verus
|
|||
class Limits
|
||||
{
|
||||
public:
|
||||
int _d3d12_dhCbvSrvUavCapacity = 10000;
|
||||
int _d3d12_dhViewsCapacity = 10000;
|
||||
int _d3d12_dhSamplersCapacity = 500;
|
||||
int _mesh_ubPerFrameCapacity = 100;
|
||||
int _mesh_ubPerMaterialFSCapacity = 1000;
|
||||
|
@ -64,6 +64,7 @@ namespace verus
|
|||
int _gapi = 0;
|
||||
int _gpuAnisotropyLevel = 4;
|
||||
int _gpuAntialiasingLevel = 0;
|
||||
bool _gpuTessellation = true;
|
||||
int _gpuTextureLodLevel = 0;
|
||||
bool _gpuTrilinearFilter = false;
|
||||
float _inputMouseSensitivity = 1;
|
||||
|
|
|
@ -7,6 +7,8 @@ namespace verus
|
|||
class BaseCommandBuffer : public Object, public Scheduled
|
||||
{
|
||||
protected:
|
||||
Vector4 _viewportSize = Vector4(0);
|
||||
|
||||
BaseCommandBuffer() = default;
|
||||
virtual ~BaseCommandBuffer() = default;
|
||||
|
||||
|
@ -17,7 +19,7 @@ namespace verus
|
|||
virtual void Begin() = 0;
|
||||
virtual void End() = 0;
|
||||
|
||||
virtual void BeginRenderPass(int renderPassHandle, int framebufferHandle, std::initializer_list<Vector4> ilClearValues, bool setViewportAndScissor = true) = 0;
|
||||
virtual void BeginRenderPass(RPHandle renderPassHandle, FBHandle framebufferHandle, std::initializer_list<Vector4> ilClearValues, bool setViewportAndScissor = true) = 0;
|
||||
virtual void NextSubpass() = 0;
|
||||
virtual void EndRenderPass() = 0;
|
||||
|
||||
|
@ -29,7 +31,7 @@ namespace verus
|
|||
virtual void SetScissor(std::initializer_list<Vector4> il) = 0;
|
||||
virtual void SetBlendConstants(const float* p) = 0;
|
||||
|
||||
virtual bool BindDescriptors(ShaderPtr shader, int setNumber, int complexSetHandle = -1) = 0;
|
||||
virtual bool BindDescriptors(ShaderPtr shader, int setNumber, CSHandle complexSetHandle = CSHandle()) = 0;
|
||||
virtual void PushConstants(ShaderPtr shader, int offset, int size, const void* p, ShaderStageFlags stageFlags = ShaderStageFlags::vs_fs) = 0;
|
||||
|
||||
virtual void PipelineImageMemoryBarrier(TexturePtr tex, ImageLayout oldLayout, ImageLayout newLayout,
|
||||
|
@ -39,6 +41,8 @@ namespace verus
|
|||
virtual void DrawIndexed(int indexCount, int instanceCount = 1, int firstIndex = 0, int vertexOffset = 0, int firstInstance = 0) = 0;
|
||||
|
||||
virtual void Dispatch(int groupCountX, int groupCountY, int groupCountZ = 1) = 0;
|
||||
|
||||
RcVector4 GetViewportSize() const { return _viewportSize; }
|
||||
};
|
||||
VERUS_TYPEDEFS(BaseCommandBuffer);
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
using namespace verus;
|
||||
using namespace verus::CGI;
|
||||
|
||||
int BaseGeometry::GetInputElementDescCount(PcInputElementDesc p)
|
||||
int BaseGeometry::GetVertexInputAttrDescCount(PcVertexInputAttrDesc p)
|
||||
{
|
||||
int i = 0;
|
||||
while (p[i]._offset >= 0)
|
||||
|
@ -11,7 +11,7 @@ int BaseGeometry::GetInputElementDescCount(PcInputElementDesc p)
|
|||
return i;
|
||||
}
|
||||
|
||||
int BaseGeometry::GetBindingCount(PcInputElementDesc p)
|
||||
int BaseGeometry::GetBindingCount(PcVertexInputAttrDesc p)
|
||||
{
|
||||
int count = 0;
|
||||
int i = 0;
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace verus
|
|||
|
||||
struct GeometryDesc
|
||||
{
|
||||
PcInputElementDesc _pInputElementDesc;
|
||||
PcVertexInputAttrDesc _pVertexInputAttrDesc;
|
||||
const int* _pStrides = nullptr;
|
||||
UINT32 _dynBindingsMask = 0;
|
||||
bool _32BitIndices = false;
|
||||
|
@ -35,8 +35,8 @@ namespace verus
|
|||
virtual void CreateIndexBuffer(int count) = 0;
|
||||
virtual void UpdateIndexBuffer(const void* p, BaseCommandBuffer* pCB = nullptr) = 0;
|
||||
|
||||
static int GetInputElementDescCount(PcInputElementDesc p);
|
||||
static int GetBindingCount(PcInputElementDesc p);
|
||||
static int GetVertexInputAttrDescCount(PcVertexInputAttrDesc p);
|
||||
static int GetBindingCount(PcVertexInputAttrDesc p);
|
||||
|
||||
bool Has32BitIndices() const { return _32BitIndices; }
|
||||
};
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace verus
|
|||
PipelineRasterizationState _rasterizationState;
|
||||
PrimitiveTopology _topology = PrimitiveTopology::triangleList;
|
||||
int _sampleCount = 1;
|
||||
int _renderPassHandle = -1;
|
||||
RPHandle _renderPassHandle;
|
||||
int _subpass = 0;
|
||||
int _multiViewport = 1; // See SV_ViewportArrayIndex semantic output by a geometry shader.
|
||||
UINT32 _vertexInputBindingsFilter = UINT32_MAX;
|
||||
|
@ -26,7 +26,7 @@ namespace verus
|
|||
bool _compute = false; // Compute pipeline, use PipelineDesc(ShaderPtr, CSZ) to set this to true.
|
||||
|
||||
// What to draw (geo)? How to draw (shader)? Where to draw (render pass)?
|
||||
PipelineDesc(GeometryPtr geo, ShaderPtr shader, CSZ branch, int renderPassHandle, int subpass = 0) :
|
||||
PipelineDesc(GeometryPtr geo, ShaderPtr shader, CSZ branch, RPHandle renderPassHandle, int subpass = 0) :
|
||||
_geometry(geo), _shader(shader), _shaderBranch(branch), _renderPassHandle(renderPassHandle), _subpass(subpass)
|
||||
{
|
||||
_colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_OFF;
|
||||
|
|
|
@ -45,6 +45,30 @@ void BaseRenderer::UpdateScheduled()
|
|||
}), _vScheduled.end());
|
||||
}
|
||||
|
||||
RPHandle BaseRenderer::CreateSimpleRenderPass(Format format, ImageLayout layout)
|
||||
{
|
||||
return CreateRenderPass(
|
||||
{
|
||||
RP::Attachment("Attach", format).LoadOpDontCare().Layout(layout),
|
||||
},
|
||||
{
|
||||
RP::Subpass("Sp0").Color({RP::Ref("Attach", ImageLayout::colorAttachment)}),
|
||||
},
|
||||
{});
|
||||
}
|
||||
|
||||
RPHandle BaseRenderer::CreateShadowRenderPass(Format format)
|
||||
{
|
||||
return CreateRenderPass(
|
||||
{
|
||||
RP::Attachment("Depth", format).LoadOpClear().Layout(ImageLayout::depthStencilReadOnly),
|
||||
},
|
||||
{
|
||||
RP::Subpass("Sp0").Color({}).DepthStencil(RP::Ref("Depth", ImageLayout::depthStencilAttachment)),
|
||||
},
|
||||
{});
|
||||
}
|
||||
|
||||
void BaseRenderer::SetAlphaBlendHelper(
|
||||
CSZ sz,
|
||||
int& colorBlendOp,
|
||||
|
|
|
@ -50,7 +50,7 @@ namespace verus
|
|||
void Unschedule(PScheduled p);
|
||||
void UpdateScheduled();
|
||||
|
||||
virtual void ImGuiInit(int renderPassHandle) = 0;
|
||||
virtual void ImGuiInit(RPHandle renderPassHandle) = 0;
|
||||
virtual void ImGuiRenderDrawData() = 0;
|
||||
|
||||
virtual void ResizeSwapChain() = 0;
|
||||
|
@ -77,10 +77,12 @@ namespace verus
|
|||
virtual void DeleteShader(PBaseShader p) = 0;
|
||||
virtual void DeleteTexture(PBaseTexture p) = 0;
|
||||
|
||||
virtual int CreateRenderPass(std::initializer_list<RP::Attachment> ilA, std::initializer_list<RP::Subpass> ilS, std::initializer_list<RP::Dependency> ilD) = 0;
|
||||
virtual int CreateFramebuffer(int renderPassHandle, std::initializer_list<TexturePtr> il, int w, int h, int swapChainBufferIndex = -1) = 0;
|
||||
virtual void DeleteRenderPass(int handle) = 0;
|
||||
virtual void DeleteFramebuffer(int handle) = 0;
|
||||
RPHandle CreateSimpleRenderPass(Format format, ImageLayout layout = ImageLayout::fsReadOnly);
|
||||
RPHandle CreateShadowRenderPass(Format format);
|
||||
virtual RPHandle CreateRenderPass(std::initializer_list<RP::Attachment> ilA, std::initializer_list<RP::Subpass> ilS, std::initializer_list<RP::Dependency> ilD) = 0;
|
||||
virtual FBHandle CreateFramebuffer(RPHandle renderPassHandle, std::initializer_list<TexturePtr> il, int w, int h, int swapChainBufferIndex = -1) = 0;
|
||||
virtual void DeleteRenderPass(RPHandle handle) = 0;
|
||||
virtual void DeleteFramebuffer(FBHandle handle) = 0;
|
||||
|
||||
static void SetAlphaBlendHelper(
|
||||
CSZ sz,
|
||||
|
|
|
@ -36,32 +36,24 @@ void BaseShader::Load(CSZ url)
|
|||
|
||||
String BaseShader::Parse(
|
||||
CSZ branchDesc,
|
||||
RString entryVS,
|
||||
RString entryHS,
|
||||
RString entryDS,
|
||||
RString entryGS,
|
||||
RString entryFS,
|
||||
RString entryCS,
|
||||
RString entry,
|
||||
String stageEntries[],
|
||||
RString stages,
|
||||
Vector<String>& vMacroName,
|
||||
Vector<String>& vMacroValue,
|
||||
CSZ prefix)
|
||||
{
|
||||
VERUS_RT_ASSERT(branchDesc);
|
||||
entryVS.clear();
|
||||
entryHS.clear();
|
||||
entryDS.clear();
|
||||
entryGS.clear();
|
||||
entryFS.clear();
|
||||
entryCS.clear();
|
||||
VERUS_FOR(i, +Stage::count)
|
||||
stageEntries[i].clear();
|
||||
stages = "(VF)";
|
||||
vMacroName.clear();
|
||||
vMacroValue.clear();
|
||||
|
||||
CSZ space = strchr(branchDesc, ' ');
|
||||
|
||||
String entry;
|
||||
space ? entry.assign(branchDesc, space) : entry.assign(branchDesc);
|
||||
String entryBranch;
|
||||
space ? entryBranch.assign(branchDesc, space) : entryBranch.assign(branchDesc);
|
||||
|
||||
if (space)
|
||||
{
|
||||
|
@ -97,44 +89,46 @@ String BaseShader::Parse(
|
|||
} while (branchDesc);
|
||||
}
|
||||
|
||||
const size_t colon = entry.find(":");
|
||||
const size_t colon = entryBranch.find(":");
|
||||
if (String::npos == colon)
|
||||
{
|
||||
entryVS = entry + "VS";
|
||||
entryHS = entry + "HS";
|
||||
entryDS = entry + "DS";
|
||||
entryGS = entry + "GS";
|
||||
entryFS = entry + "FS";
|
||||
entryCS = entry + "CS";
|
||||
return entry;
|
||||
entry = entryBranch;
|
||||
stageEntries[+Stage::vs] = entryBranch + "VS";
|
||||
stageEntries[+Stage::hs] = entryBranch + "HS";
|
||||
stageEntries[+Stage::ds] = entryBranch + "DS";
|
||||
stageEntries[+Stage::gs] = entryBranch + "GS";
|
||||
stageEntries[+Stage::fs] = entryBranch + "FS";
|
||||
stageEntries[+Stage::cs] = entryBranch + "CS";
|
||||
return entryBranch;
|
||||
}
|
||||
else
|
||||
{
|
||||
const String func = entry.substr(0, colon);
|
||||
entryVS = func + "VS";
|
||||
entryHS = func + "HS";
|
||||
entryDS = func + "DS";
|
||||
entryGS = func + "GS";
|
||||
entryFS = func + "FS";
|
||||
entryCS = func + "CS";
|
||||
return entry.substr(colon + 1);
|
||||
const String func = entryBranch.substr(0, colon);
|
||||
entry = func;
|
||||
stageEntries[+Stage::vs] = func + "VS";
|
||||
stageEntries[+Stage::hs] = func + "HS";
|
||||
stageEntries[+Stage::ds] = func + "DS";
|
||||
stageEntries[+Stage::gs] = func + "GS";
|
||||
stageEntries[+Stage::fs] = func + "FS";
|
||||
stageEntries[+Stage::cs] = func + "CS";
|
||||
return entryBranch.substr(colon + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseShader::TestParse()
|
||||
{
|
||||
String entryVS, entryHS, entryDS, entryGS, entryFS, entryCS, stages;
|
||||
String entry, stageEntries[+Stage::count], stages;
|
||||
Vector<String> vMacroName;
|
||||
Vector<String> vMacroValue;
|
||||
|
||||
Parse("",
|
||||
entryVS, entryHS, entryDS, entryGS, entryFS, entryCS, stages, vMacroName, vMacroValue, "DEF_");
|
||||
entry, stageEntries, stages, vMacroName, vMacroValue, "DEF_");
|
||||
Parse("Foo",
|
||||
entryVS, entryHS, entryDS, entryGS, entryFS, entryCS, stages, vMacroName, vMacroValue, "DEF_");
|
||||
entry, stageEntries, stages, vMacroName, vMacroValue, "DEF_");
|
||||
Parse("Bar FOO BAR XYZ (VGF)",
|
||||
entryVS, entryHS, entryDS, entryGS, entryFS, entryCS, stages, vMacroName, vMacroValue, "DEF_");
|
||||
entry, stageEntries, stages, vMacroName, vMacroValue, "DEF_");
|
||||
Parse("FooBar FOO=1 BAR=xyz XYZ= XYZ2=",
|
||||
entryVS, entryHS, entryDS, entryGS, entryFS, entryCS, stages, vMacroName, vMacroValue, "DEF_");
|
||||
entry, stageEntries, stages, vMacroName, vMacroValue, "DEF_");
|
||||
}
|
||||
|
||||
bool BaseShader::IsInIgnoreList(CSZ name) const
|
||||
|
|
|
@ -46,12 +46,8 @@ namespace verus
|
|||
void Load(CSZ url);
|
||||
static String Parse(
|
||||
CSZ branchDesc,
|
||||
RString entryVS,
|
||||
RString entryHS,
|
||||
RString entryDS,
|
||||
RString entryGS,
|
||||
RString entryFS,
|
||||
RString entryCS,
|
||||
RString entry,
|
||||
String stageEntries[],
|
||||
RString stages,
|
||||
Vector<String>& vMacroName,
|
||||
Vector<String>& vMacroValue,
|
||||
|
@ -61,8 +57,8 @@ namespace verus
|
|||
virtual void CreateDescriptorSet(int setNumber, const void* pSrc, int size,
|
||||
int capacity = 1, std::initializer_list<Sampler> il = {}, ShaderStageFlags stageFlags = ShaderStageFlags::vs_fs) = 0;
|
||||
virtual void CreatePipelineLayout() = 0;
|
||||
virtual int BindDescriptorSetTextures(int setNumber, std::initializer_list<TexturePtr> il, const int* pMips = nullptr) = 0;
|
||||
virtual void FreeDescriptorSet(int& complexSetHandle) = 0;
|
||||
virtual CSHandle BindDescriptorSetTextures(int setNumber, std::initializer_list<TexturePtr> il, const int* pMips = nullptr) = 0;
|
||||
virtual void FreeDescriptorSet(CSHandle& complexSetHandle) = 0;
|
||||
|
||||
virtual void BeginBindDescriptors() = 0;
|
||||
virtual void EndBindDescriptors() = 0;
|
||||
|
|
|
@ -28,8 +28,10 @@ void BaseTexture::LoadDDS(CSZ url, int texturePart)
|
|||
IO::Async::I().Load(url, this, IO::Async::TaskDesc(false, false, texturePart));
|
||||
}
|
||||
|
||||
void BaseTexture::LoadDDS(RcBlob blob)
|
||||
void BaseTexture::LoadDDS(CSZ url, RcBlob blob)
|
||||
{
|
||||
_name = url;
|
||||
|
||||
int offset = sizeof(IO::DDSHeader);
|
||||
IO::DDSHeader header;
|
||||
memcpy(&header, blob._p, sizeof(header));
|
||||
|
@ -70,6 +72,7 @@ void BaseTexture::LoadDDS(RcBlob blob)
|
|||
desc._width = header._width >> lod;
|
||||
desc._height = header._height >> lod;
|
||||
desc._mipLevels = header._mipMapCount - lod;
|
||||
desc._pSamplerDesc = _desc._pSamplerDesc;
|
||||
|
||||
Init(desc);
|
||||
|
||||
|
@ -97,6 +100,7 @@ void BaseTexture::LoadDDS(RcBlob blob)
|
|||
desc._width = header._width;
|
||||
desc._height = header._height;
|
||||
desc._mipLevels = header._mipMapCount;
|
||||
desc._pSamplerDesc = _desc._pSamplerDesc;
|
||||
|
||||
Init(desc);
|
||||
|
||||
|
@ -118,6 +122,7 @@ void BaseTexture::LoadDDS(RcBlob blob)
|
|||
desc._width = header._width;
|
||||
desc._height = header._height;
|
||||
desc._mipLevels = header._mipMapCount;
|
||||
desc._pSamplerDesc = _desc._pSamplerDesc;
|
||||
|
||||
Init(desc);
|
||||
|
||||
|
@ -151,6 +156,7 @@ void BaseTexture::LoadDDS(RcBlob blob)
|
|||
desc._width = header._width;
|
||||
desc._height = header._height;
|
||||
desc._mipLevels = header._mipMapCount;
|
||||
desc._pSamplerDesc = _desc._pSamplerDesc;
|
||||
|
||||
Init(desc);
|
||||
|
||||
|
@ -202,10 +208,17 @@ void BaseTexture::LoadDDSArray(CSZ* urls)
|
|||
const BYTE* pData = vData.data();
|
||||
const size_t size = vData.size();
|
||||
|
||||
int offset = sizeof(IO::DDSHeader);
|
||||
IO::DDSHeader header;
|
||||
memcpy(&header, pData, sizeof(header));
|
||||
if (!header.Validate())
|
||||
throw VERUS_RUNTIME_ERROR << "Invalid DDS header: " << _name;
|
||||
IO::DDSHeaderDXT10 header10;
|
||||
if (header.IsDXT10())
|
||||
{
|
||||
memcpy(&header10, pData + offset, sizeof(header10));
|
||||
offset += sizeof(IO::DDSHeaderDXT10);
|
||||
}
|
||||
|
||||
VERUS_QREF_CONST_SETTINGS;
|
||||
|
||||
|
@ -240,9 +253,12 @@ void BaseTexture::LoadDDSArray(CSZ* urls)
|
|||
desc._format = SelectFormat(Format::unormBC2, Format::srgbBC2);
|
||||
else if (header.IsBC3())
|
||||
desc._format = SelectFormat(Format::unormBC3, Format::srgbBC3);
|
||||
else if (header10.IsBC7())
|
||||
desc._format = SelectFormat(Format::unormBC7, Format::srgbBC7);
|
||||
desc._width = w;
|
||||
desc._height = h;
|
||||
desc._mipLevels = header._mipMapCount - lod;
|
||||
desc._pSamplerDesc = _desc._pSamplerDesc;
|
||||
|
||||
if (init)
|
||||
{
|
||||
|
@ -250,7 +266,6 @@ void BaseTexture::LoadDDSArray(CSZ* urls)
|
|||
Init(desc);
|
||||
}
|
||||
|
||||
int offset = sizeof(header);
|
||||
VERUS_U_FOR(i, header._mipMapCount)
|
||||
{
|
||||
UINT32 w = header._width >> i;
|
||||
|
@ -274,7 +289,7 @@ void BaseTexture::LoadDDSArray(CSZ* urls)
|
|||
|
||||
void BaseTexture::Async_Run(CSZ url, RcBlob blob)
|
||||
{
|
||||
LoadDDS(blob);
|
||||
LoadDDS(url, blob);
|
||||
}
|
||||
|
||||
int BaseTexture::FormatToBytesPerPixel(Format format)
|
||||
|
@ -307,6 +322,20 @@ int BaseTexture::FormatToBytesPerPixel(Format format)
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool BaseTexture::IsSRGBFormat(Format format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case Format::srgbR8G8B8A8: return true;
|
||||
case Format::srgbB8G8R8A8: return true;
|
||||
case Format::srgbBC1: return true;
|
||||
case Format::srgbBC2: return true;
|
||||
case Format::srgbBC3: return true;
|
||||
case Format::srgbBC7: return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BaseTexture::IsBC(Format format)
|
||||
{
|
||||
return format >= Format::unormBC1 && format <= Format::srgbBC7;
|
||||
|
@ -329,11 +358,12 @@ void TexturePtr::Init(RcTextureDesc desc)
|
|||
VERUS_QREF_RENDERER;
|
||||
VERUS_RT_ASSERT(!_p);
|
||||
_p = renderer->InsertTexture();
|
||||
_p->SetSamplerDesc(desc._pSamplerDesc);
|
||||
if (desc._flags & TextureDesc::Flags::sync)
|
||||
{
|
||||
Vector<BYTE> v;
|
||||
IO::FileSystem::LoadResource(desc._url, v);
|
||||
_p->LoadDDS(Blob(v.data(), v.size()));
|
||||
Vector<BYTE> vData;
|
||||
IO::FileSystem::LoadResource(desc._url, vData);
|
||||
_p->LoadDDS(desc._url, Blob(vData.data(), vData.size()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -32,11 +32,12 @@ namespace verus
|
|||
none = 0,
|
||||
colorAttachment = (1 << 0),
|
||||
inputAttachment = (1 << 1),
|
||||
depthSampled = (1 << 2),
|
||||
anyShaderResource = (1 << 3), // Will use xsReadOnly as main layout.
|
||||
generateMips = (1 << 4), // Allows GenerateMips calls.
|
||||
forceArrayTexture = (1 << 5), // Create array texture even if arrayLayers=1.
|
||||
sync = (1 << 6)
|
||||
depthSampledR = (1 << 2),
|
||||
depthSampledW = (1 << 3),
|
||||
anyShaderResource = (1 << 4), // Will use xsReadOnly as main layout.
|
||||
generateMips = (1 << 5), // Allows GenerateMips calls.
|
||||
forceArrayTexture = (1 << 6), // Create array texture even if arrayLayers=1.
|
||||
sync = (1 << 7)
|
||||
};
|
||||
|
||||
Vector4 _clearValue = Vector4(0);
|
||||
|
@ -98,8 +99,10 @@ namespace verus
|
|||
RcVector4 GetSize() const { return _size; }
|
||||
bool IsSRGB() const;
|
||||
|
||||
void SetSamplerDesc(PcSamplerDesc pSamplerDesc) { _desc._pSamplerDesc = pSamplerDesc; }
|
||||
|
||||
void LoadDDS(CSZ url, int texturePart = 0);
|
||||
void LoadDDS(RcBlob blob);
|
||||
void LoadDDS(CSZ url, RcBlob blob);
|
||||
void LoadDDSArray(CSZ* urls);
|
||||
|
||||
virtual void Async_Run(CSZ url, RcBlob blob) override;
|
||||
|
@ -109,6 +112,7 @@ namespace verus
|
|||
virtual void GenerateMips(BaseCommandBuffer* pCB = nullptr) = 0;
|
||||
|
||||
static int FormatToBytesPerPixel(Format format);
|
||||
static bool IsSRGBFormat(Format format);
|
||||
static bool IsBC(Format format);
|
||||
static bool Is4BitsBC(Format format);
|
||||
static bool IsDepthFormat(Format format);
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "BaseCommandBuffer.h"
|
||||
#include "BaseRenderer.h"
|
||||
|
||||
#include "TextureRAM.h"
|
||||
#include "DebugDraw.h"
|
||||
#include "DeferredShading.h"
|
||||
#include "Renderer.h"
|
||||
|
|
|
@ -25,13 +25,13 @@ void DebugDraw::Init()
|
|||
_shader->CreatePipelineLayout();
|
||||
|
||||
GeometryDesc geoDesc;
|
||||
const InputElementDesc ied[] =
|
||||
const VertexInputAttrDesc viaDesc[] =
|
||||
{
|
||||
{0, offsetof(Vertex, _pos), IeType::floats, 3, IeUsage::position, 0},
|
||||
{0, offsetof(Vertex, _color), IeType::ubytes, 4, IeUsage::color, 0},
|
||||
InputElementDesc::End()
|
||||
VertexInputAttrDesc::End()
|
||||
};
|
||||
geoDesc._pInputElementDesc = ied;
|
||||
geoDesc._pVertexInputAttrDesc = viaDesc;
|
||||
const int strides[] = { sizeof(Vertex), 0 };
|
||||
geoDesc._pStrides = strides;
|
||||
geoDesc._dynBindingsMask = 0x1;
|
||||
|
@ -43,7 +43,7 @@ void DebugDraw::Init()
|
|||
_offset = 0;
|
||||
|
||||
{
|
||||
PipelineDesc pipeDesc(_geo, _shader, "#", renderer.GetRenderPass_SwapChainDepth());
|
||||
PipelineDesc pipeDesc(_geo, _shader, "#", renderer.GetRenderPassHandle_SwapChainDepth());
|
||||
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_ALPHA;
|
||||
pipeDesc._topology = PrimitiveTopology::pointList;
|
||||
_pipe[PIPE_POINTS].Init(pipeDesc);
|
||||
|
@ -51,7 +51,7 @@ void DebugDraw::Init()
|
|||
_pipe[PIPE_POINTS_NO_Z].Init(pipeDesc);
|
||||
}
|
||||
{
|
||||
PipelineDesc pipeDesc(_geo, _shader, "#", renderer.GetRenderPass_SwapChainDepth());
|
||||
PipelineDesc pipeDesc(_geo, _shader, "#", renderer.GetRenderPassHandle_SwapChainDepth());
|
||||
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_ALPHA;
|
||||
pipeDesc._topology = PrimitiveTopology::lineList;
|
||||
_pipe[PIPE_LINES].Init(pipeDesc);
|
||||
|
@ -59,7 +59,7 @@ void DebugDraw::Init()
|
|||
_pipe[PIPE_LINES_NO_Z].Init(pipeDesc);
|
||||
}
|
||||
{
|
||||
PipelineDesc pipeDesc(_geo, _shader, "#", renderer.GetRenderPass_SwapChainDepth());
|
||||
PipelineDesc pipeDesc(_geo, _shader, "#", renderer.GetRenderPassHandle_SwapChainDepth());
|
||||
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_ALPHA;
|
||||
pipeDesc._rasterizationState._polygonMode = PolygonMode::line;
|
||||
pipeDesc._topology = PrimitiveTopology::triangleList;
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace verus
|
|||
PIPE_LINES_NO_Z,
|
||||
PIPE_POLY,
|
||||
PIPE_POLY_NO_Z,
|
||||
PIPE_MAX
|
||||
PIPE_COUNT
|
||||
};
|
||||
|
||||
public:
|
||||
|
@ -38,7 +38,7 @@ namespace verus
|
|||
|
||||
GeometryPwn _geo;
|
||||
ShaderPwn _shader;
|
||||
PipelinePwns<PIPE_MAX> _pipe;
|
||||
PipelinePwns<PIPE_COUNT> _pipe;
|
||||
Vector<Vertex> _vDynamicBuffer;
|
||||
UINT64 _currentFrame = UINT64_MAX;
|
||||
const int _maxVerts = 0x10000;
|
||||
|
|
|
@ -27,12 +27,11 @@ void DeferredShading::Init()
|
|||
VERUS_QREF_CONST_SETTINGS;
|
||||
VERUS_QREF_RENDERER;
|
||||
|
||||
_rp = renderer->CreateRenderPass(
|
||||
_rph = renderer->CreateRenderPass(
|
||||
{
|
||||
RP::Attachment("GBuffer0", Format::srgbR8G8B8A8).LoadOpClear().Layout(ImageLayout::fsReadOnly),
|
||||
RP::Attachment("GBuffer1", Format::floatR32).LoadOpClear().Layout(ImageLayout::fsReadOnly),
|
||||
RP::Attachment("GBuffer2", Format::unormR10G10B10A2).LoadOpClear().Layout(ImageLayout::fsReadOnly),
|
||||
RP::Attachment("GBuffer3", Format::unormR8G8B8A8).LoadOpClear().Layout(ImageLayout::fsReadOnly),
|
||||
RP::Attachment("GBuffer1", Format::unormR10G10B10A2).LoadOpClear().Layout(ImageLayout::fsReadOnly),
|
||||
RP::Attachment("GBuffer2", Format::unormR8G8B8A8).LoadOpClear().Layout(ImageLayout::fsReadOnly),
|
||||
RP::Attachment("LightAccDiff", Format::floatR11G11B10).LoadOpClear().Layout(ImageLayout::fsReadOnly),
|
||||
RP::Attachment("LightAccSpec", Format::floatR11G11B10).LoadOpClear().Layout(ImageLayout::fsReadOnly),
|
||||
RP::Attachment("Depth", Format::unormD24uintS8).LoadOpClear().Layout(ImageLayout::depthStencilAttachment),
|
||||
|
@ -42,62 +41,85 @@ void DeferredShading::Init()
|
|||
{
|
||||
RP::Ref("GBuffer0", ImageLayout::colorAttachment),
|
||||
RP::Ref("GBuffer1", ImageLayout::colorAttachment),
|
||||
RP::Ref("GBuffer2", ImageLayout::colorAttachment),
|
||||
RP::Ref("GBuffer3", ImageLayout::colorAttachment)
|
||||
RP::Ref("GBuffer2", ImageLayout::colorAttachment)
|
||||
}).DepthStencil(RP::Ref("Depth", ImageLayout::depthStencilAttachment)),
|
||||
RP::Subpass("Sp1").Input(
|
||||
{
|
||||
RP::Ref("GBuffer0", ImageLayout::fsReadOnly),
|
||||
RP::Ref("GBuffer1", ImageLayout::fsReadOnly),
|
||||
RP::Ref("GBuffer2", ImageLayout::fsReadOnly),
|
||||
RP::Ref("GBuffer3", ImageLayout::fsReadOnly)
|
||||
RP::Ref("Depth", ImageLayout::depthStencilReadOnly)
|
||||
}).Color(
|
||||
{
|
||||
RP::Ref("LightAccDiff", ImageLayout::colorAttachment),
|
||||
RP::Ref("LightAccSpec", ImageLayout::colorAttachment),
|
||||
}).DepthStencil(RP::Ref("Depth", ImageLayout::depthStencilAttachment))
|
||||
}).DepthStencil(RP::Ref("Depth", ImageLayout::depthStencilReadOnly))
|
||||
},
|
||||
{
|
||||
RP::Dependency("Sp0", "Sp1").Mode(1)
|
||||
});
|
||||
_rphCompose = renderer->CreateRenderPass(
|
||||
{
|
||||
RP::Attachment("Composed", Format::floatR11G11B10).LoadOpDontCare().Layout(ImageLayout::fsReadOnly),
|
||||
RP::Attachment("Depth", Format::unormD24uintS8).Layout(ImageLayout::depthStencilAttachment),
|
||||
},
|
||||
{
|
||||
RP::Subpass("Sp0").Color(
|
||||
{
|
||||
RP::Ref("Composed", ImageLayout::colorAttachment)
|
||||
}).DepthStencil(RP::Ref("Depth", ImageLayout::depthStencilReadOnly)),
|
||||
RP::Subpass("Sp1").Color(
|
||||
{
|
||||
RP::Ref("Composed", ImageLayout::colorAttachment)
|
||||
}).DepthStencil(RP::Ref("Depth", ImageLayout::depthStencilAttachment)),
|
||||
},
|
||||
{
|
||||
RP::Dependency("Sp0", "Sp1").Mode(1)
|
||||
});
|
||||
|
||||
_shader[S_LIGHT].Init("[Shaders]:DS.hlsl");
|
||||
_shader[S_LIGHT]->CreateDescriptorSet(0, &s_ubPerFrame, sizeof(s_ubPerFrame));
|
||||
_shader[S_LIGHT]->CreateDescriptorSet(1, &s_ubTexturesFS, sizeof(s_ubTexturesFS), 1,
|
||||
_shader[SHADER_LIGHT].Init("[Shaders]:DS.hlsl");
|
||||
_shader[SHADER_LIGHT]->CreateDescriptorSet(0, &s_ubPerFrame, sizeof(s_ubPerFrame));
|
||||
_shader[SHADER_LIGHT]->CreateDescriptorSet(1, &s_ubTexturesFS, sizeof(s_ubTexturesFS), 1,
|
||||
{
|
||||
Sampler::input,
|
||||
Sampler::input,
|
||||
Sampler::input,
|
||||
Sampler::input,
|
||||
Sampler::shadow,
|
||||
Sampler::nearest2D
|
||||
Sampler::nearestMipN
|
||||
}, CGI::ShaderStageFlags::fs);
|
||||
_shader[S_LIGHT]->CreateDescriptorSet(2, &s_ubPerMeshVS, sizeof(s_ubPerMeshVS), 1000, {}, CGI::ShaderStageFlags::vs);
|
||||
_shader[S_LIGHT]->CreateDescriptorSet(3, &s_ubShadowFS, sizeof(s_ubShadowFS), 1000, {}, CGI::ShaderStageFlags::fs);
|
||||
_shader[S_LIGHT]->CreateDescriptorSet(4, &s_ubPerObject, sizeof(s_ubPerObject), 0);
|
||||
_shader[S_LIGHT]->CreatePipelineLayout();
|
||||
_shader[SHADER_LIGHT]->CreateDescriptorSet(2, &s_ubPerMeshVS, sizeof(s_ubPerMeshVS), 1000, {}, CGI::ShaderStageFlags::vs);
|
||||
_shader[SHADER_LIGHT]->CreateDescriptorSet(3, &s_ubShadowFS, sizeof(s_ubShadowFS), 1000, {}, CGI::ShaderStageFlags::fs);
|
||||
_shader[SHADER_LIGHT]->CreateDescriptorSet(4, &s_ubPerObject, sizeof(s_ubPerObject), 0);
|
||||
_shader[SHADER_LIGHT]->CreatePipelineLayout();
|
||||
|
||||
_shader[S_COMPOSE].Init("[Shaders]:DS_Compose.hlsl");
|
||||
_shader[S_COMPOSE]->CreateDescriptorSet(0, &s_ubComposeVS, sizeof(s_ubComposeVS), 1, {}, CGI::ShaderStageFlags::vs);
|
||||
_shader[S_COMPOSE]->CreateDescriptorSet(1, &s_ubComposeFS, sizeof(s_ubComposeFS), 1,
|
||||
_shader[SHADER_COMPOSE].Init("[Shaders]:DS_Compose.hlsl");
|
||||
_shader[SHADER_COMPOSE]->CreateDescriptorSet(0, &s_ubComposeVS, sizeof(s_ubComposeVS), 2, {}, CGI::ShaderStageFlags::vs);
|
||||
_shader[SHADER_COMPOSE]->CreateDescriptorSet(1, &s_ubComposeFS, sizeof(s_ubComposeFS), 2,
|
||||
{
|
||||
Sampler::nearest2D,
|
||||
Sampler::nearest2D,
|
||||
Sampler::nearest2D,
|
||||
Sampler::nearest2D,
|
||||
Sampler::nearest2D,
|
||||
Sampler::nearest2D
|
||||
Sampler::nearestMipN,
|
||||
Sampler::nearestMipN,
|
||||
Sampler::nearestMipN,
|
||||
Sampler::nearestMipN,
|
||||
Sampler::nearestMipN,
|
||||
Sampler::nearestMipN
|
||||
}, CGI::ShaderStageFlags::fs);
|
||||
_shader[S_COMPOSE]->CreatePipelineLayout();
|
||||
_shader[SHADER_COMPOSE]->CreatePipelineLayout();
|
||||
|
||||
{
|
||||
PipelineDesc pipeDesc(renderer.GetGeoQuad(), _shader[S_COMPOSE], "#", renderer.GetRenderPass_SwapChainDepth());
|
||||
PipelineDesc pipeDesc(renderer.GetGeoQuad(), _shader[SHADER_COMPOSE], "#Compose", _rphCompose);
|
||||
pipeDesc._topology = PrimitiveTopology::triangleStrip;
|
||||
pipeDesc._depthTestEnable = false;
|
||||
_pipe[PIPE_COMPOSE].Init(pipeDesc);
|
||||
}
|
||||
{
|
||||
PipelineDesc pipeDesc(renderer.GetGeoQuad(), renderer.GetShaderQuad(), "#", renderer.GetRenderPass_SwapChainDepth());
|
||||
PipelineDesc pipeDesc(renderer.GetGeoQuad(), _shader[SHADER_COMPOSE], "#ToneMapping", renderer.GetRenderPassHandle_SwapChainDepth());
|
||||
pipeDesc._topology = PrimitiveTopology::triangleStrip;
|
||||
pipeDesc._depthTestEnable = false;
|
||||
_pipe[PIPE_TONE_MAPPING].Init(pipeDesc);
|
||||
}
|
||||
{
|
||||
PipelineDesc pipeDesc(renderer.GetGeoQuad(), renderer.GetShaderQuad(), "#", renderer.GetRenderPassHandle_SwapChainDepth());
|
||||
pipeDesc._topology = PrimitiveTopology::triangleStrip;
|
||||
pipeDesc._depthTestEnable = false;
|
||||
_pipe[PIPE_QUAD].Init(pipeDesc);
|
||||
|
@ -121,39 +143,33 @@ void DeferredShading::InitGBuffers(int w, int h)
|
|||
_tex[TEX_GBUFFER_0].Init(texDesc);
|
||||
|
||||
// GB1:
|
||||
texDesc._clearValue = Vector4(1);
|
||||
texDesc._format = Format::floatR32;
|
||||
texDesc._clearValue = Vector4(0.5f, 0.5f, 0.25f, 0.5f);
|
||||
texDesc._format = Format::unormR10G10B10A2;
|
||||
texDesc._width = w;
|
||||
texDesc._height = h;
|
||||
texDesc._flags = TextureDesc::Flags::colorAttachment | TextureDesc::Flags::inputAttachment;
|
||||
_tex[TEX_GBUFFER_1].Init(texDesc);
|
||||
|
||||
// GB2:
|
||||
texDesc._clearValue = Vector4(0.5f, 0.5f, 0.25f, 0.5f);
|
||||
texDesc._format = Format::unormR10G10B10A2;
|
||||
texDesc._width = w;
|
||||
texDesc._height = h;
|
||||
texDesc._flags = TextureDesc::Flags::colorAttachment | TextureDesc::Flags::inputAttachment;
|
||||
_tex[TEX_GBUFFER_2].Init(texDesc);
|
||||
|
||||
// GB3:
|
||||
texDesc._clearValue = Vector4(1, 1, 1, 1);
|
||||
texDesc._format = Format::unormR8G8B8A8;
|
||||
texDesc._width = w;
|
||||
texDesc._height = h;
|
||||
texDesc._flags = TextureDesc::Flags::colorAttachment | TextureDesc::Flags::inputAttachment;
|
||||
_tex[TEX_GBUFFER_3].Init(texDesc);
|
||||
_tex[TEX_GBUFFER_2].Init(texDesc);
|
||||
}
|
||||
|
||||
void DeferredShading::InitByAtmosphere(TexturePtr texShadow)
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
|
||||
_texShadowAtmo = texShadow;
|
||||
_cshLight = _shader[S_LIGHT]->BindDescriptorSetTextures(1,
|
||||
_cshLight = _shader[SHADER_LIGHT]->BindDescriptorSetTextures(1,
|
||||
{
|
||||
_tex[TEX_GBUFFER_0],
|
||||
_tex[TEX_GBUFFER_1],
|
||||
_tex[TEX_GBUFFER_2],
|
||||
_tex[TEX_GBUFFER_3],
|
||||
renderer.GetTexDepthStencil(),
|
||||
_texShadowAtmo,
|
||||
_texShadowAtmo
|
||||
});
|
||||
|
@ -170,16 +186,18 @@ void DeferredShading::OnSwapChainResized(bool init, bool done)
|
|||
|
||||
if (done)
|
||||
{
|
||||
_shader[S_LIGHT]->FreeDescriptorSet(_cshLight);
|
||||
_shader[SHADER_LIGHT]->FreeDescriptorSet(_cshLight);
|
||||
VERUS_FOR(i, VERUS_COUNT_OF(_cshQuad))
|
||||
renderer.GetShaderQuad()->FreeDescriptorSet(_cshQuad[i]);
|
||||
_shader[S_COMPOSE]->FreeDescriptorSet(_cshCompose);
|
||||
_shader[SHADER_COMPOSE]->FreeDescriptorSet(_cshToneMapping);
|
||||
_shader[SHADER_COMPOSE]->FreeDescriptorSet(_cshCompose);
|
||||
|
||||
renderer->DeleteFramebuffer(_fb);
|
||||
renderer->DeleteFramebuffer(_fbhCompose);
|
||||
renderer->DeleteFramebuffer(_fbh);
|
||||
|
||||
_tex[TEX_COMPOSED].Done();
|
||||
_tex[TEX_LIGHT_ACC_SPEC].Done();
|
||||
_tex[TEX_LIGHT_ACC_DIFF].Done();
|
||||
_tex[TEX_GBUFFER_3].Done();
|
||||
_tex[TEX_GBUFFER_2].Done();
|
||||
_tex[TEX_GBUFFER_1].Done();
|
||||
_tex[TEX_GBUFFER_0].Done();
|
||||
|
@ -198,34 +216,47 @@ void DeferredShading::OnSwapChainResized(bool init, bool done)
|
|||
texDesc._height = renderer.GetSwapChainHeight();
|
||||
texDesc._flags = TextureDesc::Flags::colorAttachment;
|
||||
_tex[TEX_LIGHT_ACC_DIFF].Init(texDesc);
|
||||
texDesc._format = Format::floatR11G11B10;
|
||||
texDesc._width = renderer.GetSwapChainWidth();
|
||||
texDesc._height = renderer.GetSwapChainHeight();
|
||||
texDesc._flags = TextureDesc::Flags::colorAttachment;
|
||||
_tex[TEX_LIGHT_ACC_SPEC].Init(texDesc);
|
||||
_tex[TEX_COMPOSED].Init(texDesc);
|
||||
|
||||
_fb = renderer->CreateFramebuffer(_rp,
|
||||
_fbh = renderer->CreateFramebuffer(_rph,
|
||||
{
|
||||
_tex[TEX_GBUFFER_0],
|
||||
_tex[TEX_GBUFFER_1],
|
||||
_tex[TEX_GBUFFER_2],
|
||||
_tex[TEX_GBUFFER_3],
|
||||
_tex[TEX_LIGHT_ACC_DIFF],
|
||||
_tex[TEX_LIGHT_ACC_SPEC],
|
||||
renderer.GetTexDepthStencil()
|
||||
},
|
||||
renderer.GetSwapChainWidth(),
|
||||
renderer.GetSwapChainHeight());
|
||||
_fbhCompose = renderer->CreateFramebuffer(_rphCompose,
|
||||
{
|
||||
_tex[TEX_COMPOSED],
|
||||
renderer.GetTexDepthStencil()
|
||||
},
|
||||
renderer.GetSwapChainWidth(),
|
||||
renderer.GetSwapChainHeight());
|
||||
|
||||
_cshCompose = _shader[S_COMPOSE]->BindDescriptorSetTextures(1,
|
||||
_cshCompose = _shader[SHADER_COMPOSE]->BindDescriptorSetTextures(1,
|
||||
{
|
||||
_tex[TEX_GBUFFER_0],
|
||||
_tex[TEX_GBUFFER_1],
|
||||
_tex[TEX_GBUFFER_2],
|
||||
_tex[TEX_GBUFFER_3],
|
||||
renderer.GetTexDepthStencil(),
|
||||
_tex[TEX_LIGHT_ACC_DIFF],
|
||||
_tex[TEX_LIGHT_ACC_SPEC]
|
||||
});
|
||||
_cshToneMapping = _shader[SHADER_COMPOSE]->BindDescriptorSetTextures(1,
|
||||
{
|
||||
_tex[TEX_COMPOSED],
|
||||
_tex[TEX_GBUFFER_1],
|
||||
_tex[TEX_GBUFFER_2],
|
||||
_tex[TEX_GBUFFER_0],
|
||||
_tex[TEX_LIGHT_ACC_DIFF],
|
||||
_tex[TEX_LIGHT_ACC_SPEC]
|
||||
});
|
||||
|
||||
VERUS_FOR(i, VERUS_COUNT_OF(_cshQuad))
|
||||
_cshQuad[i] = renderer.GetShaderQuad()->BindDescriptorSetTextures(1, { _tex[TEX_GBUFFER_0 + i] });
|
||||
|
||||
|
@ -313,12 +344,11 @@ void DeferredShading::BeginGeometryPass(bool onlySetRT, bool spriteBaking)
|
|||
_activeGeometryPass = true;
|
||||
_frame = renderer.GetFrameCount();
|
||||
|
||||
renderer.GetCommandBuffer()->BeginRenderPass(_rp, _fb,
|
||||
renderer.GetCommandBuffer()->BeginRenderPass(_rph, _fbh,
|
||||
{
|
||||
_tex[TEX_GBUFFER_0]->GetClearValue(),
|
||||
_tex[TEX_GBUFFER_1]->GetClearValue(),
|
||||
_tex[TEX_GBUFFER_2]->GetClearValue(),
|
||||
_tex[TEX_GBUFFER_3]->GetClearValue(),
|
||||
_tex[TEX_LIGHT_ACC_DIFF]->GetClearValue(),
|
||||
_tex[TEX_LIGHT_ACC_SPEC]->GetClearValue(),
|
||||
renderer.GetTexDepthStencil()->GetClearValue()
|
||||
|
@ -342,7 +372,7 @@ bool DeferredShading::BeginLightingPass()
|
|||
_activeLightingPass = true;
|
||||
|
||||
renderer.GetCommandBuffer()->NextSubpass();
|
||||
_shader[S_LIGHT]->BeginBindDescriptors();
|
||||
_shader[SHADER_LIGHT]->BeginBindDescriptors();
|
||||
|
||||
if (!IsLoaded())
|
||||
return false;
|
||||
|
@ -355,7 +385,7 @@ bool DeferredShading::BeginLightingPass()
|
|||
Scene::RDeferredLights dl = helpers.GetDeferredLights();
|
||||
|
||||
{
|
||||
PipelineDesc pipeDesc(dl.Get(CGI::LightType::dir).GetGeometry(), _shader[S_LIGHT], "#InstancedDir", _rp, 1);
|
||||
PipelineDesc pipeDesc(dl.Get(CGI::LightType::dir).GetGeometry(), _shader[SHADER_LIGHT], "#InstancedDir", _rph, 1);
|
||||
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_ADD;
|
||||
pipeDesc._colorAttachBlendEqs[1] = VERUS_COLOR_BLEND_ADD;
|
||||
pipeDesc._vertexInputBindingsFilter = (1 << 0) | (1 << 4);
|
||||
|
@ -363,7 +393,7 @@ bool DeferredShading::BeginLightingPass()
|
|||
_pipe[PIPE_INSTANCED_DIR].Init(pipeDesc);
|
||||
}
|
||||
{
|
||||
PipelineDesc pipeDesc(dl.Get(CGI::LightType::omni).GetGeometry(), _shader[S_LIGHT], "#InstancedOmni", _rp, 1);
|
||||
PipelineDesc pipeDesc(dl.Get(CGI::LightType::omni).GetGeometry(), _shader[SHADER_LIGHT], "#InstancedOmni", _rph, 1);
|
||||
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_ADD;
|
||||
pipeDesc._colorAttachBlendEqs[1] = VERUS_COLOR_BLEND_ADD;
|
||||
pipeDesc._rasterizationState._cullMode = CullMode::front;
|
||||
|
@ -373,7 +403,7 @@ bool DeferredShading::BeginLightingPass()
|
|||
_pipe[PIPE_INSTANCED_OMNI].Init(pipeDesc);
|
||||
}
|
||||
{
|
||||
PipelineDesc pipeDesc(dl.Get(CGI::LightType::spot).GetGeometry(), _shader[S_LIGHT], "#InstancedSpot", _rp, 1);
|
||||
PipelineDesc pipeDesc(dl.Get(CGI::LightType::spot).GetGeometry(), _shader[SHADER_LIGHT], "#InstancedSpot", _rph, 1);
|
||||
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_ADD;
|
||||
pipeDesc._colorAttachBlendEqs[1] = VERUS_COLOR_BLEND_ADD;
|
||||
pipeDesc._rasterizationState._cullMode = CullMode::front;
|
||||
|
@ -394,28 +424,71 @@ void DeferredShading::EndLightingPass()
|
|||
VERUS_RT_ASSERT(!_activeGeometryPass && _activeLightingPass);
|
||||
_activeLightingPass = false;
|
||||
|
||||
_shader[S_LIGHT]->EndBindDescriptors();
|
||||
_shader[SHADER_LIGHT]->EndBindDescriptors();
|
||||
renderer.GetCommandBuffer()->EndRenderPass();
|
||||
}
|
||||
|
||||
void DeferredShading::Compose(RcVector4 bgColor)
|
||||
void DeferredShading::BeginCompose(RcVector4 bgColor)
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
VERUS_QREF_SM;
|
||||
VERUS_QREF_ATMO;
|
||||
|
||||
renderer.GetCommandBuffer()->BeginRenderPass(_rphCompose, _fbhCompose,
|
||||
{
|
||||
_tex[TEX_COMPOSED]->GetClearValue(),
|
||||
renderer.GetTexDepthStencil()->GetClearValue()
|
||||
});
|
||||
|
||||
renderer.GetCommandBuffer()->BindPipeline(_pipe[PIPE_COMPOSE]);
|
||||
|
||||
_shader[S_COMPOSE]->BeginBindDescriptors();
|
||||
const Matrix4 matInvVP = VMath::inverse(sm.GetCamera()->GetMatrixVP());
|
||||
|
||||
_shader[SHADER_COMPOSE]->BeginBindDescriptors();
|
||||
s_ubComposeVS._matW = Math::QuadMatrix().UniformBufferFormat();
|
||||
s_ubComposeVS._matV = Math::ToUVMatrix().UniformBufferFormat();
|
||||
s_ubComposeFS._matInvV = sm.GetCamera()->GetMatrixVi().UniformBufferFormat();
|
||||
s_ubComposeFS._colorAmbient = Vector4(0.1f, 0.1f, 0.2f, 1).GLM();
|
||||
s_ubComposeFS._matInvVP = matInvVP.UniformBufferFormat();
|
||||
s_ubComposeFS._colorAmbient = float4(atmo.GetAmbientColor().GLM(), 0);
|
||||
s_ubComposeFS._colorBackground = bgColor.GLM();
|
||||
s_ubComposeFS._fogColor = Vector4(atmo.GetFogColor(), atmo.GetFogDensity()).GLM();
|
||||
s_ubComposeFS._zNearFarEx = sm.GetCamera()->GetZNearFarEx().GLM();
|
||||
memcpy(&s_ubComposeFS._toneMappingConfig.x, &_toneMappingConfig, sizeof(_toneMappingConfig));
|
||||
renderer.GetCommandBuffer()->BindDescriptors(_shader[SHADER_COMPOSE], 0);
|
||||
renderer.GetCommandBuffer()->BindDescriptors(_shader[SHADER_COMPOSE], 1, _cshCompose);
|
||||
_shader[SHADER_COMPOSE]->EndBindDescriptors();
|
||||
|
||||
renderer.DrawQuad();
|
||||
|
||||
renderer.GetCommandBuffer()->NextSubpass();
|
||||
}
|
||||
|
||||
void DeferredShading::EndCompose()
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
|
||||
renderer.GetCommandBuffer()->EndRenderPass();
|
||||
}
|
||||
|
||||
void DeferredShading::ToneMapping()
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
VERUS_QREF_SM;
|
||||
VERUS_QREF_ATMO;
|
||||
|
||||
renderer.GetCommandBuffer()->BindPipeline(_pipe[PIPE_TONE_MAPPING]);
|
||||
|
||||
_shader[SHADER_COMPOSE]->BeginBindDescriptors();
|
||||
s_ubComposeVS._matW = Math::QuadMatrix().UniformBufferFormat();
|
||||
s_ubComposeVS._matV = Math::ToUVMatrix().UniformBufferFormat();
|
||||
s_ubComposeFS._matInvV = sm.GetCamera()->GetMatrixVi().UniformBufferFormat();
|
||||
s_ubComposeFS._colorAmbient = float4(atmo.GetAmbientColor().GLM(), 0);
|
||||
s_ubComposeFS._fogColor = Vector4(0.5f, 0.5f, 0.5f, 0.002f).GLM();
|
||||
s_ubComposeFS._zNearFarEx = sm.GetCamera()->GetZNearFarEx().GLM();
|
||||
renderer.GetCommandBuffer()->BindDescriptors(_shader[S_COMPOSE], 0);
|
||||
renderer.GetCommandBuffer()->BindDescriptors(_shader[S_COMPOSE], 1, _cshCompose);
|
||||
_shader[S_COMPOSE]->EndBindDescriptors();
|
||||
memcpy(&s_ubComposeFS._toneMappingConfig.x, &_toneMappingConfig, sizeof(_toneMappingConfig));
|
||||
renderer.GetCommandBuffer()->BindDescriptors(_shader[SHADER_COMPOSE], 0);
|
||||
renderer.GetCommandBuffer()->BindDescriptors(_shader[SHADER_COMPOSE], 1, _cshToneMapping);
|
||||
_shader[SHADER_COMPOSE]->EndBindDescriptors();
|
||||
|
||||
renderer.DrawQuad();
|
||||
}
|
||||
|
@ -437,36 +510,38 @@ void DeferredShading::OnNewLightType(LightType type, bool wireframe)
|
|||
VERUS_QREF_RENDERER;
|
||||
VERUS_QREF_ATMO;
|
||||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case CGI::LightType::dir:
|
||||
{
|
||||
renderer.GetCommandBuffer()->BindPipeline(_pipe[PIPE_INSTANCED_DIR]);
|
||||
cb->BindPipeline(_pipe[PIPE_INSTANCED_DIR]);
|
||||
}
|
||||
break;
|
||||
case CGI::LightType::omni:
|
||||
{
|
||||
renderer.GetCommandBuffer()->BindPipeline(_pipe[PIPE_INSTANCED_OMNI]);
|
||||
cb->BindPipeline(_pipe[PIPE_INSTANCED_OMNI]);
|
||||
}
|
||||
break;
|
||||
case CGI::LightType::spot:
|
||||
{
|
||||
renderer.GetCommandBuffer()->BindPipeline(_pipe[PIPE_INSTANCED_SPOT]);
|
||||
cb->BindPipeline(_pipe[PIPE_INSTANCED_SPOT]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
renderer.GetCommandBuffer()->BindDescriptors(_shader[S_LIGHT], 0);
|
||||
renderer.GetCommandBuffer()->BindDescriptors(_shader[S_LIGHT], 1, _cshLight);
|
||||
cb->BindDescriptors(_shader[SHADER_LIGHT], 0);
|
||||
cb->BindDescriptors(_shader[SHADER_LIGHT], 1, _cshLight);
|
||||
|
||||
// Shadow:
|
||||
s_ubShadowFS._matSunShadow = atmo.GetShadowMap().GetShadowMatrixDS(0).UniformBufferFormat();
|
||||
s_ubShadowFS._matSunShadowCSM1 = atmo.GetShadowMap().GetShadowMatrixDS(1).UniformBufferFormat();
|
||||
s_ubShadowFS._matSunShadowCSM2 = atmo.GetShadowMap().GetShadowMatrixDS(2).UniformBufferFormat();
|
||||
s_ubShadowFS._matSunShadowCSM3 = atmo.GetShadowMap().GetShadowMatrixDS(3).UniformBufferFormat();
|
||||
s_ubShadowFS._shadowConfig = atmo.GetShadowMap().GetConfig().GLM();
|
||||
memcpy(&s_ubShadowFS._shadowConfig, &atmo.GetShadowMap().GetConfig(), sizeof(s_ubShadowFS._shadowConfig));
|
||||
s_ubShadowFS._splitRanges = atmo.GetShadowMap().GetSplitRanges().GLM();
|
||||
renderer.GetCommandBuffer()->BindDescriptors(_shader[S_LIGHT], 3);
|
||||
cb->BindDescriptors(_shader[SHADER_LIGHT], 3);
|
||||
}
|
||||
|
||||
void DeferredShading::UpdateUniformBufferPerFrame()
|
||||
|
@ -486,7 +561,7 @@ void DeferredShading::UpdateUniformBufferPerFrame()
|
|||
void DeferredShading::BindDescriptorsPerMeshVS()
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
renderer.GetCommandBuffer()->BindDescriptors(_shader[S_LIGHT], 2);
|
||||
renderer.GetCommandBuffer()->BindDescriptors(_shader[SHADER_LIGHT], 2);
|
||||
}
|
||||
|
||||
void DeferredShading::Load()
|
||||
|
|
|
@ -17,11 +17,11 @@ namespace verus
|
|||
#include "../Shaders/DS.inc.hlsl"
|
||||
#include "../Shaders/DS_Compose.inc.hlsl"
|
||||
|
||||
enum S
|
||||
enum SHADER
|
||||
{
|
||||
S_LIGHT,
|
||||
S_COMPOSE,
|
||||
S_MAX
|
||||
SHADER_LIGHT,
|
||||
SHADER_COMPOSE,
|
||||
SHADER_COUNT
|
||||
};
|
||||
|
||||
enum PIPE
|
||||
|
@ -30,19 +30,20 @@ namespace verus
|
|||
PIPE_INSTANCED_OMNI,
|
||||
PIPE_INSTANCED_SPOT,
|
||||
PIPE_COMPOSE,
|
||||
PIPE_TONE_MAPPING,
|
||||
PIPE_QUAD,
|
||||
PIPE_MAX
|
||||
PIPE_COUNT
|
||||
};
|
||||
|
||||
enum TEX
|
||||
{
|
||||
TEX_GBUFFER_0, // Albedo RGB, A = motion blur.
|
||||
TEX_GBUFFER_1, // Depth.
|
||||
TEX_GBUFFER_2, // RG - Normals in screen space, Emission, Metallicity.
|
||||
TEX_GBUFFER_3, // LamScale, LamBias, Specular, Gloss.
|
||||
TEX_GBUFFER_0, // Albedo, Spec.
|
||||
TEX_GBUFFER_1, // RG - Normals, Emission, Motion.
|
||||
TEX_GBUFFER_2, // LamScale, LamBias, Metallicity, Gloss.
|
||||
TEX_LIGHT_ACC_DIFF,
|
||||
TEX_LIGHT_ACC_SPEC,
|
||||
TEX_MAX
|
||||
TEX_COMPOSED,
|
||||
TEX_COUNT
|
||||
};
|
||||
|
||||
static UB_PerFrame s_ubPerFrame;
|
||||
|
@ -53,21 +54,31 @@ namespace verus
|
|||
static UB_ComposeVS s_ubComposeVS;
|
||||
static UB_ComposeFS s_ubComposeFS;
|
||||
|
||||
ShaderPwns<S_MAX> _shader;
|
||||
PipelinePwns<PIPE_MAX> _pipe;
|
||||
TexturePwns<TEX_MAX> _tex;
|
||||
ShaderPwns<SHADER_COUNT> _shader;
|
||||
PipelinePwns<PIPE_COUNT> _pipe;
|
||||
TexturePwns<TEX_COUNT> _tex;
|
||||
TexturePtr _texShadowAtmo;
|
||||
UINT64 _frame = 0;
|
||||
int _rp = -1;
|
||||
int _fb = -1;
|
||||
int _cshLight = -1;
|
||||
int _cshCompose = -1;
|
||||
int _cshQuad[6];
|
||||
RPHandle _rph;
|
||||
RPHandle _rphCompose;
|
||||
FBHandle _fbh;
|
||||
FBHandle _fbhCompose;
|
||||
CSHandle _cshLight;
|
||||
CSHandle _cshCompose;
|
||||
CSHandle _cshToneMapping;
|
||||
CSHandle _cshQuad[6];
|
||||
bool _activeGeometryPass = false;
|
||||
bool _activeLightingPass = false;
|
||||
bool _async_initPipe = false;
|
||||
|
||||
public:
|
||||
struct ToneMappingConfig
|
||||
{
|
||||
float _exposure = 0.005f;
|
||||
float _filmicLook = 0.5f;
|
||||
float _albedoScale = 0.5f;
|
||||
} _toneMappingConfig;
|
||||
|
||||
DeferredShading();
|
||||
~DeferredShading();
|
||||
|
||||
|
@ -85,13 +96,17 @@ namespace verus
|
|||
bool IsActiveGeometryPass() const { return _activeGeometryPass; }
|
||||
bool IsActiveLightingPass() const { return _activeLightingPass; }
|
||||
|
||||
int GetRenderPassHandle() const { return _rp; }
|
||||
RPHandle GetRenderPassHandle() const { return _rph; }
|
||||
RPHandle GetRenderPassHandle_Compose() const { return _rphCompose; }
|
||||
int GetSubpass_Compose() const { return 1; }
|
||||
|
||||
void BeginGeometryPass(bool onlySetRT = false, bool spriteBaking = false);
|
||||
void EndGeometryPass(bool resetRT = false);
|
||||
bool BeginLightingPass();
|
||||
void EndLightingPass();
|
||||
void Compose(RcVector4 bgColor = Vector4(0));
|
||||
void BeginCompose(RcVector4 bgColor = Vector4(0));
|
||||
void EndCompose();
|
||||
void ToneMapping();
|
||||
void AntiAliasing();
|
||||
|
||||
static bool IsLightUrl(CSZ url);
|
||||
|
|
|
@ -52,35 +52,15 @@ void Renderer::Init(PRendererDelegate pDelegate)
|
|||
|
||||
_commandBuffer.Init();
|
||||
|
||||
GeometryDesc geoDesc;
|
||||
const InputElementDesc ied[] =
|
||||
_rphSwapChain = _pBaseRenderer->CreateRenderPass(
|
||||
{
|
||||
{0, offsetof(Vertex, _pos), IeType::floats, 2, IeUsage::position, 0},
|
||||
InputElementDesc::End()
|
||||
};
|
||||
geoDesc._pInputElementDesc = ied;
|
||||
const int strides[] = { sizeof(Vertex), 0 };
|
||||
geoDesc._pStrides = strides;
|
||||
_geoQuad.Init(geoDesc);
|
||||
|
||||
_shader[S_GENERATE_MIPS].Init("[Shaders]:GenerateMips.hlsl");
|
||||
_shader[S_GENERATE_MIPS]->CreateDescriptorSet(0, &_ubGenerateMips, sizeof(_ubGenerateMips), 100,
|
||||
{ Sampler::linearClamp2D, Sampler::storage, Sampler::storage, Sampler::storage, Sampler::storage }, ShaderStageFlags::cs);
|
||||
_shader[S_GENERATE_MIPS]->CreatePipelineLayout();
|
||||
|
||||
_shader[S_QUAD].Init("[Shaders]:Quad.hlsl");
|
||||
_shader[S_QUAD]->CreateDescriptorSet(0, &_ubQuadVS, sizeof(_ubQuadVS), 100, {}, ShaderStageFlags::vs);
|
||||
_shader[S_QUAD]->CreateDescriptorSet(1, &_ubQuadFS, sizeof(_ubQuadFS), 100, { Sampler::linearClamp2D }, ShaderStageFlags::fs);
|
||||
_shader[S_QUAD]->CreatePipelineLayout();
|
||||
|
||||
PipelineDesc pipeDesc(_shader[S_GENERATE_MIPS], "#");
|
||||
_pipeGenerateMips.Init(pipeDesc);
|
||||
|
||||
_rpSwapChain = _pBaseRenderer->CreateRenderPass(
|
||||
{ RP::Attachment("Color", Format::srgbB8G8R8A8).LoadOpClear().Layout(ImageLayout::undefined, ImageLayout::presentSrc) },
|
||||
{ RP::Subpass("Sp0").Color({RP::Ref("Color", ImageLayout::colorAttachment)}) },
|
||||
RP::Attachment("Color", Format::srgbB8G8R8A8).LoadOpClear().Layout(ImageLayout::undefined, ImageLayout::presentSrc)
|
||||
},
|
||||
{
|
||||
RP::Subpass("Sp0").Color({RP::Ref("Color", ImageLayout::colorAttachment)})
|
||||
},
|
||||
{});
|
||||
_rpSwapChainDepth = _pBaseRenderer->CreateRenderPass(
|
||||
_rphSwapChainDepth = _pBaseRenderer->CreateRenderPass(
|
||||
{
|
||||
RP::Attachment("Color", Format::srgbB8G8R8A8).LoadOpClear().Layout(ImageLayout::undefined, ImageLayout::presentSrc),
|
||||
RP::Attachment("Depth", Format::unormD24uintS8).Layout(ImageLayout::depthStencilAttachment),
|
||||
|
@ -93,9 +73,40 @@ void Renderer::Init(PRendererDelegate pDelegate)
|
|||
},
|
||||
{});
|
||||
|
||||
GeometryDesc geoDesc;
|
||||
const VertexInputAttrDesc viaDesc[] =
|
||||
{
|
||||
{0, offsetof(Vertex, _pos), IeType::floats, 2, IeUsage::position, 0},
|
||||
VertexInputAttrDesc::End()
|
||||
};
|
||||
geoDesc._pVertexInputAttrDesc = viaDesc;
|
||||
const int strides[] = { sizeof(Vertex), 0 };
|
||||
geoDesc._pStrides = strides;
|
||||
_geoQuad.Init(geoDesc);
|
||||
|
||||
_shader[S_GENERATE_MIPS].Init("[Shaders]:GenerateMips.hlsl");
|
||||
_shader[S_GENERATE_MIPS]->CreateDescriptorSet(0, &_ubGenerateMips, sizeof(_ubGenerateMips), 100,
|
||||
{
|
||||
Sampler::linearClampMipN,
|
||||
Sampler::storage,
|
||||
Sampler::storage,
|
||||
Sampler::storage,
|
||||
Sampler::storage
|
||||
},
|
||||
ShaderStageFlags::cs);
|
||||
_shader[S_GENERATE_MIPS]->CreatePipelineLayout();
|
||||
|
||||
_shader[S_QUAD].Init("[Shaders]:Quad.hlsl");
|
||||
_shader[S_QUAD]->CreateDescriptorSet(0, &_ubQuadVS, sizeof(_ubQuadVS), 100, {}, ShaderStageFlags::vs);
|
||||
_shader[S_QUAD]->CreateDescriptorSet(1, &_ubQuadFS, sizeof(_ubQuadFS), 100, { Sampler::linearClampMipN }, ShaderStageFlags::fs);
|
||||
_shader[S_QUAD]->CreatePipelineLayout();
|
||||
|
||||
PipelineDesc pipeDesc(_shader[S_GENERATE_MIPS], "#");
|
||||
_pipeGenerateMips.Init(pipeDesc);
|
||||
|
||||
OnSwapChainResized(true, false);
|
||||
|
||||
_pBaseRenderer->ImGuiInit(_rpSwapChainDepth);
|
||||
_pBaseRenderer->ImGuiInit(_rphSwapChainDepth);
|
||||
ImGuiUpdateStyle();
|
||||
|
||||
_ds.Init();
|
||||
|
@ -126,6 +137,7 @@ void Renderer::Done()
|
|||
_geoQuad.Done();
|
||||
_commandBuffer.Done();
|
||||
|
||||
Scene::Grass::DoneStatic();
|
||||
Scene::Terrain::DoneStatic();
|
||||
Scene::Mesh::DoneStatic();
|
||||
|
||||
|
@ -151,7 +163,7 @@ void Renderer::Present()
|
|||
_frameCount++;
|
||||
|
||||
VERUS_QREF_TIMER;
|
||||
_fps = _fps * 0.75f + timer.GetDeltaTimeInv() * 0.25f;
|
||||
_fps = Math::Lerp(_fps, timer.GetDeltaTimeInv(), 0.25f);
|
||||
}
|
||||
|
||||
void Renderer::OnWindowResized(int w, int h)
|
||||
|
@ -170,10 +182,10 @@ void Renderer::OnSwapChainResized(bool init, bool done)
|
|||
{
|
||||
if (done)
|
||||
{
|
||||
VERUS_FOR(i, _fbSwapChainDepth.size())
|
||||
_pBaseRenderer->DeleteFramebuffer(_fbSwapChainDepth[i]);
|
||||
VERUS_FOR(i, _fbSwapChain.size())
|
||||
_pBaseRenderer->DeleteFramebuffer(_fbSwapChain[i]);
|
||||
VERUS_FOR(i, _fbhSwapChainDepth.size())
|
||||
_pBaseRenderer->DeleteFramebuffer(_fbhSwapChainDepth[i]);
|
||||
VERUS_FOR(i, _fbhSwapChain.size())
|
||||
_pBaseRenderer->DeleteFramebuffer(_fbhSwapChain[i]);
|
||||
|
||||
_texDepthStencil.Done();
|
||||
}
|
||||
|
@ -185,14 +197,15 @@ void Renderer::OnSwapChainResized(bool init, bool done)
|
|||
texDesc._format = Format::unormD24uintS8;
|
||||
texDesc._width = _swapChainWidth;
|
||||
texDesc._height = _swapChainHeight;
|
||||
texDesc._flags = TextureDesc::Flags::inputAttachment | TextureDesc::Flags::depthSampledW;
|
||||
_texDepthStencil.Init(texDesc);
|
||||
|
||||
_fbSwapChain.resize(_pBaseRenderer->GetSwapChainBufferCount());
|
||||
VERUS_FOR(i, _fbSwapChain.size())
|
||||
_fbSwapChain[i] = _pBaseRenderer->CreateFramebuffer(_rpSwapChain, {}, _swapChainWidth, _swapChainHeight, i);
|
||||
_fbSwapChainDepth.resize(_pBaseRenderer->GetSwapChainBufferCount());
|
||||
VERUS_FOR(i, _fbSwapChainDepth.size())
|
||||
_fbSwapChainDepth[i] = _pBaseRenderer->CreateFramebuffer(_rpSwapChainDepth, { _texDepthStencil }, _swapChainWidth, _swapChainHeight, i);
|
||||
_fbhSwapChain.resize(_pBaseRenderer->GetSwapChainBufferCount());
|
||||
VERUS_FOR(i, _fbhSwapChain.size())
|
||||
_fbhSwapChain[i] = _pBaseRenderer->CreateFramebuffer(_rphSwapChain, {}, _swapChainWidth, _swapChainHeight, i);
|
||||
_fbhSwapChainDepth.resize(_pBaseRenderer->GetSwapChainBufferCount());
|
||||
VERUS_FOR(i, _fbhSwapChainDepth.size())
|
||||
_fbhSwapChainDepth[i] = _pBaseRenderer->CreateFramebuffer(_rphSwapChainDepth, { _texDepthStencil }, _swapChainWidth, _swapChainHeight, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,10 +44,10 @@ namespace verus
|
|||
int _swapChainWidth = 0;
|
||||
int _swapChainHeight = 0;
|
||||
float _fps = 30;
|
||||
int _rpSwapChain = 0;
|
||||
int _rpSwapChainDepth = 0;
|
||||
Vector<int> _fbSwapChain;
|
||||
Vector<int> _fbSwapChainDepth;
|
||||
RPHandle _rphSwapChain;
|
||||
RPHandle _rphSwapChainDepth;
|
||||
Vector<FBHandle> _fbhSwapChain;
|
||||
Vector<FBHandle> _fbhSwapChainDepth;
|
||||
UB_GenerateMips _ubGenerateMips;
|
||||
UB_QuadVS _ubQuadVS;
|
||||
UB_QuadFS _ubQuadFS;
|
||||
|
@ -78,16 +78,17 @@ namespace verus
|
|||
|
||||
RDeferredShading GetDS() { return _ds; }
|
||||
CommandBufferPtr GetCommandBuffer() const { return _commandBuffer; }
|
||||
GeometryPtr GetGeoQuad() const { return _geoQuad; }
|
||||
TexturePtr GetTexDepthStencil() const { return _texDepthStencil; }
|
||||
|
||||
void OnShaderError(CSZ s);
|
||||
void OnShaderWarning(CSZ s);
|
||||
|
||||
// Window:
|
||||
App::PWindow GetMainWindow() const { return _pMainWindow; }
|
||||
App::PWindow SetMainWindow(App::PWindow p) { return Utils::Swap(_pMainWindow, p); }
|
||||
float GetSwapChainAspectRatio() const;
|
||||
|
||||
// ImGui:
|
||||
virtual void ImGuiSetCurrentContext(ImGuiContext* pContext);
|
||||
void ImGuiUpdateStyle();
|
||||
|
||||
|
@ -95,15 +96,19 @@ namespace verus
|
|||
float GetFps() const { return _fps; }
|
||||
UINT64 GetFrameCount() const { return _frameCount; }
|
||||
|
||||
int GetRenderPass_SwapChain() const { return _rpSwapChain; }
|
||||
int GetRenderPass_SwapChainDepth() const { return _rpSwapChainDepth; }
|
||||
int GetFramebuffer_SwapChain(int index) const { return _fbSwapChain[index]; }
|
||||
int GetFramebuffer_SwapChainDepth(int index) const { return _fbSwapChainDepth[index]; }
|
||||
// RenderPass & Framebuffer:
|
||||
RPHandle GetRenderPassHandle_SwapChain() const { return _rphSwapChain; }
|
||||
RPHandle GetRenderPassHandle_SwapChainDepth() const { return _rphSwapChainDepth; }
|
||||
FBHandle GetFramebufferHandle_SwapChain(int index) const { return _fbhSwapChain[index]; }
|
||||
FBHandle GetFramebufferHandle_SwapChainDepth(int index) const { return _fbhSwapChainDepth[index]; }
|
||||
|
||||
// Generate mips:
|
||||
PipelinePtr GetPipelineGenerateMips() { return _pipeGenerateMips; }
|
||||
ShaderPtr GetShaderGenerateMips() { return _shader[S_GENERATE_MIPS]; }
|
||||
UB_GenerateMips& GetUbGenerateMips() { return _ubGenerateMips; }
|
||||
|
||||
// Quad:
|
||||
GeometryPtr GetGeoQuad() const { return _geoQuad; }
|
||||
ShaderPtr GetShaderQuad() { return _shader[S_QUAD]; }
|
||||
UB_QuadVS& GetUbQuadVS() { return _ubQuadVS; }
|
||||
UB_QuadFS& GetUbQuadFS() { return _ubQuadFS; }
|
||||
|
|
48
Verus/src/CGI/TextureRAM.cpp
Normal file
48
Verus/src/CGI/TextureRAM.cpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
#include "verus.h"
|
||||
|
||||
using namespace verus;
|
||||
using namespace verus::CGI;
|
||||
|
||||
TextureRAM::TextureRAM()
|
||||
{
|
||||
}
|
||||
|
||||
TextureRAM::~TextureRAM()
|
||||
{
|
||||
Done();
|
||||
}
|
||||
|
||||
void TextureRAM::Init(RcTextureDesc desc)
|
||||
{
|
||||
VERUS_INIT();
|
||||
VERUS_RT_ASSERT(desc._width > 0 && desc._height > 0);
|
||||
VERUS_QREF_RENDERER;
|
||||
|
||||
_size = Vector4(
|
||||
float(desc._width),
|
||||
float(desc._height),
|
||||
1.f / desc._width,
|
||||
1.f / desc._height);
|
||||
_desc = desc;
|
||||
_desc._mipLevels = desc._mipLevels ? desc._mipLevels : Math::ComputeMipLevels(desc._width, desc._height, desc._depth);
|
||||
_bytesPerPixel = FormatToBytesPerPixel(desc._format);
|
||||
|
||||
_vBuffer.resize(_desc._width * _desc._height * _bytesPerPixel);
|
||||
}
|
||||
|
||||
void TextureRAM::Done()
|
||||
{
|
||||
VERUS_DONE(TextureRAM);
|
||||
}
|
||||
|
||||
void TextureRAM::UpdateSubresource(const void* p, int mipLevel, int arrayLayer, PBaseCommandBuffer pCB)
|
||||
{
|
||||
if (mipLevel || arrayLayer)
|
||||
return;
|
||||
memcpy(_vBuffer.data(), p, _vBuffer.size());
|
||||
}
|
||||
|
||||
void TextureRAM::GenerateMips(PBaseCommandBuffer pCB)
|
||||
{
|
||||
VERUS_RT_ASSERT(__FUNCTION__);
|
||||
}
|
26
Verus/src/CGI/TextureRAM.h
Normal file
26
Verus/src/CGI/TextureRAM.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
|
||||
namespace verus
|
||||
{
|
||||
namespace CGI
|
||||
{
|
||||
class TextureRAM : public BaseTexture
|
||||
{
|
||||
Vector<BYTE> _vBuffer;
|
||||
|
||||
public:
|
||||
TextureRAM();
|
||||
virtual ~TextureRAM() override;
|
||||
|
||||
virtual void Init(RcTextureDesc desc) override;
|
||||
virtual void Done() override;
|
||||
|
||||
virtual void UpdateSubresource(const void* p, int mipLevel, int arrayLayer, PBaseCommandBuffer pCB) override;
|
||||
|
||||
virtual void GenerateMips(PBaseCommandBuffer pCB) override;
|
||||
|
||||
const BYTE* GetData() const { VERUS_RT_ASSERT(IsLoaded()); return _vBuffer.data(); }
|
||||
};
|
||||
VERUS_TYPEDEFS(TextureRAM);
|
||||
}
|
||||
}
|
|
@ -37,7 +37,9 @@ namespace verus
|
|||
lineList,
|
||||
lineStrip,
|
||||
triangleList,
|
||||
triangleStrip
|
||||
triangleStrip,
|
||||
patchList3,
|
||||
patchList4
|
||||
};
|
||||
|
||||
struct PipelineRasterizationState
|
||||
|
@ -72,7 +74,9 @@ namespace verus
|
|||
gs = (1 << 3),
|
||||
fs = (1 << 4),
|
||||
cs = (1 << 5),
|
||||
vs_fs = vs | fs
|
||||
vs_fs = vs | fs,
|
||||
vs_hs_ds = vs | hs | ds,
|
||||
vs_hs_ds_fs = vs | hs | ds | fs
|
||||
};
|
||||
|
||||
enum class IeType : int
|
||||
|
@ -82,22 +86,24 @@ namespace verus
|
|||
shorts
|
||||
};
|
||||
|
||||
// See: https://docs.microsoft.com/en-us/windows/desktop/direct3d9/d3ddeclusage
|
||||
// See: https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3ddeclusage
|
||||
enum class IeUsage : int
|
||||
{
|
||||
position,
|
||||
blendWeight,
|
||||
blendWeights,
|
||||
blendIndices,
|
||||
normal,
|
||||
psize,
|
||||
texCoord,
|
||||
tangent,
|
||||
binormal,
|
||||
color
|
||||
color,
|
||||
psize,
|
||||
texCoord,
|
||||
instData,
|
||||
attr
|
||||
};
|
||||
|
||||
// See: https://docs.microsoft.com/en-us/windows/desktop/direct3d9/d3dvertexelement9
|
||||
struct InputElementDesc
|
||||
// See: https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dvertexelement9
|
||||
struct VertexInputAttrDesc
|
||||
{
|
||||
int _binding;
|
||||
int _offset;
|
||||
|
@ -106,9 +112,9 @@ namespace verus
|
|||
IeUsage _usage;
|
||||
int _usageIndex;
|
||||
|
||||
static constexpr InputElementDesc End() { return { -1, -1, IeType::floats, 0, IeUsage::position, 0 }; }
|
||||
static constexpr VertexInputAttrDesc End() { return { -1, -1, IeType::floats, 0, IeUsage::position, 0 }; }
|
||||
};
|
||||
VERUS_TYPEDEFS(InputElementDesc);
|
||||
VERUS_TYPEDEFS(VertexInputAttrDesc);
|
||||
|
||||
enum class Sampler : int
|
||||
{
|
||||
|
@ -117,15 +123,51 @@ namespace verus
|
|||
input,
|
||||
shadow,
|
||||
aniso, // Most common sampler for 3D.
|
||||
linear3D,
|
||||
nearest3D,
|
||||
linear2D,
|
||||
nearest2D,
|
||||
linearClamp3D,
|
||||
nearestClamp3D,
|
||||
linearClamp2D,
|
||||
nearestClamp2D,
|
||||
linearMipL,
|
||||
nearestMipL,
|
||||
linearMipN,
|
||||
nearestMipN,
|
||||
linearClampMipL,
|
||||
nearestClampMipL,
|
||||
linearClampMipN,
|
||||
nearestClampMipN,
|
||||
count
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class BaseHandle
|
||||
{
|
||||
int _h = -1;
|
||||
|
||||
protected:
|
||||
static T Make(int value)
|
||||
{
|
||||
T ret;
|
||||
ret._h = value;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public:
|
||||
int Get() const { return _h; }
|
||||
bool IsSet() const { return _h >= 0; }
|
||||
};
|
||||
|
||||
class RPHandle : public BaseHandle<RPHandle>
|
||||
{
|
||||
public:
|
||||
static RPHandle Make(int value) { return BaseHandle::Make(value); }
|
||||
};
|
||||
|
||||
class FBHandle : public BaseHandle<FBHandle>
|
||||
{
|
||||
public:
|
||||
static FBHandle Make(int value) { return BaseHandle::Make(value); }
|
||||
};
|
||||
|
||||
class CSHandle : public BaseHandle<CSHandle>
|
||||
{
|
||||
public:
|
||||
static CSHandle Make(int value) { return BaseHandle::Make(value); }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,16 +71,31 @@ UINT16 Convert::Uint8x4ToUint4x4(UINT32 in)
|
|||
return (x[0] << 12) | (x[1] << 8) | (x[2] << 4) | (x[3]);
|
||||
}
|
||||
|
||||
UINT32 Convert::Uint4x4ToUint8x4(UINT16 in)
|
||||
UINT32 Convert::Uint4x4ToUint8x4(UINT16 in, bool scaleTo255)
|
||||
{
|
||||
int x[4] =
|
||||
{
|
||||
(in >> 12) & 0xF,
|
||||
(in >> 8) & 0xF,
|
||||
(in >> 4) & 0xF,
|
||||
(in >> 0) & 0xF
|
||||
((in >> 12) & 0xF) << 4,
|
||||
((in >> 8) & 0xF) << 4,
|
||||
((in >> 4) & 0xF) << 4,
|
||||
((in >> 0) & 0xF) << 4
|
||||
};
|
||||
return (x[0] << 28) | (x[1] << 20) | (x[2] << 12) | (x[3] << 4);
|
||||
if (scaleTo255)
|
||||
{
|
||||
VERUS_FOR(i, 4)
|
||||
x[i] = x[i] * 255 / 0xF0;
|
||||
}
|
||||
return (x[0] << 24) | (x[1] << 16) | (x[2] << 8) | (x[3] << 0);
|
||||
}
|
||||
|
||||
float Convert::SRGBToLinear(float color)
|
||||
{
|
||||
return color < 0.04045f ? color * (1 / 12.92f) : pow((color + 0.055f) * (1 / 1.055f), 2.4f);
|
||||
}
|
||||
|
||||
float Convert::LinearToSRGB(float color)
|
||||
{
|
||||
return color < 0.0031308f ? 12.92f * color : 1.055f * pow(color, 1 / 2.4f) - 0.055f;
|
||||
}
|
||||
|
||||
UINT32 Convert::Color16To32(UINT16 in)
|
||||
|
@ -93,20 +108,35 @@ UINT32 Convert::Color16To32(UINT16 in)
|
|||
|
||||
void Convert::ColorInt32ToFloat(UINT32 in, float* out, bool sRGB)
|
||||
{
|
||||
const float gamma = sRGB ? 2.2f : 1.f;
|
||||
out[0] = pow(float(int((in >> 0) & 0xFF))* (1 / 255.f), gamma);
|
||||
out[1] = pow(float(int((in >> 8) & 0xFF))* (1 / 255.f), gamma);
|
||||
out[2] = pow(float(int((in >> 16) & 0xFF))* (1 / 255.f), gamma);
|
||||
out[3] = float(int((in >> 24) & 0xFF))* (1 / 255.f);
|
||||
out[0] = ((in >> 0) & 0xFF) * (1 / 255.f);
|
||||
out[1] = ((in >> 8) & 0xFF) * (1 / 255.f);
|
||||
out[2] = ((in >> 16) & 0xFF) * (1 / 255.f);
|
||||
out[3] = ((in >> 24) & 0xFF) * (1 / 255.f);
|
||||
if (sRGB)
|
||||
{
|
||||
out[0] = SRGBToLinear(out[0]);
|
||||
out[1] = SRGBToLinear(out[1]);
|
||||
out[2] = SRGBToLinear(out[2]);
|
||||
}
|
||||
}
|
||||
|
||||
UINT32 Convert::ColorFloatToInt32(const float* in, bool sRGB)
|
||||
{
|
||||
const float gamma = sRGB ? 1 / 2.2f : 1.f;
|
||||
const int r = Math::Clamp(int(pow(in[0], gamma) * 255.5f), 0, 255);
|
||||
const int g = Math::Clamp(int(pow(in[1], gamma) * 255.5f), 0, 255);
|
||||
const int b = Math::Clamp(int(pow(in[2], gamma) * 255.5f), 0, 255);
|
||||
const int a = Math::Clamp(int(in[3] * 255.5f), 0, 255);
|
||||
float out[4];
|
||||
out[0] = in[0];
|
||||
out[1] = in[1];
|
||||
out[2] = in[2];
|
||||
out[3] = in[3];
|
||||
if (sRGB)
|
||||
{
|
||||
out[0] = LinearToSRGB(out[0]);
|
||||
out[1] = LinearToSRGB(out[1]);
|
||||
out[2] = LinearToSRGB(out[2]);
|
||||
}
|
||||
const int r = Math::Clamp(static_cast<int>(out[0] * 255 + 0.5f), 0, 255);
|
||||
const int g = Math::Clamp(static_cast<int>(out[1] * 255 + 0.5f), 0, 255);
|
||||
const int b = Math::Clamp(static_cast<int>(out[2] * 255 + 0.5f), 0, 255);
|
||||
const int a = Math::Clamp(static_cast<int>(out[3] * 255 + 0.5f), 0, 255);
|
||||
return VERUS_COLOR_RGBA(r, g, b, a);
|
||||
}
|
||||
|
||||
|
@ -140,11 +170,16 @@ void Convert::ColorTextToFloat4(CSZ sz, float* out, bool sRGB)
|
|||
if (3 == count)
|
||||
color[3] = 255;
|
||||
}
|
||||
const float gamma = sRGB ? 2.2f : 1.f;
|
||||
out[0] = pow(float(color[0]) * (1 / 255.f), gamma);
|
||||
out[1] = pow(float(color[1]) * (1 / 255.f), gamma);
|
||||
out[2] = pow(float(color[2]) * (1 / 255.f), gamma);
|
||||
out[3] = float(color[3]) * (1 / 255.f);
|
||||
out[0] = color[0] * (1 / 255.f);
|
||||
out[1] = color[1] * (1 / 255.f);
|
||||
out[2] = color[2] * (1 / 255.f);
|
||||
out[3] = color[3] * (1 / 255.f);
|
||||
if (sRGB)
|
||||
{
|
||||
out[0] = SRGBToLinear(out[0]);
|
||||
out[1] = SRGBToLinear(out[1]);
|
||||
out[2] = SRGBToLinear(out[2]);
|
||||
}
|
||||
}
|
||||
|
||||
UINT32 Convert::ColorTextToInt32(CSZ sz)
|
||||
|
@ -321,6 +356,8 @@ String Convert::ToMd5String(const Vector<BYTE>& vBin)
|
|||
|
||||
void Convert::Test()
|
||||
{
|
||||
const float e = 1e-6f;
|
||||
|
||||
BYTE dataUint8[] = { 0, 127, 255 };
|
||||
UINT16 dataUint16[] = { 0, 127, 65535, 65534 };
|
||||
char dataSint8[] = { 64, -127, -128 };
|
||||
|
@ -336,6 +373,32 @@ void Convert::Test()
|
|||
Sint16ToSnorm(dataSint16, dataFloat, 4);
|
||||
SnormToSint16(dataFloat, dataSint16, 4);
|
||||
|
||||
BYTE colorIn[20];
|
||||
VERUS_FOR(i, 16)
|
||||
colorIn[i] = i;
|
||||
colorIn[16] = 64;
|
||||
colorIn[17] = 128;
|
||||
colorIn[18] = 192;
|
||||
colorIn[19] = 255;
|
||||
float colorOut[20];
|
||||
VERUS_FOR(i, 20)
|
||||
colorOut[i] = SRGBToLinear(colorIn[i] * (1 / 255.f));
|
||||
BYTE colorTest[20];
|
||||
VERUS_FOR(i, 20)
|
||||
colorTest[i] = static_cast<BYTE>(LinearToSRGB(colorOut[i]) * 255 + 0.5f);
|
||||
VERUS_FOR(i, 20)
|
||||
{
|
||||
if (i < 19)
|
||||
{
|
||||
const float d = colorOut[i + 1] - colorOut[i];
|
||||
if (i < 10)
|
||||
VERUS_RT_ASSERT(glm::epsilonEqual(d, colorOut[1], e));
|
||||
else
|
||||
VERUS_RT_ASSERT(glm::epsilonNotEqual(d, colorOut[1], e));
|
||||
}
|
||||
VERUS_RT_ASSERT(colorIn[i] == colorTest[i]);
|
||||
}
|
||||
|
||||
Vector<BYTE> vBin;
|
||||
vBin.resize(16);
|
||||
|
||||
|
|
|
@ -43,9 +43,11 @@ namespace verus
|
|||
|
||||
// 4 bits per channel:
|
||||
static UINT16 Uint8x4ToUint4x4(UINT32 in);
|
||||
static UINT32 Uint4x4ToUint8x4(UINT16 in);
|
||||
static UINT32 Uint4x4ToUint8x4(UINT16 in, bool scaleTo255 = false);
|
||||
|
||||
// Colors:
|
||||
static float SRGBToLinear(float color);
|
||||
static float LinearToSRGB(float color);
|
||||
static UINT32 Color16To32(UINT16 in);
|
||||
static void ColorInt32ToFloat(UINT32 in, float* out, bool sRGB = true);
|
||||
static UINT32 ColorFloatToInt32(const float* in, bool sRGB = true);
|
||||
|
|
|
@ -86,6 +86,7 @@ void EngineInit::Init(Input::PKeyMapperDelegate pKeyMapperDelegate, CGI::Rendere
|
|||
{
|
||||
Scene::Mesh::InitStatic();
|
||||
Scene::Terrain::InitStatic();
|
||||
Scene::Grass::InitStatic();
|
||||
//Scene::CForest::InitStatic();
|
||||
}
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
#define VERUS_QREF_BLUR Effects::RBlur blur = Effects::Blur::I()
|
||||
#define VERUS_QREF_BULLET Physics::RBullet bullet = Physics::Bullet::I()
|
||||
#define VERUS_QREF_CONST_SETTINGS App::RcSettings settings = App::Settings::IConst()
|
||||
#define VERUS_QREF_DEPTH Effects::RDepth depth = Effects::Depth::I()
|
||||
#define VERUS_QREF_DD CGI::RDebugDraw dd = CGI::DebugDraw::I()
|
||||
#define VERUS_QREF_DEPTH Effects::RDepth depth = Effects::Depth::I()
|
||||
#define VERUS_QREF_FSYS IO::RFileSystem fsys = IO::FileSystem::I()
|
||||
#define VERUS_QREF_GAME Game::RGame game = Game::Game::I()
|
||||
#define VERUS_QREF_GRASS Scene::RGrass grass = Scene::Grass::I()
|
||||
|
|
|
@ -9,6 +9,18 @@ bool Math::IsPowerOfTwo(int x)
|
|||
return !(x & (x - 1));
|
||||
}
|
||||
|
||||
UINT32 Math::NextPowerOfTwo(UINT32 x)
|
||||
{
|
||||
x--;
|
||||
x |= x >> 1;
|
||||
x |= x >> 2;
|
||||
x |= x >> 4;
|
||||
x |= x >> 8;
|
||||
x |= x >> 16;
|
||||
x++;
|
||||
return x;
|
||||
}
|
||||
|
||||
int Math::HighestBit(int x)
|
||||
{
|
||||
int bit = -1;
|
||||
|
@ -59,6 +71,11 @@ float Math::LinearToCos(float t)
|
|||
return cos(t * VERUS_PI) * -0.5f + 0.5f; // [1 to -1] -> [0 to 1].
|
||||
}
|
||||
|
||||
float Math::EaseInOutSine(float x)
|
||||
{
|
||||
return -(cos(VERUS_PI * x) - 1) * 0.5f;
|
||||
}
|
||||
|
||||
Vector3 Math::TriangleNormal(RcPoint3 a, RcPoint3 b, RcPoint3 c)
|
||||
{
|
||||
return VMath::normalize(VMath::cross(a - b, a - c));
|
||||
|
@ -77,15 +94,15 @@ float Math::TriangleArea(
|
|||
return sqrt(s * (s - a) * (s - b) * (s - c));
|
||||
}
|
||||
|
||||
int Math::GetStripGridIndexCount(int polyCountWidth, int polyCountHeight)
|
||||
int Math::StripGridIndexCount(int polyCountWidth, int polyCountHeight)
|
||||
{
|
||||
const int vertCountWidth = polyCountWidth + 1;
|
||||
return (vertCountWidth * 2) * polyCountHeight + (polyCountHeight - 1) * 2; // Strip and primitive restart values.
|
||||
}
|
||||
|
||||
void Math::BuildStripGrid(int polyCountWidth, int polyCountHeight, Vector<UINT16>& vIndices)
|
||||
void Math::CreateStripGrid(int polyCountWidth, int polyCountHeight, Vector<UINT16>& vIndices)
|
||||
{
|
||||
vIndices.resize(GetStripGridIndexCount(polyCountWidth, polyCountHeight));
|
||||
vIndices.resize(StripGridIndexCount(polyCountWidth, polyCountHeight));
|
||||
int offset = 0;
|
||||
const int vertCountWidth = polyCountWidth + 1;
|
||||
VERUS_FOR(h, polyCountHeight)
|
||||
|
@ -114,7 +131,7 @@ void Math::BuildStripGrid(int polyCountWidth, int polyCountHeight, Vector<UINT16
|
|||
}
|
||||
}
|
||||
|
||||
void Math::BuildListGrid(int polyCountWidth, int polyCountHeight, Vector<UINT16>& vIndices)
|
||||
void Math::CreateListGrid(int polyCountWidth, int polyCountHeight, Vector<UINT16>& vIndices)
|
||||
{
|
||||
vIndices.resize(polyCountWidth * polyCountHeight * 6);
|
||||
int offset = 0;
|
||||
|
@ -148,6 +165,23 @@ void Math::BuildListGrid(int polyCountWidth, int polyCountHeight, Vector<UINT16>
|
|||
}
|
||||
}
|
||||
|
||||
bool Math::CheckIndexBuffer(Vector<UINT16>& vIndices, int maxIndex)
|
||||
{
|
||||
Vector<UINT16> vTemp(vIndices.begin(), vIndices.end());
|
||||
std::sort(vTemp.begin(), vTemp.end());
|
||||
auto itRestart = std::find(vTemp.begin(), vTemp.end(), 0xFFFF);
|
||||
if (itRestart != vTemp.end())
|
||||
vTemp.erase(itRestart, vTemp.end());
|
||||
if (vTemp.empty())
|
||||
return false;
|
||||
if (vTemp.front() != 0)
|
||||
return false;
|
||||
if (vTemp.back() != maxIndex)
|
||||
return false;
|
||||
auto it = std::adjacent_find(vTemp.begin(), vTemp.end(), [](UINT16 a, UINT16 b) {return (b - a) > 1; });
|
||||
return vTemp.end() == it;
|
||||
}
|
||||
|
||||
Transform3 Math::BoundsDrawMatrix(RcPoint3 mn, RcPoint3 mx)
|
||||
{
|
||||
const Vector3 d = mx - mn;
|
||||
|
@ -161,6 +195,13 @@ float Math::ComputeOnePixelDistance(float size, float screenHeight, float fovY)
|
|||
return viewSliceSize / (tan(fovY * 0.5f) * 2);
|
||||
}
|
||||
|
||||
float Math::ComputeDistToMipScale(float texSize, float screenSize, float realSize, float fovY)
|
||||
{
|
||||
const float fillScreenScale = screenSize / texSize;
|
||||
const float a = realSize * fillScreenScale * 0.5f;
|
||||
return tan(fovY * 0.5f) / a;
|
||||
}
|
||||
|
||||
void Math::Quadrant(const int** ppSrcMinMax, int** ppDestMinMax, int half, int id)
|
||||
{
|
||||
VERUS_RT_ASSERT(id >= 0 && id < 4);
|
||||
|
@ -395,7 +436,7 @@ void Math::Test()
|
|||
|
||||
{
|
||||
Vector<UINT16> v;
|
||||
BuildStripGrid(2, 2, v);
|
||||
CreateStripGrid(2, 2, v);
|
||||
VERUS_RT_ASSERT(v.size() == 14);
|
||||
VERUS_RT_ASSERT(0 == v[0] && 3 == v[1] && 1 == v[2]); // First triangle is CCW.
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ namespace verus
|
|||
{
|
||||
// Bits:
|
||||
bool IsPowerOfTwo(int x);
|
||||
UINT32 NextPowerOfTwo(UINT32 x);
|
||||
int HighestBit(int x);
|
||||
bool IsNaN(float x);
|
||||
|
||||
|
@ -61,19 +62,22 @@ namespace verus
|
|||
float SmoothStep(float a, float b, float t);
|
||||
float LinearToSin(float t);
|
||||
float LinearToCos(float t);
|
||||
float EaseInOutSine(float x);
|
||||
|
||||
// Shapes:
|
||||
Vector3 TriangleNormal(RcPoint3 a, RcPoint3 b, RcPoint3 c);
|
||||
float TriangleArea(const glm::vec3& p0, const glm::vec3& p1, const glm::vec3& p2);
|
||||
|
||||
// Geometry:
|
||||
int GetStripGridIndexCount(int polyCountWidth, int polyCountHeight);
|
||||
void BuildStripGrid(int polyCountWidth, int polyCountHeight, Vector<UINT16>& vIndices);
|
||||
void BuildListGrid(int polyCountWidth, int polyCountHeight, Vector<UINT16>& vIndices);
|
||||
int StripGridIndexCount(int polyCountWidth, int polyCountHeight);
|
||||
void CreateStripGrid(int polyCountWidth, int polyCountHeight, Vector<UINT16>& vIndices);
|
||||
void CreateListGrid(int polyCountWidth, int polyCountHeight, Vector<UINT16>& vIndices);
|
||||
bool CheckIndexBuffer(Vector<UINT16>& vIndices, int maxIndex);
|
||||
|
||||
// Scene:
|
||||
Transform3 BoundsDrawMatrix(RcPoint3 mn, RcPoint3 mx);
|
||||
float ComputeOnePixelDistance(float size, float screenHeight = 120, float fovY = VERUS_PI / 4);
|
||||
float ComputeDistToMipScale(float texSize, float screenSize, float realSize, float fovY);
|
||||
void Quadrant(const int** ppSrcMinMax, int** ppDestMinMax, int half, int id);
|
||||
|
||||
int ComputeMipLevels(int w, int h, int d = 1);
|
||||
|
|
|
@ -3,6 +3,11 @@
|
|||
using namespace verus;
|
||||
using namespace verus::Scene;
|
||||
|
||||
Atmosphere::UB_PerFrame Atmosphere::s_ubPerFrame;
|
||||
Atmosphere::UB_PerMaterialFS Atmosphere::s_ubPerMaterialFS;
|
||||
Atmosphere::UB_PerMeshVS Atmosphere::s_ubPerMeshVS;
|
||||
Atmosphere::UB_PerObject Atmosphere::s_ubPerObject;
|
||||
|
||||
Atmosphere::Atmosphere()
|
||||
{
|
||||
}
|
||||
|
@ -17,20 +22,214 @@ void Atmosphere::Init()
|
|||
VERUS_INIT();
|
||||
VERUS_QREF_RENDERER;
|
||||
VERUS_QREF_CONST_SETTINGS;
|
||||
VERUS_QREF_UTILS;
|
||||
|
||||
_skyDome.Init("[Models]:SkyDome.x3d");
|
||||
|
||||
_shader.Init("[Shaders]:Sky.hlsl");
|
||||
_shader->CreateDescriptorSet(0, &s_ubPerFrame, sizeof(s_ubPerFrame), 100);
|
||||
_shader->CreateDescriptorSet(1, &s_ubPerMaterialFS, sizeof(s_ubPerMaterialFS), 100,
|
||||
{
|
||||
CGI::Sampler::aniso,
|
||||
CGI::Sampler::aniso,
|
||||
CGI::Sampler::aniso,
|
||||
CGI::Sampler::aniso
|
||||
}, CGI::ShaderStageFlags::fs);
|
||||
_shader->CreateDescriptorSet(2, &s_ubPerMeshVS, sizeof(s_ubPerMeshVS), 100, {}, CGI::ShaderStageFlags::vs);
|
||||
_shader->CreateDescriptorSet(3, &s_ubPerObject, sizeof(s_ubPerObject), 100);
|
||||
_shader->CreatePipelineLayout();
|
||||
|
||||
if (settings._sceneShadowQuality > App::Settings::ShadowQuality::none)
|
||||
_shadowMap.Init(4096);
|
||||
|
||||
renderer.GetDS().InitByAtmosphere(_shadowMap.GetTexture());
|
||||
|
||||
_sun._dirTo = VMath::normalize(Vector3(1.3f, 1, 1.3f));
|
||||
_texSky.LoadDDS("[Textures]:Sky/Sky.dds");
|
||||
|
||||
_tex[TEX_SKY].Init("[Textures]:Sky/Sky.dds");
|
||||
_tex[TEX_STARS].Init("[Textures]:Sky/Stars.dds");
|
||||
_tex[TEX_SUN].Init("[Textures]:Sky/Sun.dds");
|
||||
_tex[TEX_MOON].Init("[Textures]:Sky/Moon.dds");
|
||||
_tex[TEX_CLOUDS].Init("[Textures]:Sky/Clouds.FX.dds");
|
||||
_tex[TEX_CLOUDS_NM].Init("[Textures]:Sky/Clouds.NM.dds");
|
||||
|
||||
_clouds._phaseA.setX(utils.GetRandom().NextFloat());
|
||||
_clouds._phaseA.setY(utils.GetRandom().NextFloat());
|
||||
_clouds._phaseB.setX(utils.GetRandom().NextFloat());
|
||||
_clouds._phaseB.setY(utils.GetRandom().NextFloat());
|
||||
|
||||
_sun._matTilt = Matrix3::rotationX(-VERUS_PI / 10);
|
||||
_sun._dirToMidnight = _sun._matTilt * Vector3(0, -1, 0);
|
||||
_sun._dirTo = VMath::mulPerElem(_sun._dirToMidnight, Vector3(1, -1, 1));
|
||||
}
|
||||
|
||||
void Atmosphere::Done()
|
||||
{
|
||||
_shader->FreeDescriptorSet(_cshSkyFS);
|
||||
VERUS_DONE(Atmosphere);
|
||||
}
|
||||
|
||||
void Atmosphere::UpdateSun(float time)
|
||||
{
|
||||
// Update time and sun's color before calling this method.
|
||||
|
||||
_sun._dirTo = Matrix3::rotationZ(time * VERUS_2PI) * _sun._dirToMidnight;
|
||||
|
||||
_night = false;
|
||||
if (_sun._dirTo.getY() < 0) // Moon light:
|
||||
{
|
||||
_night = true;
|
||||
_sun._dirTo = Matrix3::rotationZ(time * VERUS_2PI + VERUS_PI) * _sun._dirToMidnight;
|
||||
_sun._color = VMath::mulPerElem(_sun._color, Vector3(0.19f, 0.21f, 0.45f));
|
||||
}
|
||||
|
||||
// Reduce light's intensity when near horizon:
|
||||
const float intensity = Math::Clamp<float>(abs(_sun._dirTo.getY()) * 4, 0, 1);
|
||||
_sun._color *= intensity;
|
||||
}
|
||||
|
||||
void Atmosphere::Update()
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
VERUS_QREF_TIMER;
|
||||
|
||||
if (!_async_loaded)
|
||||
{
|
||||
bool allTexLoaded = true;
|
||||
VERUS_FOR(i, TEX_COUNT)
|
||||
{
|
||||
if (!_tex[i]->IsLoaded())
|
||||
allTexLoaded = false;
|
||||
}
|
||||
if (_skyDome.IsLoaded() && allTexLoaded)
|
||||
{
|
||||
_async_loaded = true;
|
||||
|
||||
{
|
||||
CGI::PipelineDesc pipeDesc(_skyDome.GetGeometry(), _shader, "#Sky", renderer.GetDS().GetRenderPassHandle_Compose(), renderer.GetDS().GetSubpass_Compose());
|
||||
pipeDesc._vertexInputBindingsFilter = (1 << 0);
|
||||
pipeDesc._depthWriteEnable = false;
|
||||
pipeDesc._depthCompareOp = CGI::CompareOp::lessOrEqual;
|
||||
_pipe[PIPE_SKY].Init(pipeDesc);
|
||||
}
|
||||
{
|
||||
CGI::PipelineDesc pipeDesc(_skyDome.GetGeometry(), _shader, "#Clouds", renderer.GetDS().GetRenderPassHandle_Compose(), renderer.GetDS().GetSubpass_Compose());
|
||||
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_ALPHA;
|
||||
pipeDesc._vertexInputBindingsFilter = (1 << 0);
|
||||
pipeDesc._depthWriteEnable = false;
|
||||
pipeDesc._depthCompareOp = CGI::CompareOp::lessOrEqual;
|
||||
_pipe[PIPE_CLOUDS].Init(pipeDesc);
|
||||
}
|
||||
|
||||
_shader->FreeDescriptorSet(_cshSkyFS);
|
||||
_cshSkyFS = _shader->BindDescriptorSetTextures(1, { _tex[TEX_SKY], _tex[TEX_STARS], _tex[TEX_CLOUDS], _tex[TEX_CLOUDS_NM] });
|
||||
}
|
||||
}
|
||||
if (!_async_loaded)
|
||||
return;
|
||||
|
||||
_time = glm::fract(_time + dt * _timeSpeed);
|
||||
|
||||
_clouds._cloudiness.Update();
|
||||
|
||||
float color[3];
|
||||
GetColor(64, color, 1.5f); _fog._color = Vector3::MakeFromPointer(color) * _hdrScale;
|
||||
GetColor(208, color, 0.3f); _ambientColor = Vector3::MakeFromPointer(color) * _hdrScale;
|
||||
GetColor(240, color, 1); _sun._color = Vector3::MakeFromPointer(color) * _hdrScale;
|
||||
|
||||
glm::vec3 ambientColor = _ambientColor.GLM();
|
||||
glm::vec3 fogColor = _fog._color.GLM();
|
||||
_ambientColor = glm::saturation(0.75f, ambientColor);
|
||||
const float clearSky = Math::Min(1.f, 1.5f - _clouds._cloudiness);
|
||||
_fog._color = glm::saturation(clearSky * 0.75f, fogColor);
|
||||
_fog._colorInit = _fog._color;
|
||||
|
||||
UpdateSun(_time);
|
||||
}
|
||||
|
||||
void Atmosphere::DrawSky()
|
||||
{
|
||||
if (!_async_loaded)
|
||||
return;
|
||||
|
||||
VERUS_QREF_RENDERER;
|
||||
VERUS_QREF_SM;
|
||||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
RcCamera cam = *sm.GetCamera();
|
||||
Matrix3 matS = Matrix3::scale(Vector3(4, 1, 4)); // Stretch sky dome.
|
||||
const Matrix4 matSkyDome = cam.GetMatrixVP() * Transform3(matS, Vector3(cam.GetEyePosition()));
|
||||
|
||||
s_ubPerFrame._time_cloudiness_expo.x = _time;
|
||||
s_ubPerFrame._time_cloudiness_expo.y = _clouds._cloudiness;
|
||||
s_ubPerFrame._time_cloudiness_expo.z = 0;
|
||||
s_ubPerFrame._dirToSun = float4(_sun._dirTo.GLM(), 0);
|
||||
s_ubPerFrame._phaseAB = float4(
|
||||
_clouds._phaseA.getX(),
|
||||
_clouds._phaseA.getY(),
|
||||
_clouds._phaseB.getX(),
|
||||
_clouds._phaseB.getY());
|
||||
s_ubPerFrame._fogColor = float4(_fog._color.GLM(), 0);
|
||||
_skyDome.CopyPosDeqScale(&s_ubPerMeshVS._posDeqScale.x);
|
||||
_skyDome.CopyPosDeqBias(&s_ubPerMeshVS._posDeqBias.x);
|
||||
s_ubPerObject._matWVP = matSkyDome.UniformBufferFormat();
|
||||
|
||||
_skyDome.BindGeo(cb);
|
||||
|
||||
// <Sky>
|
||||
cb->BindPipeline(_pipe[PIPE_SKY]);
|
||||
|
||||
_shader->BeginBindDescriptors();
|
||||
cb->BindDescriptors(_shader, 0);
|
||||
cb->BindDescriptors(_shader, 1, _cshSkyFS);
|
||||
cb->BindDescriptors(_shader, 2);
|
||||
cb->BindDescriptors(_shader, 3);
|
||||
_shader->EndBindDescriptors();
|
||||
|
||||
cb->DrawIndexed(_skyDome.GetIndexCount());
|
||||
// </Sky>
|
||||
|
||||
// <Clouds>
|
||||
cb->BindPipeline(_pipe[PIPE_CLOUDS]);
|
||||
|
||||
_shader->BeginBindDescriptors();
|
||||
cb->BindDescriptors(_shader, 0);
|
||||
cb->BindDescriptors(_shader, 1, _cshSkyFS);
|
||||
cb->BindDescriptors(_shader, 2);
|
||||
cb->BindDescriptors(_shader, 3);
|
||||
_shader->EndBindDescriptors();
|
||||
|
||||
cb->DrawIndexed(_skyDome.GetIndexCount());
|
||||
// </Clouds>
|
||||
}
|
||||
|
||||
void Atmosphere::GetColor(int level, float* pOut, float scale)
|
||||
{
|
||||
if (!_texSky.IsLoaded())
|
||||
return;
|
||||
const float texCoord = _time * 256;
|
||||
const int intPartA = static_cast<int>(texCoord) & 0xFF;
|
||||
const int intPartB = (intPartA + 1) & 0xFF;
|
||||
const float fractPart = texCoord - intPartA;
|
||||
|
||||
const int offsetA = (level << 10) + (intPartA << 2);
|
||||
const int offsetB = (level << 10) + (intPartB << 2);
|
||||
auto LoadFromSky = [this](float rgb[3], int offset)
|
||||
{
|
||||
rgb[0] = Convert::SRGBToLinear(Convert::Uint8ToUnorm(_texSky.GetData()[offset + 0]));
|
||||
rgb[1] = Convert::SRGBToLinear(Convert::Uint8ToUnorm(_texSky.GetData()[offset + 1]));
|
||||
rgb[2] = Convert::SRGBToLinear(Convert::Uint8ToUnorm(_texSky.GetData()[offset + 2]));
|
||||
};
|
||||
float rgbA[3];
|
||||
float rgbB[3];
|
||||
LoadFromSky(rgbA, offsetA);
|
||||
LoadFromSky(rgbB, offsetB);
|
||||
|
||||
VERUS_FOR(i, 3)
|
||||
pOut[i] = Math::Clamp<float>(Math::Lerp(rgbA[i], rgbB[i], fractPart) * 0.5f * scale, 0, 1);
|
||||
}
|
||||
|
||||
RcVector3 Atmosphere::GetDirToSun() const
|
||||
{
|
||||
return _sun._dirTo;
|
||||
|
|
|
@ -6,6 +6,37 @@ namespace verus
|
|||
{
|
||||
class Atmosphere : public Singleton<Atmosphere>, public Object
|
||||
{
|
||||
public:
|
||||
#include "../Shaders/Sky.inc.hlsl"
|
||||
|
||||
enum PIPE
|
||||
{
|
||||
PIPE_SKY,
|
||||
PIPE_CLOUDS,
|
||||
PIPE_COUNT
|
||||
};
|
||||
|
||||
enum TEX
|
||||
{
|
||||
TEX_SKY,
|
||||
TEX_STARS,
|
||||
TEX_SUN,
|
||||
TEX_MOON,
|
||||
TEX_CLOUDS,
|
||||
TEX_CLOUDS_NM,
|
||||
TEX_COUNT
|
||||
};
|
||||
|
||||
private:
|
||||
struct Clouds
|
||||
{
|
||||
Vector4 _phaseA = Vector4(0);
|
||||
Vector4 _phaseB = Vector4(0);
|
||||
float _speedPhaseA = 0.017f;
|
||||
float _speedPhaseB = 0.003f;
|
||||
Anim::Damping<float> _cloudiness = 0.25f;
|
||||
};
|
||||
|
||||
struct Fog
|
||||
{
|
||||
Vector3 _color = Vector3(0);
|
||||
|
@ -14,7 +45,7 @@ namespace verus
|
|||
float _end = 100000;
|
||||
float _startEx = 0;
|
||||
float _endEx = 0;
|
||||
float _density = 1 / 1500.f;
|
||||
float _density = 0.0002f;
|
||||
};
|
||||
|
||||
struct Sun
|
||||
|
@ -25,12 +56,27 @@ namespace verus
|
|||
Vector3 _color = Vector3(0);
|
||||
};
|
||||
|
||||
static UB_PerFrame s_ubPerFrame;
|
||||
static UB_PerMaterialFS s_ubPerMaterialFS;
|
||||
static UB_PerMeshVS s_ubPerMeshVS;
|
||||
static UB_PerObject s_ubPerObject;
|
||||
|
||||
CGI::ShaderPwn _shader;
|
||||
CGI::PipelinePwns<PIPE_COUNT> _pipe;
|
||||
CGI::TexturePwns<TEX_COUNT> _tex;
|
||||
Clouds _clouds;
|
||||
Fog _fog;
|
||||
Sun _sun;
|
||||
Vector3 _colorAmbient = Vector3(0);
|
||||
Vector3 _ambientColor = Vector3(0);
|
||||
CascadedShadowMap _shadowMap;
|
||||
Mesh _skyDome;
|
||||
CGI::TextureRAM _texSky;
|
||||
float _time = 0.5f;
|
||||
float _timeSpeed = 1 / 300.f;
|
||||
float _hdrScale = 1000;
|
||||
CGI::CSHandle _cshSkyFS;
|
||||
bool _night = false;
|
||||
bool _async_loaded = false;
|
||||
|
||||
public:
|
||||
Atmosphere();
|
||||
|
@ -39,13 +85,28 @@ namespace verus
|
|||
void Init();
|
||||
void Done();
|
||||
|
||||
void UpdateSun(float time);
|
||||
void Update();
|
||||
void DrawSky();
|
||||
|
||||
void GetColor(int level, float* pOut, float scale);
|
||||
|
||||
// Time:
|
||||
float GetTime() const { return _time; }
|
||||
void SetTime(float x) { _time = x; }
|
||||
void SetTimeSpeed(float x) { _timeSpeed = x; }
|
||||
|
||||
RcVector3 GetAmbientColor() const { return _ambientColor; }
|
||||
|
||||
// Clouds:
|
||||
Anim::Damping<float>& GetCloudiness() { return _clouds._cloudiness; }
|
||||
void SetCloudiness(float x) { _clouds._cloudiness = x; _clouds._cloudiness.ForceTarget(); }
|
||||
|
||||
// Fog:
|
||||
RcVector3 GetFogColor() const { return _fog._color; }
|
||||
float GetFogDensity() const { return _fog._density; }
|
||||
void SetFogDensity(float d) { _fog._density = d; }
|
||||
|
||||
// Sun:
|
||||
RcVector3 GetDirToSun() const;
|
||||
RcVector3 GetSunColor() const;
|
||||
|
|
|
@ -328,7 +328,7 @@ void BaseMesh::LoadPrimaryBones()
|
|||
VERUS_FOR(i, 4)
|
||||
it->bi[i] = _skeleton.RemapBoneIndex(it->bi[i]);
|
||||
}
|
||||
BufferDataVB(_vBinding1.data(), 1);
|
||||
UpdateVertexBuffer(_vBinding1.data(), 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -367,8 +367,8 @@ void BaseMesh::LoadWarp()
|
|||
_vBinding2[i]._tan[3] = g * SHRT_MAX / 9;
|
||||
_vBinding2[i]._bin[3] = b * SHRT_MAX / 9;
|
||||
}
|
||||
BufferDataVB(_vBinding0.data(), 0);
|
||||
BufferDataVB(_vBinding2.data(), 2);
|
||||
UpdateVertexBuffer(_vBinding0.data(), 0);
|
||||
UpdateVertexBuffer(_vBinding2.data(), 2);
|
||||
}
|
||||
|
||||
vData.clear();
|
||||
|
|
|
@ -96,7 +96,7 @@ namespace verus
|
|||
|
||||
// GPU:
|
||||
virtual void CreateDeviceBuffers() {}
|
||||
virtual void BufferDataVB(const void* p, int binding) {}
|
||||
virtual void UpdateVertexBuffer(const void* p, int binding) {}
|
||||
|
||||
// Bounds:
|
||||
void GetBounds(RPoint3 mn, RPoint3 mx) const;
|
||||
|
|
488
Verus/src/Scene/Grass.cpp
Normal file
488
Verus/src/Scene/Grass.cpp
Normal file
|
@ -0,0 +1,488 @@
|
|||
#include "verus.h"
|
||||
|
||||
using namespace verus;
|
||||
using namespace verus::Scene;
|
||||
|
||||
CGI::ShaderPwn Grass::s_shader;
|
||||
Grass::UB_GrassVS Grass::s_ubGrassVS;
|
||||
Grass::UB_GrassFS Grass::s_ubGrassFS;
|
||||
|
||||
Grass::Grass()
|
||||
{
|
||||
VERUS_CT_ASSERT(16 == sizeof(Vertex));
|
||||
VERUS_FOR(i, 4)
|
||||
{
|
||||
VERUS_FOR(j, 4)
|
||||
{
|
||||
const char u0 = j * 25 + 1;
|
||||
const char v0 = i * 25 + 1;
|
||||
const char u1 = u0 + 25 - 2;
|
||||
const char v1 = v0 + 25 - 2;
|
||||
const int index = (i << 2) + j;
|
||||
_bushTexCoords[index][0][0] = u0; _bushTexCoords[index][0][1] = v1;
|
||||
_bushTexCoords[index][1][0] = u0; _bushTexCoords[index][1][1] = v0;
|
||||
_bushTexCoords[index][2][0] = u1; _bushTexCoords[index][2][1] = v0;
|
||||
_bushTexCoords[index][3][0] = u1; _bushTexCoords[index][3][1] = v1;
|
||||
_bushTexCoords[index][4][0] = u0; _bushTexCoords[index][4][1] = v1;
|
||||
_bushTexCoords[index][5][0] = u0; _bushTexCoords[index][5][1] = v0;
|
||||
_bushTexCoords[index][6][0] = u1; _bushTexCoords[index][6][1] = v0;
|
||||
_bushTexCoords[index][7][0] = u1; _bushTexCoords[index][7][1] = v1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Grass::~Grass()
|
||||
{
|
||||
Done();
|
||||
}
|
||||
|
||||
void Grass::InitStatic()
|
||||
{
|
||||
s_shader.Init("[Shaders]:DS_Grass.hlsl");
|
||||
s_shader->CreateDescriptorSet(0, &s_ubGrassVS, sizeof(s_ubGrassVS), 100,
|
||||
{
|
||||
CGI::Sampler::linearMipL,
|
||||
CGI::Sampler::linearMipN,
|
||||
CGI::Sampler::nearestMipN,
|
||||
}, CGI::ShaderStageFlags::vs);
|
||||
s_shader->CreateDescriptorSet(1, &s_ubGrassFS, sizeof(s_ubGrassFS), 100,
|
||||
{
|
||||
CGI::Sampler::aniso
|
||||
}, CGI::ShaderStageFlags::fs);
|
||||
s_shader->CreatePipelineLayout();
|
||||
}
|
||||
|
||||
void Grass::DoneStatic()
|
||||
{
|
||||
s_shader.Done();
|
||||
}
|
||||
|
||||
void Grass::Init(RTerrain terrain)
|
||||
{
|
||||
VERUS_INIT();
|
||||
VERUS_QREF_RENDERER;
|
||||
VERUS_QREF_CONST_SETTINGS;
|
||||
|
||||
_pTerrain = &terrain;
|
||||
|
||||
_bushMask = 0;
|
||||
|
||||
if (!Math::IsPowerOfTwo(_pTerrain->GetMapSide()))
|
||||
throw VERUS_RECOVERABLE << "Init(), mapSide must be power of two";
|
||||
|
||||
_mapSide = _pTerrain->GetMapSide();
|
||||
_mapShift = Math::HighestBit(_mapSide);
|
||||
|
||||
const int patchSide = _mapSide >> 4;
|
||||
const int patchShift = _mapShift - 4;
|
||||
const int patchCount = patchSide * patchSide;
|
||||
const int maxInstances = 128 * 8;
|
||||
|
||||
_vPatches.resize(patchCount);
|
||||
|
||||
CreateBuffers();
|
||||
_vInstanceBuffer.resize(maxInstances);
|
||||
|
||||
CGI::GeometryDesc geoDesc;
|
||||
const CGI::VertexInputAttrDesc viaDesc[] =
|
||||
{
|
||||
{ 0, offsetof(Vertex, _pos), CGI::IeType::shorts, 4, CGI::IeUsage::position, 0},
|
||||
{ 0, offsetof(Vertex, _tc), CGI::IeType::shorts, 4, CGI::IeUsage::texCoord, 0},
|
||||
{-1, offsetof(PerInstanceData, _patchPos), CGI::IeType::shorts, 4, CGI::IeUsage::instData, 0},
|
||||
CGI::VertexInputAttrDesc::End()
|
||||
};
|
||||
geoDesc._pVertexInputAttrDesc = viaDesc;
|
||||
const int strides[] = { sizeof(Vertex), sizeof(PerInstanceData), 0 };
|
||||
geoDesc._pStrides = strides;
|
||||
_geo.Init(geoDesc);
|
||||
_geo->CreateVertexBuffer(_vPatchMeshVB.size(), 0);
|
||||
_geo->CreateVertexBuffer(maxInstances, 1);
|
||||
_geo->CreateIndexBuffer(_vPatchMeshIB.size());
|
||||
_geo->UpdateVertexBuffer(_vPatchMeshVB.data(), 0);
|
||||
_geo->UpdateIndexBuffer(_vPatchMeshIB.data());
|
||||
|
||||
{
|
||||
CGI::PipelineDesc pipeDesc(_geo, s_shader, "#", renderer.GetDS().GetRenderPassHandle());
|
||||
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_OFF;
|
||||
pipeDesc._colorAttachBlendEqs[1] = VERUS_COLOR_BLEND_OFF;
|
||||
pipeDesc._colorAttachBlendEqs[2] = VERUS_COLOR_BLEND_OFF;
|
||||
pipeDesc._rasterizationState._cullMode = CGI::CullMode::none;
|
||||
_pipe[PIPE_MAIN].Init(pipeDesc);
|
||||
}
|
||||
{
|
||||
CGI::PipelineDesc pipeDesc(_geo, s_shader, "#Billboards", renderer.GetDS().GetRenderPassHandle());
|
||||
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_OFF;
|
||||
pipeDesc._colorAttachBlendEqs[1] = VERUS_COLOR_BLEND_OFF;
|
||||
pipeDesc._colorAttachBlendEqs[2] = VERUS_COLOR_BLEND_OFF;
|
||||
pipeDesc._topology = CGI::PrimitiveTopology::pointList;
|
||||
_pipe[PIPE_BILLBOARDS].Init(pipeDesc);
|
||||
}
|
||||
|
||||
const int texW = 1024;
|
||||
const int texH = 1024;
|
||||
_vTextureSubresData.clear();
|
||||
_vTextureSubresData.resize(texW * texH);
|
||||
|
||||
CGI::TextureDesc texDesc;
|
||||
texDesc._format = CGI::Format::srgbR8G8B8A8;
|
||||
texDesc._width = texW;
|
||||
texDesc._height = texH;
|
||||
texDesc._mipLevels = 0;
|
||||
texDesc._flags = CGI::TextureDesc::Flags::generateMips;
|
||||
_tex.Init(texDesc);
|
||||
_tex->UpdateSubresource(_vTextureSubresData.data());
|
||||
_tex->GenerateMips();
|
||||
|
||||
s_shader->FreeDescriptorSet(_cshVS);
|
||||
_cshVS = s_shader->BindDescriptorSetTextures(0,
|
||||
{
|
||||
_pTerrain->GetHeightmapTexture(),
|
||||
_pTerrain->GetNormalsTexture(),
|
||||
_pTerrain->GetMainLayerTexture(),
|
||||
});
|
||||
s_shader->FreeDescriptorSet(_cshFS);
|
||||
_cshFS = s_shader->BindDescriptorSetTextures(1,
|
||||
{
|
||||
_tex
|
||||
});
|
||||
|
||||
_vMagnets.resize(16);
|
||||
std::fill(_vMagnets.begin(), _vMagnets.end(), Magnet());
|
||||
}
|
||||
|
||||
void Grass::Done()
|
||||
{
|
||||
s_shader->FreeDescriptorSet(_cshVS);
|
||||
s_shader->FreeDescriptorSet(_cshFS);
|
||||
VERUS_DONE(Grass);
|
||||
}
|
||||
|
||||
void Grass::Update()
|
||||
{
|
||||
VERUS_UPDATE_ONCE_CHECK;
|
||||
|
||||
// Async texture loading:
|
||||
VERUS_FOR(i, s_maxBushTypes)
|
||||
{
|
||||
if (_texLoaded[i].IsInitialized() && _texLoaded[i].IsLoaded())
|
||||
OnTextureLoaded(i);
|
||||
}
|
||||
}
|
||||
|
||||
void Grass::Layout()
|
||||
{
|
||||
VERUS_QREF_SM;
|
||||
|
||||
const float zFar = sm.GetCamera()->GetZFar();
|
||||
sm.GetCamera()->SetZFar(128);
|
||||
sm.GetCamera()->Update();
|
||||
|
||||
Math::RQuadtreeIntegral quadtree = _pTerrain->GetQuadtree();
|
||||
_visiblePatchCount = 0;
|
||||
quadtree.SetDelegate(this);
|
||||
quadtree.TraverseVisible();
|
||||
quadtree.SetDelegate(_pTerrain);
|
||||
|
||||
sm.GetCamera()->SetZFar(zFar);
|
||||
sm.GetCamera()->Update();
|
||||
}
|
||||
|
||||
void Grass::Draw()
|
||||
{
|
||||
if (!_visiblePatchCount)
|
||||
return;
|
||||
|
||||
VERUS_QREF_ATMO;
|
||||
VERUS_QREF_RENDERER;
|
||||
VERUS_QREF_SM;
|
||||
VERUS_RT_ASSERT(_pTerrain->GetMapSide() == _mapSide);
|
||||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
const bool drawingDepth = Scene::SceneManager::IsDrawingDepth(Scene::DrawDepth::automatic);
|
||||
|
||||
const UINT32 bushMask = _bushMask & 0xFF; // Use only first 8 bushes, next 8 are reserved.
|
||||
const int half = _mapSide >> 1;
|
||||
|
||||
s_ubGrassVS._matW = Transform3::UniformBufferFormatIdentity();
|
||||
s_ubGrassVS._matWV = sm.GetCamera()->GetMatrixV().UniformBufferFormat();
|
||||
s_ubGrassVS._matVP = sm.GetCamera()->GetMatrixVP().UniformBufferFormat();
|
||||
s_ubGrassVS._matP = sm.GetCamera()->GetMatrixP().UniformBufferFormat();
|
||||
s_ubGrassVS._phase_mapSideInv_bushMask.x = _phase;
|
||||
s_ubGrassVS._phase_mapSideInv_bushMask.y = 1.f / _mapSide;
|
||||
s_ubGrassVS._phase_mapSideInv_bushMask.z = *(float*)&bushMask;
|
||||
s_ubGrassVS._posEye = float4(atmo.GetEyePosition().GLM(), 0);
|
||||
s_ubGrassVS._viewportSize = cb->GetViewportSize().GLM();
|
||||
//s_ubGrassVS._wind = Vector3(VMath::normalize(atmo.GetWindVelocity()) * bendByWind);
|
||||
//s_ubGrassVS._wind.w = m_shaker.Get();
|
||||
|
||||
cb->BindVertexBuffers(_geo);
|
||||
cb->BindIndexBuffer(_geo);
|
||||
|
||||
s_shader->BeginBindDescriptors();
|
||||
|
||||
cb->BindPipeline(_pipe[PIPE_BILLBOARDS]);
|
||||
cb->BindDescriptors(s_shader, 0, _cshVS);
|
||||
cb->BindDescriptors(s_shader, 1, _cshFS);
|
||||
int pointSpriteInstCount = 0;
|
||||
VERUS_FOR(i, _visiblePatchCount)
|
||||
{
|
||||
RcPatch patch = _vPatches[i];
|
||||
if (patch.type & 0x2)
|
||||
{
|
||||
const int at = _instanceCount + pointSpriteInstCount;
|
||||
_vInstanceBuffer[at]._patchPos[0] = patch.j - half;
|
||||
_vInstanceBuffer[at]._patchPos[1] = patch.h;
|
||||
_vInstanceBuffer[at]._patchPos[2] = patch.i - half;
|
||||
_vInstanceBuffer[at]._patchPos[3] = 0;
|
||||
pointSpriteInstCount++;
|
||||
}
|
||||
}
|
||||
cb->Draw(_bbVertCount, pointSpriteInstCount, _vertCount, _instanceCount);
|
||||
_instanceCount += pointSpriteInstCount;
|
||||
|
||||
cb->BindPipeline(_pipe[PIPE_MAIN]);
|
||||
cb->BindDescriptors(s_shader, 0, _cshVS);
|
||||
cb->BindDescriptors(s_shader, 1, _cshFS);
|
||||
int meshInstCount = 0;
|
||||
VERUS_FOR(i, _visiblePatchCount)
|
||||
{
|
||||
RcPatch patch = _vPatches[i];
|
||||
if (patch.type & 0x1)
|
||||
{
|
||||
const int at = _instanceCount + meshInstCount;
|
||||
_vInstanceBuffer[at]._patchPos[0] = patch.j - half;
|
||||
_vInstanceBuffer[at]._patchPos[1] = patch.h;
|
||||
_vInstanceBuffer[at]._patchPos[2] = patch.i - half;
|
||||
_vInstanceBuffer[at]._patchPos[3] = 0;
|
||||
meshInstCount++;
|
||||
}
|
||||
}
|
||||
cb->DrawIndexed(_vPatchMeshIB.size(), meshInstCount, 0, 0, _instanceCount);
|
||||
_instanceCount += meshInstCount;
|
||||
|
||||
s_shader->EndBindDescriptors();
|
||||
|
||||
_geo->UpdateVertexBuffer(_vInstanceBuffer.data(), 1);
|
||||
}
|
||||
|
||||
void Grass::ResetInstanceCount()
|
||||
{
|
||||
_instanceCount = 0;
|
||||
}
|
||||
|
||||
void Grass::QuadtreeIntegral_ProcessVisibleNode(const short* ij, RcPoint3 center)
|
||||
{
|
||||
VERUS_QREF_ATMO;
|
||||
|
||||
const RcPoint3 eyePos = atmo.GetEyePosition();
|
||||
const float distSq = VMath::distSqr(eyePos, center);
|
||||
if (distSq >= 128 * 128.f)
|
||||
return;
|
||||
|
||||
Patch patch;
|
||||
patch.i = ij[0];
|
||||
patch.j = ij[1];
|
||||
patch.h = center.getY() * 100;
|
||||
patch.type = 0;
|
||||
if (distSq <= 64 * 64.f)
|
||||
patch.type |= 0x1;
|
||||
if (distSq >= 16 * 16.f)
|
||||
patch.type |= 0x2;
|
||||
_vPatches[_visiblePatchCount++] = patch;
|
||||
}
|
||||
|
||||
void Grass::QuadtreeIntegral_GetHeights(const short* ij, float height[2])
|
||||
{
|
||||
VERUS_RT_FAIL(__FUNCTION__);
|
||||
}
|
||||
|
||||
void Grass::CreateBuffers()
|
||||
{
|
||||
VERUS_QREF_CONST_SETTINGS;
|
||||
|
||||
const int density = settings._sceneGrassDensity;
|
||||
const int side = static_cast<int>(sqrt(float(density)));
|
||||
const int count = side * side;
|
||||
const float step = 16.f / side;
|
||||
|
||||
Random random(9052);
|
||||
auto RandomStep = [&random, step]()
|
||||
{
|
||||
return (0.1f + 0.8f * random.NextFloat()) * step;
|
||||
};
|
||||
auto RandomScale = [&random]()
|
||||
{
|
||||
return random.NextFloat() * 0.4f;
|
||||
};
|
||||
|
||||
static const Point3 bushVerts[8] =
|
||||
{
|
||||
Point3(-0.5f, 0.f, 0.f), // A (0)
|
||||
Point3(-0.5f, 1.f, 0.f), // B (1)
|
||||
Point3(+0.5f, 1.f, 0.f), // C (2)
|
||||
Point3(+0.5f, 0.f, 0.f), // D (3)
|
||||
Point3(0.f, 0.f, -0.5f), // A2 (4)
|
||||
Point3(0.f, 1.f, -0.5f), // B2 (5)
|
||||
Point3(0.f, 1.f, +0.5f), // C2 (6)
|
||||
Point3(0.f, 0.f, +0.5f) // D2 (7)
|
||||
};
|
||||
static const UINT16 bushIndices[12] =
|
||||
{
|
||||
1, 0, 2,
|
||||
2, 0, 3,
|
||||
5, 6, 4,
|
||||
4, 6, 7
|
||||
};
|
||||
|
||||
struct Bush
|
||||
{
|
||||
float _x, _z;
|
||||
Point3 _vertPos[8];
|
||||
float _phaseShift;
|
||||
};
|
||||
Vector<Bush> vBushes;
|
||||
vBushes.reserve(count);
|
||||
|
||||
VERUS_FOR(i, side)
|
||||
{
|
||||
VERUS_FOR(j, side)
|
||||
{
|
||||
const Point3 bushPos(
|
||||
j * step + RandomStep(),
|
||||
0,
|
||||
i * step + RandomStep());
|
||||
const Vector3 scale(
|
||||
0.8f + RandomScale(),
|
||||
0.8f + RandomScale(),
|
||||
0.8f + RandomScale());
|
||||
const float phaseSin =
|
||||
sin(bushPos.getX() * (VERUS_2PI / 16)) *
|
||||
sin(bushPos.getZ() * (VERUS_2PI / 16)) * 0.5f + 0.5f;
|
||||
const float phase = phaseSin * 0.75f + random.NextFloat() * 0.25f;
|
||||
const float angle = random.NextFloat() * VERUS_2PI;
|
||||
|
||||
const Matrix3 matR = Matrix3::rotationY(angle);
|
||||
const Transform3 tr = VMath::appendScale(Transform3(matR, Vector3(bushPos)), scale);
|
||||
|
||||
Bush bush;
|
||||
bush._x = bushPos.getX();
|
||||
bush._z = bushPos.getZ();
|
||||
VERUS_FOR(k, 8)
|
||||
bush._vertPos[k] = tr * bushVerts[k];
|
||||
bush._phaseShift = phase;
|
||||
vBushes.push_back(bush);
|
||||
}
|
||||
}
|
||||
|
||||
std::shuffle(vBushes.begin(), vBushes.end(), random.GetGenerator());
|
||||
|
||||
const int indexedMeshVertCount = count * 8;
|
||||
_vertCount = 0;
|
||||
_bbVertCount = 0;
|
||||
_vPatchMeshVB.clear();
|
||||
_vPatchMeshVB.resize(indexedMeshVertCount + count);
|
||||
_vPatchMeshIB.clear();
|
||||
_vPatchMeshIB.reserve(count * 12);
|
||||
for (const auto& bush : vBushes)
|
||||
{
|
||||
const int indexOffset = _vertCount;
|
||||
VERUS_FOR(i, 8)
|
||||
{
|
||||
Vertex vertex;
|
||||
vertex._pos[0] = static_cast<short>(bush._vertPos[i].getX() * 1000);
|
||||
vertex._pos[1] = static_cast<short>(bush._vertPos[i].getY() * 1000);
|
||||
vertex._pos[2] = static_cast<short>(bush._vertPos[i].getZ() * 1000);
|
||||
vertex._pos[3] = bush._phaseShift * 99;
|
||||
vertex._tc[0] = _bushTexCoords[0][i][0];
|
||||
vertex._tc[1] = _bushTexCoords[0][i][1];
|
||||
vertex._tc[2] = static_cast<short>(bush._x * 1000);
|
||||
vertex._tc[3] = static_cast<short>(bush._z * 1000);
|
||||
_vPatchMeshVB[_vertCount++] = vertex;
|
||||
|
||||
if (1 == i) // Index with top-left tex coords:
|
||||
{
|
||||
const int offset = indexedMeshVertCount + _bbVertCount;
|
||||
_vPatchMeshVB[offset] = vertex;
|
||||
_bbVertCount++;
|
||||
}
|
||||
}
|
||||
VERUS_FOR(i, 12)
|
||||
_vPatchMeshIB.push_back(bushIndices[i] + indexOffset);
|
||||
}
|
||||
}
|
||||
|
||||
void Grass::ResetAllTextures()
|
||||
{
|
||||
_bushMask = 0;
|
||||
}
|
||||
|
||||
void Grass::SetTexture(int layer, CSZ url, CSZ url2)
|
||||
{
|
||||
VERUS_RT_ASSERT(url);
|
||||
_texLoaded[layer].LoadDDS(url);
|
||||
if (layer < 8)
|
||||
SetTexture(layer + 8, url2 ? url2 : url);
|
||||
}
|
||||
|
||||
void Grass::OnTextureLoaded(int layer)
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
|
||||
const int srcW = 256;
|
||||
const int srcH = 256;
|
||||
const int dstW = 1024;
|
||||
const int xFrom = (layer & 0x3) << 8;
|
||||
const int yFrom = (layer >> 2) << 8;
|
||||
|
||||
const UINT32* pSrc = reinterpret_cast<const UINT32*>(_texLoaded[layer].GetData());
|
||||
|
||||
VERUS_FOR(y, srcH)
|
||||
{
|
||||
const int ySrcOffset = y * srcW;
|
||||
const int yDstOffset = (yFrom + y) * dstW;
|
||||
memcpy(_vTextureSubresData.data() + yDstOffset + xFrom, pSrc + ySrcOffset, srcW * sizeof(UINT32));
|
||||
}
|
||||
_texLoaded[layer].Done();
|
||||
|
||||
_tex->UpdateSubresource(_vTextureSubresData.data());
|
||||
_tex->GenerateMips();
|
||||
|
||||
_bushMask |= (1 << layer);
|
||||
}
|
||||
|
||||
int Grass::BeginMagnet(RcPoint3 pos, float radius)
|
||||
{
|
||||
const int count = _vMagnets.size();
|
||||
VERUS_FOR(i, count)
|
||||
{
|
||||
if (!_vMagnets[i]._active)
|
||||
{
|
||||
_vMagnets[i]._active = true;
|
||||
_vMagnets[i]._pos = pos;
|
||||
_vMagnets[i]._radius = radius;
|
||||
_vMagnets[i]._radiusSq = radius * radius;
|
||||
_vMagnets[i]._radiusSqInv = 1 / _vMagnets[i]._radiusSq;
|
||||
_vMagnets[i]._strength = 0.5f;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Grass::EndMagnet(int index)
|
||||
{
|
||||
_vMagnets[index]._active = false;
|
||||
}
|
||||
|
||||
void Grass::UpdateMagnet(int index, RcPoint3 pos, float radius)
|
||||
{
|
||||
_vMagnets[index]._active = true;
|
||||
_vMagnets[index]._pos = pos;
|
||||
if (radius)
|
||||
{
|
||||
_vMagnets[index]._radius = radius;
|
||||
_vMagnets[index]._radiusSq = radius * radius;
|
||||
_vMagnets[index]._radiusSqInv = 1 / _vMagnets[index]._radiusSq;
|
||||
}
|
||||
}
|
114
Verus/src/Scene/Grass.h
Normal file
114
Verus/src/Scene/Grass.h
Normal file
|
@ -0,0 +1,114 @@
|
|||
#pragma once
|
||||
|
||||
namespace verus
|
||||
{
|
||||
namespace Scene
|
||||
{
|
||||
class Grass : public Object, public Math::QuadtreeIntegralDelegate
|
||||
{
|
||||
public:
|
||||
#include "../Shaders/DS_Grass.inc.hlsl"
|
||||
|
||||
enum PIPE
|
||||
{
|
||||
PIPE_MAIN,
|
||||
PIPE_BILLBOARDS,
|
||||
PIPE_COUNT
|
||||
};
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
short _pos[4]; // {xyz, phaseShift}.
|
||||
short _tc[4]; // {tc0, center.xz}.
|
||||
};
|
||||
VERUS_TYPEDEFS(Vertex);
|
||||
|
||||
struct PerInstanceData
|
||||
{
|
||||
short _patchPos[4];
|
||||
};
|
||||
VERUS_TYPEDEFS(PerInstanceData);
|
||||
|
||||
struct Patch
|
||||
{
|
||||
short i;
|
||||
short j;
|
||||
short h;
|
||||
short type;
|
||||
};
|
||||
VERUS_TYPEDEFS(Patch);
|
||||
|
||||
class Magnet
|
||||
{
|
||||
public:
|
||||
Point3 _pos;
|
||||
float _radius = 1;
|
||||
float _radiusSq = 1;
|
||||
float _radiusSqInv = 1;
|
||||
float _strength = 1;
|
||||
bool _active = false;
|
||||
};
|
||||
VERUS_TYPEDEFS(Magnet);
|
||||
|
||||
static const int s_maxBushTypes = 16;
|
||||
|
||||
private:
|
||||
static CGI::ShaderPwn s_shader;
|
||||
static UB_GrassVS s_ubGrassVS;
|
||||
static UB_GrassFS s_ubGrassFS;
|
||||
|
||||
CGI::GeometryPwn _geo;
|
||||
CGI::PipelinePwns<PIPE_COUNT> _pipe;
|
||||
CGI::TexturePwn _tex;
|
||||
CGI::TextureRAM _texLoaded[s_maxBushTypes];
|
||||
PTerrain _pTerrain = nullptr;
|
||||
Vector<Vertex> _vPatchMeshVB;
|
||||
Vector<UINT16> _vPatchMeshIB;
|
||||
Vector<PerInstanceData> _vInstanceBuffer;
|
||||
Vector<UINT32> _vTextureSubresData;
|
||||
Vector<Patch> _vPatches;
|
||||
Vector<Magnet> _vMagnets;
|
||||
int _mapSide = 0;
|
||||
int _mapShift = 0;
|
||||
int _vertCount = 0;
|
||||
int _bbVertCount = 0;
|
||||
int _instanceCount = 0;
|
||||
int _visiblePatchCount = 0;
|
||||
CGI::CSHandle _cshVS;
|
||||
CGI::CSHandle _cshFS;
|
||||
char _bushTexCoords[s_maxBushTypes][8][2];
|
||||
UINT32 _bushMask = 0;
|
||||
float _phase = 0;
|
||||
|
||||
public:
|
||||
Grass();
|
||||
~Grass();
|
||||
|
||||
static void InitStatic();
|
||||
static void DoneStatic();
|
||||
|
||||
void Init(RTerrain terrain);
|
||||
void Done();
|
||||
|
||||
void Update();
|
||||
void Layout();
|
||||
void Draw();
|
||||
|
||||
void ResetInstanceCount();
|
||||
|
||||
virtual void QuadtreeIntegral_ProcessVisibleNode(const short* ij, RcPoint3 center) override;
|
||||
virtual void QuadtreeIntegral_GetHeights(const short* ij, float height[2]) override;
|
||||
|
||||
VERUS_P(void CreateBuffers());
|
||||
|
||||
void ResetAllTextures();
|
||||
void SetTexture(int layer, CSZ url, CSZ url2 = nullptr);
|
||||
VERUS_P(void OnTextureLoaded(int layer));
|
||||
|
||||
int BeginMagnet(RcPoint3 pos, float radius);
|
||||
void EndMagnet(int index);
|
||||
void UpdateMagnet(int index, RcPoint3 pos, float radius = 0);
|
||||
};
|
||||
VERUS_TYPEDEFS(Grass);
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@ Texture::~Texture()
|
|||
Done();
|
||||
}
|
||||
|
||||
void Texture::Init(CSZ url, bool streamParts, bool sync)
|
||||
void Texture::Init(CSZ url, bool streamParts, bool sync, CGI::PcSamplerDesc pSamplerDesc)
|
||||
{
|
||||
if (_refCount)
|
||||
return;
|
||||
|
@ -26,6 +26,7 @@ void Texture::Init(CSZ url, bool streamParts, bool sync)
|
|||
CGI::TextureDesc texDesc;
|
||||
texDesc._url = url;
|
||||
texDesc._texturePart = _streamParts ? 512 : 0;
|
||||
texDesc._pSamplerDesc = pSamplerDesc;
|
||||
if (sync)
|
||||
texDesc._flags = CGI::TextureDesc::Flags::sync;
|
||||
_texTiny.Init(texDesc);
|
||||
|
@ -81,12 +82,12 @@ void Texture::Update()
|
|||
|
||||
// TexturePtr:
|
||||
|
||||
void TexturePtr::Init(CSZ url, bool streamParts, bool sync)
|
||||
void TexturePtr::Init(CSZ url, bool streamParts, bool sync, CGI::PcSamplerDesc pSamplerDesc)
|
||||
{
|
||||
VERUS_QREF_MM;
|
||||
VERUS_RT_ASSERT(!_p);
|
||||
_p = mm.InsertTexture(url);
|
||||
_p->Init(url, streamParts, sync);
|
||||
_p->Init(url, streamParts, sync, pSamplerDesc);
|
||||
}
|
||||
|
||||
void TexturePwn::Done()
|
||||
|
@ -368,9 +369,10 @@ void Material::FromString(CSZ txt)
|
|||
|
||||
void Material::BindDescriptorSetTextures()
|
||||
{
|
||||
VERUS_RT_ASSERT(-1 == _csh);
|
||||
VERUS_RT_ASSERT(!_csh.IsSet());
|
||||
VERUS_RT_ASSERT(IsLoaded());
|
||||
_csh = Scene::Mesh::GetShader()->BindDescriptorSetTextures(1, { _texAlbedo->GetTex(), _texNormal->GetTex() });
|
||||
VERUS_QREF_MM;
|
||||
_csh = Scene::Mesh::GetShader()->BindDescriptorSetTextures(1, { _texAlbedo->GetTex(), _texNormal->GetTex(), mm.GetDetailTexture(), mm.GetStrassTexture() });
|
||||
}
|
||||
|
||||
bool Material::UpdateMeshUniformBuffer(float motionBlur)
|
||||
|
@ -449,12 +451,23 @@ void MaterialManager::Init()
|
|||
|
||||
void MaterialManager::InitCmd()
|
||||
{
|
||||
CGI::SamplerDesc strassSamplerDesc;
|
||||
strassSamplerDesc.SetFilter("a");
|
||||
strassSamplerDesc.SetAddressMode("rr");
|
||||
strassSamplerDesc._mipLodBias = -2;
|
||||
|
||||
_texDefaultAlbedo.Init("[Textures]:Default.dds", false, true);
|
||||
_texDefaultNormal.Init("[Textures]:Default.NM.dds", false, true);
|
||||
//_texDetail.Init("[Textures]:Detail.FX.dds");
|
||||
//_texStrass.Init("[Textures]:Strass.dds");
|
||||
_texDetail.Init("[Textures]:Detail.FX.dds", false, true);
|
||||
_texStrass.Init("[Textures]:Strass.dds", false, true, &strassSamplerDesc);
|
||||
|
||||
_cshDefault = Scene::Mesh::GetShader()->BindDescriptorSetTextures(1, { _texDefaultAlbedo->GetTex(), _texDefaultNormal->GetTex() });
|
||||
_cshDefault = Scene::Mesh::GetShader()->BindDescriptorSetTextures(1,
|
||||
{
|
||||
_texDefaultAlbedo->GetTex(),
|
||||
_texDefaultNormal->GetTex(),
|
||||
_texDetail->GetTex(),
|
||||
_texStrass->GetTex()
|
||||
});
|
||||
}
|
||||
|
||||
void MaterialManager::Done()
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace verus
|
|||
Texture();
|
||||
~Texture();
|
||||
|
||||
void Init(CSZ url, bool streamParts = false, bool sync = false);
|
||||
void Init(CSZ url, bool streamParts = false, bool sync = false, CGI::PcSamplerDesc pSamplerDes = nullptr);
|
||||
bool Done();
|
||||
void AddRef() { _refCount++; }
|
||||
|
||||
|
@ -33,7 +33,7 @@ namespace verus
|
|||
class TexturePtr : public Ptr<Texture>
|
||||
{
|
||||
public:
|
||||
void Init(CSZ url, bool streamParts = false, bool sync = false);
|
||||
void Init(CSZ url, bool streamParts = false, bool sync = false, CGI::PcSamplerDesc pSamplerDes = nullptr);
|
||||
};
|
||||
VERUS_TYPEDEFS(TexturePtr);
|
||||
|
||||
|
@ -127,7 +127,7 @@ namespace verus
|
|||
glm::vec4 _userColor = glm::vec4(0, 0, 0, 0);
|
||||
Pick _userPick;
|
||||
Blending _blending = Blending::opaque;
|
||||
int _csh = -1;
|
||||
CGI::CSHandle _csh;
|
||||
int _refCount = 0;
|
||||
|
||||
Material();
|
||||
|
@ -152,7 +152,7 @@ namespace verus
|
|||
void FromString(CSZ txt);
|
||||
|
||||
// Mesh interaction:
|
||||
int GetComplexSetHandle() const { return _csh; }
|
||||
CGI::CSHandle GetComplexSetHandle() const { return _csh; }
|
||||
void BindDescriptorSetTextures();
|
||||
bool UpdateMeshUniformBuffer(float motionBlur = 1);
|
||||
|
||||
|
@ -183,7 +183,7 @@ namespace verus
|
|||
TexturePwn _texDefaultNormal;
|
||||
TexturePwn _texDetail;
|
||||
TexturePwn _texStrass;
|
||||
int _cshDefault = -1; // For missing, non-mandatory materials.
|
||||
CGI::CSHandle _cshDefault; // For missing, non-mandatory materials.
|
||||
|
||||
public:
|
||||
MaterialManager();
|
||||
|
@ -200,7 +200,7 @@ namespace verus
|
|||
CGI::TexturePtr GetDetailTexture() { return _texDetail->GetTex(); }
|
||||
CGI::TexturePtr GetStrassTexture() { return _texStrass->GetTex(); }
|
||||
|
||||
int GetDefaultComplexSetHandle() const { return _cshDefault; }
|
||||
CGI::CSHandle GetDefaultComplexSetHandle() const { return _cshDefault; }
|
||||
|
||||
// Textures:
|
||||
PTexture InsertTexture(CSZ url);
|
||||
|
|
|
@ -4,7 +4,7 @@ using namespace verus;
|
|||
using namespace verus::Scene;
|
||||
|
||||
CGI::ShaderPwn Mesh::s_shader;
|
||||
CGI::PipelinePwns<Mesh::PIPE_MAX> Mesh::s_pipe;
|
||||
CGI::PipelinePwns<Mesh::PIPE_COUNT> Mesh::s_pipe;
|
||||
|
||||
Mesh::UB_PerFrame Mesh::s_ubPerFrame;
|
||||
Mesh::UB_PerMaterialFS Mesh::s_ubPerMaterialFS;
|
||||
|
@ -28,11 +28,13 @@ void Mesh::InitStatic()
|
|||
VERUS_QREF_CONST_SETTINGS;
|
||||
|
||||
s_shader.Init("[Shaders]:DS_Mesh.hlsl");
|
||||
s_shader->CreateDescriptorSet(0, &s_ubPerFrame, sizeof(s_ubPerFrame), settings.GetLimits()._mesh_ubPerFrameCapacity);
|
||||
s_shader->CreateDescriptorSet(0, &s_ubPerFrame, sizeof(s_ubPerFrame), settings.GetLimits()._mesh_ubPerFrameCapacity, {}, CGI::ShaderStageFlags::vs_hs_ds_fs);
|
||||
s_shader->CreateDescriptorSet(1, &s_ubPerMaterialFS, sizeof(s_ubPerMaterialFS), settings.GetLimits()._mesh_ubPerMaterialFSCapacity,
|
||||
{
|
||||
CGI::Sampler::aniso,
|
||||
CGI::Sampler::aniso
|
||||
CGI::Sampler::aniso,
|
||||
CGI::Sampler::aniso,
|
||||
CGI::Sampler::custom
|
||||
}, CGI::ShaderStageFlags::fs);
|
||||
s_shader->CreateDescriptorSet(2, &s_ubPerMeshVS, sizeof(s_ubPerMeshVS), settings.GetLimits()._mesh_ubPerMeshVSCapacity, {}, CGI::ShaderStageFlags::vs);
|
||||
s_shader->CreateDescriptorSet(3, &s_ubSkeletonVS, sizeof(s_ubSkeletonVS), settings.GetLimits()._mesh_ubSkinningVSCapacity, {}, CGI::ShaderStageFlags::vs);
|
||||
|
@ -69,29 +71,92 @@ void Mesh::Done()
|
|||
void Mesh::BindPipeline(PIPE pipe, CGI::CommandBufferPtr cb)
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
VERUS_QREF_CONST_SETTINGS;
|
||||
VERUS_QREF_ATMO;
|
||||
|
||||
if (!settings._gpuTessellation) // Fallback:
|
||||
{
|
||||
switch (pipe)
|
||||
{
|
||||
case PIPE_TESS: pipe = PIPE_MAIN; break;
|
||||
case PIPE_TESS_ROBOTIC: pipe = PIPE_ROBOTIC; break;
|
||||
case PIPE_TESS_SKINNED: pipe = PIPE_SKINNED; break;
|
||||
};
|
||||
}
|
||||
|
||||
if (!s_pipe[pipe])
|
||||
{
|
||||
static CSZ branches[] =
|
||||
{
|
||||
"#",
|
||||
"#Robotic",
|
||||
"#Skinned",
|
||||
|
||||
"#Instanced",
|
||||
|
||||
"#Depth",
|
||||
"#DepthRobotic",
|
||||
"#DepthSkinned",
|
||||
"#Instanced",
|
||||
"#Robotic",
|
||||
"#Skinned"
|
||||
|
||||
"#Tess",
|
||||
"#TessRobotic",
|
||||
"#TessSkinned",
|
||||
|
||||
"#SolidColor",
|
||||
"#SolidColorRobotic",
|
||||
"#SolidColorSkinned",
|
||||
};
|
||||
|
||||
CGI::PipelineDesc pipeDesc(_geo, s_shader, branches[pipe], renderer.GetDS().GetRenderPassHandle());
|
||||
switch (pipe)
|
||||
|
||||
auto SetBlendEqsForDS = [&pipeDesc]()
|
||||
{
|
||||
case PIPE_DEPTH_ROBOTIC:
|
||||
case PIPE_DEPTH_SKINNED:
|
||||
pipeDesc._colorAttachBlendEqs[0] = "";
|
||||
pipeDesc.EnableDepthBias();
|
||||
default:
|
||||
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_OFF;
|
||||
pipeDesc._colorAttachBlendEqs[1] = VERUS_COLOR_BLEND_OFF;
|
||||
pipeDesc._colorAttachBlendEqs[2] = VERUS_COLOR_BLEND_OFF;
|
||||
pipeDesc._colorAttachBlendEqs[3] = VERUS_COLOR_BLEND_OFF;
|
||||
};
|
||||
|
||||
switch (pipe)
|
||||
{
|
||||
case PIPE_MAIN:
|
||||
case PIPE_ROBOTIC:
|
||||
case PIPE_SKINNED:
|
||||
{
|
||||
SetBlendEqsForDS();
|
||||
}
|
||||
break;
|
||||
case PIPE_DEPTH:
|
||||
case PIPE_DEPTH_ROBOTIC:
|
||||
case PIPE_DEPTH_SKINNED:
|
||||
{
|
||||
pipeDesc._colorAttachBlendEqs[0] = "";
|
||||
pipeDesc._renderPassHandle = atmo.GetShadowMap().GetRenderPassHandle();
|
||||
}
|
||||
break;
|
||||
case PIPE_TESS:
|
||||
case PIPE_TESS_ROBOTIC:
|
||||
case PIPE_TESS_SKINNED:
|
||||
{
|
||||
SetBlendEqsForDS();
|
||||
if (settings._gpuTessellation)
|
||||
pipeDesc._topology = CGI::PrimitiveTopology::patchList3;
|
||||
}
|
||||
break;
|
||||
case PIPE_WIREFRAME:
|
||||
case PIPE_WIREFRAME_ROBOTIC:
|
||||
case PIPE_WIREFRAME_SKINNED:
|
||||
{
|
||||
SetBlendEqsForDS();
|
||||
pipeDesc._rasterizationState._polygonMode = CGI::PolygonMode::line;
|
||||
pipeDesc._rasterizationState._depthBiasEnable = true;
|
||||
pipeDesc._rasterizationState._depthBiasConstantFactor = -1000;
|
||||
pipeDesc._depthCompareOp = CGI::CompareOp::lessOrEqual;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
SetBlendEqsForDS();
|
||||
}
|
||||
}
|
||||
pipeDesc._vertexInputBindingsFilter = _bindingsMask;
|
||||
s_pipe[pipe].Init(pipeDesc);
|
||||
|
@ -99,6 +164,29 @@ void Mesh::BindPipeline(PIPE pipe, CGI::CommandBufferPtr cb)
|
|||
cb->BindPipeline(s_pipe[pipe]);
|
||||
}
|
||||
|
||||
void Mesh::BindPipeline(CGI::CommandBufferPtr cb, bool allowTess)
|
||||
{
|
||||
VERUS_QREF_ATMO;
|
||||
if (_skeleton.IsInitialized())
|
||||
{
|
||||
if (atmo.GetShadowMap().IsRendering())
|
||||
BindPipeline(Scene::Mesh::PIPE_DEPTH_SKINNED, cb);
|
||||
else if (allowTess)
|
||||
BindPipeline(Scene::Mesh::PIPE_TESS_SKINNED, cb);
|
||||
else
|
||||
BindPipeline(Scene::Mesh::PIPE_SKINNED, cb);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (atmo.GetShadowMap().IsRendering())
|
||||
BindPipeline(Scene::Mesh::PIPE_DEPTH, cb);
|
||||
else if (allowTess)
|
||||
BindPipeline(Scene::Mesh::PIPE_TESS, cb);
|
||||
else
|
||||
BindPipeline(Scene::Mesh::PIPE_MAIN, cb);
|
||||
}
|
||||
}
|
||||
|
||||
void Mesh::BindGeo(CGI::CommandBufferPtr cb)
|
||||
{
|
||||
BindGeo(cb, _bindingsMask);
|
||||
|
@ -112,10 +200,12 @@ void Mesh::BindGeo(CGI::CommandBufferPtr cb, UINT32 bindingsFilter)
|
|||
|
||||
void Mesh::UpdateUniformBufferPerFrame()
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
VERUS_QREF_SM;
|
||||
s_ubPerFrame._matV = sm.GetCamera()->GetMatrixV().UniformBufferFormat();
|
||||
s_ubPerFrame._matP = sm.GetCamera()->GetMatrixP().UniformBufferFormat();
|
||||
s_ubPerFrame._matVP = sm.GetCamera()->GetMatrixVP().UniformBufferFormat();
|
||||
s_ubPerFrame._matP = sm.GetCamera()->GetMatrixP().UniformBufferFormat();
|
||||
s_ubPerFrame._viewportSize = renderer.GetCommandBuffer()->GetViewportSize().GLM();
|
||||
}
|
||||
|
||||
void Mesh::UpdateUniformBufferPerMaterialFS()
|
||||
|
@ -144,17 +234,17 @@ void Mesh::UpdateUniformBufferSkeletonVS()
|
|||
_skeleton.UpdateUniformBufferArray(s_ubSkeletonVS._vMatBones);
|
||||
}
|
||||
|
||||
void Mesh::UpdateUniformBufferPerObject(RcTransform3 tr)
|
||||
void Mesh::UpdateUniformBufferPerObject(RcTransform3 tr, RcVector4 color)
|
||||
{
|
||||
s_ubPerObject._matW = tr.UniformBufferFormat();
|
||||
s_ubPerObject._userColor = Vector4(1, 0, 0, 1).GLM();
|
||||
s_ubPerObject._userColor = color.GLM();
|
||||
}
|
||||
|
||||
void Mesh::UpdateUniformBufferPerObject(Point3 pos)
|
||||
void Mesh::UpdateUniformBufferPerObject(Point3 pos, RcVector4 color)
|
||||
{
|
||||
const Transform3 matT = Transform3::translation(Vector3(pos));
|
||||
s_ubPerObject._matW = matT.UniformBufferFormat();
|
||||
s_ubPerObject._userColor = Vector4(1, 0, 0, 1).GLM();
|
||||
s_ubPerObject._userColor = color.GLM();
|
||||
}
|
||||
|
||||
void Mesh::CreateDeviceBuffers()
|
||||
|
@ -162,25 +252,25 @@ void Mesh::CreateDeviceBuffers()
|
|||
_bindingsMask = 0;
|
||||
|
||||
CGI::GeometryDesc geoDesc;
|
||||
const CGI::InputElementDesc ied[] =
|
||||
const CGI::VertexInputAttrDesc viaDesc[] =
|
||||
{
|
||||
{0, offsetof(VertexInputBinding0, _pos), CGI::IeType::shorts, 4, CGI::IeUsage::position, 0},
|
||||
{0, offsetof(VertexInputBinding0, _tc0), CGI::IeType::shorts, 2, CGI::IeUsage::texCoord, 0},
|
||||
{0, offsetof(VertexInputBinding0, _nrm), CGI::IeType::ubytes, 4, CGI::IeUsage::normal, 0},
|
||||
{1, offsetof(VertexInputBinding1, _bw), CGI::IeType::shorts, 4, CGI::IeUsage::texCoord, 4},
|
||||
{1, offsetof(VertexInputBinding1, _bi), CGI::IeType::shorts, 4, CGI::IeUsage::texCoord, 5},
|
||||
{2, offsetof(VertexInputBinding2, _tan), CGI::IeType::shorts, 4, CGI::IeUsage::tangent, 6},
|
||||
{2, offsetof(VertexInputBinding2, _bin), CGI::IeType::shorts, 4, CGI::IeUsage::binormal, 7},
|
||||
{1, offsetof(VertexInputBinding1, _bw), CGI::IeType::shorts, 4, CGI::IeUsage::blendWeights, 0},
|
||||
{1, offsetof(VertexInputBinding1, _bi), CGI::IeType::shorts, 4, CGI::IeUsage::blendIndices, 0},
|
||||
{2, offsetof(VertexInputBinding2, _tan), CGI::IeType::shorts, 4, CGI::IeUsage::tangent, 0},
|
||||
{2, offsetof(VertexInputBinding2, _bin), CGI::IeType::shorts, 4, CGI::IeUsage::binormal, 0},
|
||||
{3, offsetof(VertexInputBinding3, _tc1), CGI::IeType::shorts, 2, CGI::IeUsage::texCoord, 1},
|
||||
{3, offsetof(VertexInputBinding3, _clr), CGI::IeType::ubytes, 4, CGI::IeUsage::color, 0},
|
||||
|
||||
{-4, offsetof(PerInstanceData, _matPart0), CGI::IeType::floats, 4, CGI::IeUsage::texCoord, 8},
|
||||
{-4, offsetof(PerInstanceData, _matPart1), CGI::IeType::floats, 4, CGI::IeUsage::texCoord, 9},
|
||||
{-4, offsetof(PerInstanceData, _matPart2), CGI::IeType::floats, 4, CGI::IeUsage::texCoord, 10},
|
||||
{-4, offsetof(PerInstanceData, _instData), CGI::IeType::floats, 4, CGI::IeUsage::texCoord, 11},
|
||||
CGI::InputElementDesc::End()
|
||||
{-4, offsetof(PerInstanceData, _matPart0), CGI::IeType::floats, 4, CGI::IeUsage::instData, 0},
|
||||
{-4, offsetof(PerInstanceData, _matPart1), CGI::IeType::floats, 4, CGI::IeUsage::instData, 1},
|
||||
{-4, offsetof(PerInstanceData, _matPart2), CGI::IeType::floats, 4, CGI::IeUsage::instData, 2},
|
||||
{-4, offsetof(PerInstanceData, _instData), CGI::IeType::floats, 4, CGI::IeUsage::instData, 3},
|
||||
CGI::VertexInputAttrDesc::End()
|
||||
};
|
||||
geoDesc._pInputElementDesc = ied;
|
||||
geoDesc._pVertexInputAttrDesc = viaDesc;
|
||||
const int strides[] = { sizeof(VertexInputBinding0), sizeof(VertexInputBinding1), sizeof(VertexInputBinding2), sizeof(VertexInputBinding3), sizeof(PerInstanceData), 0 };
|
||||
geoDesc._pStrides = strides;
|
||||
geoDesc._32BitIndices = _vIndices.empty();
|
||||
|
@ -236,7 +326,7 @@ void Mesh::CreateDeviceBuffers()
|
|||
}
|
||||
}
|
||||
|
||||
void Mesh::BufferDataVB(const void* p, int binding)
|
||||
void Mesh::UpdateVertexBuffer(const void* p, int binding)
|
||||
{
|
||||
_geo->UpdateVertexBuffer(p, binding);
|
||||
}
|
||||
|
|
|
@ -12,12 +12,24 @@ namespace verus
|
|||
enum PIPE
|
||||
{
|
||||
PIPE_MAIN,
|
||||
PIPE_DEPTH_ROBOTIC,
|
||||
PIPE_DEPTH_SKINNED,
|
||||
PIPE_INSTANCED,
|
||||
PIPE_ROBOTIC,
|
||||
PIPE_SKINNED,
|
||||
PIPE_MAX
|
||||
|
||||
PIPE_INSTANCED,
|
||||
|
||||
PIPE_DEPTH,
|
||||
PIPE_DEPTH_ROBOTIC,
|
||||
PIPE_DEPTH_SKINNED,
|
||||
|
||||
PIPE_TESS,
|
||||
PIPE_TESS_ROBOTIC,
|
||||
PIPE_TESS_SKINNED,
|
||||
|
||||
PIPE_WIREFRAME,
|
||||
PIPE_WIREFRAME_ROBOTIC,
|
||||
PIPE_WIREFRAME_SKINNED,
|
||||
|
||||
PIPE_COUNT
|
||||
};
|
||||
|
||||
struct PerInstanceData
|
||||
|
@ -30,7 +42,7 @@ namespace verus
|
|||
|
||||
private:
|
||||
static CGI::ShaderPwn s_shader;
|
||||
static CGI::PipelinePwns<PIPE_MAX> s_pipe;
|
||||
static CGI::PipelinePwns<PIPE_COUNT> s_pipe;
|
||||
static UB_PerFrame s_ubPerFrame;
|
||||
static UB_PerMaterialFS s_ubPerMaterialFS;
|
||||
static UB_PerMeshVS s_ubPerMeshVS;
|
||||
|
@ -64,6 +76,7 @@ namespace verus
|
|||
void Done();
|
||||
|
||||
void BindPipeline(PIPE pipe, CGI::CommandBufferPtr cb);
|
||||
void BindPipeline(CGI::CommandBufferPtr cb, bool allowTess = true);
|
||||
void BindGeo(CGI::CommandBufferPtr cb);
|
||||
void BindGeo(CGI::CommandBufferPtr cb, UINT32 bindingsFilter);
|
||||
|
||||
|
@ -73,12 +86,12 @@ namespace verus
|
|||
void UpdateUniformBufferPerMaterialFS();
|
||||
void UpdateUniformBufferPerMeshVS();
|
||||
void UpdateUniformBufferSkeletonVS();
|
||||
void UpdateUniformBufferPerObject(RcTransform3 tr);
|
||||
void UpdateUniformBufferPerObject(Point3 pos);
|
||||
void UpdateUniformBufferPerObject(RcTransform3 tr, RcVector4 color = Vector4(0.5f, 0.5f, 0.5f, 1));
|
||||
void UpdateUniformBufferPerObject(Point3 pos, RcVector4 color = Vector4(0.5f, 0.5f, 0.5f, 1));
|
||||
|
||||
CGI::GeometryPtr GetGeometry() const { return _geo; }
|
||||
virtual void CreateDeviceBuffers() override;
|
||||
virtual void BufferDataVB(const void* p, int binding) override;
|
||||
virtual void UpdateVertexBuffer(const void* p, int binding) override;
|
||||
|
||||
// Instancing:
|
||||
void PushInstance(RcTransform3 matW, RcVector4 instData);
|
||||
|
|
|
@ -8,9 +8,11 @@ namespace verus
|
|||
Scene::MaterialManager::Make();
|
||||
Scene::SceneManager::Make();
|
||||
Scene::Atmosphere::Make();
|
||||
Scene::Water::Make();
|
||||
}
|
||||
void Free_Scene()
|
||||
{
|
||||
Scene::Water::Free();
|
||||
Scene::Atmosphere::Free();
|
||||
Scene::SceneManager::Free();
|
||||
Scene::MaterialManager::Free();
|
||||
|
|
|
@ -6,8 +6,10 @@
|
|||
#include "Mesh.h"
|
||||
#include "Terrain.h"
|
||||
#include "EditorTerrain.h"
|
||||
#include "Grass.h"
|
||||
#include "ShadowMap.h"
|
||||
#include "Atmosphere.h"
|
||||
#include "Water.h"
|
||||
#include "MaterialManager.h"
|
||||
#include "SceneManager.h"
|
||||
#include "Helpers.h"
|
||||
|
|
|
@ -24,24 +24,17 @@ void ShadowMap::Init(int side)
|
|||
|
||||
_side = side;
|
||||
|
||||
_rp = renderer->CreateRenderPass(
|
||||
{
|
||||
CGI::RP::Attachment("Depth", CGI::Format::unormD16).LoadOpClear().Layout(CGI::ImageLayout::depthStencilReadOnly),
|
||||
},
|
||||
{
|
||||
CGI::RP::Subpass("Sp0").Color({}).DepthStencil(CGI::RP::Ref("Depth", CGI::ImageLayout::depthStencilAttachment)),
|
||||
},
|
||||
{});
|
||||
_rph = renderer->CreateShadowRenderPass(CGI::Format::unormD24uintS8);
|
||||
|
||||
CGI::TextureDesc texDesc;
|
||||
texDesc._clearValue = Vector4(1);
|
||||
texDesc._format = CGI::Format::unormD16;
|
||||
texDesc._format = CGI::Format::unormD24uintS8;
|
||||
texDesc._width = _side;
|
||||
texDesc._height = _side;
|
||||
texDesc._flags = CGI::TextureDesc::Flags::depthSampled;
|
||||
texDesc._flags = CGI::TextureDesc::Flags::depthSampledR;
|
||||
_tex.Init(texDesc);
|
||||
|
||||
_fb = renderer->CreateFramebuffer(_rp,
|
||||
_fbh = renderer->CreateFramebuffer(_rph,
|
||||
{
|
||||
_tex
|
||||
},
|
||||
|
@ -61,9 +54,9 @@ void ShadowMap::Begin(RcVector3 dirToSun, float zNear, float zFar)
|
|||
|
||||
const Vector3 up(0, 1, 0);
|
||||
Point3 eye, at;
|
||||
const float size = 4096 * 0.01f;
|
||||
const float size = 4096 * 0.005f;
|
||||
if (0 == zFar)
|
||||
zFar = 0x10000 * 0.005f;
|
||||
zFar = 1001;
|
||||
|
||||
at = sm.GetCamera()->GetEyePosition() + sm.GetCamera()->GetFrontDirection() * (size * (1 / 3.f));
|
||||
if (_snapToTexels)
|
||||
|
@ -77,7 +70,7 @@ void ShadowMap::Begin(RcVector3 dirToSun, float zNear, float zFar)
|
|||
atPosShadowSpaceSnapped.setY(atPosShadowSpaceSnapped.getY() - fmod(static_cast<float>(atPosShadowSpaceSnapped.getY()), texelSize));
|
||||
at = (matFromShadowSpace * atPosShadowSpaceSnapped).getXYZ();
|
||||
}
|
||||
eye = at + dirToSun * ((zNear + zFar) * 0.5f);
|
||||
eye = at + dirToSun * ((zFar - zNear) * 0.5f);
|
||||
|
||||
// Setup light space camera and use it (used for terrain draw, etc.):
|
||||
_camera.SetUpDirection(up);
|
||||
|
@ -91,9 +84,9 @@ void ShadowMap::Begin(RcVector3 dirToSun, float zNear, float zFar)
|
|||
_camera.Update();
|
||||
_pSceneCamera = sm.SetCamera(&_camera);
|
||||
|
||||
_config.setX((zFar - zNear) * 2);
|
||||
_config._penumbraScale = (zFar - zNear) * 2;
|
||||
|
||||
renderer.GetCommandBuffer()->BeginRenderPass(_rp, _fb,
|
||||
renderer.GetCommandBuffer()->BeginRenderPass(_rph, _fbh,
|
||||
{
|
||||
_tex->GetClearValue()
|
||||
});
|
||||
|
@ -199,25 +192,20 @@ void CascadedShadowMap::Init(int side)
|
|||
VERUS_QREF_RENDERER;
|
||||
|
||||
_side = side;
|
||||
if (settings._sceneShadowQuality >= App::Settings::ShadowQuality::ultra)
|
||||
_side *= 2;
|
||||
|
||||
_rp = renderer->CreateRenderPass(
|
||||
{
|
||||
CGI::RP::Attachment("Depth", CGI::Format::floatD32).LoadOpClear().Layout(CGI::ImageLayout::depthStencilReadOnly),
|
||||
},
|
||||
{
|
||||
CGI::RP::Subpass("Sp0").Color({}).DepthStencil(CGI::RP::Ref("Depth", CGI::ImageLayout::depthStencilAttachment)),
|
||||
},
|
||||
{});
|
||||
_rph = renderer->CreateShadowRenderPass(CGI::Format::unormD24uintS8);
|
||||
|
||||
CGI::TextureDesc texDesc;
|
||||
texDesc._clearValue = Vector4(1);
|
||||
texDesc._format = CGI::Format::floatD32;
|
||||
texDesc._format = CGI::Format::unormD24uintS8;
|
||||
texDesc._width = _side;
|
||||
texDesc._height = _side;
|
||||
texDesc._flags = CGI::TextureDesc::Flags::depthSampled;
|
||||
texDesc._flags = CGI::TextureDesc::Flags::depthSampledR;
|
||||
_tex.Init(texDesc);
|
||||
|
||||
_fb = renderer->CreateFramebuffer(_rp,
|
||||
_fbh = renderer->CreateFramebuffer(_rph,
|
||||
{
|
||||
_tex
|
||||
},
|
||||
|
@ -251,12 +239,14 @@ void CascadedShadowMap::Begin(RcVector3 dirToSun, float zNear, float zFar, int s
|
|||
|
||||
const Vector3 up(0, 1, 0);
|
||||
Point3 eye, at;
|
||||
int sideW, sideH, side;
|
||||
float sizeW, sizeH;
|
||||
|
||||
float zNearFrustum, zFarFrustum;
|
||||
const float closerToLight = 10000;
|
||||
const float closerToLight = 1500;
|
||||
const Matrix4 matToLightSpace = Matrix4::lookAt(Point3(0), Point3(-dirToSun), up);
|
||||
const float range = Math::Min(1000.f, cam.GetZFar() - cam.GetZNear()); // Clip terrain, etc.
|
||||
const float maxRange = (settings._sceneShadowQuality >= App::Settings::ShadowQuality::ultra) ? 850 : 350;
|
||||
const float range = Math::Min<float>(maxRange, cam.GetZFar() - cam.GetZNear()); // Clip terrain, etc.
|
||||
_camera = cam;
|
||||
|
||||
if (0 == _currentSplit)
|
||||
|
@ -277,8 +267,10 @@ void CascadedShadowMap::Begin(RcVector3 dirToSun, float zNear, float zFar, int s
|
|||
if (0 == zFar)
|
||||
zFar = abs(zFarFrustum - zNearFrustum) + closerToLight;
|
||||
|
||||
sizeW = static_cast<float>(int(frustumBounds.getZ() - frustumBounds.getX() + 0.5f) + 2);
|
||||
sizeH = static_cast<float>(int(frustumBounds.getW() - frustumBounds.getY() + 0.5f) + 2);
|
||||
sideW = static_cast<int>(frustumBounds.getZ() - frustumBounds.getX() + 2.5f);
|
||||
sideH = static_cast<int>(frustumBounds.getW() - frustumBounds.getY() + 2.5f);
|
||||
sizeW = sideW;
|
||||
sizeH = sideH;
|
||||
|
||||
// Setup CSM light space camera for full range (used for terrain layout, etc.):
|
||||
_cameraCSM.SetUpDirection(up);
|
||||
|
@ -327,14 +319,26 @@ void CascadedShadowMap::Begin(RcVector3 dirToSun, float zNear, float zFar, int s
|
|||
(frustumBounds.getY() + frustumBounds.getW()) * 0.5f,
|
||||
zNearFrustum);
|
||||
|
||||
sizeW = static_cast<float>(int(frustumBounds.getZ() - frustumBounds.getX() + 0.5f) + 2);
|
||||
sizeH = static_cast<float>(int(frustumBounds.getW() - frustumBounds.getY() + 0.5f) + 2);
|
||||
sideW = static_cast<int>(frustumBounds.getZ() - frustumBounds.getX() + 2.5f);
|
||||
sideH = static_cast<int>(frustumBounds.getW() - frustumBounds.getY() + 2.5f);
|
||||
if (_currentSplit < 3)
|
||||
{
|
||||
side = (sideW < sideH) ? sideH : sideW;
|
||||
side = Math::NextPowerOfTwo(side);
|
||||
sizeW = side;
|
||||
sizeH = side;
|
||||
}
|
||||
else
|
||||
{
|
||||
sizeW = sideW;
|
||||
sizeH = sideH;
|
||||
}
|
||||
|
||||
if (_snapToTexels)
|
||||
{
|
||||
const float sideInv = 2.f / _side;
|
||||
pos.setX(pos.getX() - fmod(static_cast<float>(pos.getX()), sizeW* sideInv));
|
||||
pos.setY(pos.getY() - fmod(static_cast<float>(pos.getY()), sizeH* sideInv));
|
||||
pos.setX(pos.getX() - fmod(static_cast<float>(pos.getX()), sizeW * sideInv));
|
||||
pos.setY(pos.getY() - fmod(static_cast<float>(pos.getY()), sizeH * sideInv));
|
||||
}
|
||||
pos = (VMath::orthoInverse(matToLightSpace) * pos).getXYZ(); // To world space.
|
||||
|
||||
|
@ -357,11 +361,11 @@ void CascadedShadowMap::Begin(RcVector3 dirToSun, float zNear, float zFar, int s
|
|||
_camera.Update();
|
||||
_pSceneCamera = sm.SetCamera(&_camera);
|
||||
|
||||
_config.setX((zFar - zNear) * 2);
|
||||
_config._penumbraScale = (zFar - zNear) * 2;
|
||||
|
||||
if (0 == _currentSplit)
|
||||
{
|
||||
renderer.GetCommandBuffer()->BeginRenderPass(_rp, _fb,
|
||||
renderer.GetCommandBuffer()->BeginRenderPass(_rph, _fbh,
|
||||
{
|
||||
_tex->GetClearValue()
|
||||
});
|
||||
|
|
|
@ -6,16 +6,26 @@ namespace verus
|
|||
{
|
||||
class ShadowMap : public Object
|
||||
{
|
||||
public:
|
||||
struct Config
|
||||
{
|
||||
float _penumbraScale = 0;
|
||||
float _penumbraLamBiasScale = 2.5f;
|
||||
float _normalDepthBias = 0.012f;
|
||||
float _csmContrastScale = 2.8f;
|
||||
};
|
||||
VERUS_TYPEDEFS(Config);
|
||||
|
||||
protected:
|
||||
Matrix4 _matShadow;
|
||||
Matrix4 _matShadowDS;
|
||||
Vector4 _config = Vector4(0);
|
||||
Config _config;
|
||||
CGI::TexturePwn _tex;
|
||||
Camera _camera;
|
||||
PCamera _pSceneCamera = nullptr;
|
||||
int _side = 0;
|
||||
int _rp = -1;
|
||||
int _fb = -1;
|
||||
CGI::RPHandle _rph;
|
||||
CGI::FBHandle _fbh;
|
||||
bool _snapToTexels = true;
|
||||
bool _rendering = false;
|
||||
|
||||
|
@ -29,7 +39,7 @@ namespace verus
|
|||
void SetSnapToTexels(bool b) { _snapToTexels = b; }
|
||||
bool IsRendering() const { return _rendering; }
|
||||
|
||||
int GetRenderPassHandle() const { return _rp; }
|
||||
CGI::RPHandle GetRenderPassHandle() const { return _rph; }
|
||||
|
||||
void Begin(RcVector3 dirToSun, float zNear = 1, float zFar = 0);
|
||||
void BeginLight(RcPoint3 pos, RcPoint3 target, float side = 10);
|
||||
|
@ -38,7 +48,7 @@ namespace verus
|
|||
RcMatrix4 GetShadowMatrix() const;
|
||||
RcMatrix4 GetShadowMatrixDS() const;
|
||||
|
||||
RcVector4 GetConfig() { return _config; }
|
||||
RConfig GetConfig() { return _config; }
|
||||
|
||||
CGI::TexturePtr GetTexture() const;
|
||||
|
||||
|
|
|
@ -3,9 +3,11 @@
|
|||
using namespace verus;
|
||||
using namespace verus::Scene;
|
||||
|
||||
CGI::ShaderPwn Terrain::s_shader;
|
||||
Terrain::UB_DrawDepth Terrain::s_ubDrawDepth;
|
||||
Terrain::UB_PerMaterialFS Terrain::s_ubPerMaterialFS;
|
||||
CGI::ShaderPwns<Terrain::SHADER_COUNT> Terrain::s_shader;
|
||||
Terrain::UB_TerrainVS Terrain::s_ubTerrainVS;
|
||||
Terrain::UB_TerrainFS Terrain::s_ubTerrainFS;
|
||||
Terrain::UB_SimpleTerrainVS Terrain::s_ubSimpleTerrainVS;
|
||||
Terrain::UB_SimpleTerrainFS Terrain::s_ubSimpleTerrainFS;
|
||||
|
||||
// TerrainPhysics:
|
||||
|
||||
|
@ -76,19 +78,67 @@ void TerrainPhysics::EnableDebugDraw(bool b)
|
|||
|
||||
// TerrainLOD:
|
||||
|
||||
void TerrainLOD::Init(int sidePoly, int step)
|
||||
void TerrainLOD::Init(int sidePoly, int step, bool addEdgeTess)
|
||||
{
|
||||
_side = sidePoly + 1;
|
||||
_vertCount = _side * _side;
|
||||
if (1 == step)
|
||||
Math::BuildListGrid(sidePoly, sidePoly, _vIB);
|
||||
Math::CreateListGrid(sidePoly, sidePoly, _vIB);
|
||||
else
|
||||
Math::BuildStripGrid(sidePoly, sidePoly, _vIB);
|
||||
_indexCount = Utils::Cast32(_vIB.size());
|
||||
Math::CreateStripGrid(sidePoly, sidePoly, _vIB);
|
||||
_firstIndex = 0;
|
||||
|
||||
if (addEdgeTess)
|
||||
{
|
||||
const int extraVerts = sidePoly * 4;
|
||||
_vIB.reserve(_vIB.capacity() + extraVerts * 4);
|
||||
_vIB.push_back(0xFFFF);
|
||||
auto ComputeIndex = [this](int i, int j)
|
||||
{
|
||||
return i * _side + j;
|
||||
};
|
||||
|
||||
// Bottom, forwards:
|
||||
VERUS_FOR(i, sidePoly)
|
||||
{
|
||||
_vIB.push_back(ComputeIndex(sidePoly, i));
|
||||
_vIB.push_back(_vertCount + i);
|
||||
_vIB.push_back(ComputeIndex(sidePoly, i + 1));
|
||||
_vIB.push_back(0xFFFF);
|
||||
}
|
||||
// Right, backwards:
|
||||
VERUS_FOR(i, sidePoly)
|
||||
{
|
||||
_vIB.push_back(ComputeIndex(sidePoly - i, sidePoly));
|
||||
_vIB.push_back(_vertCount + sidePoly + i);
|
||||
_vIB.push_back(ComputeIndex(sidePoly - i - 1, sidePoly));
|
||||
_vIB.push_back(0xFFFF);
|
||||
}
|
||||
// Top, backwards:
|
||||
VERUS_FOR(i, sidePoly)
|
||||
{
|
||||
_vIB.push_back(ComputeIndex(0, sidePoly - i));
|
||||
_vIB.push_back(_vertCount + sidePoly * 2 + i);
|
||||
_vIB.push_back(ComputeIndex(0, sidePoly - i - 1));
|
||||
_vIB.push_back(0xFFFF);
|
||||
}
|
||||
// Left, forwards:
|
||||
VERUS_FOR(i, sidePoly)
|
||||
{
|
||||
_vIB.push_back(ComputeIndex(i, 0));
|
||||
_vIB.push_back(_vertCount + sidePoly * 3 + i);
|
||||
_vIB.push_back(ComputeIndex(i + 1, 0));
|
||||
if (_vIB.size() < _vIB.capacity())
|
||||
_vIB.push_back(0xFFFF);
|
||||
}
|
||||
|
||||
_vertCount += extraVerts;
|
||||
VERUS_RT_ASSERT(Math::CheckIndexBuffer(_vIB, _vertCount - 1));
|
||||
}
|
||||
_indexCount = Utils::Cast32(_vIB.size());
|
||||
}
|
||||
|
||||
void TerrainLOD::InitGeo(short* pV, UINT16* pI, int vertexOffset)
|
||||
void TerrainLOD::InitGeo(short* pV, UINT16* pI, int vertexOffset, bool addEdgeTess)
|
||||
{
|
||||
const int edge = _side - 1;
|
||||
const int step = 16 / edge;
|
||||
|
@ -121,6 +171,39 @@ void TerrainLOD::InitGeo(short* pV, UINT16* pI, int vertexOffset)
|
|||
if (_vIB[i] != 0xFFFF)
|
||||
_vIB[i] -= vertexOffset;
|
||||
}
|
||||
|
||||
if (addEdgeTess)
|
||||
{
|
||||
const int halfStep = step / 2;
|
||||
const int vertCount = _side * _side;
|
||||
const int sidePoly = _side - 1;
|
||||
const short minPos = 0;
|
||||
const short maxPos = 16;
|
||||
VERUS_FOR(i, sidePoly)
|
||||
{
|
||||
pV[((vertCount + i) << 2) + 0] = halfStep + i * step;
|
||||
pV[((vertCount + i) << 2) + 2] = maxPos;
|
||||
pV[((vertCount + i) << 2) + 3] = -1;
|
||||
}
|
||||
VERUS_FOR(i, sidePoly)
|
||||
{
|
||||
pV[((vertCount + sidePoly + i) << 2) + 0] = maxPos;
|
||||
pV[((vertCount + sidePoly + i) << 2) + 2] = halfStep + (sidePoly - i - 1) * step;
|
||||
pV[((vertCount + sidePoly + i) << 2) + 1] = -1;
|
||||
}
|
||||
VERUS_FOR(i, sidePoly)
|
||||
{
|
||||
pV[((vertCount + sidePoly * 2 + i) << 2) + 0] = halfStep + (sidePoly - i - 1) * step;
|
||||
pV[((vertCount + sidePoly * 2 + i) << 2) + 2] = minPos;
|
||||
pV[((vertCount + sidePoly * 2 + i) << 2) + 3] = 1;
|
||||
}
|
||||
VERUS_FOR(i, sidePoly)
|
||||
{
|
||||
pV[((vertCount + sidePoly * 3 + i) << 2) + 0] = minPos;
|
||||
pV[((vertCount + sidePoly * 3 + i) << 2) + 2] = halfStep + i * step;
|
||||
pV[((vertCount + sidePoly * 3 + i) << 2) + 1] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TerrainPatch:
|
||||
|
@ -297,17 +380,35 @@ void Terrain::InitStatic()
|
|||
{
|
||||
VERUS_QREF_CONST_SETTINGS;
|
||||
|
||||
s_shader.Init("[Shaders]:DS_Terrain.hlsl");
|
||||
s_shader->CreateDescriptorSet(0, &s_ubDrawDepth, sizeof(s_ubDrawDepth), settings.GetLimits()._terrain_ubDrawDepthCapacity,
|
||||
s_shader[SHADER_MAIN].Init("[Shaders]:DS_Terrain.hlsl");
|
||||
s_shader[SHADER_MAIN]->CreateDescriptorSet(0, &s_ubTerrainVS, sizeof(s_ubTerrainVS), settings.GetLimits()._terrain_ubDrawDepthCapacity,
|
||||
{
|
||||
CGI::Sampler::linear2D
|
||||
});
|
||||
s_shader->CreateDescriptorSet(1, &s_ubPerMaterialFS, sizeof(s_ubPerMaterialFS), 1000,
|
||||
CGI::Sampler::linearMipN, // Height
|
||||
CGI::Sampler::linearMipN // Normal
|
||||
}, CGI::ShaderStageFlags::vs_hs_ds);
|
||||
s_shader[SHADER_MAIN]->CreateDescriptorSet(1, &s_ubTerrainFS, sizeof(s_ubTerrainFS), 1000,
|
||||
{
|
||||
CGI::Sampler::aniso, CGI::Sampler::aniso,
|
||||
CGI::Sampler::aniso, CGI::Sampler::aniso
|
||||
CGI::Sampler::aniso, // Normal
|
||||
CGI::Sampler::aniso, // Blend
|
||||
CGI::Sampler::aniso, // Layers
|
||||
CGI::Sampler::aniso, // LayersNM
|
||||
CGI::Sampler::aniso // Detail
|
||||
}, CGI::ShaderStageFlags::fs);
|
||||
s_shader->CreatePipelineLayout();
|
||||
s_shader[SHADER_MAIN]->CreatePipelineLayout();
|
||||
|
||||
s_shader[SHADER_SIMPLE].Init("[Shaders]:SimpleTerrain.hlsl");
|
||||
s_shader[SHADER_SIMPLE]->CreateDescriptorSet(0, &s_ubSimpleTerrainVS, sizeof(s_ubSimpleTerrainVS), settings.GetLimits()._terrain_ubDrawDepthCapacity,
|
||||
{
|
||||
CGI::Sampler::linearMipN, // Height
|
||||
CGI::Sampler::linearMipN // Normal
|
||||
}, CGI::ShaderStageFlags::vs);
|
||||
s_shader[SHADER_SIMPLE]->CreateDescriptorSet(1, &s_ubSimpleTerrainFS, sizeof(s_ubSimpleTerrainFS), 1000,
|
||||
{
|
||||
CGI::Sampler::linearMipN, // Normal
|
||||
CGI::Sampler::linearMipN, // Blend
|
||||
CGI::Sampler::linearMipN, // Layers
|
||||
}, CGI::ShaderStageFlags::fs);
|
||||
s_shader[SHADER_SIMPLE]->CreatePipelineLayout();
|
||||
}
|
||||
|
||||
void Terrain::DoneStatic()
|
||||
|
@ -319,6 +420,7 @@ void Terrain::Init(RcDesc desc)
|
|||
{
|
||||
VERUS_INIT();
|
||||
VERUS_QREF_RENDERER;
|
||||
VERUS_QREF_CONST_SETTINGS;
|
||||
|
||||
if (!Math::IsPowerOfTwo(desc._mapSide))
|
||||
throw VERUS_RECOVERABLE << "Init(), mapSide must be power of two";
|
||||
|
@ -329,6 +431,8 @@ void Terrain::Init(RcDesc desc)
|
|||
const int patchSide = _mapSide >> 4;
|
||||
const int patchShift = _mapShift - 4;
|
||||
const int patchCount = patchSide * patchSide;
|
||||
const int maxInstances = patchCount * 8;
|
||||
|
||||
_vPatches.resize(patchCount);
|
||||
_vPatchTBNs.resize(patchCount * 3);
|
||||
VERUS_P_FOR(i, patchSide)
|
||||
|
@ -345,6 +449,22 @@ void Terrain::Init(RcDesc desc)
|
|||
}
|
||||
});
|
||||
if (desc._debugHills)
|
||||
{
|
||||
if (desc._debugHills < 0)
|
||||
{
|
||||
VERUS_P_FOR(i, _mapSide)
|
||||
{
|
||||
VERUS_FOR(j, _mapSide)
|
||||
{
|
||||
const int ij[] = { i, j };
|
||||
if (((i >> 4) + (j >> 4)) & 0x1)
|
||||
SetHeightAt(ij, (i & 0xF) * 100);
|
||||
else
|
||||
SetHeightAt(ij, (j & 0xF) * 100);
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
const float scale = 1.f / desc._debugHills;
|
||||
VERUS_P_FOR(i, _mapSide)
|
||||
|
@ -358,6 +478,7 @@ void Terrain::Init(RcDesc desc)
|
|||
SetHeightAt(ij, short(res * 1000.f));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
VERUS_FOR(lod, 5)
|
||||
{
|
||||
|
@ -368,11 +489,10 @@ void Terrain::Init(RcDesc desc)
|
|||
}
|
||||
}
|
||||
_vSortedPatchIndices.resize(patchCount);
|
||||
const int maxInstances = patchCount * 8;
|
||||
|
||||
// Init LODs:
|
||||
VERUS_FOR(i, VERUS_COUNT_OF(_lods))
|
||||
_lods[i].Init(16 >> i, 1 << i);
|
||||
_lods[i].Init(16 >> i, 1 << i, i > 0);
|
||||
|
||||
Vector<short> vVB;
|
||||
Vector<UINT16> vIB;
|
||||
|
@ -387,21 +507,22 @@ void Terrain::Init(RcDesc desc)
|
|||
vbSize = 0, ibSize = 0;
|
||||
VERUS_FOR(i, VERUS_COUNT_OF(_lods))
|
||||
{
|
||||
_lods[i].InitGeo(&vVB[vbSize * 4], &vIB[ibSize], vbSize);
|
||||
_lods[i].InitGeo(&vVB[vbSize * 4], &vIB[ibSize], vbSize, i > 0);
|
||||
_lods[i]._firstIndex = ibSize;
|
||||
vbSize += _lods[i]._vertCount;
|
||||
ibSize += _lods[i]._indexCount;
|
||||
}
|
||||
_vInstanceBuffer.resize(maxInstances);
|
||||
|
||||
CGI::GeometryDesc geoDesc;
|
||||
const CGI::InputElementDesc ied[] =
|
||||
const CGI::VertexInputAttrDesc viaDesc[] =
|
||||
{
|
||||
{ 0, 0, CGI::IeType::shorts, 4, CGI::IeUsage::position, 0},
|
||||
{-1, offsetof(PerInstanceData, _posPatch), CGI::IeType::shorts, 4, CGI::IeUsage::texCoord, 8},
|
||||
{-1, offsetof(PerInstanceData, _layers), CGI::IeType::shorts, 4, CGI::IeUsage::texCoord, 9},
|
||||
CGI::InputElementDesc::End()
|
||||
{-1, offsetof(PerInstanceData, _posPatch), CGI::IeType::shorts, 4, CGI::IeUsage::instData, 0},
|
||||
{-1, offsetof(PerInstanceData, _layers), CGI::IeType::shorts, 4, CGI::IeUsage::instData, 1},
|
||||
CGI::VertexInputAttrDesc::End()
|
||||
};
|
||||
geoDesc._pInputElementDesc = ied;
|
||||
geoDesc._pVertexInputAttrDesc = viaDesc;
|
||||
const int strides[] = { sizeof(short) * 4, sizeof(PerInstanceData), 0 };
|
||||
geoDesc._pStrides = strides;
|
||||
_geo.Init(geoDesc);
|
||||
|
@ -411,14 +532,11 @@ void Terrain::Init(RcDesc desc)
|
|||
_geo->UpdateVertexBuffer(vVB.data(), 0);
|
||||
_geo->UpdateIndexBuffer(vIB.data());
|
||||
|
||||
_vInstanceBuffer.resize(maxInstances);
|
||||
|
||||
{
|
||||
CGI::PipelineDesc pipeDesc(_geo, s_shader, "#", renderer.GetDS().GetRenderPassHandle());
|
||||
CGI::PipelineDesc pipeDesc(_geo, s_shader[SHADER_MAIN], "#", renderer.GetDS().GetRenderPassHandle());
|
||||
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_OFF;
|
||||
pipeDesc._colorAttachBlendEqs[1] = VERUS_COLOR_BLEND_OFF;
|
||||
pipeDesc._colorAttachBlendEqs[2] = VERUS_COLOR_BLEND_OFF;
|
||||
pipeDesc._colorAttachBlendEqs[3] = VERUS_COLOR_BLEND_OFF;
|
||||
_pipe[PIPE_LIST].Init(pipeDesc);
|
||||
pipeDesc._topology = CGI::PrimitiveTopology::triangleStrip;
|
||||
pipeDesc._primitiveRestartEnable = true;
|
||||
|
@ -426,14 +544,36 @@ void Terrain::Init(RcDesc desc)
|
|||
}
|
||||
{
|
||||
VERUS_QREF_ATMO;
|
||||
CGI::PipelineDesc pipeDesc(_geo, s_shader, "#Depth", atmo.GetShadowMap().GetRenderPassHandle());
|
||||
CGI::PipelineDesc pipeDesc(_geo, s_shader[SHADER_MAIN], "#Depth", atmo.GetShadowMap().GetRenderPassHandle());
|
||||
pipeDesc._colorAttachBlendEqs[0] = "";
|
||||
pipeDesc.EnableDepthBias();
|
||||
_pipe[PIPE_DEPTH_LIST].Init(pipeDesc);
|
||||
pipeDesc._topology = CGI::PrimitiveTopology::triangleStrip;
|
||||
pipeDesc._primitiveRestartEnable = true;
|
||||
_pipe[PIPE_DEPTH_STRIP].Init(pipeDesc);
|
||||
}
|
||||
{
|
||||
CGI::PipelineDesc pipeDesc(_geo, s_shader[SHADER_MAIN], "#SolidColor", renderer.GetDS().GetRenderPassHandle());
|
||||
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_OFF;
|
||||
pipeDesc._colorAttachBlendEqs[1] = VERUS_COLOR_BLEND_OFF;
|
||||
pipeDesc._colorAttachBlendEqs[2] = VERUS_COLOR_BLEND_OFF;
|
||||
pipeDesc._rasterizationState._polygonMode = CGI::PolygonMode::line;
|
||||
pipeDesc._rasterizationState._depthBiasEnable = true;
|
||||
pipeDesc._rasterizationState._depthBiasConstantFactor = -50;
|
||||
pipeDesc._depthCompareOp = CGI::CompareOp::lessOrEqual;
|
||||
_pipe[PIPE_WIREFRAME_LIST].Init(pipeDesc);
|
||||
pipeDesc._topology = CGI::PrimitiveTopology::triangleStrip;
|
||||
pipeDesc._primitiveRestartEnable = true;
|
||||
_pipe[PIPE_WIREFRAME_STRIP].Init(pipeDesc);
|
||||
}
|
||||
if (settings._gpuTessellation)
|
||||
{
|
||||
CGI::PipelineDesc pipeDesc(_geo, s_shader[SHADER_MAIN], "#Tess", renderer.GetDS().GetRenderPassHandle());
|
||||
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_OFF;
|
||||
pipeDesc._colorAttachBlendEqs[1] = VERUS_COLOR_BLEND_OFF;
|
||||
pipeDesc._colorAttachBlendEqs[2] = VERUS_COLOR_BLEND_OFF;
|
||||
pipeDesc._topology = CGI::PrimitiveTopology::patchList3;
|
||||
_pipe[PIPE_TESS].Init(pipeDesc);
|
||||
}
|
||||
|
||||
CGI::TextureDesc texDesc;
|
||||
texDesc._format = CGI::Format::floatR16;
|
||||
|
@ -447,12 +587,20 @@ void Terrain::Init(RcDesc desc)
|
|||
texDesc._width = _mapSide;
|
||||
texDesc._height = _mapSide;
|
||||
texDesc._mipLevels = 0;
|
||||
texDesc._flags = CGI::TextureDesc::Flags::generateMips;
|
||||
texDesc._flags = CGI::TextureDesc::Flags::anyShaderResource | CGI::TextureDesc::Flags::generateMips;
|
||||
_tex[TEX_NORMALS].Init(texDesc);
|
||||
texDesc._flags = CGI::TextureDesc::Flags::generateMips;
|
||||
_tex[TEX_BLEND].Init(texDesc);
|
||||
|
||||
s_shader->FreeDescriptorSet(_cshVS);
|
||||
_cshVS = s_shader->BindDescriptorSetTextures(0, { _tex[TEX_HEIGHTMAP] });
|
||||
texDesc.Reset();
|
||||
texDesc._format = CGI::Format::unormR8;
|
||||
texDesc._width = _mapSide;
|
||||
texDesc._height = _mapSide;
|
||||
texDesc._flags = CGI::TextureDesc::Flags::anyShaderResource;
|
||||
_tex[TEX_MAIN_LAYER].Init(texDesc);
|
||||
|
||||
s_shader[SHADER_MAIN]->FreeDescriptorSet(_cshVS);
|
||||
_cshVS = s_shader[SHADER_MAIN]->BindDescriptorSetTextures(0, { _tex[TEX_HEIGHTMAP], _tex[TEX_NORMALS] });
|
||||
|
||||
_vBlendBuffer.resize(_mapSide * _mapSide);
|
||||
VERUS_P_FOR(i, _vBlendBuffer.size())
|
||||
|
@ -460,6 +608,7 @@ void Terrain::Init(RcDesc desc)
|
|||
_vBlendBuffer[i] = VERUS_COLOR_RGBA(255, 0, 0, 255);
|
||||
});
|
||||
UpdateBlendTexture();
|
||||
UpdateMainLayerTexture();
|
||||
|
||||
OnHeightModified();
|
||||
AddNewRigidBody();
|
||||
|
@ -469,8 +618,8 @@ void Terrain::Init(RcDesc desc)
|
|||
|
||||
void Terrain::Done()
|
||||
{
|
||||
s_shader->FreeDescriptorSet(_cshVS);
|
||||
s_shader->FreeDescriptorSet(_cshFS);
|
||||
s_shader[SHADER_MAIN]->FreeDescriptorSet(_cshVS);
|
||||
s_shader[SHADER_MAIN]->FreeDescriptorSet(_cshFS);
|
||||
|
||||
_tex.Done();
|
||||
_pipe.Done();
|
||||
|
@ -481,17 +630,6 @@ void Terrain::Done()
|
|||
VERUS_DONE(Terrain);
|
||||
}
|
||||
|
||||
int Terrain::UserPtr_GetType()
|
||||
{
|
||||
return 0;
|
||||
//return +NodeType::terrain;
|
||||
}
|
||||
|
||||
void Terrain::ResetInstanceCount()
|
||||
{
|
||||
_instanceCount = 0;
|
||||
}
|
||||
|
||||
void Terrain::Layout()
|
||||
{
|
||||
VERUS_QREF_CONST_SETTINGS;
|
||||
|
@ -520,39 +658,48 @@ void Terrain::Layout()
|
|||
sm.SetCamera(pPrevCamera);
|
||||
}
|
||||
|
||||
void Terrain::Draw()
|
||||
void Terrain::Draw(RcDrawDesc dd)
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
VERUS_QREF_SM;
|
||||
VERUS_QREF_ATMO;
|
||||
VERUS_QREF_CONST_SETTINGS;
|
||||
|
||||
if (!_visiblePatchCount)
|
||||
return;
|
||||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
const bool drawingDepth = Scene::SceneManager::IsDrawingDepth(Scene::DrawDepth::automatic);
|
||||
|
||||
s_ubDrawDepth._matW = mataff(1);
|
||||
s_ubDrawDepth._matWV = sm.GetCamera()->GetMatrixV().UniformBufferFormat();
|
||||
s_ubDrawDepth._matVP = sm.GetCamera()->GetMatrixVP().UniformBufferFormat();
|
||||
s_ubDrawDepth._posEye_mapSideInv = float4(atmo.GetEyePosition().GLM(), 0);
|
||||
s_ubDrawDepth._posEye_mapSideInv.w = 1.f / _mapSide;
|
||||
const Transform3 matW = Transform3::identity();
|
||||
s_ubTerrainVS._matW = matW.UniformBufferFormat();
|
||||
s_ubTerrainVS._matWV = Transform3(sm.GetCamera()->GetMatrixV() * matW).UniformBufferFormat();
|
||||
s_ubTerrainVS._matV = sm.GetCamera()->GetMatrixV().UniformBufferFormat();
|
||||
s_ubTerrainVS._matVP = sm.GetCamera()->GetMatrixVP().UniformBufferFormat();
|
||||
s_ubTerrainVS._matP = sm.GetCamera()->GetMatrixP().UniformBufferFormat();
|
||||
s_ubTerrainVS._eyePos_mapSideInv = float4(atmo.GetEyePosition().GLM(), 0);
|
||||
s_ubTerrainVS._eyePos_mapSideInv.w = 1.f / _mapSide;
|
||||
s_ubTerrainVS._viewportSize = cb->GetViewportSize().GLM();
|
||||
|
||||
s_ubTerrainFS._matWV = s_ubTerrainVS._matWV;
|
||||
VERUS_FOR(i, VERUS_COUNT_OF(_layerData))
|
||||
{
|
||||
s_ubPerMaterialFS._vSpecStrength[i >> 2][i & 0x3] = _layerData[i]._specStrength;
|
||||
s_ubPerMaterialFS._vDetailStrength[i >> 2][i & 0x3] = _layerData[i]._detailStrength;
|
||||
s_ubTerrainFS._vSpecStrength[i >> 2][i & 0x3] = _layerData[i]._specStrength;
|
||||
s_ubTerrainFS._vDetailStrength[i >> 2][i & 0x3] = _layerData[i]._detailStrength;
|
||||
}
|
||||
s_ubTerrainFS._lamScaleBias.x = _lamScale;
|
||||
s_ubTerrainFS._lamScaleBias.y = _lamBias;
|
||||
|
||||
renderer.GetCommandBuffer()->BindVertexBuffers(_geo);
|
||||
renderer.GetCommandBuffer()->BindIndexBuffer(_geo);
|
||||
cb->BindVertexBuffers(_geo);
|
||||
cb->BindIndexBuffer(_geo);
|
||||
|
||||
s_shader->BeginBindDescriptors();
|
||||
|
||||
bool strip = false;
|
||||
bool bindStrip = true;
|
||||
const int half = _mapSide >> 1;
|
||||
int firstInstance = 0;
|
||||
int edge = _visiblePatchCount - 1;
|
||||
int lod = _vPatches[_vSortedPatchIndices.front()]._quadtreeLOD;
|
||||
s_shader[SHADER_MAIN]->BeginBindDescriptors();
|
||||
VERUS_FOR(i, _visiblePatchCount)
|
||||
{
|
||||
RcTerrainPatch patch = _vPatches[_vSortedPatchIndices[i]];
|
||||
|
@ -563,35 +710,28 @@ void Terrain::Draw()
|
|||
|
||||
if (!lod)
|
||||
{
|
||||
if (drawingDepth)
|
||||
{
|
||||
renderer.GetCommandBuffer()->BindPipeline(_pipe[PIPE_DEPTH_LIST]);
|
||||
renderer.GetCommandBuffer()->BindDescriptors(s_shader, 0, _cshVS);
|
||||
renderer.GetCommandBuffer()->BindDescriptors(s_shader, 1, _cshFS);
|
||||
}
|
||||
if (dd._wireframe)
|
||||
cb->BindPipeline(_pipe[PIPE_WIREFRAME_LIST]);
|
||||
else if (drawingDepth)
|
||||
cb->BindPipeline(_pipe[PIPE_DEPTH_LIST]);
|
||||
else if (dd._tess && settings._gpuTessellation)
|
||||
cb->BindPipeline(_pipe[PIPE_TESS]);
|
||||
else
|
||||
{
|
||||
renderer.GetCommandBuffer()->BindPipeline(_pipe[PIPE_LIST]);
|
||||
renderer.GetCommandBuffer()->BindDescriptors(s_shader, 0, _cshVS);
|
||||
renderer.GetCommandBuffer()->BindDescriptors(s_shader, 1, _cshFS);
|
||||
cb->BindPipeline(_pipe[PIPE_LIST]);
|
||||
cb->BindDescriptors(s_shader[SHADER_MAIN], 0, _cshVS);
|
||||
cb->BindDescriptors(s_shader[SHADER_MAIN], 1, _cshFS);
|
||||
}
|
||||
}
|
||||
else if (!strip)
|
||||
else if (bindStrip)
|
||||
{
|
||||
if (drawingDepth)
|
||||
{
|
||||
strip = true;
|
||||
renderer.GetCommandBuffer()->BindPipeline(_pipe[PIPE_DEPTH_STRIP]);
|
||||
renderer.GetCommandBuffer()->BindDescriptors(s_shader, 0, _cshVS);
|
||||
renderer.GetCommandBuffer()->BindDescriptors(s_shader, 1, _cshFS);
|
||||
}
|
||||
bindStrip = false;
|
||||
if (dd._wireframe)
|
||||
cb->BindPipeline(_pipe[PIPE_WIREFRAME_STRIP]);
|
||||
else if (drawingDepth)
|
||||
cb->BindPipeline(_pipe[PIPE_DEPTH_STRIP]);
|
||||
else
|
||||
{
|
||||
strip = true;
|
||||
renderer.GetCommandBuffer()->BindPipeline(_pipe[PIPE_STRIP]);
|
||||
renderer.GetCommandBuffer()->BindDescriptors(s_shader, 0, _cshVS);
|
||||
renderer.GetCommandBuffer()->BindDescriptors(s_shader, 1, _cshFS);
|
||||
}
|
||||
cb->BindPipeline(_pipe[PIPE_STRIP]);
|
||||
cb->BindDescriptors(s_shader[SHADER_MAIN], 0, _cshVS);
|
||||
cb->BindDescriptors(s_shader[SHADER_MAIN], 1, _cshFS);
|
||||
}
|
||||
|
||||
const int instanceCount = i - firstInstance; // Drawing patches [firstInstance, i).
|
||||
|
@ -603,22 +743,43 @@ void Terrain::Draw()
|
|||
_vInstanceBuffer[at]._posPatch[1] = patchToDraw._patchHeight;
|
||||
_vInstanceBuffer[at]._posPatch[2] = patchToDraw._ijCoord[0] - half;
|
||||
_vInstanceBuffer[at]._posPatch[3] = 0;
|
||||
VERUS_ZERO_MEM(_vInstanceBuffer[at]._layers);
|
||||
if (dd._wireframe)
|
||||
{
|
||||
switch (patchToDraw._usedChannelCount)
|
||||
{
|
||||
case 1: _vInstanceBuffer[at]._layers[0] = 0; _vInstanceBuffer[at]._layers[1] = 0; _vInstanceBuffer[at]._layers[2] = 1; break;
|
||||
case 2: _vInstanceBuffer[at]._layers[0] = 0; _vInstanceBuffer[at]._layers[1] = 1; _vInstanceBuffer[at]._layers[2] = 0; break;
|
||||
case 3: _vInstanceBuffer[at]._layers[0] = 1; _vInstanceBuffer[at]._layers[1] = 1; _vInstanceBuffer[at]._layers[2] = 0; break;
|
||||
case 4: _vInstanceBuffer[at]._layers[0] = 1; _vInstanceBuffer[at]._layers[1] = 0; _vInstanceBuffer[at]._layers[2] = 0; break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
VERUS_FOR(ch, 4)
|
||||
_vInstanceBuffer[at]._layers[ch] = patchToDraw._layerForChannel[ch];
|
||||
}
|
||||
}
|
||||
|
||||
renderer.GetCommandBuffer()->DrawIndexed(_lods[lod]._indexCount, instanceCount, _lods[lod]._firstIndex, 0, _instanceCount + firstInstance);
|
||||
cb->DrawIndexed(_lods[lod]._indexCount, instanceCount, _lods[lod]._firstIndex, 0, _instanceCount + firstInstance);
|
||||
|
||||
lod = patch._quadtreeLOD;
|
||||
firstInstance = i;
|
||||
}
|
||||
}
|
||||
s_shader[SHADER_MAIN]->EndBindDescriptors();
|
||||
|
||||
_instanceCount += _visiblePatchCount;
|
||||
|
||||
_geo->UpdateVertexBuffer(_vInstanceBuffer.data(), 1);
|
||||
}
|
||||
|
||||
s_shader->EndBindDescriptors();
|
||||
void Terrain::DrawReflection()
|
||||
{
|
||||
}
|
||||
|
||||
void Terrain::ResetInstanceCount()
|
||||
{
|
||||
_instanceCount = 0;
|
||||
}
|
||||
|
||||
void Terrain::SortVisiblePatches()
|
||||
|
@ -635,6 +796,12 @@ void Terrain::SortVisiblePatches()
|
|||
});
|
||||
}
|
||||
|
||||
int Terrain::UserPtr_GetType()
|
||||
{
|
||||
return 0;
|
||||
//return +NodeType::terrain;
|
||||
}
|
||||
|
||||
void Terrain::QuadtreeIntegral_ProcessVisibleNode(const short ij[2], RcPoint3 center)
|
||||
{
|
||||
VERUS_QREF_ATMO;
|
||||
|
@ -647,6 +814,9 @@ void Terrain::QuadtreeIntegral_ProcessVisibleNode(const short ij[2], RcPoint3 ce
|
|||
const float lodF = log2(Math::Clamp((dist - 12) * (2 / 100.f), 1.f, 18.f));
|
||||
const int lod = Math::Clamp<int>(int(lodF), 0, 4);
|
||||
|
||||
if (4 == lod && center.getY() <= -20) // Cull underwater patches:
|
||||
return;
|
||||
|
||||
// Locate this patch:
|
||||
const int shiftPatch = _mapShift - 4;
|
||||
const int iPatch = ij[0] >> 4;
|
||||
|
@ -850,7 +1020,9 @@ void Terrain::LoadLayerTextures()
|
|||
if (_vLayerUrls.empty())
|
||||
return;
|
||||
|
||||
VERUS_QREF_MM;
|
||||
VERUS_QREF_RENDERER;
|
||||
|
||||
renderer->WaitIdle();
|
||||
|
||||
_tex[TEX_LAYERS].Done();
|
||||
|
@ -884,8 +1056,8 @@ void Terrain::LoadLayerTextures()
|
|||
texDesc._urls = vLayerUrlsPtrNM.data();
|
||||
_tex[TEX_LAYERS_NM].Init(texDesc);
|
||||
|
||||
s_shader->FreeDescriptorSet(_cshFS);
|
||||
_cshFS = s_shader->BindDescriptorSetTextures(1, { _tex[TEX_NORMALS], _tex[TEX_BLEND], _tex[TEX_LAYERS], _tex[TEX_LAYERS_NM] });
|
||||
s_shader[SHADER_MAIN]->FreeDescriptorSet(_cshFS);
|
||||
_cshFS = s_shader[SHADER_MAIN]->BindDescriptorSetTextures(1, { _tex[TEX_NORMALS], _tex[TEX_BLEND], _tex[TEX_LAYERS], _tex[TEX_LAYERS_NM], mm.GetDetailTexture() });
|
||||
}
|
||||
|
||||
int Terrain::GetMainLayerAt(const int ij[2]) const
|
||||
|
@ -1019,7 +1191,7 @@ void Terrain::UpdateMainLayerTexture()
|
|||
_vMainLayerSubresData[offset + j] = GetMainLayerAt(ij) * 16 + 4;
|
||||
}
|
||||
});
|
||||
//_tex[TEX_MAIN_LAYER]->UpdateSubresource(_vMainLayerSubresData.data());
|
||||
_tex[TEX_MAIN_LAYER]->UpdateSubresource(_vMainLayerSubresData.data());
|
||||
}
|
||||
|
||||
CGI::TexturePtr Terrain::GetMainLayerTexture() const
|
||||
|
@ -1039,6 +1211,7 @@ void Terrain::OnHeightModified()
|
|||
|
||||
void Terrain::AddNewRigidBody()
|
||||
{
|
||||
_physics.Done();
|
||||
_physics.Init(this, _mapSide, _mapSide, _vHeightBuffer.data(), ConvertHeight(static_cast<short>(1)));
|
||||
}
|
||||
|
||||
|
@ -1175,7 +1348,7 @@ void Terrain::Deserialize(IO::RStream stream)
|
|||
}
|
||||
else
|
||||
{
|
||||
_vPatches[i]._layerForChannel[j] = -1;
|
||||
_vPatches[i]._layerForChannel[j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1194,12 +1367,13 @@ void Terrain::Deserialize(IO::RStream stream)
|
|||
{
|
||||
UINT16 data;
|
||||
stream >> data;
|
||||
_vBlendBuffer[offset + j] = Convert::Uint4x4ToUint8x4(data);
|
||||
_vBlendBuffer[offset + j] = Convert::Uint4x4ToUint8x4(data, true);
|
||||
const int ij[] = { i, j };
|
||||
UpdateMainLayerAt(ij);
|
||||
}
|
||||
}
|
||||
UpdateBlendTexture();
|
||||
UpdateMainLayerTexture();
|
||||
// </Blend>
|
||||
|
||||
OnHeightModified();
|
||||
|
|
|
@ -40,8 +40,8 @@ namespace verus
|
|||
int _indexCount = 0;
|
||||
int _firstIndex = 0;
|
||||
|
||||
void Init(int sidePoly, int step);
|
||||
void InitGeo(short* pV, UINT16* pI, int vertexOffset);
|
||||
void Init(int sidePoly, int step, bool addEdgeTess);
|
||||
void InitGeo(short* pV, UINT16* pI, int vertexOffset, bool addEdgeTess);
|
||||
};
|
||||
VERUS_TYPEDEFS(TerrainLOD);
|
||||
|
||||
|
@ -80,6 +80,14 @@ namespace verus
|
|||
{
|
||||
public:
|
||||
#include "../Shaders/DS_Terrain.inc.hlsl"
|
||||
#include "../Shaders/SimpleTerrain.inc.hlsl"
|
||||
|
||||
enum SHADER
|
||||
{
|
||||
SHADER_MAIN,
|
||||
SHADER_SIMPLE,
|
||||
SHADER_COUNT
|
||||
};
|
||||
|
||||
enum PIPE
|
||||
{
|
||||
|
@ -87,7 +95,10 @@ namespace verus
|
|||
PIPE_STRIP,
|
||||
PIPE_DEPTH_LIST,
|
||||
PIPE_DEPTH_STRIP,
|
||||
PIPE_MAX
|
||||
PIPE_WIREFRAME_LIST,
|
||||
PIPE_WIREFRAME_STRIP,
|
||||
PIPE_TESS,
|
||||
PIPE_COUNT
|
||||
};
|
||||
|
||||
enum TEX
|
||||
|
@ -98,7 +109,7 @@ namespace verus
|
|||
TEX_LAYERS,
|
||||
TEX_LAYERS_NM,
|
||||
TEX_MAIN_LAYER,
|
||||
TEX_MAX
|
||||
TEX_COUNT
|
||||
};
|
||||
|
||||
static const int s_maxLayers = 32;
|
||||
|
@ -116,13 +127,15 @@ namespace verus
|
|||
};
|
||||
|
||||
protected:
|
||||
static CGI::ShaderPwn s_shader;
|
||||
static UB_DrawDepth s_ubDrawDepth;
|
||||
static UB_PerMaterialFS s_ubPerMaterialFS;
|
||||
static CGI::ShaderPwns<SHADER_COUNT> s_shader;
|
||||
static UB_TerrainVS s_ubTerrainVS;
|
||||
static UB_TerrainFS s_ubTerrainFS;
|
||||
static UB_SimpleTerrainVS s_ubSimpleTerrainVS;
|
||||
static UB_SimpleTerrainFS s_ubSimpleTerrainFS;
|
||||
|
||||
CGI::GeometryPwn _geo;
|
||||
CGI::PipelinePwns<PIPE_MAX> _pipe;
|
||||
CGI::TexturePwns<TEX_MAX> _tex;
|
||||
CGI::PipelinePwns<PIPE_COUNT> _pipe;
|
||||
CGI::TexturePwns<TEX_COUNT> _tex;
|
||||
Vector<TerrainPatch> _vPatches;
|
||||
Vector<TerrainPatch::TBN> _vPatchTBNs;
|
||||
Vector<UINT16> _vSortedPatchIndices;
|
||||
|
@ -136,18 +149,21 @@ namespace verus
|
|||
float _quadtreeFatten = 0.5f;
|
||||
int _mapSide = 0;
|
||||
int _mapShift = 0;
|
||||
int _visiblePatchCount = 0;
|
||||
int _vertCount = 0;
|
||||
int _indexCount = 0;
|
||||
int _instanceCount = 0;
|
||||
int _cshVS = -1;
|
||||
int _cshFS = -1;
|
||||
int _visiblePatchCount = 0;
|
||||
CGI::CSHandle _cshVS;
|
||||
CGI::CSHandle _cshFS;
|
||||
TerrainLOD _lods[5]; // Level of detail data for (16x16, 8x8, 4x4, 2x2, 1x1).
|
||||
LayerData _layerData[s_maxLayers];
|
||||
TerrainPhysics _physics;
|
||||
Math::QuadtreeIntegral _quadtree;
|
||||
|
||||
public:
|
||||
float _lamScale = 1.9f;
|
||||
float _lamBias = -0.9f;
|
||||
|
||||
struct Desc
|
||||
{
|
||||
int _mapSide = 256;
|
||||
|
@ -159,6 +175,18 @@ namespace verus
|
|||
};
|
||||
VERUS_TYPEDEFS(Desc);
|
||||
|
||||
struct DrawDesc
|
||||
{
|
||||
bool _tess = false;
|
||||
bool _wireframe = false;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
*this = DrawDesc();
|
||||
}
|
||||
};
|
||||
VERUS_TYPEDEFS(DrawDesc);
|
||||
|
||||
Terrain();
|
||||
virtual ~Terrain();
|
||||
|
||||
|
@ -168,14 +196,16 @@ namespace verus
|
|||
void Init(RcDesc desc = Desc());
|
||||
void Done();
|
||||
|
||||
virtual int UserPtr_GetType() override;
|
||||
void Layout();
|
||||
void Draw(RcDrawDesc dd = DrawDesc());
|
||||
void DrawReflection();
|
||||
|
||||
void ResetInstanceCount();
|
||||
void Layout();
|
||||
void Draw();
|
||||
|
||||
void SortVisiblePatches();
|
||||
|
||||
virtual int UserPtr_GetType() override;
|
||||
|
||||
int GetMapSide() const { return _mapSide; }
|
||||
|
||||
RTerrainPatch GetPatch(int index) { return _vPatches[index]; }
|
||||
|
|
513
Verus/src/Scene/Water.cpp
Normal file
513
Verus/src/Scene/Water.cpp
Normal file
|
@ -0,0 +1,513 @@
|
|||
#include "verus.h"
|
||||
|
||||
using namespace verus;
|
||||
using namespace verus::Scene;
|
||||
|
||||
Water::UB_WaterVS Water::s_ubWaterVS;
|
||||
Water::UB_WaterFS Water::s_ubWaterFS;
|
||||
Water::UB_Gen Water::s_ubGen;
|
||||
Water::UB_GenHeightmapFS Water::s_ubGenHeightmapFS;
|
||||
Water::UB_GenNormalsFS Water::s_ubGenNormalsFS;
|
||||
|
||||
|
||||
Water::Water()
|
||||
{
|
||||
}
|
||||
|
||||
Water::~Water()
|
||||
{
|
||||
Done();
|
||||
}
|
||||
|
||||
void Water::Init(RTerrain terrain)
|
||||
{
|
||||
VERUS_INIT();
|
||||
|
||||
VERUS_QREF_RENDERER;
|
||||
VERUS_QREF_CONST_SETTINGS;
|
||||
|
||||
_pTerrain = &terrain;
|
||||
|
||||
_rphGenHeightmap = renderer->CreateSimpleRenderPass(CGI::Format::floatR16, CGI::ImageLayout::xsReadOnly);
|
||||
_rphGenNormals = renderer->CreateSimpleRenderPass(CGI::Format::unormR10G10B10A2);
|
||||
_rphReflection = renderer->CreateRenderPass(
|
||||
{
|
||||
CGI::RP::Attachment("Color", CGI::Format::floatR11G11B10).LoadOpDontCare().Layout(CGI::ImageLayout::fsReadOnly),
|
||||
CGI::RP::Attachment("Depth", CGI::Format::unormD24uintS8).LoadOpClear().Layout(CGI::ImageLayout::depthStencilAttachment),
|
||||
},
|
||||
{
|
||||
CGI::RP::Subpass("Sp0").Color(
|
||||
{
|
||||
CGI::RP::Ref("Color", CGI::ImageLayout::colorAttachment)
|
||||
}).DepthStencil(CGI::RP::Ref("Depth", CGI::ImageLayout::depthStencilAttachment)),
|
||||
},
|
||||
{});
|
||||
|
||||
_shader[SHADER_MAIN].Init("[Shaders]:Water.hlsl");
|
||||
_shader[SHADER_MAIN]->CreateDescriptorSet(0, &s_ubWaterVS, sizeof(s_ubWaterVS), 100,
|
||||
{
|
||||
CGI::Sampler::linearClampMipL,
|
||||
CGI::Sampler::linearMipL
|
||||
}, CGI::ShaderStageFlags::vs);
|
||||
_shader[SHADER_MAIN]->CreateDescriptorSet(1, &s_ubWaterFS, sizeof(s_ubWaterFS), 100,
|
||||
{
|
||||
CGI::Sampler::linearClampMipL,
|
||||
CGI::Sampler::linearMipL,
|
||||
CGI::Sampler::custom,
|
||||
CGI::Sampler::aniso
|
||||
}, CGI::ShaderStageFlags::fs);
|
||||
_shader[SHADER_MAIN]->CreatePipelineLayout();
|
||||
|
||||
_shader[SHADER_GEN].Init("[Shaders]:WaterGen.hlsl");
|
||||
_shader[SHADER_GEN]->CreateDescriptorSet(0, &s_ubGen, sizeof(s_ubGen), 100, {}, CGI::ShaderStageFlags::vs);
|
||||
_shader[SHADER_GEN]->CreateDescriptorSet(1, &s_ubGenHeightmapFS, sizeof(s_ubGenHeightmapFS), 100, { CGI::Sampler::linearMipN }, CGI::ShaderStageFlags::fs);
|
||||
_shader[SHADER_GEN]->CreateDescriptorSet(2, &s_ubGenNormalsFS, sizeof(s_ubGenNormalsFS), 100, { CGI::Sampler::linearMipN }, CGI::ShaderStageFlags::fs);
|
||||
_shader[SHADER_GEN]->CreatePipelineLayout();
|
||||
|
||||
Vector<UINT16> vIndices;
|
||||
Math::CreateStripGrid(_gridWidth - 1, _gridHeight - 1, vIndices);
|
||||
_indexCount = vIndices.size();
|
||||
|
||||
CGI::GeometryDesc geoDesc;
|
||||
const CGI::VertexInputAttrDesc viaDesc[] =
|
||||
{
|
||||
{0, offsetof(Vertex, _pos), CGI::IeType::floats, 4, CGI::IeUsage::position, 0},
|
||||
CGI::VertexInputAttrDesc::End()
|
||||
};
|
||||
geoDesc._pVertexInputAttrDesc = viaDesc;
|
||||
const int strides[] = { sizeof(Vertex), 0 };
|
||||
geoDesc._pStrides = strides;
|
||||
_geo.Init(geoDesc);
|
||||
_geo->CreateVertexBuffer(_gridWidth * _gridHeight, 0);
|
||||
_geo->CreateIndexBuffer(vIndices.size());
|
||||
_geo->UpdateIndexBuffer(vIndices.data());
|
||||
|
||||
CreateWaterPlane();
|
||||
|
||||
{
|
||||
CGI::PipelineDesc pipeDesc(_geo, _shader[SHADER_MAIN], "#0", renderer.GetDS().GetRenderPassHandle_Compose(), renderer.GetDS().GetSubpass_Compose());
|
||||
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_ALPHA;
|
||||
//pipeDesc._rasterizationState._polygonMode = CGI::PolygonMode::line;
|
||||
pipeDesc._topology = CGI::PrimitiveTopology::triangleStrip;
|
||||
_pipe[PIPE_MAIN].Init(pipeDesc);
|
||||
}
|
||||
{
|
||||
CGI::PipelineDesc pipeDesc(renderer.GetGeoQuad(), _shader[SHADER_GEN], "#GenHeightmap", _rphGenHeightmap);
|
||||
pipeDesc._topology = CGI::PrimitiveTopology::triangleStrip;
|
||||
pipeDesc._depthTestEnable = false;
|
||||
_pipe[PIPE_GEN_HEIGHTMAP].Init(pipeDesc);
|
||||
}
|
||||
{
|
||||
CGI::PipelineDesc pipeDesc(renderer.GetGeoQuad(), _shader[SHADER_GEN], "#GenNormals", _rphGenNormals);
|
||||
pipeDesc._topology = CGI::PrimitiveTopology::triangleStrip;
|
||||
pipeDesc._depthTestEnable = false;
|
||||
_pipe[PIPE_GEN_NORMALS].Init(pipeDesc);
|
||||
}
|
||||
|
||||
CGI::TextureDesc texDesc;
|
||||
texDesc._url = "[Textures]:Water/Foam.dds";
|
||||
_tex[TEX_FOAM].Init(texDesc);
|
||||
|
||||
texDesc._url = "[Textures]:Water/Heightmap.FX.dds";
|
||||
_tex[TEX_SOURCE_HEIGHTMAP].Init(texDesc);
|
||||
|
||||
CGI::SamplerDesc normalsSamplerDesc;
|
||||
normalsSamplerDesc.SetFilter("a");
|
||||
normalsSamplerDesc.SetAddressMode("rr");
|
||||
normalsSamplerDesc._mipLodBias = 0.5f;
|
||||
normalsSamplerDesc._minLod = 1;
|
||||
texDesc.Reset();
|
||||
texDesc._format = CGI::Format::floatR16;
|
||||
texDesc._width = _genSide;
|
||||
texDesc._height = _genSide;
|
||||
texDesc._mipLevels = 0;
|
||||
texDesc._flags = CGI::TextureDesc::Flags::colorAttachment | CGI::TextureDesc::Flags::anyShaderResource | CGI::TextureDesc::Flags::generateMips;
|
||||
_tex[TEX_GEN_HEIGHTMAP].Init(texDesc);
|
||||
texDesc._format = CGI::Format::unormR10G10B10A2;
|
||||
texDesc._flags = CGI::TextureDesc::Flags::colorAttachment | CGI::TextureDesc::Flags::generateMips;
|
||||
texDesc._pSamplerDesc = &normalsSamplerDesc;
|
||||
_tex[TEX_GEN_NORMALS].Init(texDesc);
|
||||
|
||||
_fbhGenHeightmap = renderer->CreateFramebuffer(_rphGenHeightmap, { _tex[TEX_GEN_HEIGHTMAP] }, _genSide, _genSide);
|
||||
_fbhGenNormals = renderer->CreateFramebuffer(_rphGenNormals, { _tex[TEX_GEN_NORMALS] }, _genSide, _genSide);
|
||||
|
||||
_cshWaterVS = _shader[SHADER_MAIN]->BindDescriptorSetTextures(0, { _pTerrain->GetHeightmapTexture(), _tex[TEX_GEN_HEIGHTMAP] });
|
||||
|
||||
_cshGenNormals = _shader[SHADER_GEN]->BindDescriptorSetTextures(2, { _tex[TEX_GEN_HEIGHTMAP] });
|
||||
|
||||
texDesc.Reset();
|
||||
texDesc._format = CGI::Format::floatR11G11B10;
|
||||
texDesc._width = settings._screenSizeWidth;
|
||||
texDesc._height = settings._screenSizeHeight;
|
||||
texDesc._flags = CGI::TextureDesc::Flags::colorAttachment;
|
||||
_tex[TEX_REFLECTION].Init(texDesc);
|
||||
texDesc._format = CGI::Format::unormD24uintS8;
|
||||
texDesc._flags = CGI::TextureDesc::Flags::none;
|
||||
_tex[TEX_REFLECTION_DEPTH].Init(texDesc);
|
||||
|
||||
_fbhReflection = renderer->CreateFramebuffer(_rphReflection,
|
||||
{
|
||||
_tex[TEX_REFLECTION],
|
||||
_tex[TEX_REFLECTION_DEPTH]
|
||||
},
|
||||
texDesc._width,
|
||||
texDesc._height);
|
||||
|
||||
// Texture for rendering reflection onto:
|
||||
/*
|
||||
if (settings._sceneWaterQuality >= App::Settings::WaterQuality::simpleReflection)
|
||||
{
|
||||
texDesc.Reset();
|
||||
texDesc._format = CGI::Format::unormR8G8B8A8;
|
||||
texDesc._width = 512;
|
||||
texDesc._height = 512;
|
||||
texDesc._mipLevels = 0;
|
||||
texDesc._flags = CGI::TextureDesc::Flags::generateMips;
|
||||
_tex[TEX_REFLECT].Init(texDesc);
|
||||
|
||||
if (settings._sceneWaterQuality >= App::Settings::WaterQuality::trueWavesRefraction)
|
||||
_tex[TEX_REFRACT].Init(texDesc);
|
||||
|
||||
texDesc._format = CGI::Format::unormD16;
|
||||
_tex[TEX_REFLECT_DEPTH].Init(texDesc);
|
||||
}
|
||||
*/
|
||||
|
||||
VERUS_FOR(i, s_maxHarmonics)
|
||||
_amplitudes[i] = PhillipsSpectrum(0.5f + i / 2.f);
|
||||
}
|
||||
|
||||
void Water::Done()
|
||||
{
|
||||
VERUS_DONE(Water);
|
||||
}
|
||||
|
||||
void Water::Update()
|
||||
{
|
||||
VERUS_UPDATE_ONCE_CHECK;
|
||||
|
||||
VERUS_QREF_TIMER;
|
||||
_phase = fmod(_phase + dt * (1 / 29.f), 1.f);
|
||||
_phaseWave = fmod(_phaseWave + dt * (1 / 61.f), 1.f);
|
||||
}
|
||||
|
||||
void Water::Draw()
|
||||
{
|
||||
VERUS_UPDATE_ONCE_CHECK_DRAW;
|
||||
|
||||
if (!_cshWaterFS.IsSet())
|
||||
{
|
||||
if (_tex[TEX_FOAM]->IsLoaded())
|
||||
{
|
||||
_cshWaterFS = _shader[SHADER_MAIN]->BindDescriptorSetTextures(1,
|
||||
{
|
||||
_pTerrain->GetHeightmapTexture(),
|
||||
_tex[TEX_GEN_HEIGHTMAP],
|
||||
_tex[TEX_GEN_NORMALS],
|
||||
_tex[TEX_FOAM]
|
||||
});
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
VERUS_QREF_RENDERER;
|
||||
VERUS_QREF_SM;
|
||||
VERUS_QREF_CONST_SETTINGS;
|
||||
VERUS_QREF_TIMER;
|
||||
VERUS_QREF_ATMO;
|
||||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
RCamera cam = *sm.GetCamera();
|
||||
|
||||
Transform3 matW;
|
||||
|
||||
Point3 eyePosAtGroundLevel = cam.GetEyePosition();
|
||||
eyePosAtGroundLevel.setY(0);
|
||||
|
||||
Vector3 flatDir = cam.GetFrontDirection();
|
||||
flatDir.setY(0);
|
||||
flatDir = VMath::normalizeApprox(flatDir);
|
||||
const float angle = atan2(
|
||||
static_cast<float>(flatDir.getX()),
|
||||
static_cast<float>(flatDir.getZ())); // Align with high density sector.
|
||||
const Matrix3 matR = Matrix3::rotationY(angle);
|
||||
matW = Transform3(matR, Vector3(eyePosAtGroundLevel - flatDir * 5 * abs(cam.GetFrontDirection().getY())));
|
||||
|
||||
const Matrix4 matWVP = cam.GetMatrixVP() * matW;
|
||||
|
||||
s_ubWaterVS._matW = matW.UniformBufferFormat();
|
||||
s_ubWaterVS._matVP = cam.GetMatrixVP().UniformBufferFormat();
|
||||
s_ubWaterVS._eyePos = float4(cam.GetEyePosition().GLM(), 0);
|
||||
s_ubWaterVS._waterScale_distToMipScale_mapSideInv_landDistToMipScale.x = 1 / _patchSide;
|
||||
s_ubWaterVS._waterScale_distToMipScale_mapSideInv_landDistToMipScale.y = Math::ComputeDistToMipScale(_genSide << 6, renderer.GetSwapChainHeight(), _patchSide, cam.GetFOV());
|
||||
s_ubWaterVS._waterScale_distToMipScale_mapSideInv_landDistToMipScale.z = 1.f / _pTerrain->GetMapSide();
|
||||
s_ubWaterVS._waterScale_distToMipScale_mapSideInv_landDistToMipScale.w = Math::ComputeDistToMipScale(_pTerrain->GetMapSide(), renderer.GetSwapChainHeight(), _pTerrain->GetMapSide(), cam.GetFOV());
|
||||
|
||||
s_ubWaterFS._phase.x = _phase;
|
||||
s_ubWaterFS._dirToSun = float4(atmo.GetDirToSun().GLM(), 0);
|
||||
s_ubWaterFS._sunColor = float4(atmo.GetSunColor().GLM(), 0);
|
||||
|
||||
cb->BindVertexBuffers(_geo);
|
||||
cb->BindIndexBuffer(_geo);
|
||||
cb->BindPipeline(_pipe[PIPE_MAIN]);
|
||||
|
||||
_shader[SHADER_MAIN]->BeginBindDescriptors();
|
||||
cb->BindDescriptors(_shader[SHADER_MAIN], 0, _cshWaterVS);
|
||||
cb->BindDescriptors(_shader[SHADER_MAIN], 1, _cshWaterFS);
|
||||
cb->DrawIndexed(_indexCount);
|
||||
_shader[SHADER_MAIN]->EndBindDescriptors();
|
||||
|
||||
//ms_cbPerObject.matWVP = matWVP.ConstBufferFormat();
|
||||
//ms_cbPerObject.matW = matW.ConstBufferFormat();
|
||||
//ms_cbPerObject.matV = cam.GetMatrixV().ConstBufferFormat();
|
||||
|
||||
if (false)
|
||||
{
|
||||
//_sb[SB_DEPTH]->Apply(sbad);
|
||||
|
||||
if (settings._sceneWaterQuality >= App::Settings::WaterQuality::trueWavesReflection)
|
||||
{
|
||||
//renderer->SetTextures({ _tex[TEX_HEIGHTMAP] }, 0 + VERUS_ST_VS_OFFSET);
|
||||
//renderer->SetTextures({ _texLand }, 5 + VERUS_ST_VS_OFFSET);
|
||||
}
|
||||
|
||||
//_s->Bind("TDepth");
|
||||
//_s->UpdateBuffer(0);
|
||||
|
||||
//_geo->BeginDraw(0x1);
|
||||
//renderer->DrawIndexedPrimitive(CGI::PT_TRIANGLESTRIP, 0, _indexCount);
|
||||
//_geo->EndDraw(0x1);
|
||||
}
|
||||
else
|
||||
{
|
||||
VERUS_QREF_ATMO;
|
||||
|
||||
if (settings._sceneWaterQuality >= App::Settings::WaterQuality::trueWavesRefraction) // True refraction:
|
||||
{
|
||||
//renderer->StretchRect(m_tex[TEX_REFRACT], renderer.GetOffscreenColorTexture());
|
||||
//_tex[TEX_REFRACT]->GenerateMipmaps();
|
||||
}
|
||||
|
||||
//renderer->SetRenderTargets({ renderer.GetOffscreenColorTexture(), renderer.GetDS().GetGBuffer(1) }, renderer.GetOffscreenDepthTexture());
|
||||
|
||||
//_sb[SB_MASTER]->Apply(sbad);
|
||||
|
||||
if (settings._sceneWaterQuality >= App::Settings::WaterQuality::trueWavesReflection)
|
||||
{
|
||||
//renderer->SetTextures({ _tex[TEX_HEIGHTMAP] }, 0 + VERUS_ST_VS_OFFSET);
|
||||
//renderer->SetTextures({ _texLand }, 5 + VERUS_ST_VS_OFFSET);
|
||||
}
|
||||
|
||||
Matrix4 matTexSpace = Matrix4::identity();
|
||||
|
||||
if (settings._sceneWaterQuality >= App::Settings::WaterQuality::solidColor)
|
||||
{
|
||||
//renderer->SetTextures({ _tex[TEX_HEIGHTMAP_BASE] });
|
||||
//renderer->SetTextures({ _tex[TEX_FOAM] }, 2);
|
||||
//renderer->SetTextures({ _texLand }, 5);
|
||||
//renderer->SetTextures({ atmo.GetSunShadowTexture() }, 6);
|
||||
}
|
||||
if (settings._sceneWaterQuality >= App::Settings::WaterQuality::simpleReflection)
|
||||
{
|
||||
//renderer->SetTextures({ _tex[TEX_REFLECT] }, 3);
|
||||
const Transform3 matShift = Transform3::translation(Vector3(0, -0.01f, 0)); // Sky-waterline bleeding fix.
|
||||
//matTexSpace = Matrix4(Math::ToUVMatrix(0, Math::TOUV_RENDER_TARGET_VFLIP | Math::TOUV_MAP_TEXELS_TO_PIXELS, _tex[TEX_REFLECT]->GetSize()) * matShift) * matWVP;
|
||||
}
|
||||
if (settings._sceneWaterQuality >= App::Settings::WaterQuality::trueWavesReflection)
|
||||
{
|
||||
//renderer->SetTextures({ _tex[TEX_HEIGHTMAP], _tex[TEX_NORMALMAP] });
|
||||
}
|
||||
if (settings._sceneWaterQuality >= App::Settings::WaterQuality::trueWavesRefraction)
|
||||
{
|
||||
//renderer->SetTextures({ _tex[TEX_REFRACT] }, 4);
|
||||
}
|
||||
|
||||
//ms_cbPerFrame.matReflect = matTexSpace.ConstBufferFormat();
|
||||
//ms_cbPerFrame.shadowTexSize = atmo.GetSunShadowTexture() ? atmo.GetSunShadowTexture()->GetSize() : CVector4(0);
|
||||
//ms_cbPerFrame.matSunShadow = atmo.GetSunShadowMatrix(0).ConstBufferFormat();
|
||||
//ms_cbPerFrame.matSunShadowCSM1 = atmo.GetSunShadowMatrix(1).ConstBufferFormat();
|
||||
//ms_cbPerFrame.matSunShadowCSM2 = atmo.GetSunShadowMatrix(2).ConstBufferFormat();
|
||||
//ms_cbPerFrame.matSunShadowCSM3 = atmo.GetSunShadowMatrix(3).ConstBufferFormat();
|
||||
//ms_cbPerFrame.csmParams = atmo.GetParamsCSM();
|
||||
//ms_cbPerFrame.phases_mapSideInv.x = _phase;
|
||||
//ms_cbPerFrame.phases_mapSideInv.y = _phaseWave;
|
||||
//ms_cbPerFrame.phases_mapSideInv.z = 1.f / _mapSide;
|
||||
//ms_cbPerFrame.eyePos = cam.GetPositionEye();
|
||||
//ms_cbPerFrame.colorAmbient = atmo.GetAmbientColor();
|
||||
//ms_cbPerFrame.dirToSun = atmo.GetDirToSun();
|
||||
//ms_cbPerFrame.colorSun = atmo.GetSunColor();
|
||||
//ms_cbPerFrame.colorSunSpec = atmo.GetSunColor();
|
||||
//ms_cbPerFrame.fogColor = atmo.GetFogColor();
|
||||
|
||||
//char tech[8];
|
||||
//sprintf_s(tech, "T_%d", settings._sceneWaterQuality);
|
||||
//_s->Bind(tech);
|
||||
//_s->UpdateBuffer(0);
|
||||
//_s->UpdateBuffer(1);
|
||||
|
||||
//_geo->BeginDraw(0x1);
|
||||
//renderer->DrawIndexedPrimitive(CGI::PT_TRIANGLESTRIP, 0, _indexCount);
|
||||
//_geo->EndDraw(0x1);
|
||||
}
|
||||
|
||||
///renderer->SetTextures({ nullptr }, 0 + VERUS_ST_VS_OFFSET);
|
||||
|
||||
//renderer.DrawQuad(m_tex[HTEX_HEIGHTMAP]);
|
||||
}
|
||||
|
||||
void Water::BeginReflection(CGI::PBaseCommandBuffer pCB)
|
||||
{
|
||||
VERUS_QREF_SM;
|
||||
VERUS_QREF_RENDERER;
|
||||
|
||||
if (!pCB)
|
||||
pCB = &(*renderer.GetCommandBuffer());
|
||||
|
||||
_reflectionMode = sm.GetCamera()->GetEyePosition().getY() >= 0;
|
||||
_renderToTexture = true;
|
||||
|
||||
pCB->BeginRenderPass(_rphReflection, _fbhReflection,
|
||||
{
|
||||
_tex[TEX_REFLECTION]->GetClearValue(),
|
||||
_tex[TEX_REFLECTION_DEPTH]->GetClearValue()
|
||||
});
|
||||
}
|
||||
|
||||
void Water::EndReflection(CGI::PBaseCommandBuffer pCB)
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
|
||||
if (!pCB)
|
||||
pCB = &(*renderer.GetCommandBuffer());
|
||||
|
||||
pCB->EndRenderPass();
|
||||
|
||||
_reflectionMode = false;
|
||||
_renderToTexture = false;
|
||||
}
|
||||
|
||||
void Water::GenerateTextures()
|
||||
{
|
||||
if (!_cshGenHeightmap.IsSet())
|
||||
{
|
||||
if (_tex[TEX_SOURCE_HEIGHTMAP]->IsLoaded())
|
||||
_cshGenHeightmap = _shader[SHADER_GEN]->BindDescriptorSetTextures(1, { _tex[TEX_SOURCE_HEIGHTMAP] });
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
GenerateHeightmapTexture();
|
||||
GenerateNormalsTexture();
|
||||
}
|
||||
|
||||
void Water::GenerateHeightmapTexture()
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
|
||||
s_ubGen._matW = Math::QuadMatrix().UniformBufferFormat();
|
||||
s_ubGen._matV = Math::ToUVMatrix().UniformBufferFormat();
|
||||
s_ubGenHeightmapFS._phase.x = _phase;
|
||||
memcpy(&s_ubGenHeightmapFS._amplitudes, _amplitudes, sizeof(_amplitudes));
|
||||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
cb->BeginRenderPass(_rphGenHeightmap, _fbhGenHeightmap, { _tex[TEX_GEN_HEIGHTMAP]->GetClearValue(), });
|
||||
|
||||
cb->BindPipeline(_pipe[PIPE_GEN_HEIGHTMAP]);
|
||||
|
||||
_shader[SHADER_GEN]->BeginBindDescriptors();
|
||||
cb->BindDescriptors(_shader[SHADER_GEN], 0);
|
||||
cb->BindDescriptors(_shader[SHADER_GEN], 1, _cshGenHeightmap);
|
||||
_shader[SHADER_GEN]->EndBindDescriptors();
|
||||
|
||||
renderer.DrawQuad(&(*cb));
|
||||
|
||||
cb->EndRenderPass();
|
||||
|
||||
_tex[TEX_GEN_HEIGHTMAP]->GenerateMips();
|
||||
}
|
||||
|
||||
void Water::GenerateNormalsTexture()
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
|
||||
s_ubGen._matW = Math::QuadMatrix().UniformBufferFormat();
|
||||
s_ubGen._matV = Math::ToUVMatrix().UniformBufferFormat();
|
||||
s_ubGenNormalsFS._textureSize = _tex[TEX_GEN_HEIGHTMAP]->GetSize().GLM();
|
||||
s_ubGenNormalsFS._waterScale.x = 1 / _patchSide;
|
||||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
cb->BeginRenderPass(_rphGenNormals, _fbhGenNormals, { _tex[TEX_GEN_NORMALS]->GetClearValue(), });
|
||||
|
||||
cb->BindPipeline(_pipe[PIPE_GEN_NORMALS]);
|
||||
|
||||
_shader[SHADER_GEN]->BeginBindDescriptors();
|
||||
cb->BindDescriptors(_shader[SHADER_GEN], 0);
|
||||
cb->BindDescriptors(_shader[SHADER_GEN], 2, _cshGenNormals);
|
||||
_shader[SHADER_GEN]->EndBindDescriptors();
|
||||
|
||||
renderer.DrawQuad(&(*cb));
|
||||
|
||||
cb->EndRenderPass();
|
||||
|
||||
_tex[TEX_GEN_NORMALS]->GenerateMips();
|
||||
}
|
||||
|
||||
CGI::TexturePtr Water::GetCausticsTexture() const
|
||||
{
|
||||
VERUS_QREF_CONST_SETTINGS;
|
||||
if (settings._sceneWaterQuality >= App::Settings::WaterQuality::trueWavesReflection)
|
||||
return _tex[TEX_GEN_NORMALS];
|
||||
else
|
||||
return _tex[TEX_SOURCE_HEIGHTMAP];
|
||||
}
|
||||
|
||||
void Water::CreateWaterPlane()
|
||||
{
|
||||
VERUS_QREF_SM;
|
||||
|
||||
const float maxRadius = Math::Min(sm.GetCamera()->GetZFar(), 5000.f);
|
||||
const float stepW = 1.f / (_gridWidth - 1);
|
||||
const float stepH = 1.f / (_gridHeight - 1);
|
||||
|
||||
float xPolar = 0;
|
||||
float zPolar = 0;
|
||||
|
||||
Vector<glm::vec4> vVB;
|
||||
vVB.resize(_gridWidth * _gridHeight);
|
||||
|
||||
const float maxAngle = atan(maxRadius / 10); // Assume best height is 10 meters.
|
||||
VERUS_FOR(i, _gridHeight)
|
||||
{
|
||||
const float radius = tan(zPolar * maxAngle) * 10;
|
||||
VERUS_FOR(j, _gridWidth)
|
||||
{
|
||||
float xSqueeze = xPolar;
|
||||
VERUS_FOR(k, 6)
|
||||
xSqueeze = Math::EaseInOutSine(xSqueeze);
|
||||
xSqueeze = Math::Lerp(xSqueeze, xPolar, 0.2f);
|
||||
|
||||
const float xCartesian = radius * sin(xSqueeze * VERUS_2PI);
|
||||
const float zCartesian = radius * cos(xSqueeze * VERUS_2PI);
|
||||
vVB[i * _gridWidth + j] = glm::vec4(xCartesian, 0, zCartesian, 1);
|
||||
xPolar += stepW;
|
||||
}
|
||||
xPolar = 0;
|
||||
zPolar += stepH;
|
||||
}
|
||||
// Watertight mesh, pun intended:
|
||||
VERUS_FOR(i, _gridHeight)
|
||||
vVB[i * _gridWidth + (_gridWidth - 1)] = vVB[i * _gridWidth];
|
||||
|
||||
_geo->UpdateVertexBuffer(vVB.data(), 0);
|
||||
}
|
||||
|
||||
float Water::PhillipsSpectrum(float k)
|
||||
{
|
||||
const float kl = k;
|
||||
const float k2 = k * k;
|
||||
return exp(-1 / (kl * kl)) / (k2 * k2);
|
||||
}
|
119
Verus/src/Scene/Water.h
Normal file
119
Verus/src/Scene/Water.h
Normal file
|
@ -0,0 +1,119 @@
|
|||
#pragma once
|
||||
|
||||
namespace verus
|
||||
{
|
||||
namespace Scene
|
||||
{
|
||||
class Water : public Singleton<Water>, public Object
|
||||
{
|
||||
public:
|
||||
#include "../Shaders/Water.inc.hlsl"
|
||||
#include "../Shaders/WaterGen.inc.hlsl"
|
||||
|
||||
enum SHADER
|
||||
{
|
||||
SHADER_MAIN,
|
||||
SHADER_GEN,
|
||||
SHADER_COUNT
|
||||
};
|
||||
|
||||
enum PIPE
|
||||
{
|
||||
PIPE_MAIN,
|
||||
PIPE_GEN_HEIGHTMAP,
|
||||
PIPE_GEN_NORMALS,
|
||||
PIPE_COUNT
|
||||
};
|
||||
|
||||
enum TEX
|
||||
{
|
||||
TEX_FOAM,
|
||||
TEX_SOURCE_HEIGHTMAP,
|
||||
TEX_GEN_HEIGHTMAP,
|
||||
TEX_GEN_NORMALS,
|
||||
TEX_REFLECTION,
|
||||
TEX_REFLECTION_DEPTH,
|
||||
|
||||
TEX_REFRACT,
|
||||
TEX_REFLECT,
|
||||
TEX_REFLECT_DEPTH,
|
||||
TEX_COUNT
|
||||
};
|
||||
|
||||
private:
|
||||
static const int s_maxHarmonics = 4;
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
glm::vec4 _pos;
|
||||
};
|
||||
|
||||
static UB_WaterVS s_ubWaterVS;
|
||||
static UB_WaterFS s_ubWaterFS;
|
||||
static UB_Gen s_ubGen;
|
||||
static UB_GenHeightmapFS s_ubGenHeightmapFS;
|
||||
static UB_GenNormalsFS s_ubGenNormalsFS;
|
||||
|
||||
PTerrain _pTerrain = nullptr;
|
||||
Vector<Vertex> _vSwapBuffer;
|
||||
CGI::GeometryPwn _geo;
|
||||
CGI::ShaderPwns<SHADER_COUNT> _shader;
|
||||
CGI::PipelinePwns<PIPE_COUNT> _pipe;
|
||||
CGI::TexturePwns<TEX_COUNT> _tex;
|
||||
CGI::TexturePtr _texLand;
|
||||
CGI::CSHandle _cshWaterVS;
|
||||
CGI::CSHandle _cshWaterFS;
|
||||
CGI::RPHandle _rphGenHeightmap;
|
||||
CGI::FBHandle _fbhGenHeightmap;
|
||||
CGI::CSHandle _cshGenHeightmap;
|
||||
CGI::RPHandle _rphGenNormals;
|
||||
CGI::FBHandle _fbhGenNormals;
|
||||
CGI::CSHandle _cshGenNormals;
|
||||
CGI::RPHandle _rphReflection;
|
||||
CGI::FBHandle _fbhReflection;
|
||||
const int _genSide = 1024;
|
||||
const int _sideReflect = 256;
|
||||
int _gridWidth = 128;
|
||||
int _gridHeight = 512;
|
||||
int _indexCount = 0;
|
||||
const float _patchSide = 64;
|
||||
float _phase = 0;
|
||||
float _phaseWave = 0;
|
||||
float _amplitudes[s_maxHarmonics];
|
||||
bool _reflectionMode = false;
|
||||
bool _renderToTexture = false;
|
||||
bool _geoReady = false;
|
||||
|
||||
public:
|
||||
Water();
|
||||
~Water();
|
||||
|
||||
void Init(RTerrain terrain);
|
||||
void Done();
|
||||
|
||||
void Update();
|
||||
void Draw();
|
||||
|
||||
void BeginReflection(CGI::PBaseCommandBuffer pCB = nullptr);
|
||||
void EndReflection(CGI::PBaseCommandBuffer pCB = nullptr);
|
||||
|
||||
void GenerateTextures();
|
||||
VERUS_P(void GenerateHeightmapTexture());
|
||||
VERUS_P(void GenerateNormalsTexture());
|
||||
|
||||
// Caustics are highlights on ocean floor.
|
||||
CGI::TexturePtr GetCausticsTexture() const;
|
||||
|
||||
// Render reflection when above or normal view when below water level.
|
||||
bool IsReflectionMode() const { return _reflectionMode; }
|
||||
|
||||
// Is rendering done to water's renderer target?
|
||||
bool IsRenderToTexture() const { return _renderToTexture; }
|
||||
|
||||
VERUS_P(void CreateWaterPlane());
|
||||
|
||||
static float PhillipsSpectrum(float k);
|
||||
};
|
||||
VERUS_TYPEDEFS(Water);
|
||||
}
|
||||
}
|
|
@ -18,7 +18,7 @@ ConstantBuffer<UB_PerObject> g_ubPerObject : register(b0, space4);
|
|||
VK_SUBPASS_INPUT(0, g_texGBuffer0, g_samGBuffer0, t1, s1, space1);
|
||||
VK_SUBPASS_INPUT(1, g_texGBuffer1, g_samGBuffer1, t2, s2, space1);
|
||||
VK_SUBPASS_INPUT(2, g_texGBuffer2, g_samGBuffer2, t3, s3, space1);
|
||||
VK_SUBPASS_INPUT(3, g_texGBuffer3, g_samGBuffer3, t4, s4, space1);
|
||||
VK_SUBPASS_INPUT(3, g_texDepth, g_samDepth, t4, s4, space1);
|
||||
Texture2D g_texShadowCmp : register(t5, space1);
|
||||
SamplerComparisonState g_samShadowCmp : register(s5, space1);
|
||||
Texture2D g_texShadow : register(t6, space1);
|
||||
|
@ -26,18 +26,16 @@ SamplerState g_samShadow : register(s6, space1);
|
|||
|
||||
struct VSI
|
||||
{
|
||||
// Binding 0:
|
||||
VK_LOCATION_POSITION int4 pos : POSITION;
|
||||
VK_LOCATION_NORMAL float3 nrm : NORMAL;
|
||||
VK_LOCATION(8) int4 tc0 : TEXCOORD0;
|
||||
|
||||
_PER_INSTANCE_DATA
|
||||
};
|
||||
|
||||
struct VSO
|
||||
{
|
||||
float4 pos /**/ : SV_Position;
|
||||
float4 posFS /**/ : TEXCOORD0;
|
||||
float4 clipSpacePos /**/ : TEXCOORD0;
|
||||
#if defined(DEF_OMNI) || defined(DEF_SPOT)
|
||||
float3 radius_radiusSq_invRadiusSq /**/ : TEXCOORD1;
|
||||
float3 lightPosWV /**/ : TEXCOORD2;
|
||||
|
@ -56,8 +54,6 @@ VSO mainVS(VSI si)
|
|||
{
|
||||
VSO so;
|
||||
|
||||
const float3 intactPos = DequantizeUsingDeq3D(si.pos.xyz, g_ubPerMeshVS._posDeqScale.xyz, g_ubPerMeshVS._posDeqBias.xyz);
|
||||
|
||||
// World matrix, instance data:
|
||||
#ifdef DEF_INSTANCED
|
||||
const mataff matW = GetInstMatrix(
|
||||
|
@ -84,13 +80,15 @@ VSO mainVS(VSI si)
|
|||
const float3x3 matV33 = (float3x3)g_ubPerFrame._matV;
|
||||
const float3x3 matWV33 = (float3x3)matWV;
|
||||
|
||||
const float3 intactPos = DequantizeUsingDeq3D(si.pos.xyz, g_ubPerMeshVS._posDeqScale.xyz, g_ubPerMeshVS._posDeqBias.xyz);
|
||||
|
||||
#ifdef DEF_DIR
|
||||
so.pos = float4(mul(float4(intactPos, 1), g_ubPerFrame._matQuad), 1);
|
||||
so.posFS = float4(intactPos, 1);
|
||||
so.clipSpacePos = float4(intactPos, 1);
|
||||
#else
|
||||
const float3 posW = mul(float4(intactPos, 1), matW);
|
||||
so.pos = mul(float4(posW, 1), g_ubPerFrame._matVP);
|
||||
so.posFS = so.pos;
|
||||
so.clipSpacePos = so.pos;
|
||||
#endif
|
||||
|
||||
// <MoreLightParams>
|
||||
|
@ -128,15 +126,13 @@ DS_ACC_FSO mainFS(VSO si)
|
|||
{
|
||||
DS_ACC_FSO so;
|
||||
|
||||
// Clip-space position:
|
||||
#ifdef DEF_DIR
|
||||
const float3 posCS = si.posFS.xyz;
|
||||
const float3 ndcPos = si.clipSpacePos.xyz;
|
||||
#else
|
||||
const float3 posCS = si.posFS.xyz / si.posFS.w;
|
||||
const float3 ndcPos = si.clipSpacePos.xyz / si.clipSpacePos.w;
|
||||
#endif
|
||||
|
||||
// GBuffer tex. coord. from posCS:
|
||||
const float2 tc0 = mul(float4(posCS.xy, 0, 1), g_ubPerFrame._matToUV).xy;
|
||||
const float2 tc0 = mul(float4(ndcPos.xy, 0, 1), g_ubPerFrame._matToUV).xy;
|
||||
|
||||
// For Omni & Spot: light's radius and position:
|
||||
#if defined(DEF_OMNI) || defined(DEF_SPOT)
|
||||
|
@ -163,8 +159,8 @@ DS_ACC_FSO mainFS(VSO si)
|
|||
#endif
|
||||
|
||||
// GBuffer1:
|
||||
const float rawGBuffer1 = VK_SUBPASS_LOAD(g_texGBuffer1, g_samGBuffer1, tc0).r;
|
||||
const float3 posWV = DS_GetPosition(rawGBuffer1, g_ubPerFrame._matInvP, posCS.xy);
|
||||
const float depth = VK_SUBPASS_LOAD(g_texDepth, g_samDepth, tc0).r;
|
||||
const float3 posWV = DS_GetPosition(depth, g_ubPerFrame._matInvP, ndcPos.xy);
|
||||
|
||||
so.target0 = 0.0;
|
||||
so.target1 = 0.0;
|
||||
|
@ -174,35 +170,34 @@ DS_ACC_FSO mainFS(VSO si)
|
|||
#endif
|
||||
{
|
||||
// Light's diffuse & specular color:
|
||||
const float3 colorDiff = si.color_coneOut.rgb;
|
||||
const float3 colorSpec = saturate(colorDiff + dot(colorDiff, 0.1));
|
||||
const float3 hdrLightColor = si.color_coneOut.rgb;
|
||||
|
||||
// GBuffer0 (color, spec):
|
||||
// GBuffer0 (albedo, spec):
|
||||
const float4 rawGBuffer0 = VK_SUBPASS_LOAD(g_texGBuffer0, g_samGBuffer0, tc0);
|
||||
const float spec = rawGBuffer0.a;
|
||||
const float3 dirToEyeWV = normalize(-posWV);
|
||||
|
||||
// GBuffer2 (normal, emission, motion):
|
||||
const float4 rawGBuffer2 = VK_SUBPASS_LOAD(g_texGBuffer2, g_samGBuffer2, tc0);
|
||||
const float3 normalWV = DS_GetNormal(rawGBuffer2);
|
||||
const float2 emission = DS_GetEmission(rawGBuffer2);
|
||||
const float4 rawGBuffer1 = VK_SUBPASS_LOAD(g_texGBuffer1, g_samGBuffer1, tc0);
|
||||
const float3 normalWV = DS_GetNormal(rawGBuffer1);
|
||||
const float2 emission = DS_GetEmission(rawGBuffer1);
|
||||
|
||||
// GBuffer3 (lam, metal, gloss):
|
||||
const float4 rawGBuffer3 = VK_SUBPASS_LOAD(g_texGBuffer3, g_samGBuffer3, tc0);
|
||||
const float3 anisoWV = DS_GetAnisoSpec(rawGBuffer3);
|
||||
const float2 lamScaleBias = DS_GetLamScaleBias(rawGBuffer3);
|
||||
const float2 metal = DS_GetMetallicity(rawGBuffer3);
|
||||
const float gloss64 = rawGBuffer3.a * 64.0;
|
||||
const float4 rawGBuffer2 = VK_SUBPASS_LOAD(g_texGBuffer2, g_samGBuffer2, tc0);
|
||||
const float3 anisoWV = DS_GetAnisoSpec(rawGBuffer2);
|
||||
const float2 lamScaleBias = DS_GetLamScaleBias(rawGBuffer2);
|
||||
const float2 metal = DS_GetMetallicity(rawGBuffer2);
|
||||
const float gloss64 = rawGBuffer2.a * 64.0;
|
||||
const float gloss64Scaled = gloss64 * glossScale;
|
||||
|
||||
// Special:
|
||||
const float skinAlpha = emission.y;
|
||||
const float hairAlpha = metal.y;
|
||||
const float eyeAlpha = saturate(1.0 - gloss64);
|
||||
const float rim = pow(1.0 - normalWV.z, 2.0) * (0.05 + 0.2 * skinAlpha);
|
||||
const float glossEye = 25.0 * glossScale;
|
||||
const float skinMask = emission.y;
|
||||
const float hairMask = metal.y;
|
||||
const float eyeMask = saturate(1.0 - gloss64);
|
||||
const float eyeGloss = 25.0 * glossScale;
|
||||
const float2 lamScaleBiasWithHair = lerp(lamScaleBias, float2(1, 0.4), hairMask);
|
||||
|
||||
const float gloss = lerp(gloss64Scaled * gloss64Scaled * gloss64Scaled, glossEye * glossEye * glossEye, eyeAlpha);
|
||||
const float gloss = lerp(gloss64Scaled * gloss64Scaled * gloss64Scaled, eyeGloss * eyeGloss * eyeGloss, eyeMask);
|
||||
|
||||
#ifdef DEF_DIR
|
||||
const float3 dirToLightWV = -lightDirWV;
|
||||
|
@ -225,63 +220,65 @@ DS_ACC_FSO mainFS(VSO si)
|
|||
#endif
|
||||
|
||||
const float4 litRet = VerusLit(dirToLightWV, normalWV, dirToEyeWV,
|
||||
lerp(gloss * (2.0 - lightFalloff), 12.0, hairAlpha),
|
||||
lerp(lamScaleBias, float2(1, 0.4), hairAlpha),
|
||||
float4(anisoWV, hairAlpha));
|
||||
lerp(gloss * (2.0 - lightFalloff), 12.0, hairMask),
|
||||
lamScaleBiasWithHair,
|
||||
float4(anisoWV, hairMask));
|
||||
|
||||
// Shadow:
|
||||
// <Shadow>
|
||||
float shadowMask = 1.0;
|
||||
{
|
||||
#ifdef DEF_DIR
|
||||
const float4 tcShadow = ShadowCoords(float4(posWV, 1), g_ubShadowFS._matSunShadow, -posWV.z);
|
||||
const float shadowAlpha = ShadowMapCSM(
|
||||
float4 config = g_ubShadowFS._shadowConfig;
|
||||
const float lamBiasMask = saturate(lamScaleBiasWithHair.y * config.y);
|
||||
config.y = 1.0 - lamBiasMask; // Keep penumbra blurry.
|
||||
const float scale = -posWV.z - 5.0;
|
||||
const float3 posForShadow = posWV + normalWV * 0.012 * max(1.0, scale * 0.2) + dirToLightWV * max(0.0, scale * 0.002);
|
||||
const float4 tcShadow = ShadowCoords(float4(posForShadow, 1), g_ubShadowFS._matSunShadow, -posForShadow.z);
|
||||
shadowMask = ShadowMapCSM(
|
||||
g_texShadowCmp,
|
||||
g_samShadowCmp,
|
||||
g_texShadow,
|
||||
g_samShadow,
|
||||
tcShadow,
|
||||
g_ubShadowFS._shadowConfig,
|
||||
config,
|
||||
g_ubShadowFS._splitRanges,
|
||||
g_ubShadowFS._matSunShadow,
|
||||
g_ubShadowFS._matSunShadowCSM1,
|
||||
g_ubShadowFS._matSunShadowCSM2,
|
||||
g_ubShadowFS._matSunShadowCSM3);
|
||||
#else
|
||||
const float shadowAlpha = 1.0;
|
||||
#endif
|
||||
}
|
||||
// </Shadow>
|
||||
|
||||
const float intensityDiff = lightFalloff * coneIntensity * shadowAlpha;
|
||||
const float intensitySpec = saturate(intensityDiff * 2.0) * shadowAlpha;
|
||||
const float maxSpecAdd = lerp(0.2 * spec, 0.1 + spec * 0.5, metal.x);
|
||||
const float lightFalloffWithCone = lightFalloff * coneIntensity;
|
||||
const float diffLightMask = lightFalloffWithCone * shadowMask;
|
||||
const float specLightMask = saturate(lightFalloffWithCone * 2.0) * shadowMask;
|
||||
const float maxSpecAdd = (1.0 - spec) * lerp(0.01, 0.5, metal.x);
|
||||
|
||||
// Subsurface scattering effect for front & back faces:
|
||||
const float3 colorSkinSSS_Face = float3(1.6, 1.2, 0.3);
|
||||
const float3 colorSkinSSS_Back = float3(1.6, 0.8, 0.5);
|
||||
const float3 colorDiffSSS_Face = lerp(colorDiff, colorDiff * colorSkinSSS_Face, skinAlpha * pow(1.0 - litRet.y, 2.0));
|
||||
const float3 colorDiffSSS_Back = lerp(colorDiffSSS_Face, colorDiff * colorSkinSSS_Back, skinAlpha * litRet.x);
|
||||
const float3 frontSkinSSSColor = float3(1.6, 1.2, 0.3);
|
||||
const float3 backSkinSSSColor = float3(1.6, 0.8, 0.5);
|
||||
const float frontSkinSSSMask = 1.0 - litRet.y;
|
||||
const float3 hdrLightFaceColor = hdrLightColor * lerp(1.0, frontSkinSSSColor, skinMask * frontSkinSSSMask * frontSkinSSSMask);
|
||||
const float3 hdrLightColorSSS = lerp(hdrLightFaceColor, hdrLightColor * backSkinSSSColor, skinMask * litRet.x);
|
||||
|
||||
const float gray = Grayscale(rawGBuffer0.rgb);
|
||||
const float3 metalSpec = saturate(rawGBuffer0.rgb / (gray + _SINGULARITY_FIX));
|
||||
|
||||
const float3 matSpec = lerp(float3(1, 1, 1), metalSpec, saturate(metal.x + (hairAlpha - eyeAlpha) * 0.4)) * FresnelSchlick(spec, maxSpecAdd, litRet.w);
|
||||
const float3 maxDiff = colorDiffSSS_Back * intensityDiff;
|
||||
const float3 maxSpec = matSpec * colorSpec + float3(-0.03, 0.0, 0.05) * skinAlpha;
|
||||
#ifdef DEF_DIR
|
||||
const float skyIntensity = 1.0;
|
||||
const float3 skySpec = skyColor * matSpec * skyIntensity;
|
||||
#endif
|
||||
|
||||
// Very bright light:
|
||||
const float3 overbright = saturate(dot(maxDiff, 1.0 / 3.0) - 1.0); // Intensity above one.
|
||||
const float3 diffBoost = overbright * maxDiff * litRet.y * (0.25 + rawGBuffer0.rgb);
|
||||
const float3 specHue = saturate(lerp(float3(1, 1, 1), metalSpec, saturate(metal.x + (hairMask - eyeMask) * 0.4)) +
|
||||
float3(-0.03, 0.0, 0.05) * skinMask);
|
||||
const float3 hdrMaxDiff = hdrLightColorSSS * diffLightMask;
|
||||
const float3 hdrMaxSpec = hdrLightColorSSS * specLightMask * specHue * FresnelSchlick(spec, maxSpecAdd, litRet.w);
|
||||
|
||||
#ifdef DEF_DIR
|
||||
so.target0.rgb = maxDiff * litRet.y; // Lambert's cosine law.
|
||||
so.target1.rgb = maxSpec * saturate(litRet.z * intensitySpec + rim) + diffBoost;
|
||||
so.target0.rgb = hdrMaxDiff * litRet.y;
|
||||
so.target1.rgb = hdrMaxSpec * litRet.z;
|
||||
#else
|
||||
so.target0.rgb = maxDiff * litRet.y; // Lambert's cosine law.
|
||||
so.target1.rgb = maxSpec * saturate(litRet.z * intensitySpec) + diffBoost;
|
||||
so.target0.rgb = hdrMaxDiff * litRet.y;
|
||||
so.target1.rgb = hdrMaxSpec * litRet.z;
|
||||
#endif
|
||||
so.target0.rgb = max(so.target0.rgb, emission.x);
|
||||
so.target1.rgb = min(so.target1.rgb, 1.0 - emission.x);
|
||||
//so.target0.rgb = max(so.target0.rgb, emission.x);
|
||||
//so.target1.rgb = min(so.target1.rgb, 1.0 - emission.x);
|
||||
so.target0.a = 1.0;
|
||||
so.target1.a = 1.0;
|
||||
}
|
||||
|
|
|
@ -15,8 +15,8 @@ Texture2D g_texGBuffer1 : register(t2, space1);
|
|||
SamplerState g_samGBuffer1 : register(s2, space1);
|
||||
Texture2D g_texGBuffer2 : register(t3, space1);
|
||||
SamplerState g_samGBuffer2 : register(s3, space1);
|
||||
Texture2D g_texGBuffer3 : register(t4, space1);
|
||||
SamplerState g_samGBuffer3 : register(s4, space1);
|
||||
Texture2D g_texDepth : register(t4, space1);
|
||||
SamplerState g_samDepth : register(s4, space1);
|
||||
Texture2D g_texAccDiff : register(t5, space1);
|
||||
SamplerState g_samAccDiff : register(s5, space1);
|
||||
Texture2D g_texAccSpec : register(t6, space1);
|
||||
|
@ -31,6 +31,7 @@ struct VSO
|
|||
{
|
||||
float4 pos : SV_Position;
|
||||
float2 tc0 : TEXCOORD0;
|
||||
float2 clipSpacePos : TEXCOORD1;
|
||||
};
|
||||
|
||||
struct FSO
|
||||
|
@ -46,6 +47,7 @@ VSO mainVS(VSI si)
|
|||
// Standard quad:
|
||||
so.pos = float4(mul(si.pos, g_ubComposeVS._matW), 1);
|
||||
so.tc0 = mul(si.pos, g_ubComposeVS._matV).xy;
|
||||
so.clipSpacePos = so.pos.xy;
|
||||
|
||||
return so;
|
||||
}
|
||||
|
@ -56,14 +58,17 @@ FSO mainFS(VSO si)
|
|||
{
|
||||
FSO so;
|
||||
|
||||
#ifdef DEF_COMPOSE
|
||||
const float3 colorAmbient = g_ubComposeFS._colorAmbient.rgb;
|
||||
|
||||
const float2 ndcPos = si.clipSpacePos.xy;
|
||||
|
||||
const float4 rawGBuffer0 = g_texGBuffer0.Sample(g_samGBuffer0, si.tc0);
|
||||
const float1 rawGBuffer1 = g_texGBuffer1.Sample(g_samGBuffer1, si.tc0).r; // Depth for fog.
|
||||
const float4 rawGBuffer1 = g_texGBuffer1.Sample(g_samGBuffer1, si.tc0);
|
||||
const float4 rawGBuffer2 = g_texGBuffer2.Sample(g_samGBuffer2, si.tc0);
|
||||
const float4 rawGBuffer3 = g_texGBuffer3.Sample(g_samGBuffer3, si.tc0);
|
||||
const float3 normalWV = DS_GetNormal(rawGBuffer2);
|
||||
const float2 emission = DS_GetEmission(rawGBuffer2);
|
||||
const float1 rawDepth = g_texDepth.Sample(g_samDepth, si.tc0).r;
|
||||
const float3 normalWV = DS_GetNormal(rawGBuffer1);
|
||||
const float2 emission = DS_GetEmission(rawGBuffer1);
|
||||
|
||||
const float4 rawAccDiff = g_texAccDiff.Sample(g_samAccDiff, si.tc0);
|
||||
const float4 rawAccSpec = g_texAccSpec.Sample(g_samAccSpec, si.tc0);
|
||||
|
@ -74,28 +79,40 @@ FSO mainFS(VSO si)
|
|||
const float ssaoSpec = 1.0;
|
||||
const float ssaoAmb = 1.0;
|
||||
|
||||
const float3 albedo = rawGBuffer0.rgb;
|
||||
const float3 albedo = max(rawGBuffer0.rgb * g_ubComposeFS._toneMappingConfig.z, 0.0001);
|
||||
|
||||
const float depth = ToLinearDepth(rawGBuffer1, g_ubComposeFS._zNearFarEx);
|
||||
const float fog = ComputeFog(depth, g_ubComposeFS._fogColor.a);
|
||||
const float depth = ToLinearDepth(rawDepth, g_ubComposeFS._zNearFarEx);
|
||||
const float3 posW = DS_GetPosition(rawDepth, g_ubComposeFS._matInvVP, ndcPos);
|
||||
const float fog = ComputeFog(depth, g_ubComposeFS._fogColor.a, posW.y);
|
||||
|
||||
const float3 normalW = mul(normalWV, (float3x3)g_ubComposeFS._matInvV);
|
||||
const float gray = Grayscale(colorAmbient);
|
||||
const float3 colorGround = lerp(colorAmbient, float3(1, 0.88, 0.47) * gray, saturate(gray * 14.0));
|
||||
const float grayAmbient = Grayscale(colorAmbient);
|
||||
const float3 colorGround = lerp(colorAmbient, float3(1, 0.88, 0.47) * grayAmbient, saturate(grayAmbient * 14.0));
|
||||
const float3 colorAmbientFinal = lerp(colorGround, colorAmbient, saturate(normalW.y * 2.0 + 0.5));
|
||||
|
||||
const float3 color =
|
||||
albedo * saturate(accDiff.rgb * ssaoDiff + colorAmbientFinal * ssaoAmb) +
|
||||
albedo * (accDiff.rgb * ssaoDiff + colorAmbientFinal * ssaoAmb) +
|
||||
accSpec.rgb * ssaoSpec +
|
||||
albedo * emission.x;
|
||||
|
||||
const float3 colorWithFog = lerp(color, g_ubComposeFS._fogColor.rgb, fog);
|
||||
|
||||
so.color.rgb = lerp(colorWithFog, g_ubComposeFS._colorBackground.rgb, floor(rawGBuffer1) * g_ubComposeFS._colorBackground.a);
|
||||
so.color.rgb = colorWithFog;
|
||||
so.color.rgb = lerp(so.color.rgb, g_ubComposeFS._colorBackground.rgb, floor(rawDepth) * g_ubComposeFS._colorBackground.a);
|
||||
so.color.a = 1.0;
|
||||
#endif
|
||||
|
||||
#ifdef DEF_TONE_MAPPING
|
||||
const float4 rawComposed = g_texGBuffer0.Sample(g_samGBuffer0, si.tc0);
|
||||
|
||||
so.color.rgb = VerusToneMapping(rawComposed.rgb * g_ubComposeFS._toneMappingConfig.x, g_ubComposeFS._toneMappingConfig.y);
|
||||
so.color.a = 1.0;
|
||||
|
||||
#endif
|
||||
|
||||
return so;
|
||||
}
|
||||
#endif
|
||||
|
||||
//@main:#
|
||||
//@main:#Compose COMPOSE
|
||||
//@main:#ToneMapping TONE_MAPPING
|
||||
|
|
|
@ -9,8 +9,10 @@ VERUS_UBUFFER UB_ComposeVS
|
|||
VERUS_UBUFFER UB_ComposeFS
|
||||
{
|
||||
mataff _matInvV;
|
||||
matrix _matInvVP;
|
||||
float4 _colorAmbient;
|
||||
float4 _colorBackground;
|
||||
float4 _fogColor;
|
||||
float4 _zNearFarEx;
|
||||
float4 _toneMappingConfig;
|
||||
};
|
||||
|
|
237
Verus/src/Shaders/DS_Grass.hlsl
Normal file
237
Verus/src/Shaders/DS_Grass.hlsl
Normal file
|
@ -0,0 +1,237 @@
|
|||
// Copyright (C) 2020, Dmitry Maluev (dmaluev@gmail.com)
|
||||
|
||||
#include "Lib.hlsl"
|
||||
#include "LibColor.hlsl"
|
||||
#include "LibDeferredShading.hlsl"
|
||||
#include "LibSurface.hlsl"
|
||||
#include "LibVertex.hlsl"
|
||||
#include "DS_Grass.inc.hlsl"
|
||||
|
||||
ConstantBuffer<UB_GrassVS> g_ubGrassVS : register(b0, space0);
|
||||
ConstantBuffer<UB_GrassFS> g_ubGrassFS : register(b0, space1);
|
||||
|
||||
Texture2D g_texHeightVS : register(t1, space0);
|
||||
SamplerState g_samHeightVS : register(s1, space0);
|
||||
Texture2D g_texNormalVS : register(t2, space0);
|
||||
SamplerState g_samNormalVS : register(s2, space0);
|
||||
Texture2D g_texMLayerVS : register(t3, space0);
|
||||
SamplerState g_samMLayerVS : register(s3, space0);
|
||||
|
||||
Texture2D g_texAlbedo : register(t1, space1);
|
||||
SamplerState g_samAlbedo : register(s1, space1);
|
||||
|
||||
struct VSI
|
||||
{
|
||||
VK_LOCATION_POSITION int4 pos : POSITION;
|
||||
VK_LOCATION(8) int4 tc : TEXCOORD0;
|
||||
VK_LOCATION(16) int4 patchPos : INSTDATA0;
|
||||
uint vertexID : SV_VertexID;
|
||||
};
|
||||
|
||||
struct VSO
|
||||
{
|
||||
float4 pos : SV_Position;
|
||||
float2 tc0 : TEXCOORD0;
|
||||
float3 tcOffset_phaseShift : TEXCOORD1;
|
||||
float4 normal_top : TEXCOORD2;
|
||||
float2 psize : PSIZE;
|
||||
};
|
||||
|
||||
#ifdef _VS
|
||||
VSO mainVS(VSI si)
|
||||
{
|
||||
VSO so;
|
||||
|
||||
const float phase = g_ubGrassVS._phase_mapSideInv_bushMask.x;
|
||||
const float mapSideInv = g_ubGrassVS._phase_mapSideInv_bushMask.y;
|
||||
const float bushMask = g_ubGrassVS._phase_mapSideInv_bushMask.z;
|
||||
const float3 warp = g_ubGrassVS._warp_turb.xyz;
|
||||
const float turbulence = g_ubGrassVS._warp_turb.w;
|
||||
|
||||
#ifdef DEF_BILLBOARDS
|
||||
const uint bushID = si.vertexID;
|
||||
#else
|
||||
const uint bushID = si.vertexID >> 3; // 8 vertices per bush.
|
||||
#endif
|
||||
|
||||
// <FromTextures>
|
||||
float3 intactPos;
|
||||
float3 pos;
|
||||
float2 center;
|
||||
float2 pointSpriteScale = 1.0;
|
||||
float groundHeight;
|
||||
float3 normal;
|
||||
float2 tc0;
|
||||
bool bushMaskOK = true;
|
||||
{
|
||||
intactPos = si.pos.xyz * (1.0 / 1000.0);
|
||||
pos = intactPos + float3(si.patchPos.x, 0, si.patchPos.z);
|
||||
center = si.tc.zw * (1.0 / 1000.0) + si.patchPos.xz;
|
||||
#ifdef DEF_BILLBOARDS
|
||||
pointSpriteScale = intactPos.y;
|
||||
pos = float3(center.x, 0.45 * pointSpriteScale.y, center.y);
|
||||
#endif
|
||||
|
||||
const float bestPrecision = 50.0;
|
||||
const float distToEye = distance(pos + float3(0, si.patchPos.y * 0.01, 0), g_ubGrassVS._posEye.xyz);
|
||||
const float geomipsLod = log2(clamp(distToEye * (2.0 / 100.0), 1.0, 18.0));
|
||||
const float texelCenter = 0.5 * mapSideInv;
|
||||
const float mipTexelCenter = texelCenter * exp2(geomipsLod);
|
||||
const float2 tcMap = pos.xz * mapSideInv + 0.5;
|
||||
const float2 tcUniform = center * mapSideInv + 0.5;
|
||||
groundHeight = g_texHeightVS.SampleLevel(g_samHeightVS, tcMap + mipTexelCenter, geomipsLod).r + bestPrecision;
|
||||
pos.y += groundHeight;
|
||||
|
||||
const float4 rawNormal = g_texNormalVS.SampleLevel(g_samNormalVS, tcUniform + texelCenter, 0.0);
|
||||
normal = float3(rawNormal.x, 0, rawNormal.y) * 2.0 - 1.0;
|
||||
normal.y = ComputeNormalZ(normal.xz);
|
||||
|
||||
const float layer = g_texMLayerVS.SampleLevel(g_samMLayerVS, tcUniform, 0.0).r * 4.0;
|
||||
const float uShift = frac(layer) - (16.0 / 256.0);
|
||||
const float vShift = floor(layer) * 0.25;
|
||||
float vShiftAlt = 0.0;
|
||||
if (!(bushID & 0xF))
|
||||
vShiftAlt = 0.5; // Every 16th bush uses alternative texture.
|
||||
tc0 = si.tc.xy * (1.0 / 100.0) + float2(uShift, vShift + vShiftAlt);
|
||||
|
||||
// Cull blank bushes:
|
||||
const int mainLayer = round(layer * 4.0);
|
||||
const int ibushMask = asint(bushMask);
|
||||
if (!((ibushMask >> mainLayer) & 0x1))
|
||||
{
|
||||
bushMaskOK = false;
|
||||
}
|
||||
}
|
||||
// </FromTextures>
|
||||
|
||||
// <Special>
|
||||
float phaseShift = 0.0;
|
||||
float2 windWarp = 0.0;
|
||||
float top = 0.0;
|
||||
{
|
||||
#ifdef DEF_BILLBOARDS
|
||||
phaseShift = frac(si.pos.w * (1.0 / 100.0));
|
||||
windWarp = 0.0;
|
||||
top = 0.28;
|
||||
#else
|
||||
if (intactPos.y >= 0.1)
|
||||
{
|
||||
phaseShift = frac(si.pos.w * (1.0 / 100.0));
|
||||
windWarp = warp.xz * (1.0 + turbulence * sin((phase + phaseShift) * (_PI * 2.0)));
|
||||
top = 1.0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// </Special>
|
||||
|
||||
// <Warp>
|
||||
float3 posWarped = pos;
|
||||
{
|
||||
const float distToEye = -mul(float4(posWarped, 1), g_ubGrassVS._matWV).z;
|
||||
const float distant = saturate((distToEye - 50.0) * (1.0 / 50.0)); // [50.0 to 100.0] -> [0.0 to 1.0].
|
||||
const float distExt = saturate((distToEye - 25.0) * (1.0 / 25.0)); // [25.0 to 50.0] -> [0.0 to 1.0].
|
||||
|
||||
const float cliff = dot(normal.xz, normal.xz);
|
||||
float hide = cliff + step(groundHeight, 1.0) + distant;
|
||||
if (!bushMaskOK)
|
||||
hide = 1.0;
|
||||
posWarped.xz -= normal.xz;
|
||||
#ifdef DEF_BILLBOARDS
|
||||
const float distExtInv = 1.0 - distExt;
|
||||
posWarped.xz += windWarp * 0.5;
|
||||
hide += distExtInv * distExtInv;
|
||||
#else
|
||||
posWarped.xz += windWarp;
|
||||
posWarped.y -= dot(windWarp, windWarp);
|
||||
hide += distExt * distExt;
|
||||
#endif
|
||||
hide = saturate(hide);
|
||||
|
||||
#ifdef DEF_BILLBOARDS
|
||||
pointSpriteScale = lerp(pointSpriteScale, float2(0.0, pointSpriteScale.y), hide);
|
||||
#else
|
||||
posWarped = lerp(posWarped, float3(center.x, posWarped.y, center.y), hide); // Optimize by morphing to center point.
|
||||
#endif
|
||||
}
|
||||
// </Warp>
|
||||
|
||||
const float3 posW = mul(float4(posWarped, 1), g_ubGrassVS._matW).xyz;
|
||||
so.pos = mul(float4(posW, 1), g_ubGrassVS._matVP);
|
||||
so.tc0 = tc0;
|
||||
so.tcOffset_phaseShift = float3(0, 0, phaseShift);
|
||||
so.normal_top.xyz = mul(normal, (float3x3)g_ubGrassVS._matWV);
|
||||
so.normal_top.w = top;
|
||||
so.psize = 1.0;
|
||||
|
||||
#ifdef DEF_BILLBOARDS
|
||||
so.tcOffset_phaseShift.xy = tc0;
|
||||
const float2 pointSize = g_ubGrassVS._viewportSize.yx * g_ubGrassVS._viewportSize.z * pointSpriteScale;
|
||||
so.psize = pointSize * g_ubGrassVS._matP._m11;
|
||||
#else
|
||||
so.normal_top.xyz += float3(0, 0, top * top * 0.25);
|
||||
#endif
|
||||
|
||||
return so;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _GS
|
||||
[maxvertexcount(4)]
|
||||
void mainGS(point VSO si[1], inout TriangleStream<VSO> stream)
|
||||
{
|
||||
VSO so;
|
||||
|
||||
so = si[0];
|
||||
const float2 center = so.pos.xy;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
so.pos.xy = center + _POINT_SPRITE_POS_OFFSETS[i] * so.psize;
|
||||
so.tc0.xy = _POINT_SPRITE_TEX_COORDS[i];
|
||||
stream.Append(so);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _FS
|
||||
DS_FSO mainFS(VSO si)
|
||||
{
|
||||
DS_FSO so;
|
||||
|
||||
const float3 rand = Rand(si.pos.xy);
|
||||
|
||||
float2 tc = si.tc0;
|
||||
#ifdef DEF_BILLBOARDS
|
||||
tc = si.tc0 * 0.23 + si.tcOffset_phaseShift.xy;
|
||||
#endif
|
||||
|
||||
const float4 rawAlbedo = g_texAlbedo.Sample(g_samAlbedo, tc);
|
||||
const float3 normal = normalize(si.normal_top.xyz);
|
||||
const float gray = Grayscale(rawAlbedo.rgb);
|
||||
const float mask = saturate((gray - 0.25) * 4.0 + 0.25);
|
||||
|
||||
const float top = si.normal_top.w;
|
||||
const float spec = saturate(top * top * (mask + si.tcOffset_phaseShift.z * 0.1));
|
||||
const float gloss = lerp(4.0, 12.0, spec);
|
||||
|
||||
{
|
||||
DS_Reset(so);
|
||||
|
||||
DS_SetAlbedo(so, rawAlbedo.rgb);
|
||||
DS_SetSpec(so, spec);
|
||||
|
||||
DS_SetNormal(so, normal + NormalDither(rand));
|
||||
DS_SetEmission(so, 0.0, 0.0);
|
||||
|
||||
DS_SetLamScaleBias(so, float2(1.2, -0.2), 0.0);
|
||||
DS_SetMetallicity(so, 0.05, 0.0);
|
||||
DS_SetGloss(so, gloss);
|
||||
}
|
||||
|
||||
clip(rawAlbedo.a - 0.5);
|
||||
|
||||
return so;
|
||||
}
|
||||
#endif
|
||||
|
||||
//@main:#
|
||||
//@main:#Billboards BILLBOARDS (VGF)
|
18
Verus/src/Shaders/DS_Grass.inc.hlsl
Normal file
18
Verus/src/Shaders/DS_Grass.inc.hlsl
Normal file
|
@ -0,0 +1,18 @@
|
|||
// Copyright (C) 2020, Dmitry Maluev (dmaluev@gmail.com)
|
||||
|
||||
VERUS_UBUFFER UB_GrassVS
|
||||
{
|
||||
mataff _matW;
|
||||
mataff _matWV;
|
||||
matrix _matVP;
|
||||
matrix _matP;
|
||||
float4 _phase_mapSideInv_bushMask;
|
||||
float4 _posEye;
|
||||
float4 _viewportSize;
|
||||
float4 _warp_turb;
|
||||
};
|
||||
|
||||
VERUS_UBUFFER UB_GrassFS
|
||||
{
|
||||
float4 _dummy;
|
||||
};
|
|
@ -3,6 +3,8 @@
|
|||
#include "Lib.hlsl"
|
||||
#include "LibColor.hlsl"
|
||||
#include "LibDeferredShading.hlsl"
|
||||
#include "LibSurface.hlsl"
|
||||
#include "LibTessellation.hlsl"
|
||||
#include "LibVertex.hlsl"
|
||||
#include "DS_Mesh.inc.hlsl"
|
||||
|
||||
|
@ -17,8 +19,10 @@ Texture2D g_texAlbedo : register(t1, space1);
|
|||
SamplerState g_samAlbedo : register(s1, space1);
|
||||
Texture2D g_texNormal : register(t2, space1);
|
||||
SamplerState g_samNormal : register(s2, space1);
|
||||
//Texture2D g_texDetail : register(t3, space1);
|
||||
//SamplerState g_samDetail : register(s3, space1);
|
||||
Texture2D g_texDetail : register(t3, space1);
|
||||
SamplerState g_samDetail : register(s3, space1);
|
||||
Texture2D g_texStrass : register(t4, space1);
|
||||
SamplerState g_samStrass : register(s4, space1);
|
||||
|
||||
struct VSI
|
||||
{
|
||||
|
@ -28,18 +32,17 @@ struct VSI
|
|||
VK_LOCATION(8) int4 tc0 : TEXCOORD0;
|
||||
// Binding 1:
|
||||
#ifdef DEF_SKINNED
|
||||
VK_LOCATION(12) int4 bw : TEXCOORD4;
|
||||
VK_LOCATION(13) int4 bi : TEXCOORD5;
|
||||
VK_LOCATION_BLENDWEIGHTS int4 bw : BLENDWEIGHTS;
|
||||
VK_LOCATION_BLENDINDICES int4 bi : BLENDINDICES;
|
||||
#endif
|
||||
// Binding 2:
|
||||
VK_LOCATION(14) float4 tan : TEXCOORD6;
|
||||
VK_LOCATION(15) float4 bin : TEXCOORD7;
|
||||
VK_LOCATION_TANGENT float4 tan : TANGENT;
|
||||
VK_LOCATION_BINORMAL float4 bin : BINORMAL;
|
||||
// Binding 3:
|
||||
#if 0
|
||||
VK_LOCATION(9) int4 tc1 : TEXCOORD1;
|
||||
VK_LOCATION_COLOR0 float4 color : COLOR0;
|
||||
#endif
|
||||
|
||||
_PER_INSTANCE_DATA
|
||||
};
|
||||
|
||||
|
@ -47,13 +50,14 @@ struct VSO
|
|||
{
|
||||
float4 pos : SV_Position;
|
||||
float2 tc0 : TEXCOORD0;
|
||||
#ifndef DEF_DEPTH
|
||||
float4 matTBN0 : TEXCOORD2;
|
||||
float4 matTBN1 : TEXCOORD3;
|
||||
float4 matTBN2 : TEXCOORD4;
|
||||
#if !defined(DEF_DEPTH)
|
||||
float4 color0 : COLOR0;
|
||||
#if !defined(DEF_DEPTH) && !defined(DEF_SOLID_COLOR)
|
||||
float4 matTBN0 : TEXCOORD1;
|
||||
float4 matTBN1 : TEXCOORD2;
|
||||
float4 matTBN2 : TEXCOORD3;
|
||||
#endif
|
||||
#endif
|
||||
float2 depth : TEXCOORD6;
|
||||
};
|
||||
|
||||
#ifdef _VS
|
||||
|
@ -142,15 +146,76 @@ VSO mainVS(VSI si)
|
|||
#endif
|
||||
}
|
||||
|
||||
so.pos = mul(float4(posW, 1), g_ubPerFrame._matVP);
|
||||
so.pos = MulTessPos(float4(posW, 1), g_ubPerFrame._matV, g_ubPerFrame._matVP);
|
||||
so.tc0 = intactTc0;
|
||||
#ifndef DEF_DEPTH
|
||||
#if !defined(DEF_DEPTH)
|
||||
so.color0 = userColor;
|
||||
#if !defined(DEF_DEPTH) && !defined(DEF_SOLID_COLOR)
|
||||
so.matTBN0 = float4(tanWV, posW.x);
|
||||
so.matTBN1 = float4(binWV, posW.y);
|
||||
so.matTBN2 = float4(nrmWV, posW.z);
|
||||
so.color0 = userColor;
|
||||
#endif
|
||||
so.depth = so.pos.zw;
|
||||
#endif
|
||||
|
||||
return so;
|
||||
}
|
||||
#endif
|
||||
|
||||
_HSO_STRUCT;
|
||||
|
||||
#ifdef _HS
|
||||
PCFO PatchConstFunc(const OutputPatch<HSO, 3> outputPatch)
|
||||
{
|
||||
PCFO so;
|
||||
_HS_PCF_BODY(g_ubPerFrame._matP);
|
||||
return so;
|
||||
}
|
||||
|
||||
[domain("tri")]
|
||||
//[maxtessfactor(7.0)]
|
||||
[outputcontrolpoints(3)]
|
||||
[outputtopology("triangle_cw")]
|
||||
[partitioning(_PARTITION_METHOD)]
|
||||
[patchconstantfunc("PatchConstFunc")]
|
||||
HSO mainHS(InputPatch<VSO, 3> inputPatch, uint id : SV_OutputControlPointID)
|
||||
{
|
||||
HSO so;
|
||||
|
||||
_HS_PN_BODY(matTBN2, g_ubPerFrame._matP, g_ubPerFrame._viewportSize);
|
||||
|
||||
_HS_COPY(pos);
|
||||
_HS_COPY(tc0);
|
||||
#if !defined(DEF_DEPTH)
|
||||
_HS_COPY(color0);
|
||||
#if !defined(DEF_DEPTH) && !defined(DEF_SOLID_COLOR)
|
||||
_HS_COPY(matTBN0);
|
||||
_HS_COPY(matTBN1);
|
||||
_HS_COPY(matTBN2);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return so;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _DS
|
||||
[domain("tri")]
|
||||
VSO mainDS(_IN_DS)
|
||||
{
|
||||
VSO so;
|
||||
|
||||
_DS_INIT_SMOOTH_POS;
|
||||
|
||||
so.pos = ApplyProjection(smoothPosWV, g_ubPerFrame._matP);
|
||||
_DS_COPY(tc0);
|
||||
#if !defined(DEF_DEPTH)
|
||||
_DS_COPY(color0);
|
||||
#if !defined(DEF_DEPTH) && !defined(DEF_SOLID_COLOR)
|
||||
_DS_COPY(matTBN0);
|
||||
_DS_COPY(matTBN1);
|
||||
_DS_COPY(matTBN2);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return so;
|
||||
}
|
||||
|
@ -170,13 +235,8 @@ DS_FSO mainFS(VSO si)
|
|||
{
|
||||
DS_FSO so;
|
||||
|
||||
#ifdef DEF_SOLID
|
||||
DS_Reset(so);
|
||||
DS_SetAlbedo(so, si.color0.rgb);
|
||||
DS_SetDepth(so, si.depth.x / si.depth.y);
|
||||
DS_SetNormal(so, float3(0, 0, 1));
|
||||
DS_SetEmission(so, 1.0, 0.0);
|
||||
DS_SetMetallicity(so, 1.0, 0.0);
|
||||
#ifdef DEF_SOLID_COLOR
|
||||
DS_SolidColor(so, si.color0.rgb);
|
||||
#else
|
||||
_TBN_SPACE(
|
||||
si.matTBN0.xyz,
|
||||
|
@ -185,11 +245,16 @@ DS_FSO mainFS(VSO si)
|
|||
const float3 rand = Rand(si.pos.xy);
|
||||
|
||||
// <Albedo>
|
||||
float4 rawAlbedo;
|
||||
{
|
||||
const float texAlbedoEnable = ceil(g_ubPerMaterialFS._texEnableAlbedo.a);
|
||||
float4 rawAlbedo = g_texAlbedo.Sample(g_samAlbedo, si.tc0 * texAlbedoEnable);
|
||||
rawAlbedo = g_texAlbedo.Sample(g_samAlbedo, si.tc0 * texAlbedoEnable);
|
||||
rawAlbedo.rgb = lerp(g_ubPerMaterialFS._texEnableAlbedo.rgb, rawAlbedo.rgb, g_ubPerMaterialFS._texEnableAlbedo.a);
|
||||
const float2 alpha_spec = AlphaSwitch(rawAlbedo, si.tc0, g_ubPerMaterialFS._ssb_as.zw);
|
||||
}
|
||||
const float gray = Grayscale(rawAlbedo.rgb);
|
||||
// </Albedo>
|
||||
|
||||
const float2 alpha_spec = AlphaSwitch(rawAlbedo, si.tc0, g_ubPerMaterialFS._ssb_as.zw);
|
||||
const float emitAlpha = PickAlpha(rawAlbedo.rgb, g_ubPerMaterialFS._emitPick, 16.0);
|
||||
const float emitXAlpha = PickAlpha(rawAlbedo.rgb, g_ubPerMaterialFS._emitXPick, 16.0);
|
||||
const float eyeAlpha = PickAlphaRound(g_ubPerMaterialFS._eyePick, si.tc0);
|
||||
|
@ -199,61 +264,79 @@ DS_FSO mainFS(VSO si)
|
|||
const float skinAlpha = PickAlpha(rawAlbedo.rgb, g_ubPerMaterialFS._skinPick, 16.0);
|
||||
const float userAlpha = PickAlphaHue(rawAlbedo.rgb, g_ubPerMaterialFS._userPick, 32.0);
|
||||
|
||||
// Add details:
|
||||
#if 0
|
||||
const float3 colorDetail = (g_texDetail.Sample(g_samDetail, frac(si.tc0 * g_ubPerMaterialFS._ds_scale.zw)).rgb - 0.5) *
|
||||
g_ubPerMaterialFS._ds_scale.x + 0.5;
|
||||
rawAlbedo.rgb = rawAlbedo.rgb * colorDetail * 2.0;
|
||||
#endif
|
||||
|
||||
const float gray = Grayscale(rawAlbedo.rgb);
|
||||
rawAlbedo.rgb = lerp(rawAlbedo.rgb, Overlay(gray, si.color0.rgb), userAlpha * si.color0.a);
|
||||
// </Albedo>
|
||||
const float3 hairAlbedo = Overlay(alpha_spec.y, Desaturate(rawAlbedo.rgb, hairAlpha * g_ubPerMaterialFS._hairParams.w));
|
||||
|
||||
// <Gloss>
|
||||
//float gloss = lerp(g_ubPerMaterialFS._lsb_gloss_lp.z, g_ubPerMaterialFS._motionBlur_glossX.y, glossXAlpha);
|
||||
float gloss = lerp(4.4, 16.0, alpha_spec.y);
|
||||
gloss = lerp(gloss, 4.0 + alpha_spec.y, skinAlpha);
|
||||
gloss = lerp(gloss, 0.0, eyeAlpha);
|
||||
// </Gloss>
|
||||
|
||||
// <Normal>
|
||||
float3 normalWV;
|
||||
float toksvigFactor;
|
||||
float lightPassStrength;
|
||||
float3 anisoWV;
|
||||
{
|
||||
const float texNormalEnable = ceil(g_ubPerMaterialFS._texEnableNormal.a);
|
||||
float4 rawNormal = g_texNormal.Sample(g_samNormal, si.tc0 * texNormalEnable);
|
||||
rawNormal = lerp(g_ubPerMaterialFS._texEnableNormal.rgbr, rawNormal, g_ubPerMaterialFS._texEnableNormal.a);
|
||||
const float4 normalAA = NormalMapAA(rawNormal);
|
||||
const float3 normalTBN = normalAA.xyz;
|
||||
const float3 normalWV = normalize(mul(normalTBN, matFromTBN));
|
||||
|
||||
const float3 anisoWV = normalize(mul(cross(normalTBN, cross(g_ubPerMaterialFS._hairParams.xyz, normalTBN)), matFromTBN));
|
||||
// Almost solid hair color is used for picking.
|
||||
// Final albedo is calculated using specualar component.
|
||||
const float3 hairAlbedo = Overlay(alpha_spec.y, Desaturate(rawAlbedo.rgb, hairAlpha * g_ubPerMaterialFS._hairParams.w));
|
||||
normalWV = normalize(mul(normalTBN, matFromTBN));
|
||||
toksvigFactor = ComputeToksvigFactor(normalAA.a, gloss);
|
||||
lightPassStrength = rawNormal.r;
|
||||
anisoWV = normalize(mul(cross(normalTBN, cross(g_ubPerMaterialFS._hairParams.xyz, normalTBN)), matFromTBN));
|
||||
}
|
||||
// </Normal>
|
||||
|
||||
// <Detail>
|
||||
{
|
||||
const float3 rawDetail = g_texDetail.Sample(g_samDetail, si.tc0 * g_ubPerMaterialFS._ds_scale.zw).rgb;
|
||||
rawAlbedo.rgb = rawAlbedo.rgb * lerp(0.5, rawDetail, g_ubPerMaterialFS._ds_scale.x) * 2.0;
|
||||
}
|
||||
// </Detail>
|
||||
|
||||
// <Strass>
|
||||
float strass;
|
||||
{
|
||||
const float rawStrass = g_texStrass.Sample(g_samStrass, si.tc0 * g_ubPerMaterialFS._ds_scale.zw * 2.0).r;
|
||||
strass = saturate(rawStrass * (0.3 + 0.7 * alpha_spec.y) * 4.0) * g_ubPerMaterialFS._ds_scale.y;
|
||||
}
|
||||
// </Strass>
|
||||
|
||||
// <LambertianScaleBias>
|
||||
float2 lamScaleBias = g_ubPerMaterialFS._lsb_gloss_lp.xy + float2(0, rawNormal.r * 8.0 * g_ubPerMaterialFS._lsb_gloss_lp.w);
|
||||
float2 lamScaleBias = g_ubPerMaterialFS._lsb_gloss_lp.xy + float2(0, lightPassStrength * 8.0 * g_ubPerMaterialFS._lsb_gloss_lp.w);
|
||||
lamScaleBias += float2(-0.1, -0.3) * alpha_spec.y + float2(0.1, 0.2); // We bring the noise!
|
||||
lamScaleBias = lerp(lamScaleBias, float2(1, 0.45), skinAlpha);
|
||||
// </LambertianScaleBias>
|
||||
|
||||
// <Gloss>
|
||||
float gloss = lerp(g_ubPerMaterialFS._lsb_gloss_lp.z, g_ubPerMaterialFS._motionBlur_glossX.y, glossXAlpha);
|
||||
gloss = lerp(gloss, 4.0 + alpha_spec.y, skinAlpha);
|
||||
gloss = lerp(gloss, 0.0, eyeAlpha);
|
||||
// </Gloss>
|
||||
|
||||
const float strass = 0.0;
|
||||
|
||||
// <RimAlbedo>
|
||||
//const float rimA = lerp(0.3 + alpha_spec.y*0.3, 0.7, skinAlpha);
|
||||
//const float3 rimAlbedo = saturate(rawAlbedo.rgb*rimA*2.0);
|
||||
//const float rimAlbedoAmount = 1.0 - abs(normalWV.z);
|
||||
//rawAlbedo.rgb = lerp(rawAlbedo.rgb, rimAlbedo, rimAlbedoAmount*rimAlbedoAmount);
|
||||
{
|
||||
const float3 newColor = saturate((rawAlbedo.rgb + gray) * 0.6);
|
||||
const float mask = 1.0 - abs(normalWV.z);
|
||||
rawAlbedo.rgb = lerp(rawAlbedo.rgb, newColor, mask * mask * (1.0 - alpha_spec.y));
|
||||
}
|
||||
// </RimAlbedo>
|
||||
|
||||
{
|
||||
DS_Reset(so);
|
||||
|
||||
DS_SetAlbedo(so, lerp(rawAlbedo.rgb, hairAlbedo, hairAlpha));
|
||||
DS_SetSpec(so, normalAA.w * max(eyeAlpha, max(strass,
|
||||
DS_SetSpec(so, max(eyeAlpha, max(strass,
|
||||
alpha_spec.y * (1.0 + hairAlpha * 0.75) * g_ubPerMaterialFS._ssb_as.x + g_ubPerMaterialFS._ssb_as.y)));
|
||||
DS_SetDepth(so, si.depth.x / si.depth.y);
|
||||
|
||||
DS_SetNormal(so, normalWV + NormalDither(rand));
|
||||
DS_SetEmission(so, max(emitAlpha, emitXAlpha) * alpha_spec.y, skinAlpha);
|
||||
|
||||
DS_SetLamScaleBias(so, lamScaleBias, float4(anisoWV, hairAlpha));
|
||||
DS_SetMetallicity(so, metalAlpha, hairAlpha);
|
||||
DS_SetGloss(so, normalAA.w * gloss);
|
||||
DS_SetGloss(so, gloss * lerp(toksvigFactor, 1.0, eyeAlpha));
|
||||
}
|
||||
|
||||
clip(alpha_spec.x - 0.5);
|
||||
#endif
|
||||
|
||||
return so;
|
||||
|
@ -262,8 +345,19 @@ DS_FSO mainFS(VSO si)
|
|||
#endif
|
||||
|
||||
//@main:#
|
||||
//@main:#DepthRobotic DEPTH ROBOTIC (V)
|
||||
//@main:#DepthSkinned DEPTH SKINNED (V)
|
||||
//@main:#Instanced INSTANCED
|
||||
//@main:#Robotic ROBOTIC
|
||||
//@main:#Skinned SKINNED
|
||||
|
||||
//@main:#Instanced INSTANCED
|
||||
|
||||
//@main:#Depth DEPTH (V)
|
||||
//@main:#DepthRobotic DEPTH ROBOTIC (V)
|
||||
//@main:#DepthSkinned DEPTH SKINNED (V)
|
||||
|
||||
//@main:#SolidColor SOLID_COLOR
|
||||
//@main:#SolidColorRobotic SOLID_COLOR ROBOTIC
|
||||
//@main:#SolidColorSkinned SOLID_COLOR SKINNED
|
||||
|
||||
//@main:#Tess TESS (VHDF)
|
||||
//@main:#TessRobotic TESS ROBOTIC (VHDF)
|
||||
//@main:#TessSkinned TESS SKINNED (VHDF)
|
||||
|
|
|
@ -3,8 +3,9 @@
|
|||
VERUS_UBUFFER UB_PerFrame
|
||||
{
|
||||
mataff _matV;
|
||||
matrix _matP;
|
||||
matrix _matVP;
|
||||
matrix _matP;
|
||||
float4 _viewportSize;
|
||||
};
|
||||
|
||||
VERUS_UBUFFER UB_PerMaterialFS
|
||||
|
|
|
@ -3,15 +3,20 @@
|
|||
#include "Lib.hlsl"
|
||||
#include "LibColor.hlsl"
|
||||
#include "LibDeferredShading.hlsl"
|
||||
#include "LibSurface.hlsl"
|
||||
#include "LibTessellation.hlsl"
|
||||
#include "DS_Terrain.inc.hlsl"
|
||||
|
||||
#define HEIGHT_SCALE 0.01
|
||||
#define DETAIL_TC_SCALE 8.0
|
||||
|
||||
ConstantBuffer<UB_DrawDepth> g_ubDrawDepth : register(b0, space0);
|
||||
ConstantBuffer<UB_PerMaterialFS> g_ubPerMaterialFS : register(b0, space1);
|
||||
ConstantBuffer<UB_TerrainVS> g_ubTerrainVS : register(b0, space0);
|
||||
ConstantBuffer<UB_TerrainFS> g_ubTerrainFS : register(b0, space1);
|
||||
|
||||
Texture2D g_texHeightVS : register(t1, space0);
|
||||
SamplerState g_samHeightVS : register(s1, space0);
|
||||
Texture2D g_texNormalVS : register(t2, space0);
|
||||
SamplerState g_samNormalVS : register(s2, space0);
|
||||
|
||||
Texture2D g_texHeight : register(t1, space0);
|
||||
SamplerState g_samHeight : register(s1, space0);
|
||||
Texture2D g_texNormal : register(t1, space1);
|
||||
SamplerState g_samNormal : register(s1, space1);
|
||||
Texture2D g_texBlend : register(t2, space1);
|
||||
|
@ -20,60 +25,145 @@ Texture2DArray g_texLayers : register(t3, space1);
|
|||
SamplerState g_samLayers : register(s3, space1);
|
||||
Texture2DArray g_texLayersNM : register(t4, space1);
|
||||
SamplerState g_samLayersNM : register(s4, space1);
|
||||
Texture2D g_texDetail : register(t5, space1);
|
||||
SamplerState g_samDetail : register(s5, space1);
|
||||
|
||||
struct VSI
|
||||
{
|
||||
VK_LOCATION_POSITION int4 pos : POSITION;
|
||||
|
||||
VK_LOCATION(16) int4 posPatch : TEXCOORD8;
|
||||
VK_LOCATION(17) int4 layerForChannel : TEXCOORD9;
|
||||
VK_LOCATION(16) int4 posPatch : INSTDATA0;
|
||||
VK_LOCATION(17) int4 layerForChannel : INSTDATA1;
|
||||
};
|
||||
|
||||
struct VSO
|
||||
{
|
||||
float4 pos : SV_Position;
|
||||
float4 layerForChannel : TEXCOORD0;
|
||||
#ifndef DEF_DEPTH
|
||||
float3 tcBlend : TEXCOORD1;
|
||||
float4 tcLayer_tcMap : TEXCOORD2;
|
||||
float3 nrmWV : TEXCOORD0;
|
||||
#if !defined(DEF_DEPTH)
|
||||
float4 layerForChannel : TEXCOORD1;
|
||||
#if !defined(DEF_DEPTH) && !defined(DEF_SOLID_COLOR)
|
||||
float3 tcBlend : TEXCOORD2;
|
||||
float4 tcLayer_tcMap : TEXCOORD3;
|
||||
#endif
|
||||
#endif
|
||||
float2 depth : TEXCOORD3;
|
||||
};
|
||||
|
||||
static const float g_bestPrecision = 50.0;
|
||||
static const float g_layerScale = 1.0 / 8.0;
|
||||
|
||||
#ifdef _VS
|
||||
VSO mainVS(VSI si)
|
||||
{
|
||||
VSO so;
|
||||
|
||||
const float3 posEye = g_ubDrawDepth._posEye_mapSideInv.xyz;
|
||||
const float mapSideInv = g_ubDrawDepth._posEye_mapSideInv.w;
|
||||
const float3 eyePos = g_ubTerrainVS._eyePos_mapSideInv.xyz;
|
||||
const float mapSideInv = g_ubTerrainVS._eyePos_mapSideInv.w;
|
||||
|
||||
const float2 edgeCorrection = si.pos.yw;
|
||||
si.pos.yw = 0.0;
|
||||
float3 pos = si.pos.xyz + si.posPatch.xyz * float3(1, HEIGHT_SCALE, 1);
|
||||
float3 pos = si.pos.xyz + si.posPatch.xyz;
|
||||
const float2 tcMap = pos.xz * mapSideInv + 0.5; // Range [0, 1).
|
||||
const float2 posBlend = pos.xz + edgeCorrection * 0.5;
|
||||
|
||||
const float bestPrecision = 50.0;
|
||||
const float2 tcMap = pos.xz * mapSideInv + 0.5; // Range [0, 1).
|
||||
const float distToEye = distance(pos, posEye);
|
||||
// <HeightAndNormal>
|
||||
float3 intactNrm;
|
||||
{
|
||||
const float approxHeight = g_texHeightVS.SampleLevel(g_samHeightVS, tcMap + (0.5 * mapSideInv) * 16.0, 4.0).r + g_bestPrecision;
|
||||
pos.y = approxHeight;
|
||||
|
||||
const float distToEye = distance(pos, eyePos);
|
||||
const float geomipsLod = log2(clamp(distToEye * (2.0 / 100.0), 1.0, 18.0));
|
||||
const float geomipsLodFrac = frac(geomipsLod);
|
||||
const float geomipsLodBase = floor(geomipsLod);
|
||||
const float geomipsLodNext = geomipsLodBase + 1.0;
|
||||
const float2 halfTexelAB = (0.5 * mapSideInv) * exp2(float2(geomipsLodBase, geomipsLodNext));
|
||||
const float yA = g_texHeight.SampleLevel(g_samHeight, tcMap + halfTexelAB.xx, geomipsLodBase).r + bestPrecision;
|
||||
const float yB = g_texHeight.SampleLevel(g_samHeight, tcMap + halfTexelAB.yy, geomipsLodNext).r + bestPrecision;
|
||||
const float2 texelCenterAB = (0.5 * mapSideInv) * exp2(float2(geomipsLodBase, geomipsLodNext));
|
||||
const float yA = g_texHeightVS.SampleLevel(g_samHeightVS, tcMap + texelCenterAB.xx, geomipsLodBase).r + g_bestPrecision;
|
||||
const float yB = g_texHeightVS.SampleLevel(g_samHeightVS, tcMap + texelCenterAB.yy, geomipsLodNext).r + g_bestPrecision;
|
||||
pos.y = lerp(yA, yB, geomipsLodFrac);
|
||||
|
||||
so.pos = mul(float4(pos, 1), g_ubDrawDepth._matVP);
|
||||
const float4 rawNormal = g_texNormalVS.SampleLevel(g_samNormalVS, tcMap + texelCenterAB.xx, geomipsLodBase);
|
||||
intactNrm = float3(rawNormal.x, 0, rawNormal.y) * 2.0 - 1.0;
|
||||
intactNrm.y = ComputeNormalZ(intactNrm.xz);
|
||||
}
|
||||
// </HeightAndNormal>
|
||||
|
||||
so.pos = MulTessPos(float4(pos, 1), g_ubTerrainVS._matV, g_ubTerrainVS._matVP);
|
||||
so.nrmWV = mul(intactNrm, (float3x3)g_ubTerrainVS._matWV);
|
||||
#if !defined(DEF_DEPTH)
|
||||
so.layerForChannel = si.layerForChannel;
|
||||
#ifndef DEF_DEPTH
|
||||
#if !defined(DEF_DEPTH) && !defined(DEF_SOLID_COLOR)
|
||||
so.tcBlend.xy = posBlend * mapSideInv + 0.5;
|
||||
so.tcBlend.z = pos.y + 0.75;
|
||||
so.tcLayer_tcMap.xy = pos.xz * (1.0 / 8.0);
|
||||
so.tcBlend.z = pos.y;
|
||||
so.tcLayer_tcMap.xy = pos.xz * g_layerScale;
|
||||
so.tcLayer_tcMap.zw = (pos.xz + 0.5) * mapSideInv + 0.5; // Texel's center.
|
||||
#endif
|
||||
so.depth = so.pos.zw;
|
||||
#endif
|
||||
|
||||
return so;
|
||||
}
|
||||
#endif
|
||||
|
||||
_HSO_STRUCT;
|
||||
|
||||
#ifdef _HS
|
||||
PCFO PatchConstFunc(const OutputPatch<HSO, 3> outputPatch)
|
||||
{
|
||||
PCFO so;
|
||||
_HS_PCF_BODY(g_ubTerrainVS._matP);
|
||||
return so;
|
||||
}
|
||||
|
||||
[domain("tri")]
|
||||
//[maxtessfactor(7.0)]
|
||||
[outputcontrolpoints(3)]
|
||||
[outputtopology("triangle_cw")]
|
||||
[partitioning(_PARTITION_METHOD)]
|
||||
[patchconstantfunc("PatchConstFunc")]
|
||||
HSO mainHS(InputPatch<VSO, 3> inputPatch, uint id : SV_OutputControlPointID)
|
||||
{
|
||||
HSO so;
|
||||
|
||||
_HS_PN_BODY(nrmWV, g_ubTerrainVS._matP, g_ubTerrainVS._viewportSize);
|
||||
|
||||
_HS_COPY(pos);
|
||||
_HS_COPY(nrmWV);
|
||||
#if !defined(DEF_DEPTH)
|
||||
_HS_COPY(layerForChannel);
|
||||
#if !defined(DEF_DEPTH) && !defined(DEF_SOLID_COLOR)
|
||||
_HS_COPY(tcBlend);
|
||||
_HS_COPY(tcLayer_tcMap);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return so;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _DS
|
||||
[domain("tri")]
|
||||
VSO mainDS(_IN_DS)
|
||||
{
|
||||
VSO so;
|
||||
|
||||
_DS_INIT_FLAT_POS;
|
||||
_DS_INIT_SMOOTH_POS;
|
||||
|
||||
so.pos = ApplyProjection(smoothPosWV, g_ubTerrainVS._matP);
|
||||
_DS_COPY(nrmWV);
|
||||
#if !defined(DEF_DEPTH)
|
||||
_DS_COPY(layerForChannel);
|
||||
#if !defined(DEF_DEPTH) && !defined(DEF_SOLID_COLOR)
|
||||
_DS_COPY(tcBlend);
|
||||
_DS_COPY(tcLayer_tcMap);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef DEF_DEPTH
|
||||
// Fade to non-tess mesh at 80 meters. LOD 1 starts at 100 meters.
|
||||
const float tessStrength = saturate((1.0 - saturate(smoothPosWV.z / -80.0)) * 4.0);
|
||||
const float3 posWV = lerp(flatPosWV, smoothPosWV, tessStrength);
|
||||
so.pos = ApplyProjection(posWV, g_ubTerrainVS._matP);
|
||||
#endif
|
||||
|
||||
return so;
|
||||
}
|
||||
|
@ -84,15 +174,15 @@ DS_FSO mainFS(VSO si)
|
|||
{
|
||||
DS_FSO so;
|
||||
|
||||
#ifdef DEF_SOLID_COLOR
|
||||
DS_SolidColor(so, si.layerForChannel.rgb);
|
||||
#else
|
||||
const float3 rand = Rand(si.pos.xy);
|
||||
|
||||
const float4 layerForChannel = round(si.layerForChannel);
|
||||
const float2 tcLayer = si.tcLayer_tcMap.xy;
|
||||
const float2 tcMap = si.tcLayer_tcMap.zw;
|
||||
|
||||
const float gloss = 4.0;
|
||||
|
||||
const float4 layerForChannel = round(si.layerForChannel);
|
||||
|
||||
const float4 rawBlend = g_texBlend.Sample(g_samBlend, si.tcBlend.xy);
|
||||
float4 weights = float4(rawBlend.rgb, 1.0 - dot(rawBlend.rgb, float3(1, 1, 1)));
|
||||
|
||||
|
@ -108,9 +198,9 @@ DS_FSO mainFS(VSO si)
|
|||
basisBin = cross(basisTan, basisNrm);
|
||||
}
|
||||
_TBN_SPACE(
|
||||
mul(basisTan, (float3x3)g_ubDrawDepth._matWV),
|
||||
mul(basisBin, (float3x3)g_ubDrawDepth._matWV),
|
||||
mul(basisNrm, (float3x3)g_ubDrawDepth._matWV));
|
||||
mul(basisTan, (float3x3)g_ubTerrainFS._matWV),
|
||||
mul(basisBin, (float3x3)g_ubTerrainFS._matWV),
|
||||
mul(basisNrm, (float3x3)g_ubTerrainFS._matWV));
|
||||
// </Basis>
|
||||
|
||||
// <Albedo>
|
||||
|
@ -140,8 +230,8 @@ DS_FSO mainFS(VSO si)
|
|||
accAlbedo += rawAlbedos[3] * weights.a;
|
||||
albedo = accAlbedo;
|
||||
|
||||
static float vSpecStrength[_MAX_TERRAIN_LAYERS] = (float[_MAX_TERRAIN_LAYERS])g_ubPerMaterialFS._vSpecStrength;
|
||||
static float vDetailStrength[_MAX_TERRAIN_LAYERS] = (float[_MAX_TERRAIN_LAYERS])g_ubPerMaterialFS._vDetailStrength;
|
||||
static float vSpecStrength[_MAX_TERRAIN_LAYERS] = (float[_MAX_TERRAIN_LAYERS])g_ubTerrainFS._vSpecStrength;
|
||||
static float vDetailStrength[_MAX_TERRAIN_LAYERS] = (float[_MAX_TERRAIN_LAYERS])g_ubTerrainFS._vDetailStrength;
|
||||
const float4 specStrengthForChannel = float4(
|
||||
vSpecStrength[layerForChannel.r],
|
||||
vSpecStrength[layerForChannel.g],
|
||||
|
@ -157,26 +247,58 @@ DS_FSO mainFS(VSO si)
|
|||
}
|
||||
// </Albedo>
|
||||
|
||||
// <Water>
|
||||
float waterGlossBoost = 0.0;
|
||||
{
|
||||
const float dryMask = saturate(si.tcBlend.z);
|
||||
const float dryMask3 = dryMask * dryMask * dryMask;
|
||||
const float wetMask = 1.0 - dryMask;
|
||||
const float wetMask3 = wetMask * wetMask * wetMask;
|
||||
albedo.rgb *= dryMask3 * 0.5 + 0.5;
|
||||
specStrength = dryMask * saturate(specStrength + wetMask3 * wetMask3);
|
||||
waterGlossBoost = min(32.0, dryMask * wetMask3 * 128.0);
|
||||
}
|
||||
// </Water>
|
||||
|
||||
const float gloss = lerp(3.3, 15.0, specStrength) + waterGlossBoost;
|
||||
|
||||
// <Normal>
|
||||
float3 normalWV;
|
||||
float4 normalAA;
|
||||
float toksvigFactor;
|
||||
{
|
||||
float4 accNormal = 0.0;
|
||||
accNormal += g_texLayersNM.Sample(g_samLayersNM, float3(tcLayer, layerForChannel.r)) * weights.r;
|
||||
accNormal += g_texLayersNM.Sample(g_samLayersNM, float3(tcLayer, layerForChannel.g)) * weights.g;
|
||||
accNormal += g_texLayersNM.Sample(g_samLayersNM, float3(tcLayer, layerForChannel.b)) * weights.b;
|
||||
accNormal += g_texLayersNM.Sample(g_samLayersNM, float3(tcLayer, layerForChannel.a)) * weights.a;
|
||||
normalAA = NormalMapAA(accNormal);
|
||||
accNormal = lerp(accNormal, float4(0, 0.5, 0.5, 0.5), 0.5);
|
||||
const float4 normalAA = NormalMapAA(accNormal);
|
||||
normalWV = normalize(mul(normalAA.xyz, matFromTBN));
|
||||
toksvigFactor = ComputeToksvigFactor(normalAA.a, gloss);
|
||||
}
|
||||
// </Normal>
|
||||
|
||||
DS_Test(so, 0.0, 0.5, 16.0);
|
||||
// <Detail>
|
||||
{
|
||||
const float3 rawDetail = g_texDetail.Sample(g_samDetail, tcLayer * DETAIL_TC_SCALE).rgb;
|
||||
albedo.rgb = albedo.rgb * lerp(0.5, rawDetail, detailStrength) * 2.0;
|
||||
}
|
||||
// </Detail>
|
||||
|
||||
{
|
||||
DS_Reset(so);
|
||||
|
||||
DS_SetAlbedo(so, albedo.rgb);
|
||||
DS_SetDepth(so, si.depth.x / si.depth.y);
|
||||
DS_SetSpec(so, specStrength);
|
||||
|
||||
DS_SetNormal(so, normalWV + NormalDither(rand));
|
||||
DS_SetSpec(so, normalAA.w * specStrength);
|
||||
DS_SetGloss(so, normalAA.w * gloss);
|
||||
DS_SetEmission(so, 0.0, 0.0);
|
||||
|
||||
DS_SetLamScaleBias(so, g_ubTerrainFS._lamScaleBias.xy, float4(0, 0, 1, 0));
|
||||
DS_SetMetallicity(so, 0.05, 0.0);
|
||||
DS_SetGloss(so, gloss * toksvigFactor);
|
||||
}
|
||||
#endif
|
||||
|
||||
return so;
|
||||
}
|
||||
|
@ -184,3 +306,5 @@ DS_FSO mainFS(VSO si)
|
|||
|
||||
//@main:#
|
||||
//@main:#Depth DEPTH (V)
|
||||
//@main:#SolidColor SOLID_COLOR
|
||||
//@main:#Tess TESS (VHDF)
|
||||
|
|
|
@ -1,15 +1,20 @@
|
|||
// Copyright (C) 2020, Dmitry Maluev (dmaluev@gmail.com)
|
||||
|
||||
VERUS_UBUFFER UB_DrawDepth
|
||||
VERUS_UBUFFER UB_TerrainVS
|
||||
{
|
||||
mataff _matW;
|
||||
mataff _matWV;
|
||||
mataff _matWV; // For normal.
|
||||
mataff _matV; // For tess.
|
||||
matrix _matVP;
|
||||
float4 _posEye_mapSideInv;
|
||||
matrix _matP; // For tess.
|
||||
float4 _eyePos_mapSideInv;
|
||||
float4 _viewportSize;
|
||||
};
|
||||
|
||||
VERUS_UBUFFER UB_PerMaterialFS
|
||||
VERUS_UBUFFER UB_TerrainFS
|
||||
{
|
||||
mataff _matWV; // For basis.
|
||||
float4 _vSpecStrength[8];
|
||||
float4 _vDetailStrength[8];
|
||||
float4 _lamScaleBias;
|
||||
};
|
||||
|
|
|
@ -16,8 +16,8 @@ RWTexture2D<float4> g_uavOutMip4 : register(u5, space0);
|
|||
|
||||
struct CSI
|
||||
{
|
||||
uint3 _DispatchThreadID : SV_DispatchThreadID;
|
||||
uint _GroupIndex : SV_GroupIndex;
|
||||
uint3 dispatchThreadID : SV_DispatchThreadID;
|
||||
uint groupIndex : SV_GroupIndex;
|
||||
};
|
||||
|
||||
#define THREAD_GROUP_SIZE 8
|
||||
|
@ -67,14 +67,14 @@ void mainCS(CSI si)
|
|||
{
|
||||
case DIM_CASE_WE_HE:
|
||||
{
|
||||
const float2 tc = g_ub._texelSize * (si._DispatchThreadID.xy + 0.5);
|
||||
const float2 tc = g_ub._texelSize * (si.dispatchThreadID.xy + 0.5);
|
||||
|
||||
srcColor1 = g_texSrcMip.SampleLevel(g_samSrcMip, tc, g_ub._srcMipLevel);
|
||||
}
|
||||
break;
|
||||
case DIM_CASE_WO_HE:
|
||||
{
|
||||
const float2 tc = g_ub._texelSize * (si._DispatchThreadID.xy + float2(0.25, 0.5));
|
||||
const float2 tc = g_ub._texelSize * (si.dispatchThreadID.xy + float2(0.25, 0.5));
|
||||
const float2 offset = g_ub._texelSize * float2(0.5, 0.0);
|
||||
|
||||
srcColor1 = lerp(
|
||||
|
@ -85,7 +85,7 @@ void mainCS(CSI si)
|
|||
break;
|
||||
case DIM_CASE_WE_HO:
|
||||
{
|
||||
const float2 tc = g_ub._texelSize * (si._DispatchThreadID.xy + float2(0.5, 0.25));
|
||||
const float2 tc = g_ub._texelSize * (si.dispatchThreadID.xy + float2(0.5, 0.25));
|
||||
const float2 offset = g_ub._texelSize * float2(0.0, 0.5);
|
||||
|
||||
srcColor1 = lerp(
|
||||
|
@ -96,7 +96,7 @@ void mainCS(CSI si)
|
|||
break;
|
||||
case DIM_CASE_WO_HO:
|
||||
{
|
||||
const float2 tc = g_ub._texelSize * (si._DispatchThreadID.xy + float2(0.25, 0.25));
|
||||
const float2 tc = g_ub._texelSize * (si.dispatchThreadID.xy + float2(0.25, 0.25));
|
||||
const float2 offset = g_ub._texelSize * 0.5;
|
||||
|
||||
srcColor1 = lerp(
|
||||
|
@ -112,24 +112,24 @@ void mainCS(CSI si)
|
|||
break;
|
||||
}
|
||||
|
||||
g_uavOutMip1[si._DispatchThreadID.xy] = PackColor(srcColor1);
|
||||
g_uavOutMip1[si.dispatchThreadID.xy] = PackColor(srcColor1);
|
||||
|
||||
if (1 == g_ub._mipLevelCount)
|
||||
return;
|
||||
|
||||
StoreColor(si._GroupIndex, srcColor1);
|
||||
StoreColor(si.groupIndex, srcColor1);
|
||||
|
||||
GroupMemoryBarrierWithGroupSync();
|
||||
|
||||
if ((si._GroupIndex & 0x9) == 0) // 16 threads:
|
||||
if ((si.groupIndex & 0x9) == 0) // 16 threads:
|
||||
{
|
||||
const float4 srcColor2 = LoadColor(si._GroupIndex + 0x01); // {+0, +1}
|
||||
const float4 srcColor3 = LoadColor(si._GroupIndex + 0x08); // {+1, +0}
|
||||
const float4 srcColor4 = LoadColor(si._GroupIndex + 0x09); // {+1, +1}
|
||||
const float4 srcColor2 = LoadColor(si.groupIndex + 0x01); // {+0, +1}
|
||||
const float4 srcColor3 = LoadColor(si.groupIndex + 0x08); // {+1, +0}
|
||||
const float4 srcColor4 = LoadColor(si.groupIndex + 0x09); // {+1, +1}
|
||||
srcColor1 = 0.25 * (srcColor1 + srcColor2 + srcColor3 + srcColor4);
|
||||
|
||||
g_uavOutMip2[si._DispatchThreadID.xy >> 1] = PackColor(srcColor1);
|
||||
StoreColor(si._GroupIndex, srcColor1);
|
||||
g_uavOutMip2[si.dispatchThreadID.xy >> 1] = PackColor(srcColor1);
|
||||
StoreColor(si.groupIndex, srcColor1);
|
||||
}
|
||||
|
||||
if (2 == g_ub._mipLevelCount)
|
||||
|
@ -137,15 +137,15 @@ void mainCS(CSI si)
|
|||
|
||||
GroupMemoryBarrierWithGroupSync();
|
||||
|
||||
if ((si._GroupIndex & 0x1B) == 0) // 4 threads:
|
||||
if ((si.groupIndex & 0x1B) == 0) // 4 threads:
|
||||
{
|
||||
const float4 srcColor2 = LoadColor(si._GroupIndex + 0x02); // {+0, +2}
|
||||
const float4 srcColor3 = LoadColor(si._GroupIndex + 0x10); // {+2, +0}
|
||||
const float4 srcColor4 = LoadColor(si._GroupIndex + 0x12); // {+2, +2}
|
||||
const float4 srcColor2 = LoadColor(si.groupIndex + 0x02); // {+0, +2}
|
||||
const float4 srcColor3 = LoadColor(si.groupIndex + 0x10); // {+2, +0}
|
||||
const float4 srcColor4 = LoadColor(si.groupIndex + 0x12); // {+2, +2}
|
||||
srcColor1 = 0.25 * (srcColor1 + srcColor2 + srcColor3 + srcColor4);
|
||||
|
||||
g_uavOutMip3[si._DispatchThreadID.xy >> 2] = PackColor(srcColor1);
|
||||
StoreColor(si._GroupIndex, srcColor1);
|
||||
g_uavOutMip3[si.dispatchThreadID.xy >> 2] = PackColor(srcColor1);
|
||||
StoreColor(si.groupIndex, srcColor1);
|
||||
}
|
||||
|
||||
if (3 == g_ub._mipLevelCount)
|
||||
|
@ -153,14 +153,14 @@ void mainCS(CSI si)
|
|||
|
||||
GroupMemoryBarrierWithGroupSync();
|
||||
|
||||
if (si._GroupIndex == 0) // 1 thread:
|
||||
if (si.groupIndex == 0) // 1 thread:
|
||||
{
|
||||
const float4 srcColor2 = LoadColor(si._GroupIndex + 0x04); // {+0, +4}
|
||||
const float4 srcColor3 = LoadColor(si._GroupIndex + 0x20); // {+4, +0}
|
||||
const float4 srcColor4 = LoadColor(si._GroupIndex + 0x24); // {+4, +4}
|
||||
const float4 srcColor2 = LoadColor(si.groupIndex + 0x04); // {+0, +4}
|
||||
const float4 srcColor3 = LoadColor(si.groupIndex + 0x20); // {+4, +0}
|
||||
const float4 srcColor4 = LoadColor(si.groupIndex + 0x24); // {+4, +4}
|
||||
srcColor1 = 0.25 * (srcColor1 + srcColor2 + srcColor3 + srcColor4);
|
||||
|
||||
g_uavOutMip4[si._DispatchThreadID.xy >> 3] = PackColor(srcColor1);
|
||||
g_uavOutMip4[si.dispatchThreadID.xy >> 3] = PackColor(srcColor1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -6,12 +6,14 @@
|
|||
#ifdef _VULKAN
|
||||
# define VK_LOCATION(x) [[vk::location(x)]]
|
||||
# define VK_LOCATION_POSITION [[vk::location(0)]]
|
||||
# define VK_LOCATION_BLENDWEIGHT [[vk::location(1)]]
|
||||
# define VK_LOCATION_BLENDWEIGHTS [[vk::location(1)]]
|
||||
# define VK_LOCATION_BLENDINDICES [[vk::location(6)]]
|
||||
# define VK_LOCATION_NORMAL [[vk::location(2)]]
|
||||
# define VK_LOCATION_PSIZE [[vk::location(7)]]
|
||||
# define VK_LOCATION_TANGENT [[vk::location(14)]]
|
||||
# define VK_LOCATION_BINORMAL [[vk::location(15)]]
|
||||
# define VK_LOCATION_COLOR0 [[vk::location(3)]]
|
||||
# define VK_LOCATION_COLOR1 [[vk::location(4)]]
|
||||
# define VK_LOCATION_PSIZE [[vk::location(7)]]
|
||||
|
||||
# define VK_PUSH_CONSTANT [[vk::push_constant]]
|
||||
# define VK_SUBPASS_INPUT(index, tex, sam, t, s, space) layout(input_attachment_index = index) SubpassInput<float4> tex : register(t, space)
|
||||
|
@ -26,12 +28,14 @@
|
|||
#else
|
||||
# define VK_LOCATION(x)
|
||||
# define VK_LOCATION_POSITION
|
||||
# define VK_LOCATION_BLENDWEIGHT
|
||||
# define VK_LOCATION_BLENDWEIGHTS
|
||||
# define VK_LOCATION_BLENDINDICES
|
||||
# define VK_LOCATION_NORMAL
|
||||
# define VK_LOCATION_PSIZE
|
||||
# define VK_LOCATION_TANGENT
|
||||
# define VK_LOCATION_BINORMAL
|
||||
# define VK_LOCATION_COLOR0
|
||||
# define VK_LOCATION_COLOR1
|
||||
# define VK_LOCATION_PSIZE
|
||||
|
||||
# define VK_PUSH_CONSTANT
|
||||
# define VK_SUBPASS_INPUT(index, tex, sam, t, s, space)\
|
||||
|
@ -45,10 +49,10 @@
|
|||
|
||||
#ifdef DEF_INSTANCED
|
||||
# define _PER_INSTANCE_DATA\
|
||||
VK_LOCATION(16) float4 matPart0 : TEXCOORD8;\
|
||||
VK_LOCATION(17) float4 matPart1 : TEXCOORD9;\
|
||||
VK_LOCATION(18) float4 matPart2 : TEXCOORD10;\
|
||||
VK_LOCATION(19) float4 instData : TEXCOORD11;
|
||||
VK_LOCATION(16) float4 matPart0 : INSTDATA0;\
|
||||
VK_LOCATION(17) float4 matPart1 : INSTDATA1;\
|
||||
VK_LOCATION(18) float4 matPart2 : INSTDATA2;\
|
||||
VK_LOCATION(19) float4 instData : INSTDATA3;
|
||||
#else
|
||||
# define _PER_INSTANCE_DATA
|
||||
#endif
|
||||
|
@ -57,6 +61,8 @@
|
|||
const float3x3 matFromTBN = float3x3(tan, bin, nrm);\
|
||||
const float3x3 matToTBN = transpose(matFromTBN);
|
||||
|
||||
#define _PI 3.141592654
|
||||
|
||||
#define _SINGULARITY_FIX 0.001
|
||||
|
||||
#define _MAX_TERRAIN_LAYERS 32
|
||||
|
@ -70,18 +76,6 @@ matrix ToFloat4x4(mataff m)
|
|||
float4(m[3], 1));
|
||||
}
|
||||
|
||||
float ComputeNormalZ(float2 v)
|
||||
{
|
||||
return sqrt(saturate(1.0 - dot(v.rg, v.rg)));
|
||||
}
|
||||
|
||||
float4 NormalMapAA(float4 rawNormal)
|
||||
{
|
||||
float3 normal = rawNormal.agb * -2.0 + 1.0; // Dmitry's reverse!
|
||||
normal.b = ComputeNormalZ(normal.rg);
|
||||
return float4(normal, 0.8 + rawNormal.b * 0.8);
|
||||
}
|
||||
|
||||
float3 Rand(float2 uv)
|
||||
{
|
||||
return frac(sin(dot(uv, float2(12.9898, 78.233)) * float3(1, 2, 3)) * 43758.5453);
|
||||
|
@ -92,3 +86,19 @@ float3 NormalDither(float3 rand)
|
|||
const float2 rr = rand.xy * (1.0 / 333.0) - (0.5 / 333.0);
|
||||
return float3(rr, 0);
|
||||
}
|
||||
|
||||
static const float2 _POINT_SPRITE_POS_OFFSETS[4] =
|
||||
{
|
||||
float2(-0.5, 0.5),
|
||||
float2(-0.5, -0.5),
|
||||
float2(0.5, 0.5),
|
||||
float2(0.5, -0.5)
|
||||
};
|
||||
|
||||
static const float2 _POINT_SPRITE_TEX_COORDS[4] =
|
||||
{
|
||||
float2(0, 0),
|
||||
float2(0, 1),
|
||||
float2(1, 0),
|
||||
float2(1, 1)
|
||||
};
|
||||
|
|
|
@ -1,37 +1,5 @@
|
|||
// Copyright (C) 2020, Dmitry Maluev (dmaluev@gmail.com)
|
||||
|
||||
// See: http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html
|
||||
float4 ColorToLinear(float4 x)
|
||||
{
|
||||
const float3 rgb = x.rgb < 0.04045 ? x.rgb * (1.0 / 12.92) : pow(abs(x.rgb + 0.055) / 1.055, 2.4);
|
||||
return float4(rgb, x.a);
|
||||
}
|
||||
float4 ColorToSRGB(float4 x)
|
||||
{
|
||||
const float3 rgb = x.rgb < 0.0031308 ? 12.92 * x.rgb : 1.055 * pow(abs(x.rgb), 1.0 / 2.4) - 0.055;
|
||||
return float4(rgb, x.a);
|
||||
}
|
||||
|
||||
float4 HDRColorToLinear(float4 x)
|
||||
{
|
||||
return float4(x.rgb * x.rgb * 12.0, x.a);
|
||||
}
|
||||
float4 HDRColorToSRGB(float4 x)
|
||||
{
|
||||
return float4(sqrt(saturate(x.rgb * (1.0 / 12.0))), x.a);
|
||||
}
|
||||
|
||||
// See: https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/
|
||||
float3 ToneMappingACES(float3 x)
|
||||
{
|
||||
const float a = 2.51f;
|
||||
const float b = 0.03f;
|
||||
const float c = 2.43f;
|
||||
const float d = 0.59f;
|
||||
const float e = 0.14f;
|
||||
return saturate((x * (a * x + b)) / (x * (c * x + d) + e));
|
||||
}
|
||||
|
||||
// See: https://en.wikipedia.org/wiki/Grayscale
|
||||
float Grayscale(float3 color)
|
||||
{
|
||||
|
@ -44,12 +12,6 @@ float3 Desaturate(float3 color, float alpha, float lum = 1.0)
|
|||
return lerp(color, gray, alpha);
|
||||
}
|
||||
|
||||
float3 DesaturateFilmic(float3 color)
|
||||
{
|
||||
const float gray = Grayscale(color);
|
||||
return lerp(color, gray, saturate(gray * gray * gray));
|
||||
}
|
||||
|
||||
// See: http://www.chilliant.com/rgb2hsv.html
|
||||
float3 ConvertRGBtoHCV(float3 color)
|
||||
{
|
||||
|
@ -96,3 +58,41 @@ float2 AlphaSwitch(float4 albedo, float2 tc, float2 alphaSwitch)
|
|||
else
|
||||
return saturate(float2(albedo.a * 8.0, (albedo.a - 0.15) / 0.85)); // 5-bit alpha.
|
||||
}
|
||||
|
||||
// See: http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html
|
||||
float4 ColorToLinear(float4 x)
|
||||
{
|
||||
const float3 rgb = x.rgb < 0.04045 ? x.rgb * (1.0 / 12.92) : pow(abs(x.rgb + 0.055) / 1.055, 2.4);
|
||||
return float4(rgb, x.a);
|
||||
}
|
||||
float4 ColorToSRGB(float4 x)
|
||||
{
|
||||
const float3 rgb = x.rgb < 0.0031308 ? 12.92 * x.rgb : 1.055 * pow(abs(x.rgb), 1.0 / 2.4) - 0.055;
|
||||
return float4(rgb, x.a);
|
||||
}
|
||||
|
||||
float4 HDRColorToLinear(float4 x)
|
||||
{
|
||||
return float4(x.rgb * x.rgb * 12.0, x.a);
|
||||
}
|
||||
float4 HDRColorToSRGB(float4 x)
|
||||
{
|
||||
return float4(sqrt(saturate(x.rgb * (1.0 / 12.0))), x.a);
|
||||
}
|
||||
|
||||
// See: https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/
|
||||
float3 ToneMappingACES(float3 x)
|
||||
{
|
||||
const float a = 2.51f;
|
||||
const float b = 0.03f;
|
||||
const float c = 2.43f;
|
||||
const float d = 0.59f;
|
||||
const float e = 0.14f;
|
||||
return saturate((x * (a * x + b)) / (x * (c * x + d) + e));
|
||||
}
|
||||
|
||||
float3 VerusToneMapping(float3 hdr, float filmicLook = 1.0)
|
||||
{
|
||||
const float3 ldr = lerp(1.0 - exp(-hdr), ToneMappingACES(hdr), filmicLook);
|
||||
return saturate(ldr);
|
||||
}
|
||||
|
|
|
@ -2,10 +2,9 @@
|
|||
|
||||
struct DS_FSO
|
||||
{
|
||||
float4 target0 : SV_Target0; // {color, spec}
|
||||
float4 target1 : SV_Target1; // {depth}
|
||||
float4 target2 : SV_Target2; // {normal, emission, motion}
|
||||
float4 target3 : SV_Target3; // {lam, metal, gloss}
|
||||
float4 target0 : SV_Target0; // {albedo, spec}
|
||||
float4 target1 : SV_Target1; // {normal, emission, motion}
|
||||
float4 target2 : SV_Target2; // {lam, metal, gloss}
|
||||
};
|
||||
|
||||
struct DS_ACC_FSO
|
||||
|
@ -35,15 +34,20 @@ void DS_Reset(out DS_FSO so)
|
|||
so.target0 = 0.0;
|
||||
so.target1 = 0.0;
|
||||
so.target2 = 0.0;
|
||||
so.target3 = 0.0;
|
||||
}
|
||||
|
||||
void DS_SolidColor(out DS_FSO so, float3 color)
|
||||
{
|
||||
so.target0 = float4(color, 0.0);
|
||||
so.target1 = float4(EncodeNormal(float3(0, 0, 1)), 1.0, 0.0);
|
||||
so.target2 = float4(1.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
void DS_Test(out DS_FSO so, float3 normal, float spec, float gloss)
|
||||
{
|
||||
so.target0 = float4(0.5, 0.5, 0.5, spec);
|
||||
so.target1 = 0.0;
|
||||
so.target2 = float4(EncodeNormal(normal), 0.25, 0.5);
|
||||
so.target3 = float4(1.0 / 8.0, 0.5, 0.5, gloss * (1.0 / 64.0));
|
||||
so.target1 = float4(EncodeNormal(normal), 0.25, 0.5);
|
||||
so.target2 = float4(1.0 / 8.0, 0.5, 0.5, gloss * (1.0 / 64.0));
|
||||
}
|
||||
|
||||
void DS_SetAlbedo(inout DS_FSO so, float3 albedo)
|
||||
|
@ -56,11 +60,6 @@ void DS_SetSpec(inout DS_FSO so, float spec)
|
|||
so.target0.a = spec;
|
||||
}
|
||||
|
||||
void DS_SetDepth(inout DS_FSO so, float depth)
|
||||
{
|
||||
so.target1 = depth;
|
||||
}
|
||||
|
||||
float3 DS_GetNormal(float4 gbuffer)
|
||||
{
|
||||
return DecodeNormal(gbuffer.rg);
|
||||
|
@ -68,7 +67,7 @@ float3 DS_GetNormal(float4 gbuffer)
|
|||
|
||||
void DS_SetNormal(inout DS_FSO so, float3 normal)
|
||||
{
|
||||
so.target2.rg = EncodeNormal(normal);
|
||||
so.target1.rg = EncodeNormal(normal);
|
||||
}
|
||||
|
||||
float2 DS_GetEmission(float4 gbuffer)
|
||||
|
@ -80,7 +79,7 @@ float2 DS_GetEmission(float4 gbuffer)
|
|||
void DS_SetEmission(inout DS_FSO so, float emission, float skin)
|
||||
{
|
||||
const float em = HDRColorToSRGB(emission).r;
|
||||
so.target2.b = (3.0 * em - skin) * 0.25 + 0.25;
|
||||
so.target1.b = (3.0 * em - skin) * 0.25 + 0.25;
|
||||
}
|
||||
|
||||
float2 DS_GetLamScaleBias(float4 gbuffer)
|
||||
|
@ -90,30 +89,30 @@ float2 DS_GetLamScaleBias(float4 gbuffer)
|
|||
|
||||
void DS_SetLamScaleBias(inout DS_FSO so, float2 lamScaleBias, float4 aniso)
|
||||
{
|
||||
so.target3.rg = lerp(lamScaleBias * float2(1.0 / 8.0, 0.25) + float2(0, 0.5), EncodeNormal(aniso.xyz), aniso.w);
|
||||
so.target2.rg = lerp(lamScaleBias * float2(1.0 / 8.0, 0.25) + float2(0, 0.5), EncodeNormal(aniso.xyz), aniso.w);
|
||||
}
|
||||
|
||||
float2 DS_GetMetallicity(float4 gbuffer)
|
||||
{
|
||||
const float x2 = gbuffer.b * 2.0;
|
||||
const float x2 = gbuffer.b * 2.02;
|
||||
return float2(
|
||||
saturate(x2 - 1.0),
|
||||
saturate(x2 - 1.02),
|
||||
saturate(1.0 - x2));
|
||||
}
|
||||
|
||||
void DS_SetMetallicity(inout DS_FSO so, float metal, float hair)
|
||||
{
|
||||
so.target3.b = (metal - hair) * 0.5 + 0.5;
|
||||
so.target2.b = (metal - hair) * 0.5 + 0.5;
|
||||
}
|
||||
|
||||
void DS_SetGloss(inout DS_FSO so, float gloss)
|
||||
{
|
||||
so.target3.a = gloss * (1.0 / 64.0);
|
||||
so.target2.a = gloss * (1.0 / 64.0);
|
||||
}
|
||||
|
||||
float3 DS_GetPosition(float4 gbuffer, matrix matInvProj, float2 posCS)
|
||||
float3 DS_GetPosition(float4 gbuffer, matrix matInvProj, float2 ndcPos)
|
||||
{
|
||||
float4 pos = mul(float4(posCS, gbuffer.r, 1), matInvProj);
|
||||
float4 pos = mul(float4(ndcPos, gbuffer.r, 1), matInvProj);
|
||||
pos /= pos.w;
|
||||
return pos.xyz;
|
||||
}
|
||||
|
|
|
@ -13,9 +13,10 @@ float4 ToLinearDepth(float4 d, float4 zNearFarEx)
|
|||
return zNearFarEx.w / (d - zNearFarEx.z);
|
||||
}
|
||||
|
||||
float ComputeFog(float depth, float density)
|
||||
float ComputeFog(float depth, float density, float height = 0.0)
|
||||
{
|
||||
const float fog = 1.0 / exp(depth * density);
|
||||
const float strength = 1.0 - saturate(height * 0.003);
|
||||
const float fog = 1.0 / exp(depth * lerp(0.0, density, strength * strength));
|
||||
return 1.0 - saturate(fog);
|
||||
}
|
||||
|
||||
|
@ -76,9 +77,10 @@ float PCF(
|
|||
if (dzBlockers_blockerCount.y > 0.0)
|
||||
{
|
||||
const float penumbraScale = config.x;
|
||||
const float penumbraContrastMask = config.y;
|
||||
const float dzBlockers = dzBlockers_blockerCount.x / dzBlockers_blockerCount.y;
|
||||
const float penumbra = saturate(dzFrag - dzBlockers);
|
||||
const float contrast = 1.0 + max(0.0, 3.0 - penumbra * penumbraScale);
|
||||
const float contrast = 1.0 + max(0.0, 3.0 - penumbra * penumbraScale) * penumbraContrastMask;
|
||||
return saturate((ret - 0.5) * contrast + 0.5);
|
||||
}
|
||||
else
|
||||
|
@ -122,7 +124,7 @@ float ShadowMapCSM(
|
|||
float ret = 1.0;
|
||||
const float4 p = float4(pos.xyz, 1);
|
||||
float contrast = 1.0;
|
||||
const float contrastScale = 2.8;
|
||||
const float contrastScale = config.w;
|
||||
|
||||
if (pos.w > ranges.x)
|
||||
{
|
||||
|
|
|
@ -11,26 +11,26 @@ float FresnelSchlick(float minRef, float maxAdd, float power)
|
|||
return saturate(minRef + maxAdd * power);
|
||||
}
|
||||
|
||||
// See: http://www.thetenthplanet.de/archives/255
|
||||
float EnergyNorm(float gloss)
|
||||
{
|
||||
return (gloss + 2.0) / 8.0;
|
||||
return (gloss + 2.0) * (1.0 / 8.0);
|
||||
}
|
||||
|
||||
float4 VerusLit(float3 dirToLight, float3 normal, float3 dirToEye, float gloss,
|
||||
float2 lamScaleBias, float4 aniso = 0.0)
|
||||
float2 lamScaleBias, float4 aniso = 0.0, float eyeFresnel = 0.0)
|
||||
{
|
||||
float4 ret = float4(1, 0, 0, 1);
|
||||
const float3 hv = normalize(dirToEye + dirToLight);
|
||||
const float nDotL = dot(normal, dirToLight);
|
||||
const float nDotL = dot(normal, dirToLight) * lamScaleBias.x + lamScaleBias.y;
|
||||
const float nDotE = dot(normal, dirToEye);
|
||||
const float nDotH = dot(normal, hv);
|
||||
const float aDotH = SinAcos(dot(aniso.xyz, hv));
|
||||
const float3 spec = saturate(float3(EnergyNorm(gloss).xx, 1) *
|
||||
pow(saturate(float3(nDotH, aDotH, 1.0 - nDotL)), float3(gloss, gloss * 8.0, 5)));
|
||||
const float4 spec = float4(EnergyNorm(gloss).xx, 1, 1) *
|
||||
pow(saturate(float4(nDotH, aDotH, 1.0 - nDotL, 1.0 - nDotE)), float4(gloss, gloss * 8.0, 5, 5));
|
||||
ret.x = saturate(nDotL * -4.0); // For subsurface scattering effect.
|
||||
ret.y = saturate(nDotL * lamScaleBias.x + lamScaleBias.y);
|
||||
ret.y = saturate(nDotL);
|
||||
ret.z = saturate(nDotL * 8.0) * max(spec.x, spec.y * aniso.w);
|
||||
ret.w = spec.z; // For fresnel effect.
|
||||
ret.w = lerp(spec.z, spec.w, eyeFresnel); // For fresnel effect.
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue