This commit is contained in:
Dmitry 2022-03-08 02:46:50 +03:00
parent 49241c9f18
commit 2d2672829e
86 changed files with 2000 additions and 1312 deletions

View File

@ -1,4 +1,4 @@
// Copyright (C) 2021, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#include "pch.h"
using namespace verus;

View File

@ -1,4 +1,4 @@
// Copyright (C) 2021, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#pragma once
namespace verus

View File

@ -1,4 +1,4 @@
// Copyright (C) 2021, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
// Copied from Lib.hlsl:
#define VERUS_UBUFFER struct

View File

@ -1,4 +1,4 @@
// Copyright (C) 2021, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#include "pch.h"
using namespace verus;

View File

@ -1,2 +1,2 @@
// Copyright (C) 2021, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#include "pch.h"

View File

@ -1,4 +1,4 @@
// Copyright (C) 2021, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#pragma once
#include <verus.h>

View File

@ -1,4 +1,4 @@
// Copyright (C) 2021, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#include "pch.h"
using namespace verus;

View File

@ -1,4 +1,4 @@
// Copyright (C) 2021, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#pragma once
namespace verus

View File

@ -1,6 +1,6 @@
R"(
// Copyright (C) 2021, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
// Copied from Lib.hlsl:
#define VERUS_UBUFFER struct

View File

@ -1,4 +1,4 @@
// Copyright (C) 2021, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#include "pch.h"
using namespace verus;

View File

@ -1,2 +1,2 @@
// Copyright (C) 2021, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#include "pch.h"

View File

@ -1,4 +1,4 @@
// Copyright (C) 2021, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#pragma once
#include <verus.h>

View File

@ -1,4 +1,4 @@
// Copyright (C) 2021, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
/*******************************************************************************
*
* PACK format with compression & encryption.

View File

@ -6,8 +6,9 @@ using namespace verus::CGI;
// DescriptorHeap:
void DescriptorHeap::Create(ID3D12Device* pDevice, D3D12_DESCRIPTOR_HEAP_TYPE type, UINT count, bool shaderVisible)
void DescriptorHeap::Create(ID3D12Device* pDevice, D3D12_DESCRIPTOR_HEAP_TYPE type, int count, bool shaderVisible)
{
// Warning! On some hardware the maximum number of descriptor heaps is 4096!
VERUS_CT_ASSERT(sizeof(*this) == 32);
VERUS_RT_ASSERT(count > 0);
HRESULT hr = 0;
@ -22,12 +23,12 @@ void DescriptorHeap::Create(ID3D12Device* pDevice, D3D12_DESCRIPTOR_HEAP_TYPE ty
_handleIncrementSize = pDevice->GetDescriptorHandleIncrementSize(desc.Type);
}
CD3DX12_CPU_DESCRIPTOR_HANDLE DescriptorHeap::AtCPU(INT index) const
CD3DX12_CPU_DESCRIPTOR_HANDLE DescriptorHeap::AtCPU(int index) const
{
return CD3DX12_CPU_DESCRIPTOR_HANDLE(_hCPUHandleForHeapStart, index, _handleIncrementSize);
}
CD3DX12_GPU_DESCRIPTOR_HANDLE DescriptorHeap::AtGPU(INT index) const
CD3DX12_GPU_DESCRIPTOR_HANDLE DescriptorHeap::AtGPU(int index) const
{
VERUS_RT_ASSERT(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV == _type || D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER == _type);
return CD3DX12_GPU_DESCRIPTOR_HANDLE(_hGPUHandleForHeapStart, index, _handleIncrementSize);
@ -35,7 +36,7 @@ CD3DX12_GPU_DESCRIPTOR_HANDLE DescriptorHeap::AtGPU(INT index) const
// DynamicDescriptorHeap:
void DynamicDescriptorHeap::Create(ID3D12Device* pDevice, D3D12_DESCRIPTOR_HEAP_TYPE type, UINT count, UINT staticCount, bool shaderVisible)
void DynamicDescriptorHeap::Create(ID3D12Device* pDevice, D3D12_DESCRIPTOR_HEAP_TYPE type, int count, int staticCount, bool shaderVisible)
{
VERUS_CT_ASSERT(sizeof(*this) == 56);
_capacity = count;
@ -46,7 +47,6 @@ void DynamicDescriptorHeap::Create(ID3D12Device* pDevice, D3D12_DESCRIPTOR_HEAP_
HandlePair DynamicDescriptorHeap::GetNextHandlePair(int count)
{
VERUS_QREF_RENDERER;
VERUS_QREF_RENDERER_D3D12;
if (_currentFrame != renderer.GetFrameCount())
{
@ -56,7 +56,7 @@ HandlePair DynamicDescriptorHeap::GetNextHandlePair(int count)
if (_offset + count <= _capacity)
{
const INT index = _capacity * pRendererD3D12->GetRingBufferIndex() + _offset;
const int index = _capacity * renderer->GetRingBufferIndex() + _offset;
_offset += count;
_peakLoad = Math::Max<UINT64>(_peakLoad, _offset);
return HandlePair(AtCPU(index), AtGPU(index));
@ -67,6 +67,6 @@ HandlePair DynamicDescriptorHeap::GetNextHandlePair(int count)
HandlePair DynamicDescriptorHeap::GetStaticHandlePair(int index)
{
const INT indexAt = _capacity * BaseRenderer::s_ringBufferSize + index;
const int indexAt = _capacity * BaseRenderer::s_ringBufferSize + index;
return HandlePair(AtCPU(indexAt), AtGPU(indexAt));
}

View File

@ -18,10 +18,13 @@ namespace verus
ID3D12DescriptorHeap* GetD3DDescriptorHeap() const { return _pDescriptorHeap.Get(); }
void Create(ID3D12Device* pDevice, D3D12_DESCRIPTOR_HEAP_TYPE type, UINT count, bool shaderVisible = false);
void Create(ID3D12Device* pDevice, D3D12_DESCRIPTOR_HEAP_TYPE type, int count, bool shaderVisible = false);
CD3DX12_CPU_DESCRIPTOR_HANDLE AtCPU(INT index) const;
CD3DX12_GPU_DESCRIPTOR_HANDLE AtGPU(INT index) const;
CD3DX12_CPU_DESCRIPTOR_HANDLE AtCPU(int index) const;
CD3DX12_GPU_DESCRIPTOR_HANDLE AtGPU(int index) const;
D3D12_DESCRIPTOR_HEAP_TYPE GetType() const { return _type; }
UINT GetHandleIncrementSize() const { return _handleIncrementSize; }
};
VERUS_TYPEDEFS(DescriptorHeap);
@ -31,26 +34,27 @@ namespace verus
CD3DX12_GPU_DESCRIPTOR_HANDLE _hGPU;
HandlePair(
CD3DX12_CPU_DESCRIPTOR_HANDLE hCPU = CD3DX12_CPU_DESCRIPTOR_HANDLE(),
CD3DX12_GPU_DESCRIPTOR_HANDLE hGPU = CD3DX12_GPU_DESCRIPTOR_HANDLE()) : _hCPU(hCPU), _hGPU(hGPU) {}
CD3DX12_CPU_DESCRIPTOR_HANDLE hCPU = D3D12_DEFAULT,
CD3DX12_GPU_DESCRIPTOR_HANDLE hGPU = D3D12_DEFAULT) : _hCPU(hCPU), _hGPU(hGPU) {}
};
VERUS_TYPEDEFS(HandlePair);
// This descriptor heap should be refilled every frame:
class DynamicDescriptorHeap : public DescriptorHeap
{
UINT _capacity = 0;
UINT _offset = 0;
int _capacity = 0;
int _offset = 0;
UINT64 _currentFrame = UINT64_MAX;
UINT64 _peakLoad = 0;
public:
void Create(ID3D12Device* pDevice, D3D12_DESCRIPTOR_HEAP_TYPE type, UINT count, UINT staticCount = 0, bool shaderVisible = false);
void Create(ID3D12Device* pDevice, D3D12_DESCRIPTOR_HEAP_TYPE type, int count, int staticCount = 0, bool shaderVisible = false);
HandlePair GetNextHandlePair(int count = 1);
HandlePair GetStaticHandlePair(int index);
UINT GetCapacity() const { return _capacity; }
UINT GetOffset() const { return _offset; }
int GetCapacity() const { return _capacity; }
int GetOffset() const { return _offset; }
};
VERUS_TYPEDEFS(DynamicDescriptorHeap);
}

View File

@ -2,7 +2,105 @@
#include "pch.h"
using namespace verus;
using namespace verus::CGI;
D3D12_COMPARISON_FUNC CGI::ToNativeCompareOp(CompareOp compareOp)
{
switch (compareOp)
{
case CompareOp::never: return D3D12_COMPARISON_FUNC_NEVER;
case CompareOp::less: return D3D12_COMPARISON_FUNC_LESS;
case CompareOp::equal: return D3D12_COMPARISON_FUNC_EQUAL;
case CompareOp::lessOrEqual: return D3D12_COMPARISON_FUNC_LESS_EQUAL;
case CompareOp::greater: return D3D12_COMPARISON_FUNC_GREATER;
case CompareOp::notEqual: return D3D12_COMPARISON_FUNC_NOT_EQUAL;
case CompareOp::greaterOrEqual: return D3D12_COMPARISON_FUNC_GREATER_EQUAL;
case CompareOp::always: return D3D12_COMPARISON_FUNC_ALWAYS;
default: throw VERUS_RECOVERABLE << "ToNativeCompareOp()";
}
}
UINT CGI::ToNativeCubeMapFace(CubeMapFace face)
{
switch (face)
{
case CubeMapFace::posX: return 0;
case CubeMapFace::negX: return 1;
case CubeMapFace::posY: return 2;
case CubeMapFace::negY: return 3;
case CubeMapFace::posZ: return 4;
case CubeMapFace::negZ: return 5;
default: throw VERUS_RECOVERABLE << "ToNativeCubeMapFace()";
}
}
D3D12_FILL_MODE CGI::ToNativePolygonMode(PolygonMode polygonMode)
{
switch (polygonMode)
{
case PolygonMode::fill: return D3D12_FILL_MODE_SOLID;
case PolygonMode::line: return D3D12_FILL_MODE_WIREFRAME;
default: throw VERUS_RECOVERABLE << "ToNativePolygonMode()";
}
}
D3D12_CULL_MODE CGI::ToNativeCullMode(CullMode cullMode)
{
switch (cullMode)
{
case CullMode::none: return D3D12_CULL_MODE_NONE;
case CullMode::front: return D3D12_CULL_MODE_FRONT;
case CullMode::back: return D3D12_CULL_MODE_BACK;
default: throw VERUS_RECOVERABLE << "ToNativeCullMode()";
}
}
D3D_PRIMITIVE_TOPOLOGY CGI::ToNativePrimitiveTopology(PrimitiveTopology primitiveTopology)
{
switch (primitiveTopology)
{
case PrimitiveTopology::pointList: return D3D_PRIMITIVE_TOPOLOGY_POINTLIST;
case PrimitiveTopology::lineList: return D3D_PRIMITIVE_TOPOLOGY_LINELIST;
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()";
}
}
D3D12_PRIMITIVE_TOPOLOGY_TYPE CGI::ToNativePrimitiveTopologyType(PrimitiveTopology primitiveTopology)
{
switch (primitiveTopology)
{
case PrimitiveTopology::pointList: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT;
case PrimitiveTopology::lineList: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
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()";
}
}
D3D12_RESOURCE_STATES CGI::ToNativeImageLayout(ImageLayout layout)
{
switch (layout)
{
case ImageLayout::undefined: return D3D12_RESOURCE_STATE_COMMON;
case ImageLayout::general: return D3D12_RESOURCE_STATE_COMMON;
case ImageLayout::colorAttachment: return D3D12_RESOURCE_STATE_RENDER_TARGET;
case ImageLayout::depthStencilAttachment: return D3D12_RESOURCE_STATE_DEPTH_WRITE;
case ImageLayout::depthStencilReadOnly: return D3D12_RESOURCE_STATE_DEPTH_READ | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
case ImageLayout::xsReadOnly: return D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
case ImageLayout::fsReadOnly: return D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
case ImageLayout::transferSrc: return D3D12_RESOURCE_STATE_COPY_SOURCE;
case ImageLayout::transferDst: return D3D12_RESOURCE_STATE_COPY_DEST;
case ImageLayout::presentSrc: return D3D12_RESOURCE_STATE_PRESENT;
default: throw VERUS_RECOVERABLE << "ToNativeImageLayout()";
}
}
DXGI_FORMAT CGI::ToNativeFormat(Format format, bool typeless)
{
@ -56,91 +154,6 @@ DXGI_FORMAT CGI::ToNativeSampledDepthFormat(Format format)
};
}
D3D12_CULL_MODE CGI::ToNativeCullMode(CullMode cullMode)
{
switch (cullMode)
{
case CullMode::none: return D3D12_CULL_MODE_NONE;
case CullMode::front: return D3D12_CULL_MODE_FRONT;
case CullMode::back: return D3D12_CULL_MODE_BACK;
default: throw VERUS_RECOVERABLE << "ToNativeCullMode()";
}
}
D3D12_RESOURCE_STATES CGI::ToNativeImageLayout(ImageLayout layout)
{
switch (layout)
{
case ImageLayout::undefined: return D3D12_RESOURCE_STATE_COMMON;
case ImageLayout::general: return D3D12_RESOURCE_STATE_COMMON;
case ImageLayout::colorAttachment: return D3D12_RESOURCE_STATE_RENDER_TARGET;
case ImageLayout::depthStencilAttachment: return D3D12_RESOURCE_STATE_DEPTH_WRITE;
case ImageLayout::depthStencilReadOnly: return D3D12_RESOURCE_STATE_DEPTH_READ | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
case ImageLayout::xsReadOnly: return D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
case ImageLayout::fsReadOnly: return D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
case ImageLayout::transferSrc: return D3D12_RESOURCE_STATE_COPY_SOURCE;
case ImageLayout::transferDst: return D3D12_RESOURCE_STATE_COPY_DEST;
case ImageLayout::presentSrc: return D3D12_RESOURCE_STATE_PRESENT;
default: throw VERUS_RECOVERABLE << "ToNativeImageLayout()";
}
}
D3D12_FILL_MODE CGI::ToNativePolygonMode(PolygonMode polygonMode)
{
switch (polygonMode)
{
case PolygonMode::fill: return D3D12_FILL_MODE_SOLID;
case PolygonMode::line: return D3D12_FILL_MODE_WIREFRAME;
default: throw VERUS_RECOVERABLE << "ToNativePolygonMode()";
}
}
D3D_PRIMITIVE_TOPOLOGY CGI::ToNativePrimitiveTopology(PrimitiveTopology primitiveTopology)
{
switch (primitiveTopology)
{
case PrimitiveTopology::pointList: return D3D_PRIMITIVE_TOPOLOGY_POINTLIST;
case PrimitiveTopology::lineList: return D3D_PRIMITIVE_TOPOLOGY_LINELIST;
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()";
}
}
D3D12_PRIMITIVE_TOPOLOGY_TYPE CGI::ToNativePrimitiveTopologyType(PrimitiveTopology primitiveTopology)
{
switch (primitiveTopology)
{
case PrimitiveTopology::pointList: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT;
case PrimitiveTopology::lineList: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
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()";
}
}
D3D12_COMPARISON_FUNC CGI::ToNativeCompareOp(CompareOp compareOp)
{
switch (compareOp)
{
case CompareOp::never: return D3D12_COMPARISON_FUNC_NEVER;
case CompareOp::less: return D3D12_COMPARISON_FUNC_LESS;
case CompareOp::equal: return D3D12_COMPARISON_FUNC_EQUAL;
case CompareOp::lessOrEqual: return D3D12_COMPARISON_FUNC_LESS_EQUAL;
case CompareOp::greater: return D3D12_COMPARISON_FUNC_GREATER;
case CompareOp::notEqual: return D3D12_COMPARISON_FUNC_NOT_EQUAL;
case CompareOp::greaterOrEqual: return D3D12_COMPARISON_FUNC_GREATER_EQUAL;
case CompareOp::always: return D3D12_COMPARISON_FUNC_ALWAYS;
default: throw VERUS_RECOVERABLE << "ToNativeCompareOp()";
}
}
CSZ CGI::ToNativeSemanticName(ViaUsage usage)
{
static const CSZ names[] =
@ -230,17 +243,3 @@ DXGI_FORMAT CGI::ToNativeFormat(ViaUsage usage, ViaType type, int components)
default: throw VERUS_RECOVERABLE << "ToNativeFormat(); ViaType=?";
}
}
UINT CGI::ToNativeCubeMapFace(CubeMapFace face)
{
switch (face)
{
case CubeMapFace::posX: return 0;
case CubeMapFace::negX: return 1;
case CubeMapFace::posY: return 2;
case CubeMapFace::negY: return 3;
case CubeMapFace::posZ: return 4;
case CubeMapFace::negZ: return 5;
default: throw VERUS_RECOVERABLE << "ToNativeCubeMapFace()";
}
}

View File

@ -5,23 +5,23 @@ namespace verus
{
namespace CGI
{
DXGI_FORMAT ToNativeFormat(Format format, bool typeless);
DXGI_FORMAT ToNativeSampledDepthFormat(Format format);
D3D12_COMPARISON_FUNC ToNativeCompareOp(CompareOp compareOp);
D3D12_CULL_MODE ToNativeCullMode(CullMode cullMode);
D3D12_RESOURCE_STATES ToNativeImageLayout(ImageLayout layout);
UINT ToNativeCubeMapFace(CubeMapFace face);
D3D12_FILL_MODE ToNativePolygonMode(PolygonMode polygonMode);
D3D12_CULL_MODE ToNativeCullMode(CullMode cullMode);
D3D_PRIMITIVE_TOPOLOGY ToNativePrimitiveTopology(PrimitiveTopology primitiveTopology);
D3D12_PRIMITIVE_TOPOLOGY_TYPE ToNativePrimitiveTopologyType(PrimitiveTopology primitiveTopology);
D3D12_COMPARISON_FUNC ToNativeCompareOp(CompareOp compareOp);
D3D12_RESOURCE_STATES ToNativeImageLayout(ImageLayout layout);
DXGI_FORMAT ToNativeFormat(Format format, bool typeless);
DXGI_FORMAT ToNativeSampledDepthFormat(Format format);
CSZ ToNativeSemanticName(ViaUsage usage);
DXGI_FORMAT ToNativeFormat(ViaUsage usage, ViaType type, int components);
UINT ToNativeCubeMapFace(CubeMapFace face);
}
}

View File

@ -72,7 +72,7 @@ void PipelineD3D12::Init(RcPipelineDesc desc)
gpsDesc.RasterizerState.DepthBias = static_cast<INT>(desc._rasterizationState._depthBiasConstantFactor);
gpsDesc.RasterizerState.DepthBiasClamp = desc._rasterizationState._depthBiasClamp;
gpsDesc.RasterizerState.SlopeScaledDepthBias = desc._rasterizationState._depthBiasSlopeFactor;
gpsDesc.RasterizerState.DepthClipEnable = desc._rasterizationState._depthClampEnable;
gpsDesc.RasterizerState.DepthClipEnable = TRUE;
gpsDesc.RasterizerState.MultisampleEnable = FALSE;
gpsDesc.RasterizerState.AntialiasedLineEnable = (desc._colorAttachBlendEqs[0] == VERUS_COLOR_BLEND_ALPHA) ? TRUE : FALSE;
gpsDesc.RasterizerState.ForcedSampleCount = 0;
@ -184,7 +184,7 @@ void PipelineD3D12::InitMeshShading(RcPipelineDesc desc)
mspsDesc.RasterizerState.DepthBias = static_cast<INT>(desc._rasterizationState._depthBiasConstantFactor);
mspsDesc.RasterizerState.DepthBiasClamp = desc._rasterizationState._depthBiasClamp;
mspsDesc.RasterizerState.SlopeScaledDepthBias = desc._rasterizationState._depthBiasSlopeFactor;
mspsDesc.RasterizerState.DepthClipEnable = desc._rasterizationState._depthClampEnable;
mspsDesc.RasterizerState.DepthClipEnable = TRUE;
mspsDesc.RasterizerState.MultisampleEnable = FALSE;
mspsDesc.RasterizerState.AntialiasedLineEnable = (desc._colorAttachBlendEqs[0] == VERUS_COLOR_BLEND_ALPHA) ? TRUE : FALSE;
mspsDesc.RasterizerState.ForcedSampleCount = 0;

View File

@ -140,7 +140,7 @@ void RendererD3D12::CreateSwapChainBuffersRTVs()
HRESULT hr = 0;
_vSwapChainBuffers.resize(_swapChainBufferCount);
_dhSwapChainBuffersRTVs.Create(_pDevice.Get(), D3D12_DESCRIPTOR_HEAP_TYPE_RTV, _swapChainBufferCount);
VERUS_U_FOR(i, _swapChainBufferCount)
VERUS_FOR(i, _swapChainBufferCount)
{
ComPtr<ID3D12Resource> pBuffer;
if (FAILED(hr = _pSwapChain->GetBuffer(i, IID_PPV_ARGS(&pBuffer))))
@ -648,7 +648,7 @@ RPHandle RendererD3D12::CreateRenderPass(std::initializer_list<RP::Attachment> i
renderPass._vAttachments.push_back(std::move(d3dAttach));
}
auto GetAttachmentIndexByName = [&ilA](CSZ name) -> uint32_t
auto GetAttachmentIndexByName = [&ilA](CSZ name) -> int
{
if (!name)
return -1;

View File

@ -420,12 +420,22 @@ CSHandle ShaderD3D12::BindDescriptorSetTextures(int setNumber, std::initializer_
_vComplexSets.resize(complexSetHandle + 1);
}
bool toViewHeap = false;
if (setNumber & ShaderD3D12::SET_MOD_TO_VIEW_HEAP)
{
setNumber &= ~ShaderD3D12::SET_MOD_TO_VIEW_HEAP;
toViewHeap = true;
}
auto& dsd = _vDescriptorSetDesc[setNumber];
VERUS_RT_ASSERT(dsd._vSamplers.size() == il.size());
RComplexSet complexSet = _vComplexSets[complexSetHandle];
complexSet._vTextures.reserve(il.size());
complexSet._dhViews.Create(pRendererD3D12->GetD3DDevice(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, Utils::Cast32(il.size()));
if (toViewHeap)
complexSet._hpBase = pRendererD3D12->GetViewHeap().GetNextHandlePair(1 + Utils::Cast32(il.size()));
else
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;
@ -436,17 +446,37 @@ CSHandle ShaderD3D12::BindDescriptorSetTextures(int setNumber, std::initializer_
auto& texD3D12 = static_cast<RTextureD3D12>(*x);
if (Sampler::storage == dsd._vSamplers[index])
{
pRendererD3D12->GetD3DDevice()->CopyDescriptorsSimple(1,
complexSet._dhViews.AtCPU(index),
texD3D12.GetDescriptorHeapUAV().AtCPU(mip),
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
if (toViewHeap)
{
pRendererD3D12->GetD3DDevice()->CopyDescriptorsSimple(1,
CD3DX12_CPU_DESCRIPTOR_HANDLE(complexSet._hpBase._hCPU, 1 + index, pRendererD3D12->GetViewHeap().GetHandleIncrementSize()),
texD3D12.GetDescriptorHeapUAV().AtCPU(mip),
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
}
else
{
pRendererD3D12->GetD3DDevice()->CopyDescriptorsSimple(1,
complexSet._dhViews.AtCPU(index),
texD3D12.GetDescriptorHeapUAV().AtCPU(mip),
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
}
}
else
{
pRendererD3D12->GetD3DDevice()->CopyDescriptorsSimple(1,
complexSet._dhViews.AtCPU(index),
texD3D12.GetDescriptorHeapSRV().AtCPU(mip),
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
if (toViewHeap)
{
pRendererD3D12->GetD3DDevice()->CopyDescriptorsSimple(1,
CD3DX12_CPU_DESCRIPTOR_HANDLE(complexSet._hpBase._hCPU, 1 + index, pRendererD3D12->GetViewHeap().GetHandleIncrementSize()),
texD3D12.GetDescriptorHeapSRV().AtCPU(mip),
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
}
else
{
pRendererD3D12->GetD3DDevice()->CopyDescriptorsSimple(1,
complexSet._dhViews.AtCPU(index),
texD3D12.GetDescriptorHeapSRV().AtCPU(mip),
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
}
if (Sampler::custom == dsd._vSamplers[index])
{
pRendererD3D12->GetD3DDevice()->CopyDescriptorsSimple(1,
@ -540,7 +570,9 @@ CD3DX12_GPU_DESCRIPTOR_HANDLE ShaderD3D12::UpdateUniformBuffer(int setNumber, in
auto& dsd = _vDescriptorSetDesc[setNumber];
int at = 0;
if (copyDescOnly)
{
at = dsd._capacity * pRendererD3D12->GetRingBufferIndex();
}
else
{
if (dsd._offset + dsd._alignedSize > dsd._capacityInBytes)
@ -557,14 +589,26 @@ CD3DX12_GPU_DESCRIPTOR_HANDLE ShaderD3D12::UpdateUniformBuffer(int setNumber, in
dsd._index++;
}
auto hpBase = pRendererD3D12->GetViewHeap().GetNextHandlePair();
bool hpBaseUsed = false;
HandlePair hpBase;
if (complexSetHandle >= 0)
{
const auto& complexSet = _vComplexSets[complexSetHandle];
if (!complexSet._dhViews.GetD3DDescriptorHeap())
{
hpBase = complexSet._hpBase;
hpBaseUsed = true;
}
}
if (!hpBaseUsed)
hpBase = pRendererD3D12->GetViewHeap().GetNextHandlePair();
// Copy CBV:
pRendererD3D12->GetD3DDevice()->CopyDescriptorsSimple(1,
hpBase._hCPU,
dsd._dhDynamicOffsets.AtCPU(at),
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
if (complexSetHandle >= 0)
if (complexSetHandle >= 0 && !hpBaseUsed)
{
// Copy SRVs:
const auto& complexSet = _vComplexSets[complexSetHandle];

View File

@ -29,6 +29,11 @@ namespace verus
};
VERUS_TYPEDEFS(Compiled);
enum SET_MOD
{
SET_MOD_TO_VIEW_HEAP = 0x10000
};
private:
typedef Map<String, Compiled> TMapCompiled;
@ -56,6 +61,7 @@ namespace verus
Vector<TexturePtr> _vTextures;
DescriptorHeap _dhViews;
DescriptorHeap _dhSamplers;
HandlePair _hpBase;
};
VERUS_TYPEDEFS(ComplexSet);

View File

@ -390,7 +390,6 @@ void TextureD3D12::GenerateMips(PBaseCommandBuffer pCB)
pCB->BindPipeline(renderer.GetPipelineGenerateMips(!!(_desc._flags & TextureDesc::Flags::exposureMips)));
shader->BeginBindDescriptors();
const bool createComplexSets = _vCshGenerateMips.empty();
int dispatchIndex = 0;
for (int srcMip = 0; srcMip < maxMipLevel;)
{
@ -407,22 +406,15 @@ void TextureD3D12::GenerateMips(PBaseCommandBuffer pCB)
ub._mipLevelCount = dispatchMipCount;
ub._srcDimensionCase = ((srcHeight & 1) << 1) | (srcWidth & 1);
ub._srgb = IsSRGBFormat(_desc._format);
ub._texelSize.x = 1.f / dstWidth;
ub._texelSize.y = 1.f / dstHeight;
ub._dstTexelSize.x = 1.f / dstWidth;
ub._dstTexelSize.y = 1.f / dstHeight;
if (createComplexSets)
{
int mips[5] = {}; // For input texture (always mip 0) and 4 UAV mips.
VERUS_FOR(mip, dispatchMipCount)
mips[mip + 1] = srcMip + mip;
const CSHandle complexSetHandle = shader->BindDescriptorSetTextures(0, { tex, tex, tex, tex, tex }, mips);
_vCshGenerateMips.push_back(complexSetHandle);
pCB->BindDescriptors(shader, 0, complexSetHandle);
}
else
{
pCB->BindDescriptors(shader, 0, _vCshGenerateMips[dispatchIndex]);
}
int mips[5] = {}; // For input texture (always mip 0) and 4 UAV mips.
VERUS_FOR(mip, dispatchMipCount)
mips[mip + 1] = srcMip + mip;
const CSHandle complexSetHandle = shader->BindDescriptorSetTextures(0 | ShaderD3D12::SET_MOD_TO_VIEW_HEAP, { tex, tex, tex, tex, tex }, mips);
_vCshGenerateMips.push_back(complexSetHandle);
pCB->BindDescriptors(shader, 0, complexSetHandle);
pCB->Dispatch(Math::DivideByMultiple(dstWidth, 8), Math::DivideByMultiple(dstHeight, 8));
@ -479,6 +471,7 @@ void TextureD3D12::GenerateMips(PBaseCommandBuffer pCB)
if (_mainLayout != ImageLayout::xsReadOnly)
pCB->PipelineImageMemoryBarrier(tex, ImageLayout::xsReadOnly, _mainLayout, Range(0, _desc._mipLevels));
ClearCshGenerateMips();
Schedule(0);
}
@ -495,6 +488,13 @@ Continue TextureD3D12::Scheduled_Update()
}
_vStagingBuffers.clear();
ClearCshGenerateMips();
return Continue::no;
}
void TextureD3D12::ClearCshGenerateMips()
{
if (!_vCshGenerateMips.empty())
{
VERUS_QREF_RENDERER;
@ -503,8 +503,6 @@ Continue TextureD3D12::Scheduled_Update()
shader->FreeDescriptorSet(csh);
_vCshGenerateMips.clear();
}
return Continue::no;
}
void TextureD3D12::CreateSampler()

View File

@ -42,6 +42,8 @@ namespace verus
// D3D12
//
void ClearCshGenerateMips();
void CreateSampler();
ID3D12Resource* GetD3DResource() const { return _resource._pResource.Get(); }

View File

@ -76,8 +76,8 @@ void CommandBufferVulkan::End()
void CommandBufferVulkan::BeginRenderPass(RPHandle renderPassHandle, FBHandle framebufferHandle, std::initializer_list<Vector4> ilClearValues, bool setViewportAndScissor)
{
VERUS_QREF_RENDERER_VULKAN;
VERUS_QREF_CONST_SETTINGS;
RendererVulkan::RcFramebuffer framebuffer = pRendererVulkan->GetFramebuffer(framebufferHandle);
// The application must ensure (using scissor if necessary) that all rendering is contained within the render area.
VkRenderPassBeginInfo vkrpbi = {};
vkrpbi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
vkrpbi.renderPass = pRendererVulkan->GetRenderPass(renderPassHandle);
@ -94,6 +94,7 @@ void CommandBufferVulkan::BeginRenderPass(RPHandle renderPassHandle, FBHandle fr
}
vkrpbi.clearValueCount = count;
vkrpbi.pClearValues = clearValues;
// There may be a performance cost for using a render area smaller than the framebuffer, unless it matches the render area granularity for the render pass.
vkCmdBeginRenderPass(GetVkCommandBuffer(), &vkrpbi, VK_SUBPASS_CONTENTS_INLINE);
if (setViewportAndScissor)
{

View File

@ -3,6 +3,135 @@
using namespace verus;
VkCompareOp CGI::ToNativeCompareOp(CompareOp compareOp)
{
switch (compareOp)
{
case CompareOp::never: return VK_COMPARE_OP_NEVER;
case CompareOp::less: return VK_COMPARE_OP_LESS;
case CompareOp::equal: return VK_COMPARE_OP_EQUAL;
case CompareOp::lessOrEqual: return VK_COMPARE_OP_LESS_OR_EQUAL;
case CompareOp::greater: return VK_COMPARE_OP_GREATER;
case CompareOp::notEqual: return VK_COMPARE_OP_NOT_EQUAL;
case CompareOp::greaterOrEqual: return VK_COMPARE_OP_GREATER_OR_EQUAL;
case CompareOp::always: return VK_COMPARE_OP_ALWAYS;
default: throw VERUS_RECOVERABLE << "ToNativeCompareOp()";
}
}
uint32_t CGI::ToNativeCubeMapFace(CubeMapFace face)
{
switch (face)
{
case CubeMapFace::posX: return 0;
case CubeMapFace::negX: return 1;
case CubeMapFace::posY: return 2;
case CubeMapFace::negY: return 3;
case CubeMapFace::posZ: return 4;
case CubeMapFace::negZ: return 5;
default: throw VERUS_RECOVERABLE << "ToNativeCubeMapFace()";
}
}
VkPolygonMode CGI::ToNativePolygonMode(PolygonMode polygonMode)
{
switch (polygonMode)
{
case PolygonMode::fill: return VK_POLYGON_MODE_FILL;
case PolygonMode::line: return VK_POLYGON_MODE_LINE;
default: throw VERUS_RECOVERABLE << "ToNativePolygonMode()";
}
}
VkCullModeFlagBits CGI::ToNativeCullMode(CullMode cullMode)
{
switch (cullMode)
{
case CullMode::none: return VK_CULL_MODE_NONE;
case CullMode::front: return VK_CULL_MODE_FRONT_BIT;
case CullMode::back: return VK_CULL_MODE_BACK_BIT;
default: throw VERUS_RECOVERABLE << "ToNativeCullMode()";
}
}
VkPrimitiveTopology CGI::ToNativePrimitiveTopology(PrimitiveTopology primitiveTopology)
{
switch (primitiveTopology)
{
case PrimitiveTopology::pointList: return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
case PrimitiveTopology::lineList: return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
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()";
}
}
VkImageLayout CGI::ToNativeImageLayout(ImageLayout layout)
{
switch (layout)
{
case ImageLayout::undefined: return VK_IMAGE_LAYOUT_UNDEFINED;
case ImageLayout::general: return VK_IMAGE_LAYOUT_GENERAL;
case ImageLayout::colorAttachment: return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
case ImageLayout::depthStencilAttachment: return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
case ImageLayout::depthStencilReadOnly: return VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
case ImageLayout::xsReadOnly: return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
case ImageLayout::fsReadOnly: return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
case ImageLayout::transferSrc: return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
case ImageLayout::transferDst: return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
case ImageLayout::presentSrc: return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
default: throw VERUS_RECOVERABLE << "ToNativeImageLayout()";
}
}
VkShaderStageFlags CGI::ToNativeStageFlags(ShaderStageFlags stageFlags)
{
VkShaderStageFlags ret = 0;
if (stageFlags & ShaderStageFlags::vs)
ret |= VK_SHADER_STAGE_VERTEX_BIT;
if (stageFlags & ShaderStageFlags::hs)
ret |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
if (stageFlags & ShaderStageFlags::ds)
ret |= VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
if (stageFlags & ShaderStageFlags::gs)
ret |= VK_SHADER_STAGE_GEOMETRY_BIT;
if (stageFlags & ShaderStageFlags::fs)
ret |= VK_SHADER_STAGE_FRAGMENT_BIT;
if (stageFlags & ShaderStageFlags::cs)
ret |= VK_SHADER_STAGE_COMPUTE_BIT;
if (stageFlags & ShaderStageFlags::rtrg)
ret |= VK_SHADER_STAGE_RAYGEN_BIT_KHR;
if (stageFlags & ShaderStageFlags::rtah)
ret |= VK_SHADER_STAGE_ANY_HIT_BIT_KHR;
if (stageFlags & ShaderStageFlags::rtch)
ret |= VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
if (stageFlags & ShaderStageFlags::rtm)
ret |= VK_SHADER_STAGE_MISS_BIT_KHR;
if (stageFlags & ShaderStageFlags::rti)
ret |= VK_SHADER_STAGE_INTERSECTION_BIT_KHR;
if (stageFlags & ShaderStageFlags::rtc)
ret |= VK_SHADER_STAGE_CALLABLE_BIT_KHR;
return ret;
}
VkSampleCountFlagBits CGI::ToNativeSampleCount(int sampleCount)
{
switch (sampleCount)
{
case 1: return VK_SAMPLE_COUNT_1_BIT;
case 2: return VK_SAMPLE_COUNT_2_BIT;
case 4: return VK_SAMPLE_COUNT_4_BIT;
case 8: return VK_SAMPLE_COUNT_8_BIT;
case 16: return VK_SAMPLE_COUNT_16_BIT;
case 32: return VK_SAMPLE_COUNT_32_BIT;
case 64: return VK_SAMPLE_COUNT_64_BIT;
default: throw VERUS_RECOVERABLE << "ToNativeSampleCount()";
}
}
VkFormat CGI::ToNativeFormat(Format format)
{
switch (format)
@ -43,121 +172,6 @@ VkFormat CGI::ToNativeFormat(Format format)
}
}
VkCullModeFlagBits CGI::ToNativeCullMode(CullMode cullMode)
{
switch (cullMode)
{
case CullMode::none: return VK_CULL_MODE_NONE;
case CullMode::front: return VK_CULL_MODE_FRONT_BIT;
case CullMode::back: return VK_CULL_MODE_BACK_BIT;
default: throw VERUS_RECOVERABLE << "ToNativeCullMode()";
}
}
VkImageLayout CGI::ToNativeImageLayout(ImageLayout layout)
{
switch (layout)
{
case ImageLayout::undefined: return VK_IMAGE_LAYOUT_UNDEFINED;
case ImageLayout::general: return VK_IMAGE_LAYOUT_GENERAL;
case ImageLayout::colorAttachment: return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
case ImageLayout::depthStencilAttachment: return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
case ImageLayout::depthStencilReadOnly: return VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
case ImageLayout::xsReadOnly: return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
case ImageLayout::fsReadOnly: return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
case ImageLayout::transferSrc: return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
case ImageLayout::transferDst: return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
case ImageLayout::presentSrc: return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
default: throw VERUS_RECOVERABLE << "ToNativeImageLayout()";
}
}
VkPolygonMode CGI::ToNativePolygonMode(PolygonMode polygonMode)
{
switch (polygonMode)
{
case PolygonMode::fill: return VK_POLYGON_MODE_FILL;
case PolygonMode::line: return VK_POLYGON_MODE_LINE;
default: throw VERUS_RECOVERABLE << "ToNativePolygonMode()";
}
}
VkPrimitiveTopology CGI::ToNativePrimitiveTopology(PrimitiveTopology primitiveTopology)
{
switch (primitiveTopology)
{
case PrimitiveTopology::pointList: return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
case PrimitiveTopology::lineList: return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
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()";
}
}
VkSampleCountFlagBits CGI::ToNativeSampleCount(int sampleCount)
{
switch (sampleCount)
{
case 1: return VK_SAMPLE_COUNT_1_BIT;
case 2: return VK_SAMPLE_COUNT_2_BIT;
case 4: return VK_SAMPLE_COUNT_4_BIT;
case 8: return VK_SAMPLE_COUNT_8_BIT;
case 16: return VK_SAMPLE_COUNT_16_BIT;
case 32: return VK_SAMPLE_COUNT_32_BIT;
case 64: return VK_SAMPLE_COUNT_64_BIT;
default: throw VERUS_RECOVERABLE << "ToNativeSampleCount()";
}
}
VkCompareOp CGI::ToNativeCompareOp(CompareOp compareOp)
{
switch (compareOp)
{
case CompareOp::never: return VK_COMPARE_OP_NEVER;
case CompareOp::less: return VK_COMPARE_OP_LESS;
case CompareOp::equal: return VK_COMPARE_OP_EQUAL;
case CompareOp::lessOrEqual: return VK_COMPARE_OP_LESS_OR_EQUAL;
case CompareOp::greater: return VK_COMPARE_OP_GREATER;
case CompareOp::notEqual: return VK_COMPARE_OP_NOT_EQUAL;
case CompareOp::greaterOrEqual: return VK_COMPARE_OP_GREATER_OR_EQUAL;
case CompareOp::always: return VK_COMPARE_OP_ALWAYS;
default: throw VERUS_RECOVERABLE << "ToNativeCompareOp()";
}
}
VkShaderStageFlags CGI::ToNativeStageFlags(ShaderStageFlags stageFlags)
{
VkShaderStageFlags ret = 0;
if (stageFlags & ShaderStageFlags::vs)
ret |= VK_SHADER_STAGE_VERTEX_BIT;
if (stageFlags & ShaderStageFlags::hs)
ret |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
if (stageFlags & ShaderStageFlags::ds)
ret |= VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
if (stageFlags & ShaderStageFlags::gs)
ret |= VK_SHADER_STAGE_GEOMETRY_BIT;
if (stageFlags & ShaderStageFlags::fs)
ret |= VK_SHADER_STAGE_FRAGMENT_BIT;
if (stageFlags & ShaderStageFlags::cs)
ret |= VK_SHADER_STAGE_COMPUTE_BIT;
if (stageFlags & ShaderStageFlags::rtrg)
ret |= VK_SHADER_STAGE_RAYGEN_BIT_KHR;
if (stageFlags & ShaderStageFlags::rtah)
ret |= VK_SHADER_STAGE_ANY_HIT_BIT_KHR;
if (stageFlags & ShaderStageFlags::rtch)
ret |= VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
if (stageFlags & ShaderStageFlags::rtm)
ret |= VK_SHADER_STAGE_MISS_BIT_KHR;
if (stageFlags & ShaderStageFlags::rti)
ret |= VK_SHADER_STAGE_INTERSECTION_BIT_KHR;
if (stageFlags & ShaderStageFlags::rtc)
ret |= VK_SHADER_STAGE_CALLABLE_BIT_KHR;
return ret;
}
int CGI::ToNativeLocation(ViaUsage usage, int usageIndex)
{
// See: https://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/attributes.php
@ -248,17 +262,3 @@ VkFormat CGI::ToNativeFormat(ViaUsage usage, ViaType type, int components)
default: throw VERUS_RECOVERABLE << "ToNativeFormat(); ViaType=?";
}
}
uint32_t CGI::ToNativeCubeMapFace(CubeMapFace face)
{
switch (face)
{
case CubeMapFace::posX: return 0;
case CubeMapFace::negX: return 1;
case CubeMapFace::posY: return 2;
case CubeMapFace::negY: return 3;
case CubeMapFace::posZ: return 4;
case CubeMapFace::negZ: return 5;
default: throw VERUS_RECOVERABLE << "ToNativeCubeMapFace()";
}
}

View File

@ -5,25 +5,25 @@ namespace verus
{
namespace CGI
{
VkFormat ToNativeFormat(Format format);
VkCompareOp ToNativeCompareOp(CompareOp compareOp);
VkCullModeFlagBits ToNativeCullMode(CullMode cullMode);
VkImageLayout ToNativeImageLayout(ImageLayout layout);
uint32_t ToNativeCubeMapFace(CubeMapFace face);
VkPolygonMode ToNativePolygonMode(PolygonMode polygonMode);
VkCullModeFlagBits ToNativeCullMode(CullMode cullMode);
VkPrimitiveTopology ToNativePrimitiveTopology(PrimitiveTopology primitiveTopology);
VkSampleCountFlagBits ToNativeSampleCount(int sampleCount);
VkCompareOp ToNativeCompareOp(CompareOp compareOp);
VkImageLayout ToNativeImageLayout(ImageLayout layout);
VkShaderStageFlags ToNativeStageFlags(ShaderStageFlags stageFlags);
VkSampleCountFlagBits ToNativeSampleCount(int sampleCount);
VkFormat ToNativeFormat(Format format);
int ToNativeLocation(ViaUsage usage, int usageIndex);
VkFormat ToNativeFormat(ViaUsage usage, ViaType type, int components);
uint32_t ToNativeCubeMapFace(CubeMapFace face);
}
}

View File

@ -96,7 +96,7 @@ void PipelineVulkan::Init(RcPipelineDesc desc)
VkPipelineRasterizationStateCreateInfo rasterizationState = {};
rasterizationState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizationState.pNext = &rasterizationLineState;
rasterizationState.depthClampEnable = desc._rasterizationState._depthClampEnable;
rasterizationState.depthClampEnable = VK_FALSE;
rasterizationState.polygonMode = ToNativePolygonMode(desc._rasterizationState._polygonMode);
rasterizationState.cullMode = ToNativeCullMode(desc._rasterizationState._cullMode);
rasterizationState.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;

View File

@ -532,16 +532,18 @@ void RendererVulkan::CreateSwapChain(VkSwapchainKHR oldSwapchain)
if (VK_SUCCESS != (res = vkCreateSwapchainKHR(_device, &vksci, GetAllocator(), &_swapChain)))
throw VERUS_RUNTIME_ERROR << "vkCreateSwapchainKHR(); res=" << res;
vkGetSwapchainImagesKHR(_device, _swapChain, &_swapChainBufferCount, nullptr);
_vSwapChainImages.resize(_swapChainBufferCount);
vkGetSwapchainImagesKHR(_device, _swapChain, &_swapChainBufferCount, _vSwapChainImages.data());
uint32_t swapchainImageCount = _swapChainBufferCount;
vkGetSwapchainImagesKHR(_device, _swapChain, &swapchainImageCount, nullptr);
_vSwapChainImages.resize(swapchainImageCount);
vkGetSwapchainImagesKHR(_device, _swapChain, &swapchainImageCount, _vSwapChainImages.data());
_swapChainBufferCount = swapchainImageCount;
}
void RendererVulkan::CreateImageViews()
{
VkResult res = VK_SUCCESS;
_vSwapChainImageViews.resize(_swapChainBufferCount);
VERUS_U_FOR(i, _swapChainBufferCount)
VERUS_FOR(i, _swapChainBufferCount)
{
VkImageViewCreateInfo vkivci = {};
vkivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
@ -583,7 +585,7 @@ void RendererVulkan::CreateSyncObjects()
VkFenceCreateInfo vkfci = {};
vkfci.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
vkfci.flags = VK_FENCE_CREATE_SIGNALED_BIT;
VERUS_U_FOR(i, s_ringBufferSize)
VERUS_FOR(i, s_ringBufferSize)
{
if (VK_SUCCESS != (res = vkCreateSemaphore(_device, &vksci, GetAllocator(), &_acquireNextImageSemaphores[i])))
throw VERUS_RUNTIME_ERROR << "vkCreateSemaphore(); res=" << res;
@ -821,8 +823,10 @@ void RendererVulkan::BeginFrame(bool present)
throw VERUS_RUNTIME_ERROR << "vkResetFences(); res=" << res;
if (present)
{
if (VK_SUCCESS != (res = vkAcquireNextImageKHR(_device, _swapChain, UINT64_MAX, _acquireNextImageSemaphores[_ringBufferIndex], VK_NULL_HANDLE, &_swapChainBufferIndex)))
uint32_t imageIndex = _swapChainBufferIndex;
if (VK_SUCCESS != (res = vkAcquireNextImageKHR(_device, _swapChain, UINT64_MAX, _acquireNextImageSemaphores[_ringBufferIndex], VK_NULL_HANDLE, &imageIndex)))
throw VERUS_RUNTIME_ERROR << "vkAcquireNextImageKHR(); res=" << res;
_swapChainBufferIndex = imageIndex;
}
vmaSetCurrentFrameIndex(_vmaAllocator, static_cast<uint32_t>(renderer.GetFrameCount()));
@ -878,6 +882,7 @@ void RendererVulkan::Present()
const VkSwapchainKHR swapChains[] = { _swapChain };
const uint32_t imageIndex = _swapChainBufferIndex;
VkPresentInfoKHR vkpi = {};
vkpi.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
if (!_queueFamilyIndices.IsSameQueue())
@ -887,7 +892,7 @@ void RendererVulkan::Present()
}
vkpi.swapchainCount = VERUS_COUNT_OF(swapChains);
vkpi.pSwapchains = swapChains;
vkpi.pImageIndices = &_swapChainBufferIndex;
vkpi.pImageIndices = &imageIndex;
if (VK_SUCCESS != (res = vkQueuePresentKHR(_presentQueue, &vkpi)))
{
if (res != VK_ERROR_OUT_OF_DATE_KHR)
@ -1019,17 +1024,17 @@ RPHandle RendererVulkan::CreateRenderPass(std::initializer_list<RP::Attachment>
struct SubpassMetadata
{
int inputRefIndex = -1;
int colorRefIndex = -1;
int resolveRefIndex = -1;
int depthStencilRefIndex = -1;
int preserveIndex = -1;
int inputRefsOffset = -1;
int colorRefsOffset = -1;
int resolveRefsOffset = -1;
int depthStencilRefOffset = -1;
int preserveOffset = -1;
};
Vector<VkAttachmentReference> vAttachmentRef;
vAttachmentRef.reserve(20);
Vector<uint32_t> vAttachmentIndex;
vAttachmentIndex.reserve(20);
Vector<VkAttachmentReference> vAttachmentRefs;
vAttachmentRefs.reserve(20);
Vector<uint32_t> vAttachmentIndices;
vAttachmentIndices.reserve(20);
Vector<SubpassMetadata> vSubpassMetadata;
vSubpassMetadata.reserve(ilS.size());
@ -1042,61 +1047,61 @@ RPHandle RendererVulkan::CreateRenderPass(std::initializer_list<RP::Attachment>
vksd.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
vksd.inputAttachmentCount = Utils::Cast32(subpass._ilInput.size());
subpassMetadata.inputRefIndex = Utils::Cast32(vAttachmentRef.size());
subpassMetadata.inputRefsOffset = Utils::Cast32(vAttachmentRefs.size());
for (const auto& input : subpass._ilInput)
{
VkAttachmentReference vkar = {};
vkar.attachment = GetAttachmentIndexByName(input._name);
vkar.layout = ToNativeImageLayout(input._layout);
vAttachmentRef.push_back(vkar);
vAttachmentRefs.push_back(vkar);
}
vksd.colorAttachmentCount = Utils::Cast32(subpass._ilColor.size());
subpassMetadata.colorRefIndex = Utils::Cast32(vAttachmentRef.size());
subpassMetadata.colorRefsOffset = Utils::Cast32(vAttachmentRefs.size());
for (const auto& color : subpass._ilColor)
{
VkAttachmentReference vkar = {};
vkar.attachment = GetAttachmentIndexByName(color._name);
vkar.layout = ToNativeImageLayout(color._layout);
vAttachmentRef.push_back(vkar);
vAttachmentRefs.push_back(vkar);
}
if (subpass._depthStencil._name)
{
subpassMetadata.depthStencilRefIndex = Utils::Cast32(vAttachmentRef.size());
subpassMetadata.depthStencilRefOffset = Utils::Cast32(vAttachmentRefs.size());
VkAttachmentReference vkar = {};
vkar.attachment = GetAttachmentIndexByName(subpass._depthStencil._name);
vkar.layout = ToNativeImageLayout(subpass._depthStencil._layout);
vAttachmentRef.push_back(vkar);
vAttachmentRefs.push_back(vkar);
}
vksd.preserveAttachmentCount = Utils::Cast32(subpass._ilPreserve.size());
subpassMetadata.preserveIndex = Utils::Cast32(vAttachmentIndex.size());
subpassMetadata.preserveOffset = Utils::Cast32(vAttachmentIndices.size());
for (const auto& preserve : subpass._ilPreserve)
{
const uint32_t index = GetAttachmentIndexByName(preserve._name);
vAttachmentIndex.push_back(index);
vAttachmentIndices.push_back(index);
}
vSubpassDesc.push_back(vksd);
vSubpassMetadata.push_back(subpassMetadata);
}
// vAttachmentRef is ready, convert indices to actual pointers:
if (vAttachmentRef.empty())
// vAttachmentRefs is ready, convert offsets to actual pointers:
if (vAttachmentRefs.empty())
throw VERUS_RECOVERABLE << "CreateRenderPass(); No attachment references";
int index = 0;
for (auto& sd : vSubpassDesc)
{
const SubpassMetadata& sm = vSubpassMetadata[index];
if (sd.inputAttachmentCount)
sd.pInputAttachments = &vAttachmentRef[sm.inputRefIndex];
sd.pInputAttachments = &vAttachmentRefs[sm.inputRefsOffset];
if (sd.colorAttachmentCount)
sd.pColorAttachments = &vAttachmentRef[sm.colorRefIndex];
if (sm.depthStencilRefIndex >= 0)
sd.pDepthStencilAttachment = &vAttachmentRef[sm.depthStencilRefIndex];
sd.pColorAttachments = &vAttachmentRefs[sm.colorRefsOffset];
if (sm.depthStencilRefOffset >= 0)
sd.pDepthStencilAttachment = &vAttachmentRefs[sm.depthStencilRefOffset];
if (sd.preserveAttachmentCount)
sd.pPreserveAttachments = &vAttachmentIndex[sm.preserveIndex];
sd.pPreserveAttachments = &vAttachmentIndices[sm.preserveOffset];
index++;
}

View File

@ -346,8 +346,8 @@ void TextureVulkan::GenerateMips(PBaseCommandBuffer pCB)
ub._mipLevelCount = dispatchMipCount;
ub._srcDimensionCase = ((srcHeight & 1) << 1) | (srcWidth & 1);
ub._srgb = IsSRGBFormat(_desc._format);
ub._texelSize.x = 1.f / dstWidth;
ub._texelSize.y = 1.f / dstHeight;
ub._dstTexelSize.x = 1.f / dstWidth;
ub._dstTexelSize.y = 1.f / dstHeight;
if (createComplexSets)
{

View File

@ -1,4 +1,4 @@
// Copyright (C) 2021, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#define VERUS_INCLUDE_COMPRESSONATOR
#include <verus.h>

View File

@ -3,8 +3,8 @@
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<IncludePath>C:\Compressonator_4.2.5185\include;C:\Home\Projects\Verus\verus\Verus\src;C:\Home\Middleware\AMD Tootle 2.3\include;C:\Home\Middleware\bullet3-2.89\src;C:\Home\Middleware\bullet3-2.89\Extras;C:\Home\Middleware\libogg-1.3.4\include;C:\Home\Middleware\libvorbis-1.3.7\include;C:\Home\Middleware\openal-soft-1.21.1-bin\include;C:\Home\Middleware\SDL2-2.0.16\include;C:\VulkanSDK\1.2.198.1\Include;$(IncludePath)</IncludePath>
<LibraryPath>C:\Compressonator_4.2.5185\lib\VS2017\x64;C:\Home\Middleware\bullet3-2.89\bin;C:\Home\Middleware\AMD Tootle 2.3\lib;C:\Home\Middleware\libogg-1.3.4\lib;C:\Home\Middleware\libvorbis-1.3.7\lib2;C:\Home\Middleware\openal-soft-1.21.1-bin\libs\Win64;C:\Home\Middleware\SDL2-2.0.16\lib\x64;C:\VulkanSDK\1.2.198.1\Lib;$(LibraryPath)</LibraryPath>
<IncludePath>C:\Compressonator_4.2.5185\include;C:\Home\Projects\Verus\verus\Verus\src;C:\Home\Middleware\AMD Tootle 2.3\include;C:\Home\Middleware\bullet3-2.89\src;C:\Home\Middleware\bullet3-2.89\Extras;C:\Home\Middleware\libogg-1.3.4\include;C:\Home\Middleware\libvorbis-1.3.7\include;C:\Home\Middleware\openal-soft-1.21.1-bin\include;C:\Home\Middleware\SDL2-2.0.16\include;C:\VulkanSDK\1.3.204.1\Include;$(IncludePath)</IncludePath>
<LibraryPath>C:\Compressonator_4.2.5185\lib\VS2017\x64;C:\Home\Middleware\bullet3-2.89\bin;C:\Home\Middleware\AMD Tootle 2.3\lib;C:\Home\Middleware\libogg-1.3.4\lib;C:\Home\Middleware\libvorbis-1.3.7\lib2;C:\Home\Middleware\openal-soft-1.21.1-bin\libs\Win64;C:\Home\Middleware\SDL2-2.0.16\lib\x64;C:\VulkanSDK\1.3.204.1\Lib;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup />
<ItemGroup />

View File

@ -814,7 +814,7 @@ void Skeleton::AdaptBindPoseOf(RcSkeleton that)
continue;
vd /= ld;
vs /= ls;
const Matrix3 matWorldR = Matrix3::MakeRotateTo(vd, vs);
const Matrix3 matWorldR = Matrix3::MakeTrackTo(vd, vs);
const Point3 offset = pParentDst->_matFromBoneSpace * origin;
const Transform3 matToBoneOrigin = Transform3::translation(-Vector3(offset));
@ -836,7 +836,7 @@ void Skeleton::SimpleIK(CSZ boneDriven, CSZ boneDriver, RcVector3 dirDriverSpace
}
Vector3 dirDesired = dirDesiredMeshSpace;
dirDesired.LimitDot(dirActual, limitDot);
const Matrix3 matR = Matrix3::MakeRotateTo(
const Matrix3 matR = Matrix3::MakeTrackTo(
dirActual,
VMath::normalizeApprox(VMath::lerp(alpha, dirActual, dirDesired)));
const Matrix3 matDrivenFrom = pBoneDriven->_matFinal.getUpper3x3() * pBoneDriven->_matFromBoneSpace.getUpper3x3();
@ -943,7 +943,7 @@ void Skeleton::ProcessKinectData(const BYTE* p, RMotion motion, int frame)
const Vector3 kinePoseDir = VMath::normalize(bone._matExternal.getTranslation() - kinePosePos);
Matrix3 matR3;
matR3.RotateTo(bindPoseDir, kinePoseDir);
matR3.TrackTo(bindPoseDir, kinePoseDir);
const Transform3 matR(matR3, Vector3(0));
const Transform3 matT = Transform3::translation(kinePosePos - bindPosePos);
const Transform3 matOffset = Transform3::translation(kinePosePos);

View File

@ -28,9 +28,9 @@ namespace verus
protected:
Vector<PScheduled> _vScheduled;
BaseRendererDesc _desc;
UINT32 _swapChainBufferCount = 0;
UINT32 _swapChainBufferIndex = 0;
UINT32 _ringBufferIndex = 0;
int _swapChainBufferCount = 0;
int _swapChainBufferIndex = 0;
int _ringBufferIndex = 0;
BaseRenderer();
virtual ~BaseRenderer();
@ -43,9 +43,9 @@ namespace verus
void SetDesc(RBaseRendererDesc desc) { _desc = desc; }
UINT32 GetSwapChainBufferCount() const { return _swapChainBufferCount; }
UINT32 GetSwapChainBufferIndex() const { return _swapChainBufferIndex; }
UINT32 GetRingBufferIndex() const { return _ringBufferIndex; }
int GetSwapChainBufferCount() const { return _swapChainBufferCount; }
int GetSwapChainBufferIndex() const { return _swapChainBufferIndex; }
int GetRingBufferIndex() const { return _ringBufferIndex; }
void Schedule(PScheduled p);
void Unschedule(PScheduled p);

View File

@ -20,7 +20,9 @@ bool BaseTexture::IsSRGB() const
return
!Str::EndsWith(_C(_name), ".NM.dds") &&
!Str::EndsWith(_C(_name), ".FX.dds") &&
!Str::EndsWith(_C(_name), ".H.dds");
!Str::EndsWith(_C(_name), ".H.dds") &&
!Str::EndsWith(_C(_name), ".N.dds") &&
!Str::EndsWith(_C(_name), ".X.dds");
}
void BaseTexture::LoadDDS(CSZ url, int texturePart)

View File

@ -5,6 +5,37 @@ namespace verus
{
namespace CGI
{
enum class CompareOp : int
{
never,
less, // <
equal, // ==
lessOrEqual, // <=
greater, // >
notEqual, // !=
greaterOrEqual, // >=
always
};
enum class CubeMapFace : int
{
posX,
negX,
posY,
negY,
posZ,
negZ,
count,
all,
none = -1
};
enum class PolygonMode : int
{
fill,
line
};
enum class CullMode : int
{
none,
@ -12,6 +43,27 @@ namespace verus
back
};
struct PipelineRasterizationState
{
PolygonMode _polygonMode = PolygonMode::fill;
CullMode _cullMode = CullMode::back;
float _depthBiasConstantFactor = 0;
float _depthBiasClamp = 0;
float _depthBiasSlopeFactor = 0;
bool _depthBiasEnable = false;
};
enum class PrimitiveTopology : int
{
pointList,
lineList,
lineStrip,
triangleList,
triangleStrip,
patchList3,
patchList4
};
enum class ImageLayout : int
{
undefined, // Does not support device access, the contents of the memory are not guaranteed to be preserved.
@ -26,44 +78,25 @@ namespace verus
presentSrc // Must only be used for presenting a presentable image for display.
};
enum class PolygonMode : int
enum class Sampler : int
{
fill,
line
};
enum class PrimitiveTopology : int
{
pointList,
lineList,
lineStrip,
triangleList,
triangleStrip,
patchList3,
patchList4
};
struct PipelineRasterizationState
{
PolygonMode _polygonMode = PolygonMode::fill;
CullMode _cullMode = CullMode::back;
float _depthBiasConstantFactor = 0;
float _depthBiasClamp = 0;
float _depthBiasSlopeFactor = 0;
bool _depthClampEnable = false;
bool _depthBiasEnable = false;
};
enum class CompareOp : int
{
never,
less,
equal,
lessOrEqual,
greater,
notEqual,
greaterOrEqual,
always,
custom, // Not immutable, not static sampler.
input,
storage, // Also known as UAV.
lodBias,
shadow,
aniso, // Most common sampler for 3D.
anisoClamp,
anisoSharp, // For UI.
linearMipL,
nearestMipL,
linearMipN,
nearestMipN,
linearClampMipL,
nearestClampMipL,
linearClampMipN,
nearestClampMipN,
count
};
enum class ShaderStageFlags : UINT32
@ -131,40 +164,6 @@ namespace verus
};
VERUS_TYPEDEFS(VertexInputAttrDesc);
enum class Sampler : int
{
custom, // Not immutable, not static sampler.
input,
storage, // Also known as UAV.
lodBias,
shadow,
aniso, // Most common sampler for 3D.
anisoClamp,
anisoSharp, // For UI.
linearMipL,
nearestMipL,
linearMipN,
nearestMipN,
linearClampMipL,
nearestClampMipL,
linearClampMipN,
nearestClampMipN,
count
};
enum class CubeMapFace : int
{
posX,
negX,
posY,
negY,
posZ,
negZ,
count,
all,
none = -1
};
template<typename T>
class BaseHandle
{

View File

@ -316,7 +316,7 @@ void Particles::Update()
}
Matrix3 matAim3;
matAim3.AimZ(normal, &up);
matAim3.TrackToZ(normal, &up);
Transform3 matAim(matAim3, Vector3(0));
VERUS_FOR(i, _capacity)
@ -750,7 +750,7 @@ Transform3 Particles::GetBillboardMatrix(int index, float size, float spin, RcVe
if (_decal)
{
Matrix3 matAim3;
matAim3.AimZ(-normal2, &up2);
matAim3.TrackToZ(-normal2, &up2);
matAim = Transform3(matAim3, Vector3(0));
}
else
@ -759,7 +759,7 @@ Transform3 Particles::GetBillboardMatrix(int index, float size, float spin, RcVe
const Vector3 right = VMath::cross(up2, normal2);
normal2 = VMath::normalizeApprox(VMath::cross(right, up2));
Matrix3 matAim3;
matAim3.AimZ(normal2, &up2);
matAim3.TrackToZ(normal2, &up2);
matAim = Transform3(matAim3, Vector3(0));
}
}

View File

@ -109,11 +109,15 @@ void Ssr::OnSwapChainResized()
void Ssr::Generate()
{
VERUS_QREF_CONST_SETTINGS;
VERUS_QREF_RENDERER;
VERUS_QREF_SM;
VERUS_QREF_SSAO;
VERUS_QREF_ATMO;
if (!settings._postProcessSSR)
return;
if (!_csh.IsSet())
{
if (atmo.GetCubeMapBaker().GetColorTexture())

View File

@ -281,7 +281,7 @@ float BaseCharacter::ComputeThirdPersonCamera(Scene::RCamera camera, Anim::RcOrb
// Consider orientation:
Matrix3 matFromRaySpace;
matFromRaySpace.AimZ(toEye);
matFromRaySpace.TrackToZ(toEye);
Matrix3 matToRaySpace = VMath::transpose(matFromRaySpace);
toEye = (matFromRaySpace * orbit.GetMatrix() * matToRaySpace) * toEye;

View File

@ -13,29 +13,29 @@ Timer::~Timer()
void Timer::Init()
{
const TTimePoint timeNow = std::chrono::high_resolution_clock::now();
_tpInit = std::chrono::high_resolution_clock::now();
for (auto& data : _data)
{
data._t = data._dt = 0;
data._timePrev = timeNow;
data._tpPrev = _tpInit;
}
}
void Timer::Update()
{
const TTimePoint timeNow = std::chrono::high_resolution_clock::now();
const TTimePoint tpNow = std::chrono::high_resolution_clock::now();
VERUS_FOR(i, +Type::count)
{
_data[i]._dtPrev = _data[i]._dt;
_data[i]._dt = std::chrono::duration_cast<std::chrono::duration<float>>(
timeNow - _data[i]._timePrev).count() * GetGameSpeed(static_cast<Type>(i));
tpNow - _data[i]._tpPrev).count() * GetGameSpeed(static_cast<Type>(i));
if (_data[i]._dt > 0.25f) // Prevent long gaps.
_data[i]._dt = 0.25f;
_data[i]._t += _data[i]._dt;
_data[i]._timePrev2 = _data[i]._timePrev;
_data[i]._timePrev = timeNow;
_data[i]._tpPrev2 = _data[i]._tpPrev;
_data[i]._tpPrev = tpNow;
_data[i]._dtInv = _data[i]._dt > 0.0001f ? 1 / _data[i]._dt : 10000;
_data[i]._dtSq = _data[i]._dt * _data[i]._dt;
@ -54,11 +54,17 @@ void Timer::Update()
bool Timer::IsEventEvery(int ms) const
{
auto a = std::chrono::duration_cast<std::chrono::milliseconds>(_data[+Type::game]._timePrev.time_since_epoch());
auto b = std::chrono::duration_cast<std::chrono::milliseconds>(_data[+Type::game]._timePrev2.time_since_epoch());
auto a = std::chrono::duration_cast<std::chrono::milliseconds>(_data[+Type::game]._tpPrev.time_since_epoch());
auto b = std::chrono::duration_cast<std::chrono::milliseconds>(_data[+Type::game]._tpPrev2.time_since_epoch());
return a.count() / ms != b.count() / ms;
}
float Timer::GetTime() const
{
const TTimePoint tpNow = std::chrono::high_resolution_clock::now();
return std::chrono::duration_cast<std::chrono::duration<float>>(tpNow - _tpInit).count();
}
int Timer::InsertCountdown(float duration, int existingID)
{
const int count = Utils::Cast32(_vCountdowns.size());

View File

@ -25,8 +25,8 @@ namespace verus
struct Data
{
TTimePoint _timePrev;
TTimePoint _timePrev2;
TTimePoint _tpPrev;
TTimePoint _tpPrev2;
double _t = 0;
float _dt = 0;
float _dtInv = 0;
@ -38,6 +38,7 @@ namespace verus
bool _pause = false;
};
TTimePoint _tpInit;
Vector<Countdown> _vCountdowns;
Data _data[static_cast<int>(Type::count)];
@ -50,7 +51,8 @@ namespace verus
bool IsEventEvery(int ms) const;
float GetTime(Type type = Type::game) const { return static_cast<float>(_data[+type]._t); }
float GetTime() const;
float GetAccumulatedTime(Type type = Type::game) const { return static_cast<float>(_data[+type]._t); }
float GetDeltaTime(Type type = Type::game) const { return _data[+type]._dt; }
float GetGameSpeed(Type type = Type::game) const { return _data[+type]._pause ? 0 : _data[+type]._gameSpeed; }
void SetGameSpeed(float speed, Type type = Type::game) { _data[+type]._gameSpeed = speed; }
@ -88,5 +90,5 @@ namespace verus
VERUS_TYPEDEFS(PerfTimer);
}
#define VERUS_PERF_BEGIN Utils::PerfTimer perfTimer; perfTimer.Begin();
#define VERUS_PERF_END perfTimer.End(__FUNCTION__);
#define VERUS_PERF_BEGIN Utils::PerfTimer perfTimer; perfTimer.Begin();
#define VERUS_PERF_END perfTimer.End(__FUNCTION__);

View File

@ -1,6 +1,8 @@
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#pragma once
// Remember kids, unsigned integers are bad, mkay?
#define FALSE 0
#define TRUE 1
typedef int BOOL;

View File

@ -490,8 +490,8 @@ void Math::Test()
{
const Vector3 a(0, 0, 1), b(0, 0, -1), c(0, 1, 0);
Matrix3 ab, ac;
ab.RotateTo(a, b);
ac.RotateTo(a, c);
ab.TrackTo(a, b);
ac.TrackTo(a, c);
const Vector3 k = ab * a;
const Vector3 l = ac * a;
VERUS_RT_ASSERT(

View File

@ -38,56 +38,57 @@ bool Matrix3::IsOrthogonal(float e) const
glm::epsilonEqual<float>(dotZX, 0, e);
}
Matrix3 Matrix3::MakeAimZ(RcVector3 zAxis, PcVector3 pUp)
Matrix3 Matrix3::MakeTrackToZ(RcVector3 zAxis, PcVector3 pUp)
{
if (zAxis.IsZero())
return Matrix3::identity();
const Vector3 zNorm = VMath::normalizeApprox(zAxis);
if (zNorm.getY() > 0.999f)
return Matrix3::rotationX(-VERUS_PI * 0.5f);
if (zNorm.getY() < -0.999f)
return Matrix3::rotationX(VERUS_PI * 0.5f);
Vector3 up = pUp ? *pUp : Vector3(0, 1, 0);
const float d = VMath::dot(zNorm, up);
if (d + VERUS_FLOAT_THRESHOLD >= 1) // Same?
{
up = -zAxis.Perpendicular();
}
else if (d - VERUS_FLOAT_THRESHOLD < -1) // Opposite?
{
up = zAxis.Perpendicular();
}
return VMath::transpose(
Matrix4::lookAt(Point3(0), Point3(-zAxis), pUp ? *pUp : Vector3(0, 1, 0)).getUpper3x3());
Matrix4::lookAt(Point3(0), Point3(-zAxis), up).getUpper3x3());
}
Matrix3 Matrix3::AimZ(RcVector3 zAxis, PcVector3 pUp)
Matrix3 Matrix3::TrackToZ(RcVector3 zAxis, PcVector3 pUp)
{
*this = MakeAimZ(zAxis, pUp);
*this = MakeTrackToZ(zAxis, pUp);
return *this;
}
Matrix3 Matrix3::MakeRotateTo(RcVector3 v0, RcVector3 v1)
Matrix3 Matrix3::MakeTrackTo(RcVector3 vFrom, RcVector3 vTo)
{
const float e = 1e-6f;
Quat q;
const float d = VMath::dot(v0, v1);
if (d >= 1 - e)
const float d = VMath::dot(vFrom, vTo);
if (d + VERUS_FLOAT_THRESHOLD >= 1) // Same?
{
return Matrix3::identity();
}
if (d < e - 1)
else if (d - VERUS_FLOAT_THRESHOLD < -1) // Opposite?
{
Vector3 axis = VMath::cross(Vector3(1, 0, 0), v0);
if (VMath::lengthSqr(axis) < e * e)
axis = VMath::cross(Vector3(0, 1, 0), v0);
axis = VMath::normalize(axis);
q = Quat::rotation(VERUS_PI, axis);
q = Quat::rotation(VERUS_PI, vFrom.Perpendicular());
}
else
{
const float s = sqrt((1 + d) * 2);
const float invs = 1 / s;
const Vector3 c = VMath::cross(v0, v1);
const Vector3 c = VMath::cross(vFrom, vTo);
q = Quat(c * invs, s * 0.5f);
q = VMath::normalize(q);
}
return Matrix3(q);
}
Matrix3 Matrix3::RotateTo(RcVector3 v0, RcVector3 v1)
Matrix3 Matrix3::TrackTo(RcVector3 vFrom, RcVector3 vTo)
{
*this = MakeRotateTo(v0, v1);
*this = MakeTrackTo(vFrom, vTo);
return *this;
}

View File

@ -19,10 +19,12 @@ namespace verus
bool IsOrthogonal(float e = VERUS_FLOAT_THRESHOLD) const;
static Matrix3 MakeAimZ(RcVector3 zAxis, PcVector3 pUp = nullptr);
Matrix3 AimZ(RcVector3 zAxis, PcVector3 pUp = nullptr);
static Matrix3 MakeRotateTo(RcVector3 v0, RcVector3 v1);
Matrix3 RotateTo(RcVector3 v0, RcVector3 v1);
// More stable than Quat::rotation(), tries to maintain the up vector:
static Matrix3 MakeTrackToZ(RcVector3 zAxis, PcVector3 pUp = nullptr);
Matrix3 TrackToZ(RcVector3 zAxis, PcVector3 pUp = nullptr);
// More stable than Quat::rotation(), perpendicular vector is somewhat random:
static Matrix3 MakeTrackTo(RcVector3 vFrom, RcVector3 vTo);
Matrix3 TrackTo(RcVector3 vFrom, RcVector3 vTo);
static Matrix3 Lerp(const Matrix3& a, const Matrix3& b, float t);
};

View File

@ -140,6 +140,14 @@ Vector3 Vector3::Reflect(RcVector3 normal, float bounce) const
return (*this) - normal * ((1 + bounce) * VMath::dot(*this, normal));
}
Vector3 Vector3::Perpendicular() const
{
Vector3 axis = VMath::cross(Vector3(1, 0, 0), (*this));
if (VMath::lengthSqr(axis) < VERUS_FLOAT_THRESHOLD * VERUS_FLOAT_THRESHOLD)
axis = VMath::cross(Vector3(0, 1, 0), (*this));
return axis;
}
// Vector4:
Vector4 Vector4::MakeFromPointer(const float* p)

View File

@ -58,6 +58,8 @@ namespace verus
void LimitDot(const Vector3& v, float d);
Vector3 Reflect(const Vector3& normal, float bounce = 1) const;
Vector3 Perpendicular() const;
};
VERUS_TYPEDEFS(Vector3);

View File

@ -285,7 +285,7 @@ void BaseMesh::LoadX3D3(RcBlob blob)
sp >> index;
pVB[i]._pos[3] = index;
}
_rigidSkeleton = true;
_robotic = true;
}
break;
default:
@ -479,6 +479,13 @@ void BaseMesh::RecalculateTangentSpace()
}
}
int BaseMesh::GetPipelineIndex(bool instanced) const
{
if (_skeleton.IsInitialized())
return _robotic ? 2 : 3;
return instanced ? 1 : 0;
}
btBvhTriangleMeshShape* BaseMesh::InitShape(RcTransform3 tr, CSZ url)
{
if (!_vertCount)

View File

@ -56,7 +56,7 @@ namespace verus
float _tc0Deq[4];
float _tc1Deq[4];
bool _loadOnly = false;
bool _rigidSkeleton = false;
bool _robotic = false;
bool _initShape = false;
public:
@ -112,6 +112,7 @@ namespace verus
// GPU:
virtual void CreateDeviceBuffers() {}
virtual void UpdateVertexBuffer(const void* p, int binding) {}
int GetPipelineIndex(bool instanced = false) const;
// Physics:
btBvhTriangleMeshShape* GetShape() const { return _pShape; }

View File

@ -6,6 +6,7 @@ using namespace verus::Scene;
LightMapBaker::LightMapBaker()
{
VERUS_ZERO_MEM(_queuedCount);
}
LightMapBaker::~LightMapBaker()
@ -17,11 +18,15 @@ void LightMapBaker::Init(RcDesc desc)
{
VERUS_INIT();
VERUS_QREF_RENDERER;
VERUS_QREF_TIMER;
_desc = desc;
_pathname = desc._pathname;
_desc._pathname = nullptr;
_stats = Stats();
_stats._startTime = timer.GetTime();
_currentI = 0;
_currentJ = 0;
@ -77,8 +82,8 @@ void LightMapBaker::Init(RcDesc desc)
_rph = renderer->CreateRenderPass(
{
CGI::RP::Attachment("Color", CGI::Format::unormR8).LoadOpClear().Layout(CGI::ImageLayout::fsReadOnly),
CGI::RP::Attachment("Depth", CGI::Format::unormD16).LoadOpClear().Layout(CGI::ImageLayout::depthStencilAttachment),
CGI::RP::Attachment("Color", CGI::Format::floatR32).LoadOpClear().Layout(CGI::ImageLayout::fsReadOnly),
CGI::RP::Attachment("Depth", CGI::Format::unormD24uintS8).LoadOpClear().Layout(CGI::ImageLayout::depthStencilAttachment),
},
{
CGI::RP::Subpass("Sp0").Color(
@ -88,37 +93,95 @@ void LightMapBaker::Init(RcDesc desc)
},
{});
{
CGI::PipelineDesc pipeDesc(renderer.GetGeoQuad(), renderer.GetShaderQuad(), "#HemicubeMask", _rph);
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_MUL;
pipeDesc._topology = CGI::PrimitiveTopology::triangleStrip;
pipeDesc.DisableDepthTest();
_pipe[PIPE_HEMICUBE_MASK].Init(pipeDesc);
}
{
CGI::PipelineDesc pipeDesc(renderer.GetGeoQuad(), renderer.GetShaderQuad(), "#", renderer.GetRenderPassHandle_AutoWithDepth());
pipeDesc._topology = CGI::PrimitiveTopology::triangleStrip;
pipeDesc.DisableDepthTest();
_pipe[PIPE_QUAD].Init(pipeDesc);
}
CGI::TextureDesc texDesc;
texDesc._name = "LightMapBaker.ColorTex";
texDesc._clearValue = Vector4::Replicate(1);
texDesc._format = CGI::Format::unormR8;
texDesc._width = _desc._texLumelSide;
texDesc._height = _desc._texLumelSide;
texDesc._mipLevels = 0;
texDesc._flags = CGI::TextureDesc::Flags::colorAttachment | CGI::TextureDesc::Flags::generateMips;
texDesc._readbackMip = -1;
_tex[TEX_COLOR].Init(texDesc);
texDesc.Reset();
texDesc._name = "LightMapBaker.DepthTex";
texDesc._clearValue = Vector4(1);
texDesc._format = CGI::Format::unormD16;
texDesc._format = CGI::Format::unormD24uintS8;
texDesc._width = _desc._texLumelSide;
texDesc._height = _desc._texLumelSide;
_tex[TEX_DEPTH].Init(texDesc);
texDesc.Reset();
texDesc._name = "LightMapBaker.Dummy";
texDesc._format = CGI::Format::unormR8G8B8A8;
texDesc._width = 16;
texDesc._height = 16;
_tex[TEX_DUMMY].Init(texDesc);
_fbh = renderer->CreateFramebuffer(_rph,
VERUS_FOR(ringBufferIndex, CGI::BaseRenderer::s_ringBufferSize)
{
VERUS_FOR(batchIndex, s_batchSize)
{
_tex[TEX_COLOR],
_tex[TEX_DEPTH]
},
_desc._texLumelSide,
_desc._texLumelSide);
CGI::TextureDesc texDesc;
texDesc._name = "LightMapBaker.ColorTex";
texDesc._clearValue = Vector4::Replicate(1);
texDesc._format = CGI::Format::floatR32;
texDesc._width = _desc._texLumelSide;
texDesc._height = _desc._texLumelSide;
texDesc._mipLevels = 0;
texDesc._flags = CGI::TextureDesc::Flags::colorAttachment | CGI::TextureDesc::Flags::generateMips;
texDesc._readbackMip = -1;
_texColor[ringBufferIndex][batchIndex].Init(texDesc);
}
_cshQuad[ringBufferIndex] = renderer.GetShaderQuad()->BindDescriptorSetTextures(1, { _texColor[ringBufferIndex][0] });
}
_cshHemicubeMask = renderer.GetShaderQuad()->BindDescriptorSetTextures(1, { _tex[TEX_DUMMY] });
VERUS_FOR(ringBufferIndex, CGI::BaseRenderer::s_ringBufferSize)
{
VERUS_FOR(batchIndex, s_batchSize)
{
CGI::TexturePtr tex = _texColor[ringBufferIndex][batchIndex];
_fbh[ringBufferIndex][batchIndex] = renderer->CreateFramebuffer(_rph,
{
tex,
_tex[TEX_DEPTH]
},
_desc._texLumelSide,
_desc._texLumelSide);
// Define texture:
renderer.GetCommandBuffer()->BeginRenderPass(_rph, _fbh[ringBufferIndex][batchIndex],
{
tex->GetClearValue(),
_tex[TEX_DEPTH]->GetClearValue()
});
renderer.GetCommandBuffer()->EndRenderPass();
tex->GenerateMips();
}
_vQueued[ringBufferIndex].resize(s_batchSize);
}
_drawEmptyState = CGI::BaseRenderer::s_ringBufferSize + 1;
}
void LightMapBaker::Done()
{
VERUS_QREF_RENDERER;
renderer->DeleteFramebuffer(_fbh);
if (renderer.GetShaderQuad())
{
VERUS_FOR(ringBufferIndex, CGI::BaseRenderer::s_ringBufferSize)
renderer.GetShaderQuad()->FreeDescriptorSet(_cshQuad[ringBufferIndex]);
renderer.GetShaderQuad()->FreeDescriptorSet(_cshHemicubeMask);
}
VERUS_FOR(ringBufferIndex, CGI::BaseRenderer::s_ringBufferSize)
{
VERUS_FOR(batchIndex, s_batchSize)
renderer->DeleteFramebuffer(_fbh[ringBufferIndex][batchIndex]);
}
renderer->DeleteRenderPass(_rph);
VERUS_DONE(LightMapBaker);
}
@ -127,42 +190,251 @@ void LightMapBaker::Update()
{
if (!IsInitialized() || !IsBaking())
return;
VERUS_FOR(rep, _repsPerUpdate)
if (_drawEmptyState)
{
if (_currentI == _desc._texHeight)
if (CGI::BaseRenderer::s_ringBufferSize + 1 == _drawEmptyState)
DrawEmpty();
_drawEmptyState--;
if (!_drawEmptyState)
{
Save();
_desc._mode = Mode::idle;
break;
float value = 0;
_texColor[0][0]->ReadbackSubresource(&value, false);
_normalizationFactor = 1 / value;
}
else
{
return;
}
}
_currentUV = glm::vec2(
(_currentJ + 0.5f) / _desc._texWidth,
(_currentI + 0.5f) / _desc._texHeight);
VERUS_QREF_RENDERER;
_quadtree.TraverseVisible(_currentUV);
const int ringBufferIndex = renderer->GetRingBufferIndex();
auto NextLumel = [this]()
{
_currentJ++;
if (_currentJ == _desc._texWidth)
{
_currentJ = 0;
_currentI++;
}
};
int& queuedCount = _queuedCount[ringBufferIndex];
if (queuedCount > 0) // Was there anything queued?
{
VERUS_FOR(i, queuedCount)
{
float value = 0;
_texColor[ringBufferIndex][i]->ReadbackSubresource(&value, false);
const BYTE value8 = Convert::UnormToUint8(Math::Clamp<float>(value * _normalizationFactor, 0, 1));
BYTE* pDst = reinterpret_cast<BYTE*>(_vQueued[ringBufferIndex][i]._pDst);
VERUS_FOR(j, 3)
pDst[j] = Math::Max(pDst[j], value8);
pDst[3] = 0xFF;
}
}
// Clear queued:
memset(_vQueued[ringBufferIndex].data(), 0, sizeof(Queued) * s_batchSize);
queuedCount = 0;
if (_currentI >= _desc._texHeight)
{
bool finish = true;
VERUS_FOR(ringBufferIndex, CGI::BaseRenderer::s_ringBufferSize)
{
if (_queuedCount[ringBufferIndex])
{
finish = false;
break;
}
}
if (finish)
{
ComputeEdgePadding();
Save();
_desc._mode = Mode::idle;
}
return;
}
VERUS_FOR(rep, _repsPerUpdate)
{
// Fill queue:
int& queuedCount = _queuedCount[ringBufferIndex];
VERUS_RT_ASSERT(!queuedCount);
while (queuedCount + s_maxLayers <= s_batchSize) // Enough space for this lumel?
{
_currentUV = glm::vec2(
(_currentJ + 0.5f) / _desc._texWidth,
(_currentI + 0.5f) / _desc._texHeight);
_currentLayer = 0;
_quadtree.TraverseVisible(_currentUV);
_stats._maxLayer = Math::Max<int>(_stats._maxLayer, _currentLayer);
NextLumel();
if (_currentI >= _desc._texHeight)
break; // No more lumels.
}
// Draw queue:
VERUS_FOR(i, queuedCount)
{
RQueued queued = _vQueued[ringBufferIndex][i];
DrawLumel(queued._pos, queued._nrm, i);
}
}
const int progressPrev = static_cast<int>(_stats._progress * 100);
_stats._progress = Math::Clamp<float>((_currentI * _desc._texWidth + _currentJ) * _invMapSize, 0, 1);
const int progressNext = static_cast<int>(_stats._progress * 100);
if (progressPrev != progressNext)
{
VERUS_QREF_TIMER;
const float elapsedTime = timer.GetTime() - _stats._startTime;
char buffer[80];
sprintf_s(buffer, "Elapsed time: %.1fs, max layer: %d, progress: %.1f%%", elapsedTime, _stats._maxLayer, _stats._progress * 100);
_stats._info = buffer;
}
_progress = Math::Clamp<float>((_currentI * _desc._texWidth + _currentJ) * _invMapSize, 0, 1);
}
void LightMapBaker::DrawLumel(RcPoint3 eyePos, RcVector3 frontDir)
void LightMapBaker::Draw()
{
if (!IsInitialized() || !IsBaking())
return;
VERUS_QREF_RENDERER;
renderer.GetCommandBuffer()->BeginRenderPass(_rph, _fbh,
const int ringBufferIndex = renderer->GetRingBufferIndex();
auto cb = renderer.GetCommandBuffer();
auto shader = renderer.GetShaderQuad();
cb->BindPipeline(_pipe[PIPE_QUAD]);
shader->BeginBindDescriptors();
cb->BindDescriptors(shader, 0);
cb->BindDescriptors(shader, 1, _cshQuad[ringBufferIndex]);
shader->EndBindDescriptors();
renderer.DrawQuad(cb.Get());
}
void LightMapBaker::DrawEmpty()
{
// Let's compute normalization factor by drawing an empty scene.
VERUS_QREF_RENDERER;
auto cb = renderer.GetCommandBuffer();
CGI::TexturePtr tex = _texColor[0][0];
cb->BeginRenderPass(_rph, _fbh[0][0],
{
_tex[TEX_COLOR]->GetClearValue(),
tex->GetClearValue(),
_tex[TEX_DEPTH]->GetClearValue()
});
renderer.GetCommandBuffer()->EndRenderPass();
DrawHemicubeMask();
cb->EndRenderPass();
tex->GenerateMips();
tex->ReadbackSubresource(nullptr);
}
void LightMapBaker::DrawHemicubeMask()
{
VERUS_QREF_RENDERER;
auto cb = renderer.GetCommandBuffer();
auto shader = renderer.GetShaderQuad();
const float side = static_cast<float>(_desc._texLumelSide);
cb->BindPipeline(_pipe[PIPE_HEMICUBE_MASK]);
cb->SetViewport({ Vector4(0, 0, side, side) });
shader->BeginBindDescriptors();
cb->BindDescriptors(shader, 0);
cb->BindDescriptors(shader, 1, _cshHemicubeMask);
shader->EndBindDescriptors();
renderer.DrawQuad(cb.Get());
}
void LightMapBaker::DrawLumel(RcPoint3 pos, RcVector3 nrm, int batchIndex)
{
VERUS_QREF_RENDERER;
VERUS_QREF_SM;
const int ringBufferIndex = renderer->GetRingBufferIndex();
auto cb = renderer.GetCommandBuffer();
auto shader = renderer.GetShaderQuad();
CGI::TexturePtr tex = _texColor[ringBufferIndex][batchIndex];
cb->BeginRenderPass(_rph, _fbh[ringBufferIndex][batchIndex],
{
tex->GetClearValue(),
_tex[TEX_DEPTH]->GetClearValue()
});
if (_pDelegate)
{
const glm::vec2 randVec = glm::circularRand(1.f);
const Matrix3 m3 = Matrix3::MakeTrackTo(Vector3(0, 0, 1), nrm);
const Vector3 perpVecA = m3 * Vector3(randVec.x, randVec.y, 0); // Up.
const Vector3 perpVecB = VMath::cross(perpVecA, nrm); // Side.
DrawLumelDesc drawLumelDesc;
drawLumelDesc._eyePos = pos;
drawLumelDesc._frontDir = nrm;
_pDelegate->LightMapBaker_Draw(CGI::CubeMapFace::none, drawLumelDesc);
VERUS_FOR(i, 5)
{
const CGI::CubeMapFace cubeMapFace = static_cast<CGI::CubeMapFace>(i);
Camera cam;
cam.MoveEyeTo(drawLumelDesc._eyePos);
switch (cubeMapFace)
{
case CGI::CubeMapFace::posX:
cam.MoveAtTo(drawLumelDesc._eyePos + perpVecB);
cam.SetUpDirection(perpVecA);
break;
case CGI::CubeMapFace::negX:
cam.MoveAtTo(drawLumelDesc._eyePos - perpVecB);
cam.SetUpDirection(perpVecA);
break;
case CGI::CubeMapFace::posY:
cam.MoveAtTo(drawLumelDesc._eyePos + perpVecA);
cam.SetUpDirection(-nrm);
break;
case CGI::CubeMapFace::negY:
cam.MoveAtTo(drawLumelDesc._eyePos - perpVecA);
cam.SetUpDirection(nrm);
break;
case CGI::CubeMapFace::posZ:
cam.MoveAtTo(drawLumelDesc._eyePos + nrm);
cam.SetUpDirection(perpVecA);
break;
}
cam.SetYFov(VERUS_PI * 0.5f);
cam.SetAspectRatio(1);
cam.SetZNear(0.00001f);
cam.SetZFar(_desc._distance);
cam.Update();
PCamera pPrevCamera = sm.SetCamera(&cam);
drawLumelDesc._frontDir = cam.GetFrontDirection();
_pDelegate->LightMapBaker_Draw(cubeMapFace, drawLumelDesc);
sm.SetCamera(pPrevCamera);
}
_pDelegate->LightMapBaker_Draw(CGI::CubeMapFace::negZ, drawLumelDesc);
DrawHemicubeMask();
}
cb->EndRenderPass();
tex->GenerateMips();
tex->ReadbackSubresource(nullptr);
}
Continue LightMapBaker::Quadtree_ProcessNode(void* pToken, void* pUser)
@ -171,6 +443,7 @@ Continue LightMapBaker::Quadtree_ProcessNode(void* pToken, void* pUser)
const int index = _currentI * _desc._texWidth + _currentJ;
if (Math::IsPointInsideTriangle(face._v[0]._tc, face._v[1]._tc, face._v[2]._tc, _currentUV))
{
VERUS_QREF_RENDERER;
switch (GetMode())
{
case Mode::faces:
@ -180,15 +453,23 @@ Continue LightMapBaker::Quadtree_ProcessNode(void* pToken, void* pUser)
break;
case Mode::ambientOcclusion:
{
VERUS_RT_ASSERT(_currentLayer < s_maxLayers);
const Vector3 bc = Math::Barycentric(face._v[0]._tc, face._v[1]._tc, face._v[2]._tc, _currentUV);
const glm::vec3 pos = Math::BarycentricInterpolation(face._v[0]._pos, face._v[1]._pos, face._v[2]._pos, bc);
const glm::vec3 nrm = Math::BarycentricInterpolation(face._v[0]._nrm, face._v[1]._nrm, face._v[2]._nrm, bc);
const glm::vec4 nrm2 = glm::vec4(glm::normalize(nrm) * 0.5f + 0.5f, 1.f);
const int ringBufferIndex = renderer->GetRingBufferIndex();
int& queuedCount = _queuedCount[ringBufferIndex];
RQueued queued = _vQueued[ringBufferIndex][queuedCount];
queued._pos = pos;
queued._nrm = glm::normalize(nrm);
queued._pDst = &_vMap[index];
_vMap[index] = Convert::ColorFloatToInt32(&nrm2.x);
_currentLayer++;
queuedCount++;
DrawLumel(pos, nrm);
return (_currentLayer >= s_maxLayers) ? Continue::no : Continue::yes;
}
break;
}
@ -196,7 +477,98 @@ Continue LightMapBaker::Quadtree_ProcessNode(void* pToken, void* pUser)
return Continue::yes;
}
void LightMapBaker::ComputeEdgePadding(int radius)
{
const int radiusSq = radius * radius;
VERUS_P_FOR(i, _desc._texHeight)
{
const int offset = i * _desc._texWidth;
VERUS_FOR(j, _desc._texWidth)
{
BYTE* pOriginChannels = reinterpret_cast<BYTE*>(&_vMap[offset + j]);
if (pOriginChannels[3])
continue;
int minRadiusSq = INT_MAX;
BYTE color[4] = {};
for (int di = -radius; di <= radius; ++di)
{
const int ki = i + di;
if (ki < 0 || ki >= _desc._texHeight)
continue;
for (int dj = -radius; dj <= radius; ++dj)
{
const int kj = j + dj;
if (kj < 0 || kj >= _desc._texWidth)
continue;
if (!di && !dj)
continue;
const int lenSq = di * di + dj * dj;
if (lenSq > radiusSq)
continue;
BYTE* pKernelChannels = reinterpret_cast<BYTE*>(&_vMap[ki * _desc._texWidth + kj]);
if (!pKernelChannels[3])
continue;
if (lenSq < minRadiusSq)
{
minRadiusSq = lenSq;
memcpy(color, pKernelChannels, 3);
}
}
}
if (minRadiusSq != INT_MAX)
memcpy(pOriginChannels, color, 3);
}
});
}
void LightMapBaker::Save()
{
IO::FileSystem::SaveImage(_C(_pathname), _vMap.data(), _desc._texWidth, _desc._texHeight, IO::ImageFormat::extension);
}
void LightMapBaker::BindPipeline(PIPE pipe, CGI::CommandBufferPtr cb)
{
VERUS_RT_ASSERT(pipe >= PIPE_MESH_SIMPLE_BAKE_AO && pipe <= PIPE_MESH_SIMPLE_BAKE_AO_SKINNED);
if (!_pipe[pipe])
{
static CSZ branches[] =
{
"#BakeAO",
"#BakeAOInstanced",
"#BakeAORobotic",
"#BakeAOSkinned"
};
CGI::PipelineDesc pipeDesc(_desc._pMesh->GetGeometry(), Mesh::GetSimpleShader(), branches[pipe], _rph);
pipeDesc._vertexInputBindingsFilter = _desc._pMesh->GetBindingsMask();
_pipe[pipe].Init(pipeDesc);
}
cb->BindPipeline(_pipe[pipe]);
}
void LightMapBaker::SetViewportFor(CGI::CubeMapFace cubeMapFace, CGI::CommandBufferPtr cb)
{
const float sideDiv2 = static_cast<float>(_desc._texLumelSide >> 1);
const float sideDiv4 = static_cast<float>(_desc._texLumelSide >> 2);
switch (cubeMapFace)
{
case CGI::CubeMapFace::posX:
cb->SetViewport({ Vector4(-sideDiv4, sideDiv4, sideDiv2, sideDiv2) });
break;
case CGI::CubeMapFace::negX:
cb->SetViewport({ Vector4(sideDiv2 + sideDiv4, sideDiv4, sideDiv2, sideDiv2) });
break;
case CGI::CubeMapFace::posY:
cb->SetViewport({ Vector4(sideDiv4, -sideDiv4, sideDiv2, sideDiv2) });
break;
case CGI::CubeMapFace::negY:
cb->SetViewport({ Vector4(sideDiv4, sideDiv2 + sideDiv4, sideDiv2, sideDiv2) });
break;
case CGI::CubeMapFace::posZ:
cb->SetViewport({ Vector4(sideDiv4, sideDiv4, sideDiv2, sideDiv2) });
break;
}
}

View File

@ -5,8 +5,25 @@ namespace verus
{
namespace Scene
{
struct DrawLumelDesc
{
Transform3 _matV;
Point3 _eyePos;
Vector3 _frontDir;
};
VERUS_TYPEDEFS(DrawLumelDesc);
struct LightMapBakerDelegate
{
virtual void LightMapBaker_Draw(CGI::CubeMapFace cubeMapFace, RcDrawLumelDesc drawLumelDesc) = 0;
};
VERUS_TYPEDEFS(LightMapBakerDelegate);
class LightMapBaker : public Singleton<LightMapBaker>, public Object, public Math::QuadtreeDelegate
{
static const int s_batchSize = 400;
static const int s_maxLayers = 8;
struct Vertex
{
glm::vec3 _pos;
@ -21,11 +38,30 @@ namespace verus
};
VERUS_TYPEDEFS(Face);
struct Queued
{
Point3 _pos;
Vector3 _nrm;
void* _pDst;
};
VERUS_TYPEDEFS(Queued);
public:
enum PIPE
{
PIPE_MESH_SIMPLE_BAKE_AO,
PIPE_MESH_SIMPLE_BAKE_AO_INSTANCED,
PIPE_MESH_SIMPLE_BAKE_AO_ROBOTIC,
PIPE_MESH_SIMPLE_BAKE_AO_SKINNED,
PIPE_HEMICUBE_MASK,
PIPE_QUAD,
PIPE_COUNT
};
enum TEX
{
TEX_COLOR,
TEX_DEPTH,
TEX_DUMMY,
TEX_COUNT
};
@ -36,34 +72,53 @@ namespace verus
ambientOcclusion
};
struct Stats
{
String _info;
float _progress = 0;
float _startTime = 0;
int _maxLayer = 0;
};
VERUS_TYPEDEFS(Stats);
struct Desc
{
PcBaseMesh _pMesh = nullptr;
CSZ _pathname = nullptr;
Mode _mode = Mode::idle;
int _texCoordIndex = 0;
int _texWidth = 256;
int _texHeight = 256;
int _texLumelSide = 256;
float _distance = 1;
PcMesh _pMesh = nullptr;
CSZ _pathname = nullptr;
Mode _mode = Mode::idle;
int _texCoordSet = 0;
int _texWidth = 256;
int _texHeight = 256;
int _texLumelSide = 128;
float _distance = 2;
};
VERUS_TYPEDEFS(Desc);
private:
Math::Quadtree _quadtree;
Vector<Face> _vFaces;
Vector<UINT32> _vMap;
String _pathname;
Desc _desc;
CGI::TexturePwns<TEX_COUNT> _tex;
CGI::RPHandle _rph;
CGI::FBHandle _fbh;
int _repsPerUpdate = 1;
int _currentI = 0;
int _currentJ = 0;
glm::vec2 _currentUV;
float _progress = 0;
float _invMapSize = 0;
Math::Quadtree _quadtree;
PLightMapBakerDelegate _pDelegate = nullptr;
Vector<Face> _vFaces;
Vector<UINT32> _vMap;
Vector<Queued> _vQueued[CGI::BaseRenderer::s_ringBufferSize];
String _pathname;
Desc _desc;
CGI::PipelinePwns<PIPE_COUNT> _pipe;
CGI::TexturePwns<TEX_COUNT> _tex;
CGI::TexturePwns<s_batchSize> _texColor[CGI::BaseRenderer::s_ringBufferSize];
CGI::RPHandle _rph;
CGI::FBHandle _fbh[CGI::BaseRenderer::s_ringBufferSize][s_batchSize];
CGI::CSHandle _cshQuad[CGI::BaseRenderer::s_ringBufferSize];
CGI::CSHandle _cshHemicubeMask;
int _repsPerUpdate = 1;
int _drawEmptyState = 0;
int _queuedCount[CGI::BaseRenderer::s_ringBufferSize];
int _currentLayer = 0;
int _currentI = 0;
int _currentJ = 0;
glm::vec2 _currentUV;
float _invMapSize = 0;
float _normalizationFactor = 0;
Stats _stats;
public:
LightMapBaker();
@ -73,8 +128,15 @@ namespace verus
void Done();
void Update();
void Draw();
void DrawLumel(RcPoint3 eyePos, RcVector3 frontDir);
PLightMapBakerDelegate SetDelegate(PLightMapBakerDelegate p) { return Utils::Swap(_pDelegate, p); }
void DrawEmpty();
void DrawHemicubeMask();
void DrawLumel(RcPoint3 pos, RcVector3 nrm, int batchIndex);
RcDesc GetDesc() const { return _desc; }
bool IsBaking() const { return Mode::idle != _desc._mode; }
Mode GetMode() const { return _desc._mode; }
@ -82,9 +144,14 @@ namespace verus
virtual Continue Quadtree_ProcessNode(void* pToken, void* pUser) override;
Str GetPathname() const { return _C(_pathname); }
float GetProgress() const { return _progress; }
RcStats GetStats() const { return _stats; }
float GetProgress() const { return _stats._progress; }
void ComputeEdgePadding(int radius = 32);
void Save();
void BindPipeline(PIPE pipe, CGI::CommandBufferPtr cb);
void SetViewportFor(CGI::CubeMapFace cubeMapFace, CGI::CommandBufferPtr cb);
};
VERUS_TYPEDEFS(LightMapBaker);
}

View File

@ -87,62 +87,88 @@ void Mesh::Done()
VERUS_DONE(Mesh);
}
void Mesh::Draw(RcDrawDesc dd, CGI::CommandBufferPtr cb)
void Mesh::Draw(RcDrawDesc drawDesc, CGI::CommandBufferPtr cb)
{
auto shader = GetShader();
if (dd._pipe != PIPE_COUNT)
BindPipeline(dd._pipe, cb);
else
BindPipeline(cb, dd._allowTess);
if (drawDesc._bindPipeline)
{
if (drawDesc._pipe != PIPE_COUNT)
BindPipeline(drawDesc._pipe, cb);
else
BindPipeline(cb, drawDesc._allowTess); // Auto.
}
BindGeo(cb);
// Set 0:
UpdateUniformBufferPerFrame();
if (drawDesc._pOverrideFogColor)
s_ubSimplePerFrame._fogColor = drawDesc._pOverrideFogColor->GLM();
cb->BindDescriptors(shader, 0);
if (dd._bindMaterial)
// Set 1:
if (drawDesc._bindMaterial)
{
// Material buffer should already be updated. For example call Material::UpdateMeshUniformBuffer.
cb->BindDescriptors(shader, 1, dd._cshMaterial);
cb->BindDescriptors(shader, 1, drawDesc._cshMaterial);
}
// Set 2:
UpdateUniformBufferPerMeshVS();
cb->BindDescriptors(shader, 2);
if (dd._bindSkeleton)
// Set 3:
if (drawDesc._bindSkeleton)
{
UpdateUniformBufferSkeletonVS();
cb->BindDescriptors(shader, 3);
}
UpdateUniformBufferPerObject(dd._matW, dd._userColor);
// Set 4:
UpdateUniformBufferPerObject(drawDesc._matW, drawDesc._userColor);
cb->BindDescriptors(shader, 4);
cb->DrawIndexed(GetIndexCount());
}
void Mesh::DrawSimple(RcDrawDesc dd, CGI::CommandBufferPtr cb)
void Mesh::DrawSimple(RcDrawDesc drawDesc, CGI::CommandBufferPtr cb)
{
DrawSimpleMode mode = DrawSimpleMode::envMap;
if (dd._pipe >= PIPE_SIMPLE_PLANAR_REF && dd._pipe <= PIPE_SIMPLE_PLANAR_REF_SKINNED)
if (drawDesc._pipe >= PIPE_SIMPLE_PLANAR_REF && drawDesc._pipe <= PIPE_SIMPLE_PLANAR_REF_SKINNED)
mode = DrawSimpleMode::planarReflection;
auto shader = GetSimpleShader();
BindPipeline(dd._pipe, cb);
if (drawDesc._bindPipeline)
BindPipeline(drawDesc._pipe, cb);
BindGeo(cb);
// Set 0:
UpdateUniformBufferSimplePerFrame(mode);
if (drawDesc._pOverrideFogColor)
s_ubSimplePerFrame._fogColor = drawDesc._pOverrideFogColor->GLM();
cb->BindDescriptors(shader, 0);
if (dd._bindMaterial)
// Set 1:
if (drawDesc._bindMaterial)
{
// Material buffer should already be updated. For example call Material::UpdateMeshUniformBuffer.
cb->BindDescriptors(shader, 1, dd._cshMaterial);
cb->BindDescriptors(shader, 1, drawDesc._cshMaterial);
}
// Set 2:
UpdateUniformBufferPerMeshVS();
cb->BindDescriptors(shader, 2);
if (dd._bindSkeleton)
// Set 3:
if (drawDesc._bindSkeleton)
{
UpdateUniformBufferSimpleSkeletonVS();
cb->BindDescriptors(shader, 3);
}
UpdateUniformBufferPerObject(dd._matW, dd._userColor);
// Set 4:
UpdateUniformBufferPerObject(drawDesc._matW, drawDesc._userColor);
cb->BindDescriptors(shader, 4);
cb->DrawIndexed(GetIndexCount());
@ -161,15 +187,15 @@ void Mesh::BindPipeline(PIPE pipe, CGI::CommandBufferPtr cb)
{
case PIPE_TESS: pipe = PIPE_MAIN; break;
case PIPE_TESS_INSTANCED: pipe = PIPE_INSTANCED; break;
case PIPE_TESS_PLANT: pipe = PIPE_PLANT; break;
case PIPE_TESS_ROBOTIC: pipe = PIPE_ROBOTIC; break;
case PIPE_TESS_SKINNED: pipe = PIPE_SKINNED; break;
case PIPE_TESS_PLANT: pipe = PIPE_PLANT; break;
case PIPE_DEPTH_TESS: pipe = PIPE_DEPTH; break;
case PIPE_DEPTH_TESS_INSTANCED: pipe = PIPE_DEPTH_INSTANCED; break;
case PIPE_DEPTH_TESS_PLANT: pipe = PIPE_DEPTH_PLANT; break;
case PIPE_DEPTH_TESS_ROBOTIC: pipe = PIPE_DEPTH_ROBOTIC; break;
case PIPE_DEPTH_TESS_SKINNED: pipe = PIPE_DEPTH_SKINNED; break;
case PIPE_DEPTH_TESS_PLANT: pipe = PIPE_DEPTH_PLANT; break;
};
}
@ -179,27 +205,27 @@ void Mesh::BindPipeline(PIPE pipe, CGI::CommandBufferPtr cb)
{
"#",
"#Instanced",
"#Plant",
"#Robotic",
"#Skinned",
"#Plant",
"#Tess",
"#TessInstanced",
"#TessPlant",
"#TessRobotic",
"#TessSkinned",
"#TessPlant",
"#Depth",
"#DepthInstanced",
"#DepthPlant",
"#DepthRobotic",
"#DepthSkinned",
"#DepthPlant",
"#DepthTess",
"#DepthTessInstanced",
"#DepthTessPlant",
"#DepthTessRobotic",
"#DepthTessSkinned",
"#DepthTessPlant",
"#SolidColor",
"#SolidColorInstanced",
@ -265,18 +291,18 @@ void Mesh::BindPipeline(PIPE pipe, CGI::CommandBufferPtr cb)
{
case PIPE_MAIN:
case PIPE_INSTANCED:
case PIPE_PLANT:
case PIPE_ROBOTIC:
case PIPE_SKINNED:
case PIPE_PLANT:
{
SetBlendEqsForDS();
}
break;
case PIPE_TESS:
case PIPE_TESS_INSTANCED:
case PIPE_TESS_PLANT:
case PIPE_TESS_ROBOTIC:
case PIPE_TESS_SKINNED:
case PIPE_TESS_PLANT:
{
SetBlendEqsForDS();
if (settings._gpuTessellation)
@ -285,9 +311,9 @@ void Mesh::BindPipeline(PIPE pipe, CGI::CommandBufferPtr cb)
break;
case PIPE_DEPTH:
case PIPE_DEPTH_INSTANCED:
case PIPE_DEPTH_PLANT:
case PIPE_DEPTH_ROBOTIC:
case PIPE_DEPTH_SKINNED:
case PIPE_DEPTH_PLANT:
{
pipeDesc._colorAttachBlendEqs[0] = "";
pipeDesc._renderPassHandle = atmo.GetShadowMapBaker().GetRenderPassHandle();
@ -295,9 +321,9 @@ void Mesh::BindPipeline(PIPE pipe, CGI::CommandBufferPtr cb)
break;
case PIPE_DEPTH_TESS:
case PIPE_DEPTH_TESS_INSTANCED:
case PIPE_DEPTH_TESS_PLANT:
case PIPE_DEPTH_TESS_ROBOTIC:
case PIPE_DEPTH_TESS_SKINNED:
case PIPE_DEPTH_TESS_PLANT:
{
pipeDesc._colorAttachBlendEqs[0] = "";
pipeDesc._renderPassHandle = atmo.GetShadowMapBaker().GetRenderPassHandle();
@ -332,40 +358,40 @@ void Mesh::BindPipeline(PIPE pipe, CGI::CommandBufferPtr cb)
void Mesh::BindPipeline(CGI::CommandBufferPtr cb, bool allowTess)
{
VERUS_QREF_ATMO;
if (_skeleton.IsInitialized())
static PIPE pipes[] =
{
if (atmo.GetShadowMapBaker().IsBaking())
{
if (allowTess)
BindPipeline(PIPE_DEPTH_TESS_SKINNED, cb);
else
BindPipeline(PIPE_DEPTH_SKINNED, cb);
}
else
{
if (allowTess)
BindPipeline(PIPE_TESS_SKINNED, cb);
else
BindPipeline(PIPE_SKINNED, cb);
}
}
PIPE_MAIN,
PIPE_INSTANCED,
PIPE_ROBOTIC,
PIPE_SKINNED
};
static PIPE tessPipes[] =
{
PIPE_TESS,
PIPE_TESS_INSTANCED,
PIPE_TESS_ROBOTIC,
PIPE_TESS_SKINNED
};
static PIPE depthPipes[] =
{
PIPE_DEPTH,
PIPE_DEPTH_INSTANCED,
PIPE_DEPTH_ROBOTIC,
PIPE_DEPTH_SKINNED
};
static PIPE depthTessPipes[] =
{
PIPE_DEPTH_TESS,
PIPE_DEPTH_TESS_INSTANCED,
PIPE_DEPTH_TESS_ROBOTIC,
PIPE_DEPTH_TESS_SKINNED
};
if (atmo.GetShadowMapBaker().IsBaking())
BindPipeline(allowTess ? depthTessPipes[GetPipelineIndex()] : depthPipes[GetPipelineIndex()], cb);
else
{
if (atmo.GetShadowMapBaker().IsBaking())
{
if (allowTess)
BindPipeline(PIPE_DEPTH_TESS, cb);
else
BindPipeline(PIPE_DEPTH, cb);
}
else
{
if (allowTess)
BindPipeline(PIPE_TESS, cb);
else
BindPipeline(PIPE_MAIN, cb);
}
}
BindPipeline(allowTess ? tessPipes[GetPipelineIndex()] : pipes[GetPipelineIndex()], cb);
}
void Mesh::BindPipelineInstanced(CGI::CommandBufferPtr cb, bool allowTess, bool plant)

View File

@ -22,27 +22,27 @@ namespace verus
{
PIPE_MAIN,
PIPE_INSTANCED,
PIPE_PLANT,
PIPE_ROBOTIC,
PIPE_SKINNED,
PIPE_PLANT,
PIPE_TESS,
PIPE_TESS_INSTANCED,
PIPE_TESS_PLANT,
PIPE_TESS_ROBOTIC,
PIPE_TESS_SKINNED,
PIPE_TESS_PLANT,
PIPE_DEPTH,
PIPE_DEPTH_INSTANCED,
PIPE_DEPTH_PLANT,
PIPE_DEPTH_ROBOTIC,
PIPE_DEPTH_SKINNED,
PIPE_DEPTH_PLANT,
PIPE_DEPTH_TESS,
PIPE_DEPTH_TESS_INSTANCED,
PIPE_DEPTH_TESS_PLANT,
PIPE_DEPTH_TESS_ROBOTIC,
PIPE_DEPTH_TESS_SKINNED,
PIPE_DEPTH_TESS_PLANT,
PIPE_WIREFRAME,
PIPE_WIREFRAME_INSTANCED,
@ -113,9 +113,11 @@ namespace verus
Transform3 _matW = Transform3::identity();
Vector4 _userColor = Vector4(0);
CGI::CSHandle _cshMaterial;
PcVector4 _pOverrideFogColor = nullptr;
PIPE _pipe = PIPE_COUNT;
bool _allowTess = true;
bool _bindMaterial = true;
bool _bindPipeline = true;
bool _bindSkeleton = true;
};
VERUS_TYPEDEFS(DrawDesc);
@ -129,8 +131,8 @@ namespace verus
void Init(RcDesc desc = Desc());
void Done();
void Draw(RcDrawDesc dd, CGI::CommandBufferPtr cb);
void DrawSimple(RcDrawDesc dd, CGI::CommandBufferPtr cb);
void Draw(RcDrawDesc drawDesc, CGI::CommandBufferPtr cb);
void DrawSimple(RcDrawDesc drawDesc, CGI::CommandBufferPtr cb);
void BindPipeline(PIPE pipe, CGI::CommandBufferPtr cb);
void BindPipeline(CGI::CommandBufferPtr cb, bool allowTess = true);
@ -164,6 +166,8 @@ namespace verus
int GetInstanceCount(bool fromFirstInstance = false) const { return fromFirstInstance ? _instanceCount - _firstInstance : _instanceCount; }
int GetInstanceCapacity() const { return _instanceCapacity; }
int GetFirstInstance() const { return _firstInstance; }
UINT32 GetBindingsMask() const { return _bindingsMask; }
};
VERUS_TYPEDEFS(Mesh);
}

View File

@ -164,7 +164,7 @@ void Light::ConeFromPoint(RcPoint3 point, bool coneIn)
Transform3 Light::GetTransformNoScale() const
{
const Matrix3 matR = Matrix3::MakeAimZ(_data._dir);
const Matrix3 matR = Matrix3::MakeTrackToZ(_data._dir);
return Transform3(matR, Vector3(GetPosition()));
}
@ -199,7 +199,7 @@ Vector3 Light::ComputeScale()
void Light::ComputeTransform()
{
const Matrix3 matR = Matrix3::MakeAimZ(_data._dir);
const Matrix3 matR = Matrix3::MakeTrackToZ(_data._dir);
const Transform3 tr = VMath::appendScale(Transform3(matR, Vector3(GetPosition())), ComputeScale());
SceneNode::SetTransform(tr);
}

View File

@ -57,7 +57,7 @@ FSO mainFS(VSO si)
const float sunStrength = g_ubBloomLightShaftsFS._maxDist_sunGloss_wideStrength_sunStrength.w;
const float2 ndcPos = ToNdcPos(si.tc0);
const float rawDepth = g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.f).r;
const float rawDepth = g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.0).r;
const float3 posW = DS_GetPosition(rawDepth, g_ubBloomLightShaftsFS._matInvVP, ndcPos);
const float3 eyePos = g_ubBloomLightShaftsFS._eyePos.xyz;
@ -67,8 +67,8 @@ FSO mainFS(VSO si)
const float2 spec = pow(saturate(dot(g_ubBloomLightShaftsFS._dirToSun.xyz, pickingRayDir)), float2(7, sunGloss));
const float strength = dot(spec, float2(wideStrength, sunStrength));
float3 lightShafts = 0.f;
if (strength >= 0.0001f)
float3 lightShafts = 0.0;
if (strength >= 0.0001)
{
const float3 rand = Rand(si.pos.xy);
@ -84,7 +84,7 @@ FSO mainFS(VSO si)
const float stride = maxDist / sampleCount;
float pickingRayLen = rand.y * stride;
float acc = 0.f;
float acc = 0.0;
[unroll] for (int i = 0; i < sampleCount; ++i)
{
const float3 pos = eyePos + pickingRayDir * pickingRayLen;
@ -104,7 +104,7 @@ FSO mainFS(VSO si)
acc += shadowMask * step(pickingRayLen, depth);
pickingRayLen += stride;
}
lightShafts = acc * (1.f / sampleCount) * g_ubBloomLightShaftsFS._sunColor.rgb * g_ubBloomFS._exposure.x * strength;
lightShafts = acc * (1.0 / sampleCount) * g_ubBloomLightShaftsFS._sunColor.rgb * g_ubBloomFS._exposure.x * strength;
}
so.color.rgb = lightShafts;
@ -112,14 +112,14 @@ FSO mainFS(VSO si)
const float colorScale = g_ubBloomFS._colorScale_colorBias.x;
const float colorBias = g_ubBloomFS._colorScale_colorBias.y;
const float4 rawColor = g_texColor.SampleLevel(g_samColor, si.tc0, 0.f);
const float4 rawColor = g_texColor.SampleLevel(g_samColor, si.tc0, 0.0);
const float3 color = rawColor.rgb * g_ubBloomFS._exposure.x;
const float3 bloom = saturate((color - colorBias) * colorScale);
so.color.rgb = bloom;
#endif
so.color.a = 1.f;
so.color.a = 1.0;
return so;
}

View File

@ -37,8 +37,8 @@ struct FSO
float GlossBoost(float gloss)
{
const float x = 1.f - gloss;
return 1.f - x * x;
const float x = 1.0 - gloss;
return 1.0 - x * x;
}
#ifdef _VS
@ -60,19 +60,19 @@ FSO mainFS(VSO si)
FSO so;
#ifdef DEF_SSR
const float alpha = g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.f).r;
const float gloss = g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.f).a;
const float alpha = g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.0).r;
const float gloss = g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.0).a;
const float gloss64 = gloss * 64.f;
const float eyeMask = saturate(1.f - gloss64);
const float scaleByAlpha = 1.f - alpha;
const float scaleByGloss = 1.f - GlossBoost(lerp(gloss, 0.75f, eyeMask));
const float scale = max(0.001f, min(scaleByAlpha, scaleByGloss));
const float gloss64 = gloss * 64.0;
const float eyeMask = saturate(1.0 - gloss64);
const float scaleByAlpha = 1.0 - alpha;
const float scaleByGloss = 1.0 - GlossBoost(lerp(gloss, 0.75, eyeMask));
const float scale = max(0.001, min(scaleByAlpha, scaleByGloss));
const int sampleCount = max(4, g_ubBlurFS._sampleCount * scale);
const float radius = g_ubBlurFS._radius_invRadius_stride.x * scale;
const float invRadius = 1.f / radius;
const float stride = radius * 2.f / (sampleCount - 1);
const float invRadius = 1.0 / radius;
const float stride = radius * 2.0 / (sampleCount - 1);
#else
const int sampleCount = g_ubBlurFS._sampleCount;
const float radius = g_ubBlurFS._radius_invRadius_stride.x;
@ -80,22 +80,22 @@ FSO mainFS(VSO si)
const float stride = g_ubBlurFS._radius_invRadius_stride.z;
#endif
float4 acc = 0.f;
float4 acc = 0.0;
float2 offset_weightSum = float2(-radius, 0);
for (int i = 0; i < sampleCount; ++i)
{
// Poor man's gaussian kernel:
const float curve = smoothstep(1.f, 0.f, abs(offset_weightSum.x) * invRadius);
const float curve = smoothstep(1.0, 0.0, abs(offset_weightSum.x) * invRadius);
const float weight = curve * curve;
#ifdef DEF_U
const float2 tc = si.tc0 + float2(offset_weightSum.x, 0);
#else
const float2 tc = si.tc0 + float2(0, offset_weightSum.x);
#endif
acc += g_tex.SampleLevel(g_sam, tc, 0.f) * weight;
acc += g_tex.SampleLevel(g_sam, tc, 0.0) * weight;
offset_weightSum += float2(stride, weight);
}
acc *= 1.f / offset_weightSum.y;
acc *= 1.0 / offset_weightSum.y;
so.color = acc;
@ -109,7 +109,7 @@ FSO mainFS(VSO si)
float DepthToCircleOfConfusion(float depth, float focusDist)
{
return abs((depth - focusDist * 2.f) / depth + 1.f);
return abs((depth - focusDist * 2.0) / depth + 1.0);
}
#ifdef _VS
@ -133,47 +133,47 @@ FSO mainDofFS(VSO si)
const float focusDist = g_ubExtraBlurFS._focusDist_blurStrength.x;
const float blurStrength = g_ubExtraBlurFS._focusDist_blurStrength.y;
const float rawOriginDepth = g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.f).r;
const float rawOriginDepth = g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.0).r;
const float originDepth = ToLinearDepth(rawOriginDepth, g_ubExtraBlurFS._zNearFarEx);
const float scale = DepthToCircleOfConfusion(originDepth, focusDist) * blurStrength;
const int sampleCount = clamp(g_ubBlurFS._sampleCount * scale, 3, 31);
const float radius = g_ubBlurFS._radius_invRadius_stride.x * scale;
const float invRadius = 1.f / radius;
const float invRadius = 1.0 / radius;
const float2 blurDir = g_ubExtraBlurFS._blurDir.xy;
const float2 blurDir2 = g_ubExtraBlurFS._blurDir.zw * radius;
const float stride = radius * 2.f / (sampleCount - 1);
const float stride = radius * 2.0 / (sampleCount - 1);
const float2 stride2D = stride * blurDir;
float4 acc = 0.f;
float4 acc = 0.0;
float2 offset_weightSum = float2(-radius, 0);
float2 tc = si.tc0 - blurDir * radius;
for (int i = 0; i < sampleCount; ++i)
{
//const float origin = 1.f - abs(offset_weightSum.x) * invRadius; // Will generate buggy code in Vulkan!
//const float origin = 1.0 - abs(offset_weightSum.x) * invRadius; // Will generate buggy code in Vulkan!
const float origin = abs(offset_weightSum.x) * invRadius;
const float rawKernelDepth = g_texDepth.SampleLevel(g_samDepth, tc, 0.f).r;
const float rawKernelDepth = g_texDepth.SampleLevel(g_samDepth, tc, 0.0).r;
const float kernelDepth = ToLinearDepth(rawKernelDepth, g_ubExtraBlurFS._zNearFarEx);
const float kernelDeeper = kernelDepth - originDepth;
const float kernelScale = DepthToCircleOfConfusion(kernelDepth, focusDist) * blurStrength;
// Blurry area should not sample sharp area unless it is closer to the camera.
float weight = min(scale, min(2.f, max(kernelScale, kernelDeeper)));
float weight = min(scale, min(2.0, max(kernelScale, kernelDeeper)));
#ifdef DEF_U // 1st pass - make a rhombus:
weight *= 1.f - 0.5f * origin;
const float4 colorA = g_tex.SampleLevel(g_sam, tc - blurDir2 + blurDir2 * origin, 0.f);
const float4 colorB = g_tex.SampleLevel(g_sam, tc + blurDir2 - blurDir2 * origin, 0.f);
acc += lerp(colorA, colorB, 0.5f) * weight;
weight *= 1.0 - 0.5 * origin;
const float4 colorA = g_tex.SampleLevel(g_sam, tc - blurDir2 + blurDir2 * origin, 0.0);
const float4 colorB = g_tex.SampleLevel(g_sam, tc + blurDir2 - blurDir2 * origin, 0.0);
acc += lerp(colorA, colorB, 0.5) * weight;
#else // 2nd pass - blur the rhombus:
acc += g_tex.SampleLevel(g_sam, tc, 0.f) * weight;
acc += g_tex.SampleLevel(g_sam, tc, 0.0) * weight;
#endif
offset_weightSum += float2(stride, weight);
tc += stride2D;
}
acc *= 1.f / offset_weightSum.y;
acc *= 1.0 / offset_weightSum.y;
so.color = acc;
@ -204,16 +204,16 @@ FSO mainSsaoFS(VSO si)
FSO so;
// 4x4 box blur, using texture filtering.
float4 acc = 0.f;
float4 acc = 0.0;
[unroll] for (int i = -1; i <= 1; i += 2)
{
#ifdef DEF_U
acc += g_tex.SampleLevel(g_sam, si.tc0, 0.f, int2(i, 0));
acc += g_tex.SampleLevel(g_sam, si.tc0, 0.0, int2(i, 0));
#else // Sampling from sRGB, use alpha channel:
acc += g_tex.SampleLevel(g_sam, si.tc0, 0.f, int2(0, i)).aaaa;
acc += g_tex.SampleLevel(g_sam, si.tc0, 0.0, int2(0, i)).aaaa;
#endif
}
acc *= 0.5f;
acc *= 0.5;
so.color = acc;
#ifndef DEF_V // Make sure to write R channel to alpha, destination is sRGB.
@ -244,26 +244,26 @@ FSO mainAntiAliasingFS(VSO si)
{
FSO so;
const float4 rawGBuffer1 = g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.f);
const float4 rawGBuffer1 = g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.0);
const float3 normalWV = DS_GetNormal(rawGBuffer1);
// <DepthBased>
float originDeeper;
float depthBasedEdge;
{
const float rawOriginDepth = g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.f).r;
const float rawOriginDepth = g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.0).r;
const float originDepth = ToLinearDepth(rawOriginDepth, g_ubExtraBlurFS._zNearFarEx);
const float4 rawKernelDepths = float4(
g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.f, int2(-1, +0)).r, // L
g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.f, int2(+0, -1)).r, // T
g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.f, int2(+1, +0)).r, // R
g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.f, int2(+0, +1)).r); // B
g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.0, int2(-1, +0)).r, // L
g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.0, int2(+0, -1)).r, // T
g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.0, int2(+1, +0)).r, // R
g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.0, int2(+0, +1)).r); // B
const float4 kernelDepths = ToLinearDepth(rawKernelDepths, g_ubExtraBlurFS._zNearFarEx);
const float minDepth = min(min(kernelDepths[0], kernelDepths[1]), min(kernelDepths[2], kernelDepths[3]));
const float equalize = 1.f / originDepth;
const float equalize = 1.0 / originDepth;
originDeeper = saturate((originDepth - minDepth) * equalize);
const float4 depthOffsets = abs((originDepth - kernelDepths) * equalize);
depthBasedEdge = saturate(dot(depthOffsets, 1.f));
depthBasedEdge = saturate(dot(depthOffsets, 1.0));
}
// </DepthBased>
@ -271,11 +271,11 @@ FSO mainAntiAliasingFS(VSO si)
float normalBasedEdge;
{
const float4 rawNrmLT = float4(
g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.f, int2(-1, +0)).rg,
g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.f, int2(+0, -1)).rg);
g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.0, int2(-1, +0)).rg,
g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.0, int2(+0, -1)).rg);
const float4 rawNrmRB = float4(
g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.f, int2(+1, +0)).rg,
g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.f, int2(+0, +1)).rg);
g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.0, int2(+1, +0)).rg,
g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.0, int2(+0, +1)).rg);
const float4 diffA = rawNrmLT - rawNrmRB;
const float4 diffB = rawNrmLT - rawNrmRB.zwxy;
const float4 dots = float4(
@ -284,7 +284,7 @@ FSO mainAntiAliasingFS(VSO si)
dot(diffB.xy, diffB.xy),
dot(diffB.zw, diffB.zw));
const float maxDot = max(max(dots.x, dots.y), max(dots.z, dots.w));
normalBasedEdge = saturate(maxDot * maxDot * 10.f);
normalBasedEdge = saturate(maxDot * maxDot * 10.0);
}
// </NormalBased>
@ -294,21 +294,21 @@ FSO mainAntiAliasingFS(VSO si)
const float omni = max(perp.z * perp.z * perp.z, originDeeper);
const float2 dirs[4] =
{
lerp(perp.xy * +4.f, float2(-0.6f, -0.3f), omni),
lerp(perp.xy * -2.f, float2(+0.3f, -0.6f), omni),
lerp(perp.xy * -4.f, float2(-0.3f, +0.6f), omni),
lerp(perp.xy * +2.f, float2(+0.6f, +0.3f), omni)
lerp(perp.xy * +4.0, float2(-0.6, -0.3), omni),
lerp(perp.xy * -2.0, float2(+0.3, -0.6), omni),
lerp(perp.xy * -4.0, float2(-0.3, +0.6), omni),
lerp(perp.xy * +2.0, float2(+0.6, +0.3), omni)
};
const float2 offsetScale = g_ubExtraBlurFS._textureSize.zw * max(normalBasedEdge, depthBasedEdge);
const float3 kernelColors[4] =
{
g_tex.SampleLevel(g_sam, si.tc0 + dirs[0] * offsetScale, 0.f).rgb,
g_tex.SampleLevel(g_sam, si.tc0 + dirs[1] * offsetScale, 0.f).rgb,
g_tex.SampleLevel(g_sam, si.tc0 + dirs[2] * offsetScale, 0.f).rgb,
g_tex.SampleLevel(g_sam, si.tc0 + dirs[3] * offsetScale, 0.f).rgb
g_tex.SampleLevel(g_sam, si.tc0 + dirs[0] * offsetScale, 0.0).rgb,
g_tex.SampleLevel(g_sam, si.tc0 + dirs[1] * offsetScale, 0.0).rgb,
g_tex.SampleLevel(g_sam, si.tc0 + dirs[2] * offsetScale, 0.0).rgb,
g_tex.SampleLevel(g_sam, si.tc0 + dirs[3] * offsetScale, 0.0).rgb
};
so.color.rgb = (kernelColors[0] + kernelColors[1] + kernelColors[2] + kernelColors[3]) * 0.25f;
so.color.a = 1.f;
so.color.rgb = (kernelColors[0] + kernelColors[1] + kernelColors[2] + kernelColors[3]) * 0.25;
so.color.a = 1.0;
return so;
}
@ -333,7 +333,7 @@ FSO mainMotionFS(VSO si)
FSO so;
const float3 rand = Rand(si.pos.xy);
const float offsetScale = 0.45f + 0.05f * rand.x; // Blur 45% - 50% of frame time.
const float offsetScale = 0.45 + 0.05 * rand.x; // Blur 45% - 50% of frame time.
#if _SHADER_QUALITY <= _Q_LOW
const int sampleCount = 12;
@ -345,11 +345,11 @@ FSO mainMotionFS(VSO si)
const int sampleCount = 32;
#endif
const float4 rawGBuffer1 = g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.f);
const float4 rawGBuffer1 = g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.0);
const float rawOriginDepth = g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.f).r;
const float rawOriginDepth = g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.0).r;
const float originDepth = ToLinearDepth(rawOriginDepth, g_ubExtraBlurFS._zNearFarEx);
const float equalize = 1.f / originDepth;
const float equalize = 1.0 / originDepth;
float2 tcFrom;
{
@ -361,9 +361,9 @@ FSO mainMotionFS(VSO si)
}
const float2 stride = (si.tc0 - tcFrom) * offsetScale / (sampleCount - 1);
const float2 tcOrigin = lerp(tcFrom, si.tc0, 0.75f); // Start from this location up to offsetScale.
const float2 tcOrigin = lerp(tcFrom, si.tc0, 0.75); // Start from this location up to offsetScale.
float4 acc = float4(g_tex.SampleLevel(g_sam, si.tc0, 0.f).rgb, 1); // Must have at least one sample.
float4 acc = float4(g_tex.SampleLevel(g_sam, si.tc0, 0.0).rgb, 1); // Must have at least one sample.
[unroll] for (int i = 0; i < sampleCount; ++i)
{
if (i == sampleCount / 2)
@ -371,14 +371,14 @@ FSO mainMotionFS(VSO si)
const float2 kernelCoords = tcOrigin + stride * i;
const float rawKernelDepth = g_texDepth.SampleLevel(g_samDepth, kernelCoords, 0.f).r;
const float rawKernelDepth = g_texDepth.SampleLevel(g_samDepth, kernelCoords, 0.0).r;
const float kernelDepth = ToLinearDepth(rawKernelDepth, g_ubExtraBlurFS._zNearFarEx);
const float kernelDeeper = kernelDepth - originDepth;
const float allowed = saturate(1.f + kernelDeeper * equalize) * rawGBuffer1.a; // Closer points require extra care.
const float weight = 1.f + saturate(kernelDeeper); // To fix the seam between foreground and background.
const float allowed = saturate(1.0 + kernelDeeper * equalize) * rawGBuffer1.a; // Closer points require extra care.
const float weight = 1.0 + saturate(kernelDeeper); // To fix the seam between foreground and background.
const float3 kernelColor = g_tex.SampleLevel(g_sam, kernelCoords, 0.f).rgb;
acc += lerp(0.f, float4(kernelColor * weight, weight), allowed);
const float3 kernelColor = g_tex.SampleLevel(g_sam, kernelCoords, 0.0).rgb;
acc += lerp(0.0, float4(kernelColor * weight, weight), allowed);
}
acc /= acc.a;

View File

@ -49,15 +49,15 @@ FSO mainFS(VSO si)
const float noiseStrength = g_ubCinemaFS._brightness_noiseStrength.y;
const float3 rawFilmGrain = g_texFilmGrain.Sample(g_samFilmGrain, si.tcFilmGrain).rgb;
const float3 filmGrain = lerp(1.f, 0.5f + rawFilmGrain.rgb, noiseStrength);
const float3 filmGrain = lerp(1.0, 0.5 + rawFilmGrain.rgb, noiseStrength);
// Vignette:
const float2 tcOffset = si.tc0 * 1.4f - 0.7f;
const float2 tcOffset = si.tc0 * 1.4 - 0.7;
const float lamp = saturate(dot(tcOffset, tcOffset));
const float3 lampColor = lerp(1.f, float3(0.64f, 0.48f, 0.36f), lamp);
const float3 lampColor = lerp(1.0, float3(0.64, 0.48, 0.36), lamp);
so.color.rgb = saturate(filmGrain * lampColor * brightness);
so.color.a = saturate(dot(filmGrain, 1.f / 3.f) - 1.f);
so.color.a = saturate(dot(filmGrain, 1.0 / 3.0) - 1.0);
return so;
}

View File

@ -86,7 +86,7 @@ VSO mainVS(VSI si)
const float3 posUnit = mul(float3(0, 0, 1), matW33); // Need to know the scale.
so.radius_radiusSq_invRadiusSq.y = dot(posUnit, posUnit);
so.radius_radiusSq_invRadiusSq.x = sqrt(so.radius_radiusSq_invRadiusSq.y);
so.radius_radiusSq_invRadiusSq.z = 1.f / so.radius_radiusSq_invRadiusSq.y;
so.radius_radiusSq_invRadiusSq.z = 1.0 / so.radius_radiusSq_invRadiusSq.y;
const float4 posOrigin = float4(0, 0, 0, 1);
so.lightPosWV = mul(posOrigin, matWV).xyz;
#endif
@ -94,13 +94,13 @@ VSO mainVS(VSI si)
#ifdef DEF_DIR
const float3 posUnit = mul(float3(0, 0, 1), matWV33); // Assume no scale in matWV33.
so.lightDirWV_invConeDelta = float4(posUnit, 1);
#elif DEF_SPOT
#elif defined(DEF_SPOT)
so.lightDirWV_invConeDelta.xyz = normalize(mul(float3(0, 0, 1), matWV33));
const float3 posCone = mul(float3(0, 1, 1), matW33);
const float3 dirCone = normalize(posCone);
const float3 dirUnit = normalize(posUnit);
const float coneOut = dot(dirUnit, dirCone);
const float invConeDelta = 1.f / (coneIn - coneOut);
const float invConeDelta = 1.0 / (coneIn - coneOut);
so.lightDirWV_invConeDelta.w = invConeDelta;
so.color_coneOut.a = coneOut;
#endif
@ -134,7 +134,7 @@ DS_ACC_FSO mainFS(VSO si)
// For Dir & Spot: light's direction & cone:
#ifdef DEF_DIR
const float3 lightDirWV = si.lightDirWV_invConeDelta.xyz;
#elif DEF_SPOT
#elif defined(DEF_SPOT)
const float3 lightDirWV = si.lightDirWV_invConeDelta.xyz;
const float invConeDelta = si.lightDirWV_invConeDelta.w;
const float coneOut = si.color_coneOut.a;
@ -144,8 +144,8 @@ DS_ACC_FSO mainFS(VSO si)
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.f;
so.target1 = 0.f;
so.target0 = 0.0;
so.target1 = 0.0;
#if defined(DEF_OMNI) || defined(DEF_SPOT)
if (posWV.z <= lightPosWV.z + radius)
@ -169,20 +169,20 @@ DS_ACC_FSO mainFS(VSO si)
const float3 anisoWV = DS_GetAnisoSpec(rawGBuffer2);
const float2 lamScaleBias = DS_GetLamScaleBias(rawGBuffer2);
const float2 metalMask = DS_GetMetallicity(rawGBuffer2);
const float gloss64 = rawGBuffer2.a * 64.f;
const float gloss64 = rawGBuffer2.a * 64.0;
// Special:
const float skinMask = emission.y;
const float hairMask = metalMask.y;
const float eyeMask = saturate(1.f - gloss64);
const float eyeGloss = 48.f;
const float2 lamScaleBiasWithHair = lerp(lamScaleBias, float2(1, 0.4f), hairMask);
const float eyeMask = saturate(1.0 - gloss64);
const float eyeGloss = 48.0;
const float2 lamScaleBiasWithHair = lerp(lamScaleBias, float2(1, 0.4), hairMask);
const float gloss4K = lerp(gloss64 * gloss64, eyeGloss * eyeGloss, eyeMask);
#ifdef DEF_DIR
const float3 dirToLightWV = -lightDirWV;
const float lightFalloff = 1.f;
const float lightFalloff = 1.0;
#else
const float3 toLightWV = lightPosWV - posWV;
const float3 dirToLightWV = normalize(toLightWV);
@ -192,22 +192,22 @@ DS_ACC_FSO mainFS(VSO si)
#ifdef DEF_SPOT // Extra step for spot light:
const float coneIntensity = ComputeSpotLightConeIntensity(dirToLightWV, lightDirWV, coneOut, invConeDelta);
#else
const float coneIntensity = 1.f;
const float coneIntensity = 1.0;
#endif
const float4 litRet = VerusLit(dirToLightWV, normalWV, dirToEyeWV,
lerp(gloss4K * (2.f - lightFalloff), 12.f, hairMask),
lerp(gloss4K * (2.0 - lightFalloff), 12.0, hairMask),
lamScaleBiasWithHair,
float4(anisoWV, hairMask));
// <Shadow>
float shadowMask = 1.f;
float shadowMask = 1.0;
{
#ifdef DEF_DIR
const float lightPassOffset = saturate((lamScaleBiasWithHair.y - 0.5f) * 5.f) * 2.f;
const float lightPassOffset = saturate((lamScaleBiasWithHair.y - 0.5) * 5.0) * 2.0;
float4 shadowConfig = g_ubShadowFS._shadowConfig;
const float lamBiasMask = saturate(lamScaleBiasWithHair.y * shadowConfig.y);
shadowConfig.y = 1.f - lamBiasMask; // Keep penumbra blurry.
shadowConfig.y = 1.0 - lamBiasMask; // Keep penumbra blurry.
const float3 posForShadow = AdjustPosForShadow(posWV, normalWV, dirToLightWV, -posWV.z, lightPassOffset);
shadowMask = ShadowMapCSM(
g_texShadowCmp,
@ -229,25 +229,25 @@ DS_ACC_FSO mainFS(VSO si)
const float lightFalloffWithCone = lightFalloff * coneIntensity;
const float diffLightMask = lightFalloffWithCone * shadowMask;
const float specLightMask = saturate(lightFalloffWithCone * 2.f) * shadowMask;
const float specLightMask = saturate(lightFalloffWithCone * 2.0) * shadowMask;
// Subsurface scattering effect for front & back faces:
const float3 frontSkinSSSColor = float3(1.6f, 1.2f, 0.3f);
const float3 backSkinSSSColor = float3(1.6f, 0.8f, 0.5f);
const float frontSkinSSSMask = 1.f - litRet.y;
const float3 lightFaceColor = lightColor * lerp(1.f, frontSkinSSSColor, skinMask * frontSkinSSSMask * frontSkinSSSMask);
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 lightFaceColor = lightColor * lerp(1.0, frontSkinSSSColor, skinMask * frontSkinSSSMask * frontSkinSSSMask);
const float3 lightColorSSS = lerp(lightFaceColor, lightColor * backSkinSSSColor, skinMask * litRet.x);
const float3 metalColor = ToMetalColor(rawGBuffer0.rgb);
const float3 specColor = saturate(lerp(1.f, metalColor, saturate(metalMask.x + (hairMask - eyeMask) * 0.4f)) + float3(-0.03f, 0.f, 0.05f) * skinMask);
const float3 specColor = saturate(lerp(1.0, metalColor, saturate(metalMask.x + (hairMask - eyeMask) * 0.4)) + float3(-0.03, 0.0, 0.05) * skinMask);
const float3 maxDiff = lightColorSSS * diffLightMask;
const float3 maxSpec = lightColorSSS * specLightMask * specColor * specMask;
so.target0.rgb = ToSafeHDR(maxDiff * litRet.y);
so.target1.rgb = ToSafeHDR(maxSpec * litRet.z);
so.target0.a = 1.f;
so.target1.a = 1.f;
so.target0.a = 1.0;
so.target1.a = 1.0;
}
#if defined(DEF_OMNI) || defined(DEF_SPOT)
else

View File

@ -73,10 +73,10 @@ VSO mainVS(VSI si)
const float3 posUnit = mul(float3(0, 0, 1), matW33); // Need to know the scale.
so.radius_radiusSq_invRadiusSq.y = dot(posUnit, posUnit);
so.radius_radiusSq_invRadiusSq.x = sqrt(so.radius_radiusSq_invRadiusSq.y);
so.radius_radiusSq_invRadiusSq.z = 1.f / so.radius_radiusSq_invRadiusSq.y;
so.radius_radiusSq_invRadiusSq.z = 1.0 / so.radius_radiusSq_invRadiusSq.y;
const float4 posOrigin = float4(0, 0, 0, 1);
so.lightPosWV = mul(posOrigin, matWV).xyz;
so.color_coneOut = float4(color, 1.f);
so.color_coneOut = float4(color, 1.0);
// </MoreAOParams>
return so;
@ -88,7 +88,7 @@ FSO mainFS(VSO si)
{
FSO so;
so.color = 1.f;
so.color = 1.0;
const float3 ndcPos = si.clipSpacePos.xyz / si.clipSpacePos.w;
@ -105,17 +105,17 @@ FSO mainFS(VSO si)
if (posWV.z <= lightPosWV.z + radius)
{
const float4 rawGBuffer1 = g_texGBuffer1.SampleLevel(g_samGBuffer1, tc0, 0.f);
const float4 rawGBuffer1 = g_texGBuffer1.SampleLevel(g_samGBuffer1, tc0, 0.0);
const float3 normalWV = DS_GetNormal(rawGBuffer1);
const float3 toLightWV = lightPosWV - posWV;
const float3 dirToLightWV = normalize(toLightWV);
const float distToLightSq = dot(toLightWV, toLightWV);
const float lightFalloff = min(0.25f, ComputePointLightIntensity(distToLightSq, radiusSq, invRadiusSq));
const float lightFalloff = min(0.25, ComputePointLightIntensity(distToLightSq, radiusSq, invRadiusSq));
const float nDotL = saturate(0.1f + dot(normalWV, dirToLightWV));
const float nDotL = saturate(0.1 + dot(normalWV, dirToLightWV));
so.color = 1.f - nDotL * lightFalloff;
so.color = 1.0 - nDotL * lightFalloff;
}
else
{

View File

@ -43,18 +43,18 @@ DS_FSO mainFS(VSO si)
{
DS_FSO so;
const float4 rawGBuffer0 = g_texGBuffer0.SampleLevel(g_samGBuffer0, si.tc0, 0.f);
const float4 rawGBuffer1 = g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.f);
const float4 rawGBuffer2 = g_texGBuffer2.SampleLevel(g_samGBuffer2, si.tc0, 0.f);
const float4 rawGBuffer0 = g_texGBuffer0.SampleLevel(g_samGBuffer0, si.tc0, 0.0);
const float4 rawGBuffer1 = g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.0);
const float4 rawGBuffer2 = g_texGBuffer2.SampleLevel(g_samGBuffer2, si.tc0, 0.0);
so.target0 = rawGBuffer0;
so.target1 = rawGBuffer1;
so.target2 = rawGBuffer2;
if (rawGBuffer1.a < 0.5f)
if (rawGBuffer1.a < 0.5)
{
// Defringe:
float minDist = 1000.f;
float minDist = 1000.0;
[unroll] for (int i = -7; i <= 7; ++i)
{
[unroll] for (int j = -7; j <= 7; ++j)
@ -62,15 +62,15 @@ DS_FSO mainFS(VSO si)
const float2 offset = float2(j, i);
const float dist = dot(offset, offset);
const float4 rawKernel1 = g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.f, int2(j, i));
const float4 rawKernel1 = g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.0, int2(j, i));
const float kernelAlpha = rawKernel1.a;
if (kernelAlpha >= 0.5f && dist < minDist)
if (kernelAlpha >= 0.5 && dist < minDist)
{
minDist = dist;
const float4 rawKernel0 = g_texGBuffer0.SampleLevel(g_samGBuffer0, si.tc0, 0.f, int2(j, i));
const float4 rawKernel2 = g_texGBuffer2.SampleLevel(g_samGBuffer2, si.tc0, 0.f, int2(j, i));
const float4 rawKernel0 = g_texGBuffer0.SampleLevel(g_samGBuffer0, si.tc0, 0.0, int2(j, i));
const float4 rawKernel2 = g_texGBuffer2.SampleLevel(g_samGBuffer2, si.tc0, 0.0, int2(j, i));
so.target0 = rawKernel0;
so.target1.rgb = rawKernel1.rgb;

View File

@ -70,14 +70,14 @@ FSO2 mainFS(VSO si)
const float2 ndcPos = si.clipSpacePos.xy;
// <Sample>
const float4 rawGBuffer0 = g_texGBuffer0.SampleLevel(g_samGBuffer0, si.tc0, 0.f);
const float4 rawGBuffer1 = g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.f);
const float4 rawGBuffer0 = g_texGBuffer0.SampleLevel(g_samGBuffer0, si.tc0, 0.0);
const float4 rawGBuffer1 = g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.0);
#ifdef DEF_AO
const float4 rawGBuffer2 = g_texGBuffer2.SampleLevel(g_samGBuffer2, si.tc0, 0.f);
const float4 rawGBuffer2 = g_texGBuffer2.SampleLevel(g_samGBuffer2, si.tc0, 0.0);
#endif
const float rawDepth = g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.f).r;
const float4 rawAccDiff = g_texAccDiff.SampleLevel(g_samAccDiff, si.tc0, 0.f);
const float4 rawAccSpec = g_texAccSpec.SampleLevel(g_samAccSpec, si.tc0, 0.f);
const float rawDepth = g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.0).r;
const float4 rawAccDiff = g_texAccDiff.SampleLevel(g_samAccDiff, si.tc0, 0.0);
const float4 rawAccSpec = g_texAccSpec.SampleLevel(g_samAccSpec, si.tc0, 0.0);
// </Sample>
// White color means 50% albedo, black is not really black:
@ -88,18 +88,18 @@ FSO2 mainFS(VSO si)
const float depth = ToLinearDepth(rawDepth, g_ubComposeFS._zNearFarEx);
#ifdef DEF_AO
const float aoDiff = 0.5f + 0.5f * rawGBuffer2.r;
const float aoDiff = 0.5 + 0.5 * rawGBuffer2.r;
const float aoSpec = aoDiff;
const float aoAmb = rawGBuffer2.r;
#else
const float aoDiff = 1.f;
const float aoSpec = 1.f;
const float aoAmb = 1.f;
const float aoDiff = 1.0;
const float aoSpec = 1.0;
const float aoAmb = 1.0;
#endif
const float3 normalW = mul(normalWV, (float3x3)g_ubComposeFS._matInvV);
const float grayAmbient = Grayscale(ambientColor);
const float3 finalAmbientColor = lerp(grayAmbient * 0.25f, ambientColor, normalW.y * 0.5f + 0.5f);
const float3 finalAmbientColor = lerp(grayAmbient * 0.25, ambientColor, normalW.y * 0.5 + 0.5);
const float3 color = realAlbedo * (rawAccDiff.rgb * aoDiff + finalAmbientColor * aoAmb + emission.x) + rawAccSpec.rgb * aoSpec;
@ -107,17 +107,17 @@ FSO2 mainFS(VSO si)
float3 underwaterColor;
{
const float diffuseMask = ToWaterDiffuseMask(posW.y);
const float refractMask = saturate((diffuseMask - 0.5f) * 2.f);
const float refractMask = saturate((diffuseMask - 0.5) * 2.0);
const float3 waterDiffColorShallowAmbient = g_ubComposeFS._waterDiffColorShallow.rgb * ambientColor;
const float3 waterDiffColorDeepAmbient = g_ubComposeFS._waterDiffColorDeep.rgb * ambientColor;
const float deepAmbientColor = 0.5f + 0.5f * refractMask;
const float deepAmbientColor = 0.5 + 0.5 * refractMask;
const float3 planktonColor = lerp(
waterDiffColorDeepAmbient * deepAmbientColor,
waterDiffColorShallowAmbient,
diffuseMask);
underwaterColor = lerp(realAlbedo * planktonColor * 10.f, color, refractMask);
underwaterColor = lerp(realAlbedo * planktonColor * 10.0, color, refractMask);
const float fog = ComputeFog(depth, g_ubComposeFS._waterDiffColorShallow.a);
underwaterColor = lerp(underwaterColor, planktonColor * 0.1f, fog * saturate(1.f - refractMask + g_ubComposeFS._waterDiffColorDeep.a));
underwaterColor = lerp(underwaterColor, planktonColor * 0.1, fog * saturate(1.0 - refractMask + g_ubComposeFS._waterDiffColorDeep.a));
}
// </Underwater>
@ -131,11 +131,11 @@ FSO2 mainFS(VSO si)
so.target0.rgb = lerp(colorWithFog, realAlbedo, floor(rawDepth));
so.target0.rgb = ToSafeHDR(so.target0.rgb);
so.target0.a = 1.f;
so.target0.a = 1.0;
// <BackgroundColor>
const float2 normalWasSet = ceil(rawGBuffer1.rg);
const float bg = 1.f - saturate(normalWasSet.r + normalWasSet.g);
const float bg = 1.0 - saturate(normalWasSet.r + normalWasSet.g);
so.target0.rgb = lerp(so.target0.rgb, g_ubComposeFS._backgroundColor.rgb, bg * g_ubComposeFS._backgroundColor.a);
// </BackgroundColor>
@ -146,9 +146,9 @@ FSO2 mainFS(VSO si)
const float3 posWV = mul(float4(posW, 1), g_ubComposeFS._matV);
const float3 toPosDirWV = normalize(posWV);
const float dp = -toPosDirWV.z;
const float smoothSpec = pow(saturate(dp), 4096.f * lightGlossScale);
const float spec = saturate((smoothSpec - 0.5f) * 3.f + 0.5f);
so.target0 = max(so.target0, spec * 30000.f);
const float smoothSpec = pow(saturate(dp), 4096.0 * lightGlossScale);
const float spec = saturate((smoothSpec - 0.5) * 3.0 + 0.5);
so.target0 = max(so.target0, spec * 30000.0);
#endif
return so;
@ -160,32 +160,32 @@ FSO mainFS(VSO si)
FSO so;
// <Sample>
const float4 rawGBuffer0 = g_texGBuffer0.SampleLevel(g_samGBuffer0, si.tc0, 0.f);
const float4 rawGBuffer1 = g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.f);
const float4 rawComposed = g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.f);
const float4 rawGBuffer0 = g_texGBuffer0.SampleLevel(g_samGBuffer0, si.tc0, 0.0);
const float4 rawGBuffer1 = g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.0);
const float4 rawComposed = g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.0);
#ifdef DEF_BLOOM
const float4 rawAccDiff = g_texAccDiff.SampleLevel(g_samAccDiff, si.tc0, 0.f);
const float4 rawAccDiff = g_texAccDiff.SampleLevel(g_samAccDiff, si.tc0, 0.0);
#endif
// </Sample>
const float gray = Grayscale(rawComposed.rgb);
const float3 exposedComposed = Desaturate(rawComposed.rgb, saturate(1.f - gray * 0.03f)) * g_ubComposeFS._ambientColor_exposure.a;
so.color.rgb = VerusToneMapping(exposedComposed, 0.5f);
so.color.a = 1.f;
const float3 exposedComposed = Desaturate(rawComposed.rgb, saturate(1.0 - gray * 0.03)) * g_ubComposeFS._ambientColor_exposure.a;
so.color.rgb = VerusToneMapping(exposedComposed, 0.5);
so.color.a = 1.0;
// SolidColor (using special value 1 for emission):
so.color.rgb = lerp(so.color.rgb, rawGBuffer0.rgb, floor(rawGBuffer1.b));
#ifdef DEF_BLOOM
const float3 bloom = rawAccDiff.rgb;
so.color.rgb += bloom * (1.f - so.color.rgb);
so.color.rgb += bloom * (1.0 - so.color.rgb);
#endif
if (false)
{
const float gray = dot(rawComposed.rgb, 1.f / 3.f);
so.color.r = saturate((gray - 5000.f) * 0.001f);
so.color.gb *= 0.5f;
const float gray = dot(rawComposed.rgb, 1.0 / 3.0);
so.color.r = saturate((gray - 5000.0) * 0.001);
so.color.gb *= 0.5;
}
return so;

View File

@ -34,31 +34,31 @@ VSO mainVS(VSI si)
{
VSO so;
const float pointSpriteSize = si.tc0.x * (1.f / 500.f);
const float angle = si.tc0.y * (1.f / 32767.f);
const float pointSpriteSize = si.tc0.x * (1.0 / 500.0);
const float angle = si.tc0.y * (1.0 / 32767.0);
const float3 toEye = g_ubForestVS._eyePos.xyz - si.pos.xyz;
const float distToScreen = length(g_ubForestVS._eyePosScreen.xyz - si.pos.xyz);
const float nearAlpha = saturate((distToScreen - 60.f) * (1.f / 30.f)); // From 60m to 90m.
const float farAlpha = 1.f - saturate((distToScreen - 900.f) * (1.f / 100.f)); // From 900m to 1000m.
const float nearAlpha = saturate((distToScreen - 60.0) * (1.0 / 30.0)); // From 60m to 90m.
const float farAlpha = 1.0 - saturate((distToScreen - 900.0) * (1.0 / 100.0)); // From 900m to 1000m.
so.pos = mul(si.pos, g_ubForestVS._matWVP);
so.tc0 = 0.f;
so.color.rgb = RandomColor(si.pos.xz, 0.3f, 0.2f);
so.tc0 = 0.0;
so.color.rgb = RandomColor(si.pos.xz, 0.3, 0.2);
so.color.a = nearAlpha * farAlpha;
so.psize.xy = pointSpriteSize * (g_ubForestVS._viewportSize.yx * g_ubForestVS._viewportSize.z) * g_ubForestVS._matP._m11;
so.psize.xy *= ceil(so.color.a); // Hide if too close.
so.psize.z = saturate(pointSpriteSize * 0.25f - 0.5f);
so.psize.z = saturate(pointSpriteSize * 0.25 - 0.5);
float2 param0 = toEye.xy;
float2 param1 = toEye.zz;
param0.y = max(0.f, param0.y); // Only upper hemisphere.
param0.y = max(0.0, param0.y); // Only upper hemisphere.
param1.y = length(toEye.xz); // Distance in XZ-plane.
so.angles.xy = (atan2(param0, param1) + _PI) * (0.5f / _PI); // atan2(x, z) and atan2(max(0.f, y), length(toEye.xz)). From 0 to 1.
so.angles.y = (so.angles.y - 0.5f) * 4.f; // Choose this quadrant.
so.angles.xy = (atan2(param0, param1) + _PI) * (0.5 / _PI); // atan2(x, z) and atan2(max(0.0, y), length(toEye.xz)). From 0 to 1.
so.angles.y = (so.angles.y - 0.5) * 4.0; // Choose this quadrant.
so.angles.xy = saturate(so.angles.xy);
so.angles.x = frac(so.angles.x - angle + 0.5f); // Turn.
so.angles.x = frac(so.angles.x - angle + 0.5); // Turn.
return so;
}
@ -83,21 +83,21 @@ void mainGS(point VSO si[1], inout TriangleStream<VSO> stream)
float2 ComputeTexCoords(float2 tc, float2 angles)
{
const float marginBias = 16.f / 512.f;
const float marginScale = 1.f - marginBias * 2.f;
const float marginBias = 16.0 / 512.0;
const float marginScale = 1.0 - marginBias * 2.0;
const float2 tcMargin = tc * marginScale + marginBias;
const float2 frameCount = float2(16, 16);
const float2 frameScale = 1.f / frameCount;
const float2 frameBias = floor(min(angles * frameCount + 0.5f, float2(256, frameCount.y - 0.5f)));
const float2 frameScale = 1.0 / frameCount;
const float2 frameBias = floor(min(angles * frameCount + 0.5, float2(256, frameCount.y - 0.5)));
return (tcMargin + frameBias) * frameScale;
}
float ComputeMask(float2 tc, float alpha)
{
const float2 tcCenter = tc - 0.5f;
const float rad = saturate(dot(tcCenter, tcCenter) * 4.f);
return saturate(rad + (alpha * 2.f - 1.f));
const float2 tcCenter = tc - 0.5;
const float rad = saturate(dot(tcCenter, tcCenter) * 4.0);
return saturate(rad + (alpha * 2.0 - 1.0));
}
#ifdef _FS
@ -109,7 +109,7 @@ void mainFS(VSO si)
const float alpha = g_texGBuffer1.Sample(g_samGBuffer1, tc).a;
clip(alpha * mask - 0.53f);
clip(alpha * mask - 0.53);
}
#else
DS_FSO mainFS(VSO si)
@ -128,10 +128,10 @@ DS_FSO mainFS(VSO si)
so.target2 = rawGBuffer2;
so.target0.rgb *= si.color.rgb;
const float lamBiasRatio = 1.f - ComputeMask(si.tc0, 0.5f);
so.target2.g = lerp(so.target2.g, 0.25f, lamBiasRatio * lamBiasRatio * si.psize.z);
const float lamBiasRatio = 1.0 - ComputeMask(si.tc0, 0.5);
so.target2.g = lerp(so.target2.g, 0.25, lamBiasRatio * lamBiasRatio * si.psize.z);
clip(rawGBuffer1.a * mask - 0.53f);
clip(rawGBuffer1.a * mask - 0.53);
return so;
}

View File

@ -57,43 +57,43 @@ VSO mainVS(VSI si)
float3 inPos;
float3 pos;
float2 center;
float2 pointSpriteSize = 1.f;
float2 pointSpriteSize = 1.0;
float groundHeight;
float3 normal;
float2 tc0;
bool bushMaskOK = true;
{
inPos = si.pos.xyz * (1.f / 1000.f);
inPos = si.pos.xyz * (1.0 / 1000.0);
pos = inPos + float3(si.patchPos.x, 0, si.patchPos.z);
center = si.tc.zw * (1.f / 1000.f) + si.patchPos.xz;
center = si.tc.zw * (1.0 / 1000.0) + si.patchPos.xz;
#ifdef DEF_BILLBOARDS
pointSpriteSize = inPos.y;
pos = float3(center.x, 0.45f * pointSpriteSize.y, center.y);
pos = float3(center.x, 0.45 * pointSpriteSize.y, center.y);
#endif
const float distToEye = distance(pos + float3(0, si.patchPos.y * 0.01f, 0), g_ubGrassVS._posEye.xyz);
const float geomipsLod = log2(clamp(distToEye * (2.f / 100.f), 1.f, 18.f));
const float texelCenter = 0.5f * mapSideInv;
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.5f;
const float2 tcUniform = center * mapSideInv + 0.5f;
const float2 tcMap = pos.xz * mapSideInv + 0.5;
const float2 tcUniform = center * mapSideInv + 0.5;
groundHeight = UnpackTerrainHeight(g_texHeightVS.SampleLevel(g_samHeightVS, tcMap + mipTexelCenter, geomipsLod).r);
pos.y += groundHeight;
const float4 rawNormal = g_texNormalVS.SampleLevel(g_samNormalVS, tcUniform + texelCenter, 0.f);
normal = float3(rawNormal.x, 0, rawNormal.y) * 2.f - 1.f;
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.f).r * 4.f;
const float uShift = frac(layer) - (16.f / 256.f);
const float vShift = floor(layer) * 0.25f;
float vShiftAlt = 0.f;
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.5f; // Every 16th bush uses alternative texture.
tc0 = si.tc.xy * (1.f / 100.f) + float2(uShift, vShift + vShiftAlt);
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.f);
const int mainLayer = round(layer * 4.0);
const int ibushMask = asint(bushMask);
if (!((ibushMask >> mainLayer) & 0x1))
{
@ -103,20 +103,20 @@ VSO mainVS(VSI si)
// </FromTextures>
// <Special>
float phaseShift = 0.f;
float2 windWarp = 0.f;
float top = 0.f;
float phaseShift = 0.0;
float2 windWarp = 0.0;
float top = 0.0;
{
#ifdef DEF_BILLBOARDS
phaseShift = frac(si.pos.w * (1.f / 100.f));
windWarp = 0.f;
top = 0.28f;
phaseShift = frac(si.pos.w * (1.0 / 100.0));
windWarp = 0.0;
top = 0.28;
#else
if (inPos.y >= 0.1f)
if (inPos.y >= 0.1)
{
phaseShift = frac(si.pos.w * (1.f / 100.f));
windWarp = warp.xz * (1.f + turbulence * sin((phase + phaseShift) * (_PI * 2.f)));
top = 1.f;
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
}
@ -126,17 +126,17 @@ VSO mainVS(VSI si)
float3 posWarped = pos;
{
const float distToEye = -mul(float4(posWarped, 1), g_ubGrassVS._matWV).z;
const float distant = saturate((distToEye - 50.f) * (1.f / 50.f)); // [50 to 100] -> [0 to 1].
const float distExt = saturate((distToEye - 25.f) * (1.f / 25.f)); // [25 to 50] -> [0 to 1].
const float distant = saturate((distToEye - 50.0) * (1.0 / 50.0)); // [50 to 100] -> [0 to 1].
const float distExt = saturate((distToEye - 25.0) * (1.0 / 25.0)); // [25 to 50] -> [0 to 1].
const float cliff = dot(normal.xz, normal.xz);
float hide = cliff + step(groundHeight, 1.f) + distant;
float hide = cliff + step(groundHeight, 1.0) + distant;
if (!bushMaskOK)
hide = 1.f;
hide = 1.0;
posWarped.xz -= normal.xz;
#ifdef DEF_BILLBOARDS
const float distExtInv = 1.f - distExt;
posWarped.xz += windWarp * 0.5f;
const float distExtInv = 1.0 - distExt;
posWarped.xz += windWarp * 0.5;
hide += distExtInv * distExtInv;
#else
posWarped.xz += windWarp;
@ -146,7 +146,7 @@ VSO mainVS(VSI si)
hide = saturate(hide);
#ifdef DEF_BILLBOARDS
pointSpriteSize = lerp(pointSpriteSize, float2(0.f, pointSpriteSize.y), hide);
pointSpriteSize = lerp(pointSpriteSize, float2(0.0, pointSpriteSize.y), hide);
#else
posWarped = lerp(posWarped, float3(center.x, posWarped.y, center.y), hide); // Optimize by morphing to center point.
#endif
@ -159,13 +159,13 @@ VSO mainVS(VSI si)
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.f;
so.psize = 1.0;
#ifdef DEF_BILLBOARDS
so.tcOffset_phaseShift.xy = tc0;
so.psize = pointSpriteSize * (g_ubGrassVS._viewportSize.yx * g_ubGrassVS._viewportSize.z) * g_ubGrassVS._matP._m11;
#else
so.normal_top.xyz += float3(0, 0, top * top * 0.25f);
so.normal_top.xyz += float3(0, 0, top * top * 0.25);
#endif
return so;
@ -196,17 +196,17 @@ DS_FSO mainFS(VSO si)
float2 tc = si.tc0;
#ifdef DEF_BILLBOARDS
tc = si.tc0 * 0.23f + si.tcOffset_phaseShift.xy;
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.25f) * 2.f + 0.2f);
const float mask = saturate((gray - 0.25) * 2.0 + 0.2);
const float top = si.normal_top.w;
const float specMask = saturate(top * top * (mask + si.tcOffset_phaseShift.z * 0.1f));
const float gloss = lerp(4.f, 12.f, specMask);
const float specMask = saturate(top * top * (mask + si.tcOffset_phaseShift.z * 0.1));
const float gloss = lerp(4.0, 12.0, specMask);
{
DS_Reset(so);
@ -215,15 +215,15 @@ DS_FSO mainFS(VSO si)
DS_SetSpecMask(so, specMask);
DS_SetNormal(so, normal);
DS_SetEmission(so, 0.f, 0.f);
DS_SetMotionBlurMask(so, 1.f);
DS_SetEmission(so, 0.0, 0.0);
DS_SetMotionBlurMask(so, 1.0);
DS_SetLamScaleBias(so, float2(1.2f, -0.2f), 0.f);
DS_SetMetallicity(so, 0.05f, 0.f);
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.5f);
clip(rawAlbedo.a - 0.5);
return so;
}

View File

@ -84,7 +84,7 @@ VSO mainVS(VSI si)
const float3 inTan = si.tan.xyz;
const float3 inBin = si.bin.xyz;
float addLamBias = 0.f;
float addLamBias = 0.0;
#if defined(DEF_SKINNED) || defined(DEF_ROBOTIC)
const float4 warpMask = float4(
1,
@ -95,14 +95,14 @@ VSO mainVS(VSI si)
#elif defined(DEF_PLANT)
{
const float3 normPos = NormalizePosition(si.pos.xyz);
const float weightY = saturate(normPos.y * normPos.y - 0.01f);
const float3 offsetXYZ = normPos - float3(0.5f, 0.8f, 0.5f);
const float weightXZ = saturate((dot(offsetXYZ.xz, offsetXYZ.xz) - 0.01f) * 0.4f);
const float weightY = saturate(normPos.y * normPos.y - 0.01);
const float3 offsetXYZ = normPos - float3(0.5, 0.8, 0.5);
const float weightXZ = saturate((dot(offsetXYZ.xz, offsetXYZ.xz) - 0.01) * 0.4);
const float phaseShiftY = frac(userColor.x + userColor.z);
const float phaseShiftXZ = frac(phaseShiftY + inPos.x + inPos.z);
const float2 bending = (float2(0.7f, 0.5f) + float2(0.3f, 0.5f) *
sin((g_ubPerObject._userColor.rg + float2(phaseShiftY, phaseShiftXZ)) * (_PI * 2.f))) * float2(weightY, weightXZ);
const float2 bending = (float2(0.7, 0.5) + float2(0.3, 0.5) *
sin((g_ubPerObject._userColor.rg + float2(phaseShiftY, phaseShiftXZ)) * (_PI * 2.0))) * float2(weightY, weightXZ);
const float3x3 matW33 = (float3x3)matW;
const float3x3 matBending = (float3x3)g_ubPerObject._matW;
@ -121,7 +121,7 @@ VSO mainVS(VSI si)
lerp(matW33[2], matNewW33[2], userColor.a),
matW[3]);
const float weight = 1.f - saturate(dot(offsetXYZ, offsetXYZ));
const float weight = 1.0 - saturate(dot(offsetXYZ, offsetXYZ));
addLamBias = (-(weight * weight * weight)) * saturate(userColor.a);
}
const float3 pos = inPos;
@ -137,13 +137,13 @@ VSO mainVS(VSI si)
float3 binWV;
{
#ifdef DEF_SKINNED
const float4 weights = si.bw * (1.f / 255.f);
const float4 weights = si.bw * (1.0 / 255.0);
const float4 indices = si.bi;
float3 posSkinned = 0.f;
float3 nrmSkinned = 0.f;
float3 tanSkinned = 0.f;
float3 binSkinned = 0.f;
float3 posSkinned = 0.0;
float3 nrmSkinned = 0.0;
float3 tanSkinned = 0.0;
float3 binSkinned = 0.0;
for (int i = 0; i < 4; ++i)
{
@ -158,7 +158,7 @@ VSO mainVS(VSI si)
nrmWV = mul(nrmSkinned, (float3x3)matWV);
tanWV = mul(tanSkinned, (float3x3)matWV);
binWV = mul(binSkinned, (float3x3)matWV);
#elif DEF_ROBOTIC
#elif defined(DEF_ROBOTIC)
const int index = si.pos.w;
const mataff matBone = g_ubSkeletonVS._vMatBones[index];
@ -190,7 +190,7 @@ VSO mainVS(VSI si)
#if !defined(DEF_DEPTH)
so.color0 = userColor;
#ifdef DEF_PLANT
so.color0.rgb = RandomColor(userColor.xz, 0.3f, 0.2f);
so.color0.rgb = RandomColor(userColor.xz, 0.3, 0.2);
so.color0.a = addLamBias;
#endif
#if !defined(DEF_DEPTH) && !defined(DEF_SOLID_COLOR)
@ -214,7 +214,7 @@ PCFO PatchConstFunc(const OutputPatch<HSO, 3> outputPatch)
}
[domain("tri")]
[maxtessfactor(7.f)]
[maxtessfactor(7.0)]
[outputcontrolpoints(3)]
[outputtopology("triangle_cw")]
[partitioning(_PARTITION_METHOD)]
@ -251,7 +251,7 @@ VSO mainDS(_IN_DS)
const float3 toEyeWV = g_ubPerFrame._eyePosWV_invTessDistSq.xyz - flatPosWV;
const float distToEyeSq = dot(toEyeWV, toEyeWV);
const float tessStrength = 1.f - saturate(distToEyeSq * g_ubPerFrame._eyePosWV_invTessDistSq.w * 1.1f - 0.1f);
const float tessStrength = 1.0 - saturate(distToEyeSq * g_ubPerFrame._eyePosWV_invTessDistSq.w * 1.1 - 0.1);
const float3 posWV = lerp(flatPosWV, smoothPosWV, tessStrength);
so.pos = ApplyProjection(posWV, g_ubPerFrame._matP);
_DS_COPY(tc0);
@ -273,7 +273,7 @@ VSO mainDS(_IN_DS)
void mainFS(VSO si)
{
const float rawAlbedo = g_texAlbedo.Sample(g_samAlbedo, si.tc0).a;
clip(rawAlbedo - 1.f / 16.f);
clip(rawAlbedo - 1.0 / 16.0);
}
#else
DS_FSO mainFS(VSO si)
@ -330,13 +330,13 @@ DS_FSO mainFS(VSO si)
// <Pick>
const float2 alpha_spec = AlphaSwitch(rawAlbedo, tc0, mm_alphaSwitch);
const float emitAlpha = PickAlpha(rawAlbedo.rgb, mm_emissionPick, 16.f);
const float emitAlpha = PickAlpha(rawAlbedo.rgb, mm_emissionPick, 16.0);
const float eyeAlpha = PickAlphaRound(mm_eyePick, tc0);
const float glossAlpha = PickAlpha(rawAlbedo.rgb, mm_glossPick, 32.f);
const float hairAlpha = round(PickAlpha(rawAlbedo.rgb, mm_hairPick, 16.f));
const float metalAlpha = PickAlpha(rawAlbedo.rgb, mm_metalPick, 16.f);
const float skinAlpha = PickAlpha(rawAlbedo.rgb, mm_skinPick, 16.f);
const float userAlpha = PickAlpha(rawAlbedo.rgb, mm_userPick, 16.f);
const float glossAlpha = PickAlpha(rawAlbedo.rgb, mm_glossPick, 32.0);
const float hairAlpha = round(PickAlpha(rawAlbedo.rgb, mm_hairPick, 16.0));
const float metalAlpha = PickAlpha(rawAlbedo.rgb, mm_metalPick, 16.0);
const float skinAlpha = PickAlpha(rawAlbedo.rgb, mm_skinPick, 16.0);
const float userAlpha = PickAlpha(rawAlbedo.rgb, mm_userPick, 16.0);
// </Pick>
#ifdef DEF_PLANT
@ -348,10 +348,10 @@ DS_FSO mainFS(VSO si)
const float specMask = saturate(alpha_spec.y * mm_specScaleBias.x + mm_specScaleBias.y);
// <Gloss>
float gloss = lerp(4.f, 16.f, alpha_spec.y) * mm_glossScaleBias.x + mm_glossScaleBias.y;
float gloss = lerp(4.0, 16.0, alpha_spec.y) * mm_glossScaleBias.x + mm_glossScaleBias.y;
gloss = lerp(gloss, mm_gloss, glossAlpha);
gloss = lerp(gloss, 4.f + alpha_spec.y, skinAlpha);
gloss = lerp(gloss, 0.f, eyeAlpha);
gloss = lerp(gloss, 4.0 + alpha_spec.y, skinAlpha);
gloss = lerp(gloss, 0.0, eyeAlpha);
// </Gloss>
// <Normal>
@ -375,7 +375,7 @@ DS_FSO mainFS(VSO si)
// <Detail>
{
const float3 rawDetail = g_texDetail.Sample(g_samDetail, tc0 * mm_detailScale).rgb;
rawAlbedo.rgb = rawAlbedo.rgb * lerp(0.5f, rawDetail, mm_detail) * 2.f;
rawAlbedo.rgb = rawAlbedo.rgb * lerp(0.5, rawDetail, mm_detail) * 2.0;
}
// </Detail>
@ -383,14 +383,14 @@ DS_FSO mainFS(VSO si)
float strass;
{
const float rawStrass = g_texStrass.Sample(g_samStrass, tc0 * mm_strassScale).r;
strass = saturate(rawStrass * (0.6f + 1.4f * alpha_spec.y));
strass = saturate(rawStrass * (0.6 + 1.4 * alpha_spec.y));
}
// </Strass>
// <LambertianScaleBias>
float2 lamScaleBias = mm_lamScaleBias + float2(0, lightPassStrength * 8.f * mm_lightPass);
lamScaleBias += float2(-0.1f, -0.3f) * alpha_spec.y + float2(0.1f, 0.2f); // We bring the noise!
lamScaleBias = lerp(lamScaleBias, float2(1, 0.45f), skinAlpha);
float2 lamScaleBias = mm_lamScaleBias + float2(0, lightPassStrength * 8.0 * mm_lightPass);
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);
#ifdef DEF_PLANT
lamScaleBias.y += si.color0.a;
#endif
@ -398,17 +398,17 @@ DS_FSO mainFS(VSO si)
// <RimAlbedo>
{
const float3 newColor = saturate((rawAlbedo.rgb + gray) * 0.6f);
const float mask = 1.f - abs(normalWV.z);
rawAlbedo.rgb = lerp(rawAlbedo.rgb, newColor, mask * mask * (1.f - alpha_spec.y));
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>
// <SpecFresnel>
float specMaskWithFresnel;
{
const float fresnelMask = pow(saturate(1.f - normalWV.z), 5.f);
const float maxSpecAdd = (1.f - specMask) * lerp(0.04f + 0.2f * specMask, 0.6f, metalAlpha);
const float fresnelMask = pow(saturate(1.0 - normalWV.z), 5.0);
const float maxSpecAdd = (1.0 - specMask) * lerp(0.04 + 0.2 * specMask, 0.6, metalAlpha);
specMaskWithFresnel = FresnelSchlick(specMask, maxSpecAdd, fresnelMask);
}
// </SpecFresnel>
@ -417,7 +417,7 @@ DS_FSO mainFS(VSO si)
DS_Reset(so);
DS_SetAlbedo(so, lerp(rawAlbedo.rgb, hairAlbedo, hairAlpha));
DS_SetSpecMask(so, lerp(max(strass, specMaskWithFresnel), 0.15f, eyeAlpha));
DS_SetSpecMask(so, lerp(max(strass, specMaskWithFresnel), 0.15, eyeAlpha));
DS_SetNormal(so, normalWV + NormalDither(rand));
DS_SetEmission(so, emitAlpha * mm_emission, skinAlpha);
@ -425,10 +425,10 @@ DS_FSO mainFS(VSO si)
DS_SetLamScaleBias(so, lamScaleBias, float4(anisoWV, hairAlpha));
DS_SetMetallicity(so, metalAlpha, hairAlpha);
DS_SetGloss(so, gloss * lerp(toksvigFactor, 1.f, eyeAlpha));
DS_SetGloss(so, gloss * lerp(toksvigFactor, 1.0, eyeAlpha));
}
clip(alpha_spec.x - 0.5f);
clip(alpha_spec.x - 0.5);
#endif
return so;
@ -438,27 +438,27 @@ DS_FSO mainFS(VSO si)
//@main:#
//@main:#Instanced INSTANCED
//@main:#Plant PLANT INSTANCED
//@main:#Robotic ROBOTIC
//@main:#Skinned SKINNED
//@main:#Plant PLANT INSTANCED
//@main:#Tess TESS (VHDF)
//@main:#TessInstanced TESS INSTANCED (VHDF)
//@main:#TessPlant TESS PLANT INSTANCED (VHDF)
//@main:#TessRobotic TESS ROBOTIC (VHDF)
//@main:#TessSkinned TESS SKINNED (VHDF)
//@main:#TessPlant TESS PLANT INSTANCED (VHDF)
//@main:#Depth DEPTH
//@main:#DepthInstanced DEPTH INSTANCED
//@main:#DepthPlant DEPTH PLANT INSTANCED
//@main:#DepthRobotic DEPTH ROBOTIC
//@main:#DepthSkinned DEPTH SKINNED
//@main:#DepthPlant DEPTH PLANT INSTANCED
//@main:#DepthTess DEPTH TESS (VHDF)
//@main:#DepthTessInstanced DEPTH TESS INSTANCED (VHDF)
//@main:#DepthTessPlant DEPTH TESS PLANT INSTANCED (VHDF)
//@main:#DepthTessRobotic DEPTH TESS ROBOTIC (VHDF)
//@main:#DepthTessSkinned DEPTH TESS SKINNED (VHDF)
//@main:#DepthTessPlant DEPTH TESS PLANT INSTANCED (VHDF)
//@main:#SolidColor SOLID_COLOR
//@main:#SolidColorInstanced SOLID_COLOR INSTANCED

View File

@ -48,15 +48,15 @@ FSO mainFS(VSO si)
{
FSO so;
const float4 rawGBuffer0 = g_texGBuffer0.SampleLevel(g_samGBuffer0, si.tc0, 0.f);
const float4 rawGBuffer2 = g_texGBuffer2.SampleLevel(g_samGBuffer2, si.tc0, 0.f);
const float4 rawReflect = g_texReflect.SampleLevel(g_samReflect, si.tc0, 0.f);
const float4 rawGBuffer0 = g_texGBuffer0.SampleLevel(g_samGBuffer0, si.tc0, 0.0);
const float4 rawGBuffer2 = g_texGBuffer2.SampleLevel(g_samGBuffer2, si.tc0, 0.0);
const float4 rawReflect = g_texReflect.SampleLevel(g_samReflect, si.tc0, 0.0);
const float specMask = rawGBuffer0.a;
const float3 metalColor = ToMetalColor(rawGBuffer0.rgb);
const float2 metalMask = DS_GetMetallicity(rawGBuffer2);
so.color.rgb = rawReflect.rgb * lerp(1.f, metalColor, metalMask.x) * specMask;
so.color.a = 1.f;
so.color.rgb = rawReflect.rgb * lerp(1.0, metalColor, metalMask.x) * specMask;
so.color.a = 1.0;
return so;
}

View File

@ -7,7 +7,7 @@
#include "LibTessellation.hlsl"
#include "DS_Terrain.inc.hlsl"
#define DETAIL_TC_SCALE 8.f
#define DETAIL_TC_SCALE 8.0
ConstantBuffer<UB_TerrainVS> g_ubTerrainVS : register(b0, space0);
ConstantBuffer<UB_TerrainFS> g_ubTerrainFS : register(b0, space1);
@ -48,7 +48,7 @@ struct VSO
#endif
};
static const float g_layerScale = 1.f / 8.f;
static const float g_layerScale = 1.0 / 8.0;
#ifdef _VS
VSO mainVS(VSI si)
@ -59,29 +59,29 @@ VSO mainVS(VSI si)
const float mapSideInv = g_ubTerrainVS._eyePos_mapSideInv.w;
const float2 edgeCorrection = si.pos.yw;
si.pos.yw = 0.f;
si.pos.yw = 0.0;
float3 pos = si.pos.xyz + si.posPatch.xyz;
const float2 tcMap = pos.xz * mapSideInv + 0.5f; // Range [0, 1).
const float2 posBlend = pos.xz + edgeCorrection * 0.5f;
const float2 tcMap = pos.xz * mapSideInv + 0.5; // Range [0, 1).
const float2 posBlend = pos.xz + edgeCorrection * 0.5;
// <HeightAndNormal>
float3 inNrm;
{
const float approxHeight = UnpackTerrainHeight(g_texHeightVS.SampleLevel(g_samHeightVS, tcMap + (0.5f * mapSideInv) * 16.f, 4.f).r);
const float approxHeight = UnpackTerrainHeight(g_texHeightVS.SampleLevel(g_samHeightVS, tcMap + (0.5 * mapSideInv) * 16.0, 4.0).r);
pos.y = approxHeight;
const float distToEye = distance(pos, eyePos);
const float geomipsLod = log2(clamp(distToEye * (2.f / 100.f), 1.f, 18.f));
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.f;
const float2 texelCenterAB = (0.5f * mapSideInv) * exp2(float2(geomipsLodBase, geomipsLodNext));
const float geomipsLodNext = geomipsLodBase + 1.0;
const float2 texelCenterAB = (0.5 * mapSideInv) * exp2(float2(geomipsLodBase, geomipsLodNext));
const float yA = UnpackTerrainHeight(g_texHeightVS.SampleLevel(g_samHeightVS, tcMap + texelCenterAB.xx, geomipsLodBase).r);
const float yB = UnpackTerrainHeight(g_texHeightVS.SampleLevel(g_samHeightVS, tcMap + texelCenterAB.yy, geomipsLodNext).r);
pos.y = lerp(yA, yB, geomipsLodFrac);
const float4 rawNormal = g_texNormalVS.SampleLevel(g_samNormalVS, tcMap + texelCenterAB.xx, geomipsLodBase);
inNrm = float3(rawNormal.x, 0, rawNormal.y) * 2.f - 1.f;
inNrm = float3(rawNormal.x, 0, rawNormal.y) * 2.0 - 1.0;
inNrm.y = ComputeNormalZ(inNrm.xz);
}
// </HeightAndNormal>
@ -91,10 +91,10 @@ VSO mainVS(VSI si)
#if !defined(DEF_DEPTH)
so.layerForChannel = si.layerForChannel;
#if !defined(DEF_DEPTH) && !defined(DEF_SOLID_COLOR)
so.tcBlend.xy = posBlend * mapSideInv + 0.5f;
so.tcBlend.xy = posBlend * mapSideInv + 0.5;
so.tcBlend.z = pos.y;
so.tcLayer_tcMap.xy = pos.xz * g_layerScale;
so.tcLayer_tcMap.zw = (pos.xz + 0.5f) * mapSideInv + 0.5f; // Texel's center.
so.tcLayer_tcMap.zw = (pos.xz + 0.5) * mapSideInv + 0.5; // Texel's center.
#endif
#endif
@ -113,7 +113,7 @@ PCFO PatchConstFunc(const OutputPatch<HSO, 3> outputPatch)
}
[domain("tri")]
[maxtessfactor(7.f)]
[maxtessfactor(7.0)]
[outputcontrolpoints(3)]
[outputtopology("triangle_cw")]
[partitioning(_PARTITION_METHOD)]
@ -159,7 +159,7 @@ VSO mainDS(_IN_DS)
#ifndef DEF_DEPTH
// Fade to non-tess mesh at 80 meters. LOD 1 starts at 100 meters.
const float tessStrength = saturate((1.f - saturate(smoothPosWV.z / -80.f)) * 4.f);
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
@ -183,13 +183,13 @@ DS_FSO mainFS(VSO si)
const float2 tcMap = si.tcLayer_tcMap.zw;
const float4 rawBlend = g_texBlend.Sample(g_samBlend, si.tcBlend.xy);
float4 weights = float4(rawBlend.rgb, 1.f - dot(rawBlend.rgb, float3(1, 1, 1)));
float4 weights = float4(rawBlend.rgb, 1.0 - dot(rawBlend.rgb, float3(1, 1, 1)));
// <Basis>
float3 basisTan, basisBin, basisNrm;
{
const float4 rawBasis = g_texNormal.Sample(g_samNormal, tcMap);
const float4 basis = rawBasis * 2.f - 1.f;
const float4 basis = rawBasis * 2.0 - 1.0;
basisNrm = float3(basis.x, 0, basis.y);
basisTan = float3(0, basis.z, basis.w);
basisNrm.y = ComputeNormalZ(basisNrm.xz);
@ -218,11 +218,11 @@ DS_FSO mainFS(VSO si)
Grayscale(rawAlbedos[0].rgb),
Grayscale(rawAlbedos[1].rgb),
Grayscale(rawAlbedos[2].rgb),
Grayscale(rawAlbedos[3].rgb)) - 0.25f) * 8.f + 0.25f);
Grayscale(rawAlbedos[3].rgb)) - 0.25) * 8.0 + 0.25);
weights = saturate(weights + weights * mask);
const float weightsSum = dot(weights, 1.f);
const float weightsSum = dot(weights, 1.0);
weights /= weightsSum;
float4 accAlbedo = 0.f;
float4 accAlbedo = 0.0;
accAlbedo += rawAlbedos[0] * weights.r;
accAlbedo += rawAlbedos[1] * weights.g;
accAlbedo += rawAlbedos[2] * weights.b;
@ -251,26 +251,26 @@ DS_FSO mainFS(VSO si)
{
const float dryMask = saturate(si.tcBlend.z);
const float dryMask3 = dryMask * dryMask * dryMask;
const float wetMask = 1.f - dryMask;
const float wetMask = 1.0 - dryMask;
const float wetMask3 = wetMask * wetMask * wetMask;
albedo.rgb *= dryMask3 * 0.5f + 0.5f;
specMask = dryMask * saturate(specMask + wetMask3 * wetMask3 * 0.1f);
waterGlossBoost = min(32.f, dryMask * wetMask3 * 100.f);
albedo.rgb *= dryMask3 * 0.5 + 0.5;
specMask = dryMask * saturate(specMask + wetMask3 * wetMask3 * 0.1);
waterGlossBoost = min(32.0, dryMask * wetMask3 * 100.0);
}
// </Water>
const float gloss = lerp(3.3f, 15.f, specMask) + waterGlossBoost;
const float gloss = lerp(3.3, 15.0, specMask) + waterGlossBoost;
// <Normal>
float3 normalWV;
float toksvigFactor;
{
float4 accNormal = 0.f;
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;
accNormal = lerp(accNormal, float4(0, 0.5f, 0.5f, 0.5f), 0.5f);
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);
@ -280,15 +280,15 @@ DS_FSO mainFS(VSO si)
// <Detail>
{
const float3 rawDetail = g_texDetail.Sample(g_samDetail, tcLayer * DETAIL_TC_SCALE).rgb;
albedo.rgb = albedo.rgb * lerp(0.5f, rawDetail, detailStrength) * 2.f;
albedo.rgb = albedo.rgb * lerp(0.5, rawDetail, detailStrength) * 2.0;
}
// </Detail>
// <SpecFresnel>
float specMaskWithFresnel;
{
const float fresnelMask = pow(saturate(1.f - normalWV.z), 5.f);
const float maxSpecAdd = (1.f - specMask) * (0.04f + 0.2f * specMask);
const float fresnelMask = pow(saturate(1.0 - normalWV.z), 5.0);
const float maxSpecAdd = (1.0 - specMask) * (0.04 + 0.2 * specMask);
specMaskWithFresnel = FresnelSchlick(specMask, maxSpecAdd, fresnelMask);
}
// </SpecFresnel>
@ -300,11 +300,11 @@ DS_FSO mainFS(VSO si)
DS_SetSpecMask(so, specMaskWithFresnel);
DS_SetNormal(so, normalWV + NormalDither(rand));
DS_SetEmission(so, 0.f, 0.f);
DS_SetMotionBlurMask(so, 1.f);
DS_SetEmission(so, 0.0, 0.0);
DS_SetMotionBlurMask(so, 1.0);
DS_SetLamScaleBias(so, g_ubTerrainFS._lamScaleBias.xy, float4(0, 0, 1, 0));
DS_SetMetallicity(so, 0.05f, 0.f);
DS_SetMetallicity(so, 0.05, 0.0);
DS_SetGloss(so, gloss * toksvigFactor);
}
#endif

View File

@ -34,7 +34,7 @@ VSO mainVS(VSI si)
VSO so;
so.pos = si.pos;
so.tc0 = si.tc0.xy / 32767.f;
so.tc0 = si.tc0.xy / 32767.0;
so.color = ColorToLinear(si.color);
return so;

View File

@ -28,88 +28,82 @@ struct CSI
#define DIM_CASE_WE_HO 2
#define DIM_CASE_WO_HO 3
groupshared float gs_R[64];
groupshared float gs_G[64];
groupshared float gs_B[64];
groupshared float gs_A[64];
groupshared float gs_channelR[THREAD_GROUP_SIZE * THREAD_GROUP_SIZE];
groupshared float gs_channelG[THREAD_GROUP_SIZE * THREAD_GROUP_SIZE];
groupshared float gs_channelB[THREAD_GROUP_SIZE * THREAD_GROUP_SIZE];
groupshared float gs_channelA[THREAD_GROUP_SIZE * THREAD_GROUP_SIZE];
void StoreColor(uint index, float4 color)
{
gs_R[index] = color.r;
gs_G[index] = color.g;
gs_B[index] = color.b;
gs_A[index] = color.a;
gs_channelR[index] = color.r;
gs_channelG[index] = color.g;
gs_channelB[index] = color.b;
gs_channelA[index] = color.a;
}
float4 LoadColor(uint index)
{
return float4(gs_R[index], gs_G[index], gs_B[index], gs_A[index]);
return float4(gs_channelR[index], gs_channelG[index], gs_channelB[index], gs_channelA[index]);
}
float4 PackColor(float4 x)
{
if (g_ub._srgb)
{
return ColorToSRGB(x);
}
else
{
return x;
}
return g_ub._srgb ? ColorToSRGB(x) : x;
}
#ifdef _CS
[numthreads(THREAD_GROUP_SIZE, THREAD_GROUP_SIZE, 1)]
void mainCS(CSI si)
{
float4 srcColor1 = 0.f;
float2 tc = 0.f;
float4 srcColor1 = 0.0;
float2 tc = 0.0;
switch (g_ub._srcDimensionCase)
{
case DIM_CASE_WE_HE:
{
tc = g_ub._texelSize * (si.dispatchThreadID.xy + 0.5f);
tc = g_ub._dstTexelSize * (si.dispatchThreadID.xy + 0.5);
srcColor1 = g_texSrcMip.SampleLevel(g_samSrcMip, tc, g_ub._srcMipLevel);
}
break;
case DIM_CASE_WO_HE:
{
tc = g_ub._texelSize * (si.dispatchThreadID.xy + float2(0.25f, 0.5f));
const float2 offset = g_ub._texelSize * float2(0.5f, 0.f);
tc = g_ub._dstTexelSize * (si.dispatchThreadID.xy + float2(0.25, 0.5));
const float2 offset = g_ub._dstTexelSize * float2(0.5, 0.0);
srcColor1 = lerp(
g_texSrcMip.SampleLevel(g_samSrcMip, tc, g_ub._srcMipLevel),
g_texSrcMip.SampleLevel(g_samSrcMip, tc + offset, g_ub._srcMipLevel),
0.5f);
0.5);
}
break;
case DIM_CASE_WE_HO:
{
tc = g_ub._texelSize * (si.dispatchThreadID.xy + float2(0.5f, 0.25f));
const float2 offset = g_ub._texelSize * float2(0.f, 0.5f);
tc = g_ub._dstTexelSize * (si.dispatchThreadID.xy + float2(0.5, 0.25));
const float2 offset = g_ub._dstTexelSize * float2(0.0, 0.5);
srcColor1 = lerp(
g_texSrcMip.SampleLevel(g_samSrcMip, tc, g_ub._srcMipLevel),
g_texSrcMip.SampleLevel(g_samSrcMip, tc + offset, g_ub._srcMipLevel),
0.5f);
0.5);
}
break;
case DIM_CASE_WO_HO:
{
tc = g_ub._texelSize * (si.dispatchThreadID.xy + float2(0.25f, 0.25f));
const float2 offset = g_ub._texelSize * 0.5f;
tc = g_ub._dstTexelSize * (si.dispatchThreadID.xy + 0.25);
const float2 offset = g_ub._dstTexelSize * 0.5;
srcColor1 = lerp(
lerp(
g_texSrcMip.SampleLevel(g_samSrcMip, tc, g_ub._srcMipLevel),
g_texSrcMip.SampleLevel(g_samSrcMip, tc + float2(offset.x, 0.f), g_ub._srcMipLevel),
0.5f),
lerp(g_texSrcMip.SampleLevel(g_samSrcMip, tc + float2(0.f, offset.y), g_ub._srcMipLevel),
g_texSrcMip.SampleLevel(g_samSrcMip, tc + float2(offset.x, offset.y), g_ub._srcMipLevel),
0.5f),
0.5f);
g_texSrcMip.SampleLevel(g_samSrcMip, tc + float2(offset.x, 0.0), g_ub._srcMipLevel),
0.5),
lerp(
g_texSrcMip.SampleLevel(g_samSrcMip, tc + float2(0.0, offset.y), g_ub._srcMipLevel),
g_texSrcMip.SampleLevel(g_samSrcMip, tc + offset, g_ub._srcMipLevel),
0.5),
0.5);
}
break;
}
@ -117,32 +111,30 @@ void mainCS(CSI si)
#ifdef DEF_EXPOSURE
if (0 == g_ub._srcMipLevel)
{
const float2 delta = 0.5f - tc;
const float2 centerWeighted = saturate((dot(delta, delta) - float2(0.1f, 0.01f)) * float2(4.f, 200.f));
const float2 delta = 0.5 - tc;
const float2 centerWeighted = saturate((dot(delta, delta) - float2(0.1, 0.01)) * float2(4.0, 200.0));
const float gray = Grayscale(srcColor1.rgb);
const float2 mask = saturate((float2(-1, 1) * gray + float2(0.1f, -0.99f)) * float2(10, 100));
const float2 mask = saturate((float2(-1, 1) * gray + float2(0.1, -0.99)) * float2(10, 100));
const float filter = max(mask.x, mask.y) * centerWeighted.y;
const float alpha = max(centerWeighted.x, filter);
srcColor1.rgb = lerp(srcColor1.rgb, 0.5f, alpha);
srcColor1.a = 1.f - alpha;
srcColor1.rgb = lerp(srcColor1.rgb, 0.5, alpha);
srcColor1.a = 1.0 - alpha;
}
#endif
g_uavOutMip1[si.dispatchThreadID.xy] = PackColor(srcColor1);
StoreColor(si.groupIndex, srcColor1);
if (1 == g_ub._mipLevelCount)
return;
StoreColor(si.groupIndex, srcColor1);
GroupMemoryBarrierWithGroupSync();
if ((si.groupIndex & 0x9) == 0) // 16 threads:
if ((si.groupIndex & 0x9) == 0) // 16 threads (0, 2, 4, 6, 16, 18, 20, 22, etc.):
{
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.25f * (srcColor1 + srcColor2 + srcColor3 + srcColor4);
srcColor1 = 0.25 * (srcColor1 + srcColor2 + srcColor3 + srcColor4);
g_uavOutMip2[si.dispatchThreadID.xy >> 1] = PackColor(srcColor1);
StoreColor(si.groupIndex, srcColor1);
@ -150,15 +142,14 @@ void mainCS(CSI si)
if (2 == g_ub._mipLevelCount)
return;
GroupMemoryBarrierWithGroupSync();
if ((si.groupIndex & 0x1B) == 0) // 4 threads:
if ((si.groupIndex & 0x1B) == 0) // 4 threads (0, 4, 32, 36):
{
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.25f * (srcColor1 + srcColor2 + srcColor3 + srcColor4);
srcColor1 = 0.25 * (srcColor1 + srcColor2 + srcColor3 + srcColor4);
g_uavOutMip3[si.dispatchThreadID.xy >> 2] = PackColor(srcColor1);
StoreColor(si.groupIndex, srcColor1);
@ -166,7 +157,6 @@ void mainCS(CSI si)
if (3 == g_ub._mipLevelCount)
return;
GroupMemoryBarrierWithGroupSync();
if (si.groupIndex == 0) // 1 thread:
@ -174,7 +164,7 @@ void mainCS(CSI si)
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.25f * (srcColor1 + srcColor2 + srcColor3 + srcColor4);
srcColor1 = 0.25 * (srcColor1 + srcColor2 + srcColor3 + srcColor4);
g_uavOutMip4[si.dispatchThreadID.xy >> 3] = PackColor(srcColor1);
}

View File

@ -6,5 +6,5 @@ VERUS_UBUFFER UB_GenerateMips
int _mipLevelCount;
int _srcDimensionCase;
int _srgb;
float2 _texelSize;
float2 _dstTexelSize;
};

View File

@ -29,7 +29,7 @@
# else
# define VK_POINT_SIZE
# endif
# define VK_SET_POINT_SIZE so.psize = 1.f
# define VK_SET_POINT_SIZE so.psize = 1.0
#else
# define VK_LOCATION(x)
# define VK_LOCATION_POSITION
@ -46,7 +46,7 @@
# define VK_SUBPASS_INPUT(index, tex, sam, t, s, space)\
Texture2D tex : register(t, space);\
SamplerState sam : register(s, space)
# define VK_SUBPASS_LOAD(tex, sam, tc) tex.SampleLevel(sam, tc, 0.f)
# define VK_SUBPASS_LOAD(tex, sam, tc) tex.SampleLevel(sam, tc, 0.0)
# define VK_POINT_SIZE
# define VK_SET_POINT_SIZE
@ -66,9 +66,9 @@
const float3x3 matFromTBN = float3x3(tan, bin, nrm);\
const float3x3 matToTBN = transpose(matFromTBN);
#define _PI 3.141592654f
#define _PI 3.141592654
#define _SINGULARITY_FIX 0.001f
#define _SINGULARITY_FIX 0.001
#define _MAX_TERRAIN_LAYERS 32
@ -88,45 +88,45 @@ float2 ToNdcPos(float2 tc)
float2 ToTexCoords(float2 ndcPos)
{
return ndcPos * float2(0.5f, -0.5f) + 0.5f;
return ndcPos * float2(0.5, -0.5) + 0.5;
}
// Asymmetric abs():
float2 AsymAbs(float2 x, float negScale = -1.f, float posScale = 1.f)
float2 AsymAbs(float2 x, float negScale = -1.0, float posScale = 1.0)
{
return x * lerp(posScale, negScale, step(x, 0.f));
return x * lerp(posScale, negScale, step(x, 0.0));
}
float3 Rand(float2 uv)
{
return frac(sin(dot(uv, float2(12.9898f, 78.233f)) * float3(1, 2, 3)) * 43758.5453f);
return frac(sin(dot(uv, float2(12.9898, 78.233)) * float3(1, 2, 3)) * 43758.5453);
}
float4 Rand2(float2 pos)
{
const float4 primeA = float4(9.907f, 9.923f, 9.929f, 9.931f);
const float4 primeB = float4(9.941f, 9.949f, 9.967f, 9.973f);
const float4 primeA = float4(9.907, 9.923, 9.929, 9.931);
const float4 primeB = float4(9.941, 9.949, 9.967, 9.973);
return frac(primeA * pos.x + primeB * pos.y);
}
float3 RandomColor(float2 pos, float randLum, float randRGB)
{
const float4 r = Rand2(pos);
return (1.f - randLum - randRGB) + r.a * randLum + r.rgb * randRGB;
return (1.0 - randLum - randRGB) + r.a * randLum + r.rgb * randRGB;
}
float3 NormalDither(float3 rand)
{
const float2 rr = rand.xy * (1.f / 333.f) - (0.5f / 333.f);
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.5f, 0.5f),
float2(-0.5f, -0.5f),
float2(0.5f, 0.5f),
float2(0.5f, -0.5f)
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] =
@ -141,12 +141,12 @@ static const float2 _POINT_SPRITE_TEX_COORDS[4] =
float3 ToRealAlbedo(float3 albedo)
{
return max(albedo.rgb * 0.5f, 0.0001f);
return max(albedo.rgb * 0.5, 0.0001);
}
float3 ToMetalColor(float3 albedo)
{
const float gray = dot(albedo, 1.f / 3.f);
const float gray = dot(albedo, 1.0 / 3.0);
return saturate(albedo / (gray + _SINGULARITY_FIX));
}
@ -155,7 +155,7 @@ float3 ToSafeHDR(float3 hdr)
{
// Typical ambient is 4000.
// Typical sunlight is 16000.
return clamp(hdr, 0.f, 32000.f);
return clamp(hdr, 0.0, 32000.0);
}
// See: https://en.wikipedia.org/wiki/Schlick%27s_approximation
@ -168,22 +168,80 @@ float FresnelSchlick(float minRef, float maxAdd, float power)
float UnpackTerrainHeight(float height)
{
return height * 0.01f;
return height * 0.01;
}
float ToLandMask(float height)
{
return saturate(height * 0.2f + 1.f); // [-5 to 0] -> [0 to 1]
return saturate(height * 0.2 + 1.0); // [-5 to 0] -> [0 to 1]
}
float ToWaterDiffuseMask(float height)
{
const float mask = saturate(height * 0.02f + 1.f); // [-50 to 0] -> [0 to 1]
const float mask = saturate(height * 0.02 + 1.0); // [-50 to 0] -> [0 to 1]
return mask * mask * mask;
}
float3 ReflectionDimming(float3 hdr, float scale)
{
const float gray = dot(hdr, 1.f / 3.f);
return lerp(hdr * scale, hdr, saturate(gray * (1.f / 65536.f)));
const float gray = dot(hdr, 1.0 / 3.0);
return lerp(hdr * scale, hdr, saturate(gray * (1.0 / 65536.0)));
}
// Also known as The Multiplier Map, for hemicube's shape compensation.
float ComputeHemicubeMask(float2 tc)
{
// Hint. Compare two pixels when looking at them from the focal point of hemicube:
// one is in the middle of hemicube's face and the other one is at the corner.
// What will be the ratio of their areas (solid angles)?
const float2 atc = abs(tc * 2.0 - 1.0);
if (atc.y < 0.5)
{
if (atc.x < 0.5)
{
const float3 faceNrm = float3(0, 0, 1);
const float3 v = float3(atc.x * 2.0, atc.y * 2.0, 1);
const float len = length(v);
const float3 vn = v / len;
const float cosLaw = vn.z;
const float distFactor = 1.0 / (len * len);
const float faceFactor = dot(vn, faceNrm);
return cosLaw * distFactor * faceFactor;
}
else
{
const float3 faceNrm = float3(1, 0, 0);
const float3 v = float3(1, atc.y * 2.0, 2.0 - 2.0 * atc.x);
const float len = length(v);
const float3 vn = v / len;
const float cosLaw = vn.z;
const float distFactor = 1.0 / (len * len);
const float faceFactor = dot(vn, faceNrm);
return cosLaw * distFactor * faceFactor;
}
}
else
{
if (atc.x < 0.5)
{
const float3 faceNrm = float3(0, 1, 0);
const float3 v = float3(atc.x * 2.0, 1, 2.0 - 2.0 * atc.y);
const float len = length(v);
const float3 vn = v / len;
const float cosLaw = vn.z;
const float distFactor = 1.0 / (len * len);
const float faceFactor = dot(vn, faceNrm);
return cosLaw * distFactor * faceFactor;
}
else
{
return 0.0;
}
}
}

View File

@ -3,41 +3,41 @@
// See: https://en.wikipedia.org/wiki/Grayscale
float Grayscale(float3 color)
{
return dot(color, float3(0.2126f, 0.7152f, 0.0722f));
return dot(color, float3(0.2126, 0.7152, 0.0722));
}
float3 Desaturate(float3 color, float alpha, float lum = 1.f)
float3 Desaturate(float3 color, float alpha, float lum = 1.0)
{
const float gray = Grayscale(color) * lum;
return lerp(color, gray, alpha);
}
// See: http://www.chilliant.com/rgb2hsv.html
// See: https://www.chilliant.com/rgb2hsv.html
float3 ConvertRGBtoHCV(float3 color)
{
const float4 p = (color.g < color.b) ? float4(color.bg, -1.f, 2.f / 3.f) : float4(color.gb, 0.f, -1.f / 3.f);
const float4 p = (color.g < color.b) ? float4(color.bg, -1.0, 2.0 / 3.0) : float4(color.gb, 0.0, -1.0 / 3.0);
const float4 q = (color.r < p.x) ? float4(p.xyw, color.r) : float4(color.r, p.yzx);
const float c = q.x - min(q.w, q.y);
const float h = abs((q.w - q.y) / (6.f * c + _SINGULARITY_FIX) + q.z);
const float h = abs((q.w - q.y) / (6.0 * c + _SINGULARITY_FIX) + q.z);
return float3(h, c, q.x);
}
float Contrast(float gray, float contrast)
{
return saturate(((gray - 0.5f) * contrast) + 0.5f);
return saturate(((gray - 0.5) * contrast) + 0.5);
}
float3 Overlay(float3 colorA, float3 colorB)
{
const float3 x = step(0.5f, colorA);
return lerp(colorA * colorB * 2.f, 1.f - (2.f * (1.f - colorA) * (1.f - colorB)), x);
const float3 x = step(0.5, colorA);
return lerp(colorA * colorB * 2.0, 1.0 - (2.0 * (1.0 - colorA) * (1.0 - colorB)), x);
}
// <AlbedoPick>
float PickAlpha(float3 albedo, float4 pick, float sharp)
{
const float3 d = albedo - pick.rgb;
return saturate(1.f - dot(d, d) * sharp) * pick.a;
return saturate(1.0 - dot(d, d) * sharp) * pick.a;
}
float PickAlphaRound(float4 pick, float2 tc)
@ -53,47 +53,47 @@ float2 AlphaSwitch(float4 albedo, float2 tc, float2 alphaSwitch)
if (all(frac(tc) >= alphaSwitch))
return float2(albedo.a, Grayscale(albedo.rgb)); // 8-bit alpha.
else
return saturate(float2(albedo.a * 8.f, (albedo.a - 0.15f) / 0.85f)); // 5-bit alpha.
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.04045f ? x.rgb * (1.f / 12.92f) : pow(abs(x.rgb + 0.055f) / 1.055f, 2.4f);
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.0031308f ? 12.92f * x.rgb : 1.055f * pow(abs(x.rgb), 1.f / 2.4f) - 0.055f;
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);
}
float3 ToneMappingReinhard(float3 x)
{
return x / (1.f + x);
return x / (1.0 + x);
}
float3 ToneMappingInvReinhard(float3 x)
{
return -x / (x - 1.f);
return -x / (x - 1.0);
}
// 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;
const float a = 2.51;
const float b = 0.03;
const float c = 2.43;
const float d = 0.59;
const float e = 0.14;
return saturate((x * (a * x + b)) / (x * (c * x + d) + e));
}
float3 VerusToneMapping(float3 hdr, float filmicLook = 1.f)
float3 VerusToneMapping(float3 hdr, float filmicLook = 1.0)
{
const float maxValue = max(max(hdr.r, hdr.g), hdr.b);
const float desatMask = saturate(maxValue * 0.15f);
const float desatMask = saturate(maxValue * 0.15);
hdr = lerp(hdr, maxValue, desatMask * desatMask); // Color crosstalk.
const float3 ldr = lerp(1.f - exp(-hdr), ToneMappingACES(hdr), filmicLook);
return saturate(ldr * 1.2f - 0.002f); // Add some clipping.
const float3 ldr = lerp(1.0 - exp(-hdr), ToneMappingACES(hdr), filmicLook);
return saturate(ldr * 1.2 - 0.002); // Add some clipping.
}

View File

@ -16,38 +16,38 @@ struct DS_ACC_FSO
// See: http://aras-p.info/texts/CompactNormalStorage.html#method04spheremap
float2 EncodeNormal(float3 n)
{
const float rf = rsqrt(abs(8.f * n.z + 8.f));
return n.xy * rf + 0.5f;
const float rf = rsqrt(abs(8.0 * n.z + 8.0));
return n.xy * rf + 0.5;
}
float3 DecodeNormal(float2 enc)
{
const float2 fenc = enc * 4.f - 2.f;
const float2 fenc = enc * 4.0 - 2.0;
const float f = dot(fenc, fenc);
const float2 f2 = 1.f - f * float2(0.25f, 0.5f);
const float2 f2 = 1.0 - f * float2(0.25, 0.5);
const float g = sqrt(abs(f2.x));
return float3(fenc * g, f2.y);
}
void DS_Reset(out DS_FSO so)
{
so.target0 = 0.f;
so.target1 = 0.f;
so.target2 = 0.f;
so.target0 = 0.0;
so.target1 = 0.0;
so.target2 = 0.0;
}
void DS_SolidColor(out DS_FSO so, float3 color)
{
so.target0 = float4(color, 0.f);
so.target1 = float4(EncodeNormal(float3(0, 0, 1)), 0.25f, 0);
so.target2 = float4(1.f / 8.f, 0.5f, 0.5f, 0);
so.target0 = float4(color, 0.0);
so.target1 = float4(EncodeNormal(float3(0, 0, 1)), 0.25, 0);
so.target2 = float4(1.0 / 8.0, 0.5, 0.5, 0);
}
void DS_Test(out DS_FSO so, float3 normal, float specMask, float gloss)
{
so.target0 = float4(0.5f, 0.5f, 0.5f, specMask);
so.target1 = float4(EncodeNormal(normal), 0.25f, 0.5f);
so.target2 = float4(1.f / 8.f, 0.5f, 0.5f, gloss * (1.f / 64.f));
so.target0 = float4(0.5, 0.5, 0.5, specMask);
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)
@ -72,15 +72,15 @@ void DS_SetNormal(inout DS_FSO so, float3 normal)
float2 DS_GetEmission(float4 gbuffer)
{
const float2 em_skin = saturate((gbuffer.b - 0.25f) * float2(1.f / 0.75f, -1.f / 0.25f));
const float em = exp2(em_skin.x * 15.f) - 1.f;
const float2 em_skin = saturate((gbuffer.b - 0.25) * float2(1.0 / 0.75, -1.0 / 0.25));
const float em = exp2(em_skin.x * 15.0) - 1.0;
return float2(em, em_skin.y);
}
void DS_SetEmission(inout DS_FSO so, float emission, float skinMask)
{
const float em = saturate(log2(1.f + emission) * (1.f / 15.f));
so.target1.b = (3.f * em - skinMask) * 0.25f + 0.25f;
const float em = saturate(log2(1.0 + emission) * (1.0 / 15.0));
so.target1.b = (3.0 * em - skinMask) * 0.25 + 0.25;
}
void DS_SetMotionBlurMask(inout DS_FSO so, float motionBlurMask)
@ -95,25 +95,25 @@ float2 DS_GetLamScaleBias(float4 gbuffer)
void DS_SetLamScaleBias(inout DS_FSO so, float2 lamScaleBias, float4 aniso)
{
so.target2.rg = lerp(lamScaleBias * float2(1.f / 8.f, 0.25f) + float2(0, 0.5f), 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.02f;
const float x2 = gbuffer.b * 2.02;
return float2(
saturate(x2 - 1.02f),
saturate(1.f - x2));
saturate(x2 - 1.02),
saturate(1.0 - x2));
}
void DS_SetMetallicity(inout DS_FSO so, float metalMask, float hairMask)
{
so.target2.b = (metalMask - hairMask) * 0.5f + 0.5f;
so.target2.b = (metalMask - hairMask) * 0.5 + 0.5;
}
void DS_SetGloss(inout DS_FSO so, float gloss)
{
so.target2.a = gloss * (1.f / 64.f);
so.target2.a = gloss * (1.0 / 64.0);
}
float3 DS_GetPosition(float4 gbuffer, matrix matInvProj, float2 ndcPos)

View File

@ -16,26 +16,26 @@ float4 ToLinearDepth(float4 dz, float4 zNearFarEx)
return zNearFarEx.w / (dz - zNearFarEx.z);
}
float ComputeFog(float depth, float density, float height = 0.f)
float ComputeFog(float depth, float density, float height = 0.0)
{
const float strength = 1.f - saturate(height * 0.003f);
const float power = depth * lerp(0.f, density, strength * strength);
const float fog = 1.f / exp(power * power);
return 1.f - saturate(fog);
const float strength = 1.0 - saturate(height * 0.003);
const float power = depth * lerp(0.0, density, strength * strength);
const float fog = 1.0 / exp(power * power);
return 1.0 - saturate(fog);
}
float3 AdjustPosForShadow(float3 pos, float3 normal, float3 dirToLight, float depth, float offset = 0.f)
float3 AdjustPosForShadow(float3 pos, float3 normal, float3 dirToLight, float depth, float offset = 0.0)
{
const float scale = depth - 5.f;
const float scale = depth - 5.0;
return pos +
normal * 0.015f * max(1.f, scale * 0.2f) +
dirToLight * max(0.f, scale * 0.002f + offset);
normal * 0.015 * max(1.0, scale * 0.2) +
dirToLight * max(0.0, scale * 0.002 + offset);
}
float ComputePenumbraContrast(float deltaScale, float strength, float dzFrag, float dzBlockers)
{
const float delta = saturate(dzFrag - dzBlockers);
return 1.f + max(0.f, 3.f - delta * deltaScale) * strength;
return 1.0 + max(0.0, 3.0 - delta * deltaScale) * strength;
}
float PCF(
@ -51,7 +51,7 @@ float PCF(
return texCmp.SampleCmpLevelZero(samCmp, tc.xy, dzFrag).r;
#elif _SHADOW_QUALITY <= _Q_HIGH
// High quality, use 5x5 PCF:
float sum = 0.f;
float sum = 0.0;
[unroll] for (int y = -2; y <= 2; y += 2)
{
[unroll] for (int x = -2; x <= 2; x += 2)
@ -62,11 +62,11 @@ float PCF(
sum += texCmp.SampleCmpLevelZero(samCmp, tc.xy, dzFrag, offset).r;
}
}
sum *= (1.f / 9.f); // 3x3
if (sum * (1.f - sum) != 0.f)
sum *= (1.0 / 9.0); // 3x3
if (sum * (1.0 - sum) != 0.0)
{
float2 dzBlockers_blockerCount = 0.f;
sum = 0.f;
float2 dzBlockers_blockerCount = 0.0;
sum = 0.0;
[unroll] for (int y = -2; y <= 2; ++y)
{
[unroll] for (int x = -2; x <= 2; ++x)
@ -79,12 +79,12 @@ float PCF(
dzBlockers_blockerCount += float2(dzBlocker, 1);
}
}
const float ret = sum *= (1.f / 21.f); // 5x5 - 4
if (dzBlockers_blockerCount.y > 0.f)
const float ret = sum *= (1.0 / 21.0); // 5x5 - 4
if (dzBlockers_blockerCount.y > 0.0)
{
const float dzBlockers = dzBlockers_blockerCount.x / dzBlockers_blockerCount.y;
const float contrast = ComputePenumbraContrast(config.x, config.y, dzFrag, dzBlockers);
return saturate((ret - 0.5f) * contrast + 0.5f);
return saturate((ret - 0.5) * contrast + 0.5);
}
else
{
@ -97,7 +97,7 @@ float PCF(
}
#else
// Ultra quality, use 7x7 PCF:
float sum = 0.f;
float sum = 0.0;
[unroll] for (int y = -3; y <= 3; y += 2)
{
[unroll] for (int x = -3; x <= 3; x += 2)
@ -108,11 +108,11 @@ float PCF(
sum += texCmp.SampleCmpLevelZero(samCmp, tc.xy, dzFrag, offset).r;
}
}
sum *= (1.f / 16.f); // 4x4
if (sum * (1.f - sum) != 0.f)
sum *= (1.0 / 16.0); // 4x4
if (sum * (1.0 - sum) != 0.0)
{
float2 dzBlockers_blockerCount = 0.f;
sum = 0.f;
float2 dzBlockers_blockerCount = 0.0;
sum = 0.0;
[unroll] for (int y = -3; y <= 3; ++y)
{
[unroll] for (int x = -3; x <= 3; ++x)
@ -125,12 +125,12 @@ float PCF(
dzBlockers_blockerCount += float2(dzBlocker, 1);
}
}
const float ret = sum *= (1.f / 45.f); // 7x7 - 4
if (dzBlockers_blockerCount.y > 0.f)
const float ret = sum *= (1.0 / 45.0); // 7x7 - 4
if (dzBlockers_blockerCount.y > 0.0)
{
const float dzBlockers = dzBlockers_blockerCount.x / dzBlockers_blockerCount.y;
const float contrast = ComputePenumbraContrast(config.x, config.y, dzFrag, dzBlockers);
return saturate((ret - 0.5f) * contrast + 0.5f);
return saturate((ret - 0.5) * contrast + 0.5);
}
else
{
@ -161,8 +161,8 @@ float ShadowMap(
float4 config)
{
const float ret = PCF(texCmp, samCmp, tex, sam, tc, config);
const float2 center = tc.xy * 2.f - 1.f;
return max(ret, saturate(dot(center, center) * (9.f / 4.f) - 1.f));
const float2 center = tc.xy * 2.0 - 1.0;
return max(ret, saturate(dot(center, center) * (9.0 / 4.0) - 1.0));
}
float SimpleShadowMap(
@ -171,14 +171,14 @@ float SimpleShadowMap(
float3 tc)
{
const float ret = SimplePCF(texCmp, samCmp, tc);
const float2 center = tc.xy * 2.f - 1.f;
return max(ret, saturate(dot(center, center) * (9.f / 4.f) - 1.f));
const float2 center = tc.xy * 2.0 - 1.0;
return max(ret, saturate(dot(center, center) * (9.0 / 4.0) - 1.0));
}
bool IsClippedCSM(float4 clipSpacePos)
{
const float4 absPos = abs(clipSpacePos);
return all(absPos.xyz <= absPos.w * float3(1.01f, 1.01f, 1.f));
return all(absPos.xyz <= absPos.w * float3(1.01, 1.01, 1.0));
}
float ShadowMapCSM(
@ -197,51 +197,51 @@ float ShadowMapCSM(
float4 config)
{
#if _SHADOW_QUALITY >= _Q_HIGH
float ret = 1.f;
float contrast = 1.f;
float ret = 1.0;
float contrast = 1.0;
const float contrastScale = config.w;
const float4 clipSpacePos = mul(float4(inPos, 1.f), matScreen);
const float4 clipSpacePos = mul(float4(inPos, 1.0), matScreen);
const float depth = clipSpacePos.w;
if (IsClippedCSM(clipSpacePos))
{
if (depth >= csmSplitRanges.x)
{
const float fadeStart = (csmSplitRanges.x + csmSplitRanges.w) * 0.5f;
const float fadeStart = (csmSplitRanges.x + csmSplitRanges.w) * 0.5;
const float fade = saturate((depth - fadeStart) / (csmSplitRanges.w - fadeStart));
contrast = contrastScale * contrastScale * contrastScale;
const float3 tc = mul(float4(biasedPos, 1.f), mat0).xyz;
const float3 tc = mul(float4(biasedPos, 1.0), mat0).xyz;
ret = max(PCF(texCmp, samCmp, tex, sam, tc, config), fade);
}
else if (depth >= csmSplitRanges.y)
{
contrast = contrastScale * contrastScale;
const float3 tc = mul(float4(biasedPos, 1.f), mat1).xyz;
const float3 tc = mul(float4(biasedPos, 1.0), mat1).xyz;
ret = PCF(texCmp, samCmp, tex, sam, tc, config);
}
else if (depth >= csmSplitRanges.z)
{
contrast = contrastScale;
const float3 tc = mul(float4(biasedPos, 1.f), mat2).xyz;
const float3 tc = mul(float4(biasedPos, 1.0), mat2).xyz;
ret = PCF(texCmp, samCmp, tex, sam, tc, config);
}
else
{
const float3 tc = mul(float4(biasedPos, 1.f), mat3).xyz;
const float3 tc = mul(float4(biasedPos, 1.0), mat3).xyz;
ret = PCF(texCmp, samCmp, tex, sam, tc, config);
}
return saturate((ret - 0.5f) * contrast + 0.5f);
return saturate((ret - 0.5) * contrast + 0.5);
}
else
return 1.f;
return 1.0;
#else
const float3 tc = mul(float4(biasedPos, 1.f), mat0).xyz;
if (all(tc.xy >= 0.f) && all(tc.xy < 1.f))
const float3 tc = mul(float4(biasedPos, 1.0), mat0).xyz;
if (all(tc.xy >= 0.0) && all(tc.xy < 1.0))
return ShadowMap(texCmp, samCmp, tex, sam, tc, config);
else
return 1.f;
return 1.0;
#endif
}
@ -260,50 +260,50 @@ float SimpleShadowMapCSM(
bool clipping = true)
{
#if _SHADOW_QUALITY >= _Q_HIGH
float ret = 1.f;
float contrast = 1.f;
float ret = 1.0;
float contrast = 1.0;
const float contrastScale = config.w;
const float4 clipSpacePos = mul(float4(inPos, 1.f), matScreen);
const float4 clipSpacePos = mul(float4(inPos, 1.0), matScreen);
const float depth = clipSpacePos.w;
if (!clipping || IsClippedCSM(clipSpacePos))
{
if (depth >= csmSplitRanges.x)
{
const float fadeStart = (csmSplitRanges.x + csmSplitRanges.w) * 0.5f;
const float fadeStart = (csmSplitRanges.x + csmSplitRanges.w) * 0.5;
const float fade = saturate((depth - fadeStart) / (csmSplitRanges.w - fadeStart));
contrast = contrastScale * contrastScale * contrastScale;
const float3 tc = mul(float4(biasedPos, 1.f), mat0).xyz;
const float3 tc = mul(float4(biasedPos, 1.0), mat0).xyz;
ret = max(SimplePCF(texCmp, samCmp, tc), fade);
}
else if (depth >= csmSplitRanges.y)
{
contrast = contrastScale * contrastScale;
const float3 tc = mul(float4(biasedPos, 1.f), mat1).xyz;
const float3 tc = mul(float4(biasedPos, 1.0), mat1).xyz;
ret = SimplePCF(texCmp, samCmp, tc);
}
else if (depth >= csmSplitRanges.z)
{
contrast = contrastScale;
const float3 tc = mul(float4(biasedPos, 1.f), mat2).xyz;
const float3 tc = mul(float4(biasedPos, 1.0), mat2).xyz;
ret = SimplePCF(texCmp, samCmp, tc);
}
else
{
const float3 tc = mul(float4(biasedPos, 1.f), mat3).xyz;
const float3 tc = mul(float4(biasedPos, 1.0), mat3).xyz;
ret = SimplePCF(texCmp, samCmp, tc);
}
return saturate((ret - 0.5f) * contrast + 0.5f);
return saturate((ret - 0.5) * contrast + 0.5);
}
else
return 1.f;
return 1.0;
#else
const float3 tc = mul(float4(biasedPos, 1.f), mat0).xyz;
if (all(tc.xy >= 0.f) && all(tc.xy < 1.f))
const float3 tc = mul(float4(biasedPos, 1.0), mat0).xyz;
if (all(tc.xy >= 0.0) && all(tc.xy < 1.0))
return SimpleShadowMap(texCmp, samCmp, tc);
else
return 1.f;
return 1.0;
#endif
}

View File

@ -2,16 +2,56 @@
float SinAcos(float x)
{
return sqrt(saturate(1.f - x * x));
return sqrt(saturate(1.0 - x * x));
}
float EnergyNorm(float gloss)
{
return (gloss + 8.f) * (1.f / (8.f * _PI));
return (gloss + 8.0) * (1.0 / (8.0 * _PI));
}
// Aka D:
float MicrofacetDistribution(float alphaRoughnessSq, float nDotH)
{
const float f = (nDotH * nDotH) * (alphaRoughnessSq - 1.0) + 1.0;
return alphaRoughnessSq / (f * f);
}
// Aka V:
float MaskingShadowingFunction(float alphaRoughnessSq, float nDotL, float nDotV)
{
const float2 nDotL_nDotV = float2(nDotL, nDotV);
const float2 nDotLSq_nDotVSq = nDotL_nDotV * nDotL_nDotV;
const float2 ggxl_ggxv = nDotL_nDotV.yx * sqrt(alphaRoughnessSq + (1.0 - alphaRoughnessSq) * nDotLSq_nDotVSq);
const float ggx = ggxl_ggxv.x + ggxl_ggxv.y;
if (ggx > 0.0)
return 0.5 / ggx;
return 0.0;
}
void VerusLit2(float3 normal, float3 dirToLight, float3 dirToEye, float metallic, float roughness, float3 albedo, out float3 diff, out float3 spec)
{
const float alphaRoughness = roughness * roughness;
const float alphaRoughnessSq = alphaRoughness * alphaRoughness;
const float3 hv = normalize(dirToLight + dirToEye);
const float nDotL = saturate(dot(normal, dirToLight));
const float nDotV = saturate(dot(normal, dirToEye));
const float nDotH = saturate(dot(normal, hv));
const float vDotH = saturate(dot(dirToEye, hv));
const float3 diffuse = albedo * (1.0 - metallic);
const float3 f0 = lerp(0.04, albedo, metallic);
const float3 f = f0 + (1.0 - f0) * pow(saturate(1.0 - vDotH), 5.0);
diff = nDotL * (1 - f) * diffuse;
spec = nDotL * f * MicrofacetDistribution(alphaRoughnessSq, nDotH) * MaskingShadowingFunction(alphaRoughnessSq, nDotL, nDotV);
diff = diff + spec;
}
float4 VerusLit(float3 dirToLight, float3 normal, float3 dirToEye, float gloss,
float2 lamScaleBias, float4 aniso = 0.f, float eyeFresnel = 0.f)
float2 lamScaleBias, float4 aniso = 0.0, float eyeFresnel = 0.0)
{
float4 ret = float4(1, 0, 0, 1);
const float3 hv = normalize(dirToEye + dirToLight);
@ -21,14 +61,14 @@ float4 VerusLit(float3 dirToLight, float3 normal, float3 dirToEye, float gloss,
const float nDotH = dot(normal, hv);
const float aDotH = SinAcos(dot(aniso.xyz, hv));
const float4 spec = pow(saturate(float4(nDotH, aDotH, 1.f - nDotL, 1.f - nDotE)), float4(gloss, gloss * 8.f, 5, 5));
const float4 spec = pow(saturate(float4(nDotH, aDotH, 1.0 - nDotL, 1.0 - nDotE)), float4(gloss, gloss * 8.0, 5, 5));
const float maxSpec = max(spec.x, spec.y * aniso.w);
const float specContrast = 1.f + gloss * (0.5f / 4096.f);
const float specContrast = 1.0 + gloss * (0.5 / 4096.0);
ret.x = saturate(nDotLRaw * -4.f); // For subsurface scattering effect.
ret.x = saturate(nDotLRaw * -4.0); // For subsurface scattering effect.
ret.y = saturate(nDotL);
ret.z = saturate(nDotL * 8.f) * saturate((maxSpec - 0.5f) * specContrast + 0.5f) * EnergyNorm(gloss);
ret.z = saturate(nDotL * 8.0) * saturate((maxSpec - 0.5) * specContrast + 0.5) * EnergyNorm(gloss);
ret.w = lerp(spec.z, spec.w, eyeFresnel); // For fresnel effect.
return ret;
@ -36,9 +76,9 @@ float4 VerusLit(float3 dirToLight, float3 normal, float3 dirToEye, float gloss,
float ComputePointLightIntensity(float distSq, float radiusSq, float invRadiusSq)
{
const float scaleFivePercent = 19.f * invRadiusSq;
const float invSquareLaw = 1.f / max(0.1f, distSq * scaleFivePercent);
const float x = max(0.f, radiusSq - distSq); // Zero at radius.
const float scaleFivePercent = 19.0 * invRadiusSq;
const float invSquareLaw = 1.0 / max(0.1, distSq * scaleFivePercent);
const float x = max(0.0, radiusSq - distSq); // Zero at radius.
const float limit = x * x * invRadiusSq * invRadiusSq;
return min(invSquareLaw, limit);
}

View File

@ -2,20 +2,20 @@
float ComputeNormalZ(float2 v)
{
return sqrt(saturate(1.f - dot(v.xy, v.xy)));
return sqrt(saturate(1.0 - dot(v.xy, v.xy)));
}
float4 NormalMapAA(float4 rawNormal)
{
float3 normal = rawNormal.agb * -2.f + 1.f; // Dmitry's reverse!
float3 normal = rawNormal.agb * -2.0 + 1.0; // Dmitry's reverse!
normal.z = ComputeNormalZ(normal.xy);
const float len = rawNormal.b + 0.5f;
const float len = rawNormal.b + 0.5;
return float4(normal, len * len);
}
float ComputeToksvigFactor(float len, float gloss)
{
return len / lerp(gloss + _SINGULARITY_FIX, 1.f, len);
return len / lerp(gloss + _SINGULARITY_FIX, 1.0, len);
}
float3 ComputeNormals(Texture2D tex, SamplerState sam, float2 tc, float damp, int scale = 1)
@ -29,10 +29,10 @@ float3 ComputeNormals(Texture2D tex, SamplerState sam, float2 tc, float damp, in
const float r = damp * tex.Sample(sam, tc, int2(+scale, 0)).r;
const float br = damp * tex.Sample(sam, tc, int2(+scale, +scale)).r;
const float dX = (-47.f * tl - 162.f * l - 47.f * bl) + (47.f * tr + 162.f * r + 47.f * br); // Left + Right.
const float dY = (-47.f * tl - 162.f * t - 47.f * tr) + (47.f * bl + 162.f * b + 47.f * br); // Top + Bottom.
const float dX = (-47.0 * tl - 162.0 * l - 47.0 * bl) + (47.0 * tr + 162.0 * r + 47.0 * br); // Left + Right.
const float dY = (-47.0 * tl - 162.0 * t - 47.0 * tr) + (47.0 * bl + 162.0 * b + 47.0 * br); // Top + Bottom.
const float3 normal = normalize(float3(dX, dY, 1));
return normal * 0.5f + 0.5f;
return normal * 0.5 + 0.5;
}

View File

@ -35,16 +35,16 @@ struct PCFO
so.posWV[2] = ComputeBezierPoint(inputPatch[nextID].pos.xyz, inputPatch[thisID].pos.xyz, inputPatch[nextID].nrmWV.xyz); \
so.clipped = ComputeClipping(matP, so.posWV[0], so.posWV[1], so.posWV[2]); \
so.oppositeEdgeTessFactor = ComputeEdgeTessFactor(matP, inputPatch[thisID].pos.xyz, inputPatch[nextID].pos.xyz, viewportSize.xy); \
const float3 normal = (inputPatch[thisID].nrmWV.xyz + inputPatch[nextID].nrmWV.xyz) * 0.5f; \
so.oppositeEdgeTessFactor = (normal.z < -0.75f) ? 0.f : max(1.f, so.oppositeEdgeTessFactor * (1.f - abs(normal.z * 0.75f)));
const float3 normal = (inputPatch[thisID].nrmWV.xyz + inputPatch[nextID].nrmWV.xyz) * 0.5; \
so.oppositeEdgeTessFactor = (normal.z < -0.75) ? 0.0 : max(1.0, so.oppositeEdgeTessFactor * (1.0 - abs(normal.z * 0.75)));
#define _HS_PNAEN_BODY(nrmWV, matP, viewportSize) \
const uint thisID = id; \
const uint nextID = (thisID < 2) ? thisID + 1 : 0; \
const uint thisEX = 3 + 2 * id; \
const uint nextEX = thisEX + 1; \
const float kA = max(_SINGULARITY_FIX, 1.f - dot(inputPatch[thisID].nrmWV.xyz, inputPatch[thisEX].nrmWV.xyz)); \
const float kB = max(_SINGULARITY_FIX, 1.f - dot(inputPatch[nextID].nrmWV.xyz, inputPatch[nextEX].nrmWV.xyz)); \
const float kA = max(_SINGULARITY_FIX, 1.0 - dot(inputPatch[thisID].nrmWV.xyz, inputPatch[thisEX].nrmWV.xyz)); \
const float kB = max(_SINGULARITY_FIX, 1.0 - dot(inputPatch[nextID].nrmWV.xyz, inputPatch[nextEX].nrmWV.xyz)); \
const float sum = kA + kB; \
const float ratio = kB / sum; \
float3 myCP, exCP; \
@ -57,8 +57,8 @@ struct PCFO
so.posWV[2] = lerp(myCP, exCP, ratio); \
so.clipped = ComputeClipping(matP, so.posWV[0], so.posWV[1], so.posWV[2]); \
so.oppositeEdgeTessFactor = ComputeEdgeTessFactor(matP, inputPatch[thisID].pos.xyz, inputPatch[nextID].pos.xyz, viewportSize.xy); \
const float3 normal = (inputPatch[thisID].nrmWV.xyz + inputPatch[thisEX].nrmWV.xyz + inputPatch[nextID].nrmWV.xyz + inputPatch[nextEX].nrmWV.xyz) * 0.25f; \
so.oppositeEdgeTessFactor = (normal.z < -0.75f) ? 0.f : max(1.f, so.oppositeEdgeTessFactor * (1.f - abs(normal.z * 0.75f)));
const float3 normal = (inputPatch[thisID].nrmWV.xyz + inputPatch[thisEX].nrmWV.xyz + inputPatch[nextID].nrmWV.xyz + inputPatch[nextEX].nrmWV.xyz) * 0.25; \
so.oppositeEdgeTessFactor = (normal.z < -0.75) ? 0.0 : max(1.0, so.oppositeEdgeTessFactor * (1.0 - abs(normal.z * 0.75)));
// Patch Constant Function, here central bezier control point is calculated:
#define _HS_PCF_BODY(matP) \
@ -75,11 +75,11 @@ struct PCFO
const float3 b003 = outputPatch[2].posWV[0]; \
const float3 b102 = outputPatch[2].posWV[1]; \
const float3 b201 = outputPatch[2].posWV[2]; \
const float3 e = (b210 + b120 + b021 + b012 + b102 + b201) * (1.f / 6.f); \
const float3 v = (b003 + b030 + b300) * (1.f / 3.f); \
so.b111 = e + (e - v) * 0.5f; \
const float3 e = (b210 + b120 + b021 + b012 + b102 + b201) * (1.0 / 6.0); \
const float3 v = (b003 + b030 + b300) * (1.0 / 3.0); \
so.b111 = e + (e - v) * 0.5; \
const float b111Clipped = IsClipped(ApplyProjection(so.b111, matP)); \
if (outputPatch[0].clipped && outputPatch[1].clipped && outputPatch[2].clipped && b111Clipped) { so.tessFactors[0] = 0.f; }
if (outputPatch[0].clipped && outputPatch[1].clipped && outputPatch[2].clipped && b111Clipped) { so.tessFactors[0] = 0.0; }
#define _DS_INIT_FLAT_POS \
const float3 flatPosWV = \
@ -90,7 +90,7 @@ struct PCFO
#define _DS_INIT_SMOOTH_POS \
const float3 uvw = domainLocation; \
const float3 uvwSq = uvw * uvw; \
const float3 uvwSq3 = uvwSq * 3.f; \
const float3 uvwSq3 = uvwSq * 3.0; \
const float3 smoothPosWV = \
outputPatch[0].posWV[0] * uvwSq.x * uvw.x + \
outputPatch[1].posWV[0] * uvwSq.y * uvw.y + \
@ -101,13 +101,13 @@ struct PCFO
outputPatch[1].posWV[2] * uvwSq3.z * uvw.y + \
outputPatch[2].posWV[1] * uvwSq3.z * uvw.x + \
outputPatch[2].posWV[2] * uvwSq3.x * uvw.z + \
si.b111 * uvw.x * uvw.y * uvw.z * 6.f
si.b111 * uvw.x * uvw.y * uvw.z * 6.0
float3 ComputeBezierPoint(float3 posA, float3 posB, float3 nrmA)
{
// Project a 1/3 midpoint on the plane, which is defined by the nearest vertex and it's normal.
const float extrudeLen = dot(posB - posA, nrmA);
return (2.f * posA + posB - extrudeLen * nrmA) * (1.f / 3.f);
return (2.0 * posA + posB - extrudeLen * nrmA) * (1.0 / 3.0);
}
// Optimized version of the projection transform:
@ -126,13 +126,13 @@ float2 ProjectAndScale(float3 posWV, matrix matP, float2 viewportSize)
{
const float4 clipSpacePos = ApplyProjection(posWV, matP);
const float2 ndcPos = clipSpacePos.xy / clipSpacePos.w;
return ndcPos * viewportSize * (32.f / 1080.f);
return ndcPos * viewportSize * (32.0 / 1080.0);
}
float IsClipped(float4 clipSpacePos)
{
const float4 absPos = abs(clipSpacePos);
return all(absPos.xyz <= absPos.w * 2.f) ? 0.f : 1.f; // Safe area, because patch can have all points outside, but still be visible.
return all(absPos.xyz <= absPos.w * 2.0) ? 0.0 : 1.0; // Safe area, because patch can have all points outside, but still be visible.
}
float ComputeClipping(matrix matP, float3 posA, float3 posB, float3 posC)

View File

@ -3,7 +3,7 @@
float3 DequantizeUsingDeq3D(float3 v, float3 scale, float3 bias) { return v * scale + bias; }
float2 DequantizeUsingDeq2D(float2 v, float2 scale, float2 bias) { return v * scale + bias; }
float3 NormalizePosition(float3 v) { return v * (1.f / 65535.f) + 0.5f; }
float3 NormalizePosition(float3 v) { return v * (1.0 / 65535.0) + 0.5; }
mataff GetInstMatrix(float4 part0, float4 part1, float4 part2)
{
@ -16,7 +16,7 @@ mataff GetInstMatrix(float4 part0, float4 part1, float4 part2)
float3 Warp(float3 pos, float4 center_radInv, float3 offset)
{
const float3 d = pos - center_radInv.xyz;
const float scale = saturate(1.f - dot(d, d) * center_radInv.w);
const float scale = saturate(1.0 - dot(d, d) * center_radInv.w);
return offset * scale;
}
@ -33,5 +33,5 @@ float3 ApplyWarp(float3 pos, float4 zones[32], float4 mask)
float4 GetWarpScale()
{
return float4(1, 1.f / 32767.f, 1, 1);
return float4(1, 1.0 / 32767.0, 1, 1);
}

View File

@ -73,7 +73,7 @@ FSO mainFS(VSO si)
const float4 rawColor = g_tex.Sample(g_sam, si.tc0);
so.color = rawColor * si.color0;
so.color.a *= 1.f - si.additive;
so.color.a *= 1.0 - si.additive;
return so;
}

View File

@ -43,10 +43,16 @@ FSO mainFS(VSO si)
{
FSO so;
so.color = g_tex.SampleLevel(g_sam, si.tc0, 0.f);
#ifdef DEF_HEMICUBE_MASK
const float weight = ComputeHemicubeMask(si.tc0);
so.color = weight;
#else
so.color = g_tex.SampleLevel(g_sam, si.tc0, 0.0);
#endif
return so;
}
#endif
//@main:#
//@main:#HemicubeMask HEMICUBE_MASK

View File

@ -49,20 +49,20 @@ VSO mainVS(VSI si)
const float3 eyePos = g_ubSimpleForestVS._eyePos_clipDistanceOffset.xyz;
const float clipDistanceOffset = g_ubSimpleForestVS._eyePos_clipDistanceOffset.w;
const float pointSpriteSize = si.tc0.x * (1.f / 500.f);
const float angle = si.tc0.y * (1.f / 32767.f);
const float pointSpriteSize = si.tc0.x * (1.0 / 500.0);
const float angle = si.tc0.y * (1.0 / 32767.0);
const float3 toEye = eyePos - si.pos.xyz;
const float distToScreen = length(g_ubSimpleForestVS._eyePosScreen.xyz - si.pos.xyz);
const float nearAlpha = saturate((distToScreen - 6.f) * (1.f / 3.f)); // From 6m to 9m.
const float farAlpha = 1.f - saturate((distToScreen - 900.f) * (1.f / 100.f)); // From 900m to 1000m.
const float nearAlpha = saturate((distToScreen - 6.0) * (1.0 / 3.0)); // From 6m to 9m.
const float farAlpha = 1.0 - saturate((distToScreen - 900.0) * (1.0 / 100.0)); // From 900m to 1000m.
so.pos = mul(si.pos, g_ubSimpleForestVS._matWVP);
so.tc0 = 0.f;
so.tc0 = 0.0;
so.dirToEye = toEye;
so.posW_depth = float4(si.pos.xyz, so.pos.z);
so.color.rgb = RandomColor(si.pos.xz, 0.3f, 0.2f);
so.color.rgb = RandomColor(si.pos.xz, 0.3, 0.2);
so.color.a = nearAlpha * farAlpha;
so.psize = (pointSpriteSize * (g_ubSimpleForestVS._viewportSize.yx * g_ubSimpleForestVS._viewportSize.z)).xyxy;
so.psize.xy *= g_ubSimpleForestVS._pointSpriteScale.xy * g_ubSimpleForestVS._matP._m11;
@ -70,12 +70,12 @@ VSO mainVS(VSI si)
float2 param0 = toEye.xy;
float2 param1 = toEye.zz;
param0.y = max(0.f, param0.y); // Only upper hemisphere.
param0.y = max(0.0, param0.y); // Only upper hemisphere.
param1.y = length(toEye.xz); // Distance in XZ-plane.
so.angles.xy = (atan2(param0, param1) + _PI) * (0.5f / _PI); // atan2(x, z) and atan2(max(0.f, y), length(toEye.xz)). From 0 to 1.
so.angles.y = (so.angles.y - 0.5f) * 4.f; // Choose this quadrant.
so.angles.xy = (atan2(param0, param1) + _PI) * (0.5 / _PI); // atan2(x, z) and atan2(max(0.0, y), length(toEye.xz)). From 0 to 1.
so.angles.y = (so.angles.y - 0.5) * 4.0; // Choose this quadrant.
so.angles.xy = saturate(so.angles.xy);
so.angles.x = frac(so.angles.x - angle + 0.5f); // Turn.
so.angles.x = frac(so.angles.x - angle + 0.5); // Turn.
return so;
}
@ -103,21 +103,21 @@ void mainGS(point VSO si[1], inout TriangleStream<VSO> stream)
float2 ComputeTexCoords(float2 tc, float2 angles)
{
const float marginBias = 16.f / 512.f;
const float marginScale = 1.f - marginBias * 2.f;
const float marginBias = 16.0 / 512.0;
const float marginScale = 1.0 - marginBias * 2.0;
const float2 tcMargin = tc * marginScale + marginBias;
const float2 frameCount = float2(16, 16);
const float2 frameScale = 1.f / frameCount;
const float2 frameBias = floor(min(angles * frameCount + 0.5f, float2(256, frameCount.y - 0.5f)));
const float2 frameScale = 1.0 / frameCount;
const float2 frameBias = floor(min(angles * frameCount + 0.5, float2(256, frameCount.y - 0.5)));
return (tcMargin + frameBias) * frameScale;
}
float ComputeMask(float2 tc, float alpha)
{
const float2 tcCenter = tc - 0.5f;
const float rad = saturate(dot(tcCenter, tcCenter) * 4.f);
return saturate(rad + (alpha * 2.f - 1.f));
const float2 tcCenter = tc - 0.5;
const float rad = saturate(dot(tcCenter, tcCenter) * 4.0);
return saturate(rad + (alpha * 2.0 - 1.0));
}
#ifdef _FS
@ -146,7 +146,7 @@ FSO mainFS(VSO si)
// GBuffer2:
const float2 lamScaleBias = DS_GetLamScaleBias(rawGBuffer2);
const float gloss64 = rawGBuffer2.a * 64.f;
const float gloss64 = rawGBuffer2.a * 64.0;
const float gloss4K = gloss64 * gloss64;
// <Shadow>
@ -154,7 +154,7 @@ FSO mainFS(VSO si)
{
float4 shadowConfig = g_ubSimpleForestFS._shadowConfig;
const float lamBiasMask = saturate(lamScaleBias.y * shadowConfig.y);
shadowConfig.y = 1.f - lamBiasMask; // Keep penumbra blurry.
shadowConfig.y = 1.0 - lamBiasMask; // Keep penumbra blurry.
const float3 posForShadow = AdjustPosForShadow(si.posW_depth.xyz, normal, g_ubSimpleForestFS._dirToSun.xyz, depth);
shadowMask = SimpleShadowMapCSM(
g_texShadowCmp,
@ -180,14 +180,14 @@ FSO mainFS(VSO si)
const float3 specColor = litRet.z * g_ubSimpleForestFS._sunColor.rgb * shadowMask * specMask;
so.color.rgb = realAlbedo * diffColor + specColor;
so.color.a = 1.f;
so.color.a = 1.0;
const float fog = ComputeFog(depth, g_ubSimpleForestFS._fogColor.a, si.posW_depth.y);
so.color.rgb = lerp(so.color.rgb, g_ubSimpleForestFS._fogColor.rgb, fog);
so.color.rgb = ToSafeHDR(so.color.rgb);
clip(alpha * mask * step(0.f, si.clipDistance) - 0.53f);
clip(alpha * mask * step(0.0, si.clipDistance) - 0.53);
return so;
}

View File

@ -39,7 +39,7 @@ struct VSO
float4 color0 : COLOR0;
float2 tc0 : TEXCOORD0;
float4 posW_depth : TEXCOORD1;
#if !defined(DEF_TEXTURE)
#if !defined(DEF_TEXTURE) && !defined(DEF_BAKE_AO)
float3 nrmW : TEXCOORD2;
float3 dirToEye : TEXCOORD3;
#endif
@ -81,12 +81,12 @@ VSO mainVS(VSI si)
float3 posW;
float3 nrmW;
{
#ifdef DEF_SKINNED
const float4 weights = si.bw * (1.f / 255.f);
#if defined(DEF_SKINNED)
const float4 weights = si.bw * (1.0 / 255.0);
const float4 indices = si.bi;
float3 posSkinned = 0.f;
float3 nrmSkinned = 0.f;
float3 posSkinned = 0.0;
float3 nrmSkinned = 0.0;
for (int i = 0; i < 4; ++i)
{
@ -97,7 +97,7 @@ VSO mainVS(VSI si)
posW = mul(float4(posSkinned, 1), matW).xyz;
nrmW = mul(nrmSkinned, (float3x3)matW);
#elif DEF_ROBOTIC
#elif defined(DEF_ROBOTIC)
const int index = si.pos.w;
const mataff matBone = g_ubSimpleSkeletonVS._vMatBones[index];
@ -117,7 +117,7 @@ VSO mainVS(VSI si)
so.posW_depth = float4(posW, so.pos.z);
so.color0 = userColor;
so.tc0 = inTc0;
#if !defined(DEF_TEXTURE)
#if !defined(DEF_TEXTURE) && !defined(DEF_BAKE_AO)
so.nrmW = nrmW;
so.dirToEye = eyePos - posW;
#endif
@ -132,11 +132,36 @@ FSO mainFS(VSO si)
{
FSO so;
#ifdef DEF_TEXTURE
#if defined(DEF_TEXTURE)
const float4 rawAlbedo = g_texAlbedo.Sample(g_samAlbedo, si.tc0);
so.color.rgb = rawAlbedo.rgb * si.color0.rgb;
so.color.rgb = ToSafeHDR(so.color.rgb);
so.color.a = 1.f;
so.color.a = 1.0;
#elif defined(DEF_BAKE_AO)
// <Material>
const float2 mm_alphaSwitch = g_ubSimplePerMaterialFS._alphaSwitch_anisoSpecDir.xy;
const float4 mm_tc0ScaleBias = g_ubSimplePerMaterialFS._tc0ScaleBias;
// </Material>
const float2 tc0 = si.tc0 * mm_tc0ScaleBias.xy + mm_tc0ScaleBias.zw;
// <Albedo>
const float4 rawAlbedo = g_texAlbedo.Sample(g_samAlbedo, tc0);
// </Albedo>
// <Pick>
const float2 alpha_spec = AlphaSwitch(rawAlbedo, tc0, mm_alphaSwitch);
// </Pick>
so.color.rgb = rawAlbedo.rgb * si.color0.rgb;
const float fogFactor = saturate(si.posW_depth.w * g_ubSimplePerFrame._fogColor.a);
so.color.rgb = lerp(so.color.rgb, g_ubSimplePerFrame._fogColor.rgb, fogFactor);
so.color.rgb = ToSafeHDR(so.color.rgb);
so.color.a = 1.0;
clip(alpha_spec.x - 0.5);
#else
// <Material>
const float2 mm_alphaSwitch = g_ubSimplePerMaterialFS._alphaSwitch_anisoSpecDir.xy;
@ -171,12 +196,12 @@ FSO mainFS(VSO si)
// <Pick>
const float2 alpha_spec = AlphaSwitch(rawAlbedo, tc0, mm_alphaSwitch);
const float emitAlpha = PickAlpha(rawAlbedo.rgb, mm_emissionPick, 16.f);
const float emitAlpha = PickAlpha(rawAlbedo.rgb, mm_emissionPick, 16.0);
const float eyeAlpha = PickAlphaRound(mm_eyePick, tc0);
const float glossAlpha = PickAlpha(rawAlbedo.rgb, mm_glossPick, 32.f);
const float hairAlpha = round(PickAlpha(rawAlbedo.rgb, mm_hairPick, 16.f));
const float skinAlpha = PickAlpha(rawAlbedo.rgb, mm_skinPick, 16.f);
const float userAlpha = PickAlpha(rawAlbedo.rgb, mm_userPick, 16.f);
const float glossAlpha = PickAlpha(rawAlbedo.rgb, mm_glossPick, 32.0);
const float hairAlpha = round(PickAlpha(rawAlbedo.rgb, mm_hairPick, 16.0));
const float skinAlpha = PickAlpha(rawAlbedo.rgb, mm_skinPick, 16.0);
const float userAlpha = PickAlpha(rawAlbedo.rgb, mm_userPick, 16.0);
// </Pick>
rawAlbedo.rgb = lerp(rawAlbedo.rgb, Overlay(gray, si.color0.rgb), userAlpha * si.color0.a);
@ -185,15 +210,15 @@ FSO mainFS(VSO si)
const float specMask = saturate(alpha_spec.y * mm_specScaleBias.x + mm_specScaleBias.y);
// <Gloss>
float gloss = lerp(4.f, 16.f, alpha_spec.y) * mm_glossScaleBias.x + mm_glossScaleBias.y;
float gloss = lerp(4.0, 16.0, alpha_spec.y) * mm_glossScaleBias.x + mm_glossScaleBias.y;
gloss = lerp(gloss, mm_gloss, glossAlpha);
gloss = lerp(gloss, 4.f + alpha_spec.y, skinAlpha);
gloss = lerp(gloss, 0.f, eyeAlpha);
gloss = lerp(gloss, 4.0 + alpha_spec.y, skinAlpha);
gloss = lerp(gloss, 0.0, eyeAlpha);
const float gloss4K = gloss * gloss;
// </Gloss>
// <LambertianScaleBias>
const float2 lamScaleBias = lerp(mm_lamScaleBias, float2(1, 0.45f), skinAlpha);
const float2 lamScaleBias = lerp(mm_lamScaleBias, float2(1, 0.45), skinAlpha);
// </LambertianScaleBias>
const float3 normal = normalize(si.nrmW);
@ -205,7 +230,7 @@ FSO mainFS(VSO si)
{
float4 shadowConfig = g_ubSimplePerFrame._shadowConfig;
const float lamBiasMask = saturate(lamScaleBias.y * shadowConfig.y);
shadowConfig.y = 1.f - lamBiasMask; // Keep penumbra blurry.
shadowConfig.y = 1.0 - lamBiasMask; // Keep penumbra blurry.
const float3 posForShadow = AdjustPosForShadow(si.posW_depth.xyz, normal, g_ubSimplePerFrame._dirToSun.xyz, depth);
shadowMask = SimpleShadowMapCSM(
g_texShadowCmp,
@ -232,14 +257,14 @@ FSO mainFS(VSO si)
const float emission = emitAlpha * mm_emission;
so.color.rgb = realAlbedo * (diffColor + emission) + specColor;
so.color.a = 1.f;
so.color.a = 1.0;
const float fog = ComputeFog(depth, g_ubSimplePerFrame._fogColor.a, si.posW_depth.y);
so.color.rgb = lerp(so.color.rgb, g_ubSimplePerFrame._fogColor.rgb, fog);
const float fogFactor = ComputeFog(depth, g_ubSimplePerFrame._fogColor.a, si.posW_depth.y);
so.color.rgb = lerp(so.color.rgb, g_ubSimplePerFrame._fogColor.rgb, fogFactor);
so.color.rgb = ToSafeHDR(so.color.rgb);
clip(alpha_spec.x - 0.5f);
clip(alpha_spec.x - 0.5);
#endif
return so;
@ -255,3 +280,8 @@ FSO mainFS(VSO si)
//@main:#TextureInstanced TEXTURE INSTANCED
//@main:#TextureRobotic TEXTURE ROBOTIC
//@main:#TextureSkinned TEXTURE SKINNED
//@main:#BakeAO BAKE_AO
//@main:#BakeAOInstanced BAKE_AO INSTANCED
//@main:#BakeAORobotic BAKE_AO ROBOTIC
//@main:#BakeAOSkinned BAKE_AO SKINNED

View File

@ -47,7 +47,7 @@ struct FSO
float4 color : SV_Target0;
};
static const float g_layerScale = 1.f / 8.f;
static const float g_layerScale = 1.0 / 8.0;
#ifdef _VS
VSO mainVS(VSI si)
@ -59,29 +59,29 @@ VSO mainVS(VSI si)
const float clipDistanceOffset = g_ubSimpleTerrainVS._mapSideInv_clipDistanceOffset.y;
const float2 edgeCorrection = si.pos.yw;
si.pos.yw = 0.f;
si.pos.yw = 0.0;
float3 pos = si.pos.xyz + si.posPatch.xyz;
const float2 tcMap = pos.xz * mapSideInv + 0.5f; // Range [0, 1).
const float2 posBlend = pos.xz + edgeCorrection * 0.5f;
const float2 tcMap = pos.xz * mapSideInv + 0.5; // Range [0, 1).
const float2 posBlend = pos.xz + edgeCorrection * 0.5;
// <HeightAndNormal>
float3 inNrm;
{
const float approxHeight = UnpackTerrainHeight(g_texHeightVS.SampleLevel(g_samHeightVS, tcMap + (0.5f * mapSideInv) * 16.f, 4.f).r);
const float approxHeight = UnpackTerrainHeight(g_texHeightVS.SampleLevel(g_samHeightVS, tcMap + (0.5 * mapSideInv) * 16.0, 4.0).r);
pos.y = approxHeight;
const float distToEye = distance(pos, eyePos);
const float geomipsLod = log2(clamp(distToEye * (2.f / 100.f), 1.f, 18.f));
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.f;
const float2 texelCenterAB = (0.5f * mapSideInv) * exp2(float2(geomipsLodBase, geomipsLodNext));
const float geomipsLodNext = geomipsLodBase + 1.0;
const float2 texelCenterAB = (0.5 * mapSideInv) * exp2(float2(geomipsLodBase, geomipsLodNext));
const float yA = UnpackTerrainHeight(g_texHeightVS.SampleLevel(g_samHeightVS, tcMap + texelCenterAB.xx, geomipsLodBase).r);
const float yB = UnpackTerrainHeight(g_texHeightVS.SampleLevel(g_samHeightVS, tcMap + texelCenterAB.yy, geomipsLodNext).r);
pos.y = lerp(yA, yB, geomipsLodFrac);
const float4 rawNormal = g_texNormalVS.SampleLevel(g_samNormalVS, tcMap + texelCenterAB.xx, geomipsLodBase);
inNrm = float3(rawNormal.x, 0, rawNormal.y) * 2.f - 1.f;
inNrm = float3(rawNormal.x, 0, rawNormal.y) * 2.0 - 1.0;
inNrm.y = ComputeNormalZ(inNrm.xz);
}
// </HeightAndNormal>
@ -90,9 +90,9 @@ VSO mainVS(VSI si)
so.posW_depth = float4(pos, so.pos.z);
so.nrmW = mul(inNrm, (float3x3)g_ubSimpleTerrainVS._matW);
so.layerForChannel = si.layerForChannel;
so.tcBlend = posBlend * mapSideInv + 0.5f;
so.tcBlend = posBlend * mapSideInv + 0.5;
so.tcLayer_tcMap.xy = pos.xz * g_layerScale;
so.tcLayer_tcMap.zw = (pos.xz + 0.5f) * mapSideInv + 0.5f; // Texel's center.
so.tcLayer_tcMap.zw = (pos.xz + 0.5) * mapSideInv + 0.5; // Texel's center.
so.dirToEye = eyePos - pos;
so.clipDistance = pos.y + clipDistanceOffset;
@ -109,7 +109,7 @@ FSO mainFS(VSO si)
const float2 tcLayer = si.tcLayer_tcMap.xy;
const float4 rawBlend = g_texBlend.Sample(g_samBlend, si.tcBlend);
float4 weights = float4(rawBlend.rgb, 1.f - dot(rawBlend.rgb, float3(1, 1, 1)));
float4 weights = float4(rawBlend.rgb, 1.0 - dot(rawBlend.rgb, float3(1, 1, 1)));
// <Albedo>
float4 albedo;
@ -122,7 +122,7 @@ FSO mainFS(VSO si)
g_texLayers.Sample(g_samLayers, float3(tcLayer, layerForChannel.b)),
g_texLayers.Sample(g_samLayers, float3(tcLayer, layerForChannel.a))
};
float4 accAlbedo = 0.f;
float4 accAlbedo = 0.0;
accAlbedo += rawAlbedos[0] * weights.r;
accAlbedo += rawAlbedos[1] * weights.g;
accAlbedo += rawAlbedos[2] * weights.b;
@ -145,15 +145,15 @@ FSO mainFS(VSO si)
{
const float dryMask = saturate(si.posW_depth.y);
const float dryMask3 = dryMask * dryMask * dryMask;
const float wetMask = 1.f - dryMask;
const float wetMask = 1.0 - dryMask;
const float wetMask3 = wetMask * wetMask * wetMask;
realAlbedo *= dryMask3 * 0.5f + 0.5f;
specMask = dryMask * saturate(specMask + wetMask3 * wetMask3 * 0.1f);
waterGlossBoost = min(32.f, dryMask * wetMask3 * 100.f);
realAlbedo *= dryMask3 * 0.5 + 0.5;
specMask = dryMask * saturate(specMask + wetMask3 * wetMask3 * 0.1);
waterGlossBoost = min(32.0, dryMask * wetMask3 * 100.0);
}
// </Water>
const float gloss64 = lerp(3.3f, 15.f, specMask) + waterGlossBoost;
const float gloss64 = lerp(3.3, 15.0, specMask) + waterGlossBoost;
const float gloss4K = gloss64 * gloss64;
const float3 normal = normalize(si.nrmW);
@ -165,7 +165,7 @@ FSO mainFS(VSO si)
{
float4 shadowConfig = g_ubSimpleTerrainFS._shadowConfig;
const float lamBiasMask = saturate(g_ubSimpleTerrainFS._lamScaleBias.y * shadowConfig.y);
shadowConfig.y = 1.f - lamBiasMask; // Keep penumbra blurry.
shadowConfig.y = 1.0 - lamBiasMask; // Keep penumbra blurry.
const float3 posForShadow = AdjustPosForShadow(si.posW_depth.xyz, normal, g_ubSimpleTerrainFS._dirToSun.xyz, depth);
shadowMask = SimpleShadowMapCSM(
g_texShadowCmp,
@ -191,7 +191,7 @@ FSO mainFS(VSO si)
const float3 specColor = litRet.z * g_ubSimpleTerrainFS._sunColor.rgb * shadowMask * specMask;
so.color.rgb = realAlbedo * diffColor + specColor;
so.color.a = 1.f;
so.color.a = 1.0;
const float fog = ComputeFog(depth, g_ubSimpleTerrainFS._fogColor.a, si.posW_depth.y);
so.color.rgb = lerp(so.color.rgb, g_ubSimpleTerrainFS._fogColor.rgb, fog);

View File

@ -65,12 +65,12 @@ VSO mainVS(VSI si)
const float3 inPos = DequantizeUsingDeq3D(si.pos.xyz, g_ubPerMeshVS._posDeqScale.xyz, g_ubPerMeshVS._posDeqBias.xyz);
so.pos = mul(float4(inPos, 1), g_ubPerObject._matWVP).xyww; // Peg the depth. (c) ATI
so.color0 = pow(saturate(dot(normalize(inPos * float3(1, 0.25f, 1)), g_ubPerFrame._dirToSun.xyz)), 4.f);
so.tc0 = float2(g_ubPerFrame._time_cloudiness.x, 0.5f - inPos.y);
so.tcStars = inPos.xz * 16.f; // Stars.
so.color0 = pow(saturate(dot(normalize(inPos * float3(1, 0.25, 1)), g_ubPerFrame._dirToSun.xyz)), 4.0);
so.tc0 = float2(g_ubPerFrame._time_cloudiness.x, 0.5 - inPos.y);
so.tcStars = inPos.xz * 16.0; // Stars.
#ifdef DEF_CLOUDS
so.tcPhaseA = inPos.xz * (4.f - 4.f * inPos.y) + g_ubPerFrame._phaseAB.xy;
so.tcPhaseB = inPos.xz * (2.f - 2.f * inPos.y) + g_ubPerFrame._phaseAB.zw;
so.tcPhaseA = inPos.xz * (4.0 - 4.0 * inPos.y) + g_ubPerFrame._phaseAB.xy;
so.tcPhaseB = inPos.xz * (2.0 - 2.0 * inPos.y) + g_ubPerFrame._phaseAB.zw;
#endif
return so;
@ -98,62 +98,62 @@ FSO mainFS(VSO si)
const float time = g_ubPerFrame._time_cloudiness.x;
const float cloudiness = g_ubPerFrame._time_cloudiness.y;
const float dayRatio = (1.f - abs(0.5f - time) * 1.9f);
const float dayRatio = (1.0 - abs(0.5 - time) * 1.9);
const float sunAlpha = g_ubPerFrame._sunColor.a;
const float sunBoost = si.color0.r * sunAlpha;
#ifdef DEF_CLOUDS
const float3 rawSky = g_texSky.Sample(g_samSky, float2(time, 0.3f)).rgb;
const float3 rawRim = g_texSky.Sample(g_samSky, float2(time, 0.4f)).rgb;
const float3 rawSky = g_texSky.Sample(g_samSky, float2(time, 0.3)).rgb;
const float3 rawRim = g_texSky.Sample(g_samSky, float2(time, 0.4)).rgb;
const float colorA = g_texClouds.Sample(g_samClouds, si.tcPhaseA).r;
const float colorB = g_texClouds.Sample(g_samClouds, si.tcPhaseB).r;
const float4 normalA = g_texCloudsNM.Sample(g_samCloudsNM, si.tcPhaseA);
const float4 normalB = g_texCloudsNM.Sample(g_samCloudsNM, si.tcPhaseB);
const float noon = saturate(g_ubPerFrame._dirToSun.y);
const float noonHalf = noon * 0.5f;
const float avgColor = (colorA + colorB) * 0.5f;
const float negative = 1.f - avgColor;
const float3 cloudColor = saturate(Desaturate(rawSky, 0.4f + noonHalf) + 0.4f * noon); // White, bright clouds at noon.
const float3 rimColor = saturate(rawRim * 2.f);
const float noonHalf = noon * 0.5;
const float avgColor = (colorA + colorB) * 0.5;
const float negative = 1.0 - avgColor;
const float3 cloudColor = saturate(Desaturate(rawSky, 0.4 + noonHalf) + 0.4 * noon); // White, bright clouds at noon.
const float3 rimColor = saturate(rawRim * 2.0);
float3 normal = 1.f - (normalA.agb + normalB.agb);
float3 normal = 1.0 - (normalA.agb + normalB.agb);
normal.b = ComputeNormalZ(normal.rg);
normal.xyz = normal.xzy; // From normal-map space to world.
const float clearSky = 1.f - cloudiness;
const float clearSkySoft = 0.6f + 0.4f * clearSky;
const float alpha = saturate((avgColor - clearSky) * 3.f);
const float clearSky = 1.0 - cloudiness;
const float clearSkySoft = 0.6 + 0.4 * clearSky;
const float alpha = saturate((avgColor - clearSky) * 3.0);
const float directLight = saturate(dot(normal, g_ubPerFrame._dirToSun.xyz)) * sunAlpha;
const float edgeMask = saturate((0.9f - alpha) * 2.f);
const float glowAmbient = edgeMask * 0.1f + noonHalf * 0.25f + sunBoost * dayRatio;
const float edgeMask = saturate((0.9 - alpha) * 2.0);
const float glowAmbient = edgeMask * 0.1 + noonHalf * 0.25 + sunBoost * dayRatio;
const float glow = saturate(lerp(directLight * directLight, edgeMask, noonHalf) + glowAmbient);
const float diff = saturate((0.6f + 0.4f * (max(directLight, negative) + sunBoost)) * dayRatio * clearSkySoft);
const float diff = saturate((0.6 + 0.4 * (max(directLight, negative) + sunBoost)) * dayRatio * clearSkySoft);
const float3 finalColor = saturate(diff * cloudColor + glow * rimColor * clearSkySoft * 0.25f);
const float3 finalColor = saturate(diff * cloudColor + glow * rimColor * clearSkySoft * 0.25);
const float hdrScale = Grayscale(g_ubPerFrame._ambientColor.xyz) * (10.f - 6.f * cloudiness);
const float hdrScale = Grayscale(g_ubPerFrame._ambientColor.xyz) * (10.0 - 6.0 * cloudiness);
so.color.rgb = finalColor * hdrScale;
so.color.a = alpha;
// <Fog>
{
const float cloudScale = cloudiness * cloudiness;
const float fogBias = 0.01f + 0.49f * cloudScale;
const float fogContrast = 1.f + 2.f * cloudScale;
const float fog = saturate((si.tc0.y - 0.5f + fogBias) * (fogContrast / fogBias));
const float fogBias = 0.01 + 0.49 * cloudScale;
const float fogContrast = 1.0 + 2.0 * cloudScale;
const float fog = saturate((si.tc0.y - 0.5 + fogBias) * (fogContrast / fogBias));
so.color.rgb = lerp(so.color.rgb, g_ubPerFrame._fogColor.rgb, fog);
so.color.a = max(so.color.a, fog);
}
// </Fog>
#else
const float4 rawSky = g_texSky.Sample(g_samSky, si.tc0);
const float3 skyColor = rawSky.rgb + rand * lerp(0.001f, 0.01f, rawSky.rgb); // Dithering.
const float3 skyColor = rawSky.rgb + rand * lerp(0.001, 0.01, rawSky.rgb); // Dithering.
const float4 rawStars = g_texStars.Sample(g_samStars, si.tcStars);
const float hdrScale = Grayscale(g_ubPerFrame._ambientColor.xyz) * (4.f + 3.f * sunBoost);
so.color = float4(skyColor.rgb * hdrScale + rawStars.rgb * 50.f, 1);
const float hdrScale = Grayscale(g_ubPerFrame._ambientColor.xyz) * (4.0 + 3.0 * sunBoost);
so.color = float4(skyColor.rgb * hdrScale + rawStars.rgb * 50.0, 1);
#endif
so.color.rgb = ToSafeHDR(so.color.rgb);
@ -168,14 +168,14 @@ FSO mainSkyBodyFS(VSO_SKY_BODY si)
so.color = g_texClouds.Sample(g_samClouds, si.tc0);
const float mask = abs(si.height);
#ifdef DEF_SUN
so.color.rgb *= lerp(float3(1.f, 0.2f, 0.001f), 1.f, mask);
so.color.rgb *= (60.f * 1000.f) + (100.f * 1000.f) * mask;
so.color.rgb *= lerp(float3(1.0, 0.2, 0.001), 1.0, mask);
so.color.rgb *= (60.0 * 1000.0) + (100.0 * 1000.0) * mask;
so.color.rgb = ToSafeHDR(so.color.rgb);
#endif
#ifdef DEF_MOON
const float hdrScale = Grayscale(g_ubPerFrame._ambientColor.xyz) * 12.f;
so.color.rgb *= lerp(float3(1.f, 0.9f, 0.8f), 1.f, mask);
so.color.rgb *= max(100.f, hdrScale);
const float hdrScale = Grayscale(g_ubPerFrame._ambientColor.xyz) * 12.0;
so.color.rgb *= lerp(float3(1.0, 0.9, 0.8), 1.0, mask);
so.color.rgb *= max(100.0, hdrScale);
so.color.a *= mask;
#endif

View File

@ -16,7 +16,7 @@ Texture2D g_texDepth : register(t3, space1);
SamplerState g_samDepth : register(s3, space1);
// Normalized diagonal 1/sqrt(1+1+1):
static const float g_s = 0.57735f;
static const float g_s = 0.57735;
static const float3 g_rays[8] =
{
float3(+g_s, +g_s, +g_s),
@ -70,35 +70,35 @@ FSO mainFS(VSO si)
const float weightScale = g_ubSsaoFS._smallRad_largeRad_weightScale_weightBias.z;
const float weightBias = g_ubSsaoFS._smallRad_largeRad_weightScale_weightBias.w;
const float3 randNormalWV = g_texRandNormals.SampleLevel(g_samRandNormals, si.tcNorm, 0.f).xyz * 2.f - 1.f;
const float3 randNormalWV = g_texRandNormals.SampleLevel(g_samRandNormals, si.tcNorm, 0.0).xyz * 2.0 - 1.0;
const float4 rawGBuffer1 = g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.f);
const float4 rawGBuffer1 = g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.0);
const float3 normalWV = DS_GetNormal(rawGBuffer1);
const float rawDepth = g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.f).r;
const float rawDepth = g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.0).r;
const float originDepth = ToLinearDepth(rawDepth, g_ubSsaoFS._zNearFarEx);
const float perspectScale = 1.f / originDepth;
const float perspectScale = 1.0 / originDepth;
const float4 scale = float4(smallRad, smallRad, largeRad, largeRad) * perspectScale * g_ubSsaoFS._camScale.xyxy;
float2 acc = _SINGULARITY_FIX;
[unroll] for (uint i = 0; i < 8; i++)
{
const float3 randRayWV = reflect(g_rays[i], randNormalWV);
const float3 hemiRayWV = randRayWV + normalWV * saturate(-dot(normalWV, randRayWV)) * 2.f;
const float3 hemiRayWV = randRayWV + normalWV * saturate(-dot(normalWV, randRayWV)) * 2.0;
const float nDotR = saturate(dot(normalWV, hemiRayWV));
const float3 smallRay = hemiRayWV * float3(scale.xy, smallRad);
const float3 largeRay = hemiRayWV * float3(scale.zw, largeRad);
const float2 rawKernelDepths = float2(
g_texDepth.SampleLevel(g_samDepth, si.tc0 + smallRay.xy, 0.f).r,
g_texDepth.SampleLevel(g_samDepth, si.tc0 + largeRay.xy, 0.f).r);
g_texDepth.SampleLevel(g_samDepth, si.tc0 + smallRay.xy, 0.0).r,
g_texDepth.SampleLevel(g_samDepth, si.tc0 + largeRay.xy, 0.0).r);
const float2 kernelDepths = ToLinearDepth(rawKernelDepths, g_ubSsaoFS._zNearFarEx);
const float2 kernelDeeper = kernelDepths - originDepth;
const float2 rayCloser = kernelDeeper + float2(smallRay.z, largeRay.z);
const float2 visible = step(0.f, rayCloser);
const float2 visible = step(0.0, rayCloser);
const float weight = saturate(weightBias + weightScale * rayCloser.y) * nDotR;
acc += float2(min(visible.x, visible.y) * weight, weight);

View File

@ -19,10 +19,10 @@ SamplerState g_samEnv : register(s4, space1);
static const float3 g_tetrahedron[4] =
{
float3(-1.f, -1.f, -1.f),
float3(+1.f, +1.f, -1.f),
float3(-1.f, +1.f, +1.f),
float3(+1.f, -1.f, +1.f)
float3(-1.0, -1.0, -1.0),
float3(+1.0, +1.0, -1.0),
float3(-1.0, +1.0, +1.0),
float3(+1.0, -1.0, +1.0)
};
struct VSI
@ -44,14 +44,14 @@ struct FSO
float SoftBorderMask(float2 tc)
{
const float2 mask = saturate((1.f - abs(0.5f - tc)) * 10.f - 5.f);
const float2 mask = saturate((1.0 - abs(0.5 - tc)) * 10.0 - 5.0);
return mask.x * mask.y;
}
float AlphaBoost(float alpha)
{
const float x = 1.f - alpha;
return 1.f - x * x;
const float x = 1.0 - alpha;
return 1.0 - x * x;
}
#ifdef _VS
@ -81,11 +81,11 @@ FSO mainFS(VSO si)
// Position:
const float2 ndcPos = ToNdcPos(si.tc0);
const float rawDepth = g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.f).r;
const float rawDepth = g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.0).r;
const float3 posWV = DS_GetPosition(rawDepth, g_ubSsrFS._matInvP, ndcPos);
// Normal:
const float4 rawGBuffer1 = g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.f);
const float4 rawGBuffer1 = g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.0);
const float3 normalWV = DS_GetNormal(rawGBuffer1);
// Ray from eye:
@ -95,29 +95,29 @@ FSO mainFS(VSO si)
// Reflected ray:
const float3 reflectedDir = reflect(rayFromEye, normalWV);
const float complement = saturate(dot(-rayFromEye, normalWV));
const float fresnel = 1.f - complement * complement;
const float fresnel = 1.0 - complement * complement;
// Environment map:
const float3 reflectedDirW = mul(reflectedDir, (float3x3)g_ubSsrFS._matInvV);
float3 envColor = 0.f;
float3 envColor = 0.0;
#if _SHADER_QUALITY <= _Q_MEDIUM
envColor = g_texEnv.SampleLevel(g_samEnv, reflectedDirW, 0.f).rgb * fresnel;
envColor = g_texEnv.SampleLevel(g_samEnv, reflectedDirW, 0.0).rgb * fresnel;
#else
[unroll] for (int i = 0; i < 4; ++i)
{
const float3 dir = reflectedDirW + g_tetrahedron[i] * 0.003f;
envColor += g_texEnv.SampleLevel(g_samEnv, dir, 0.f).rgb;
const float3 dir = reflectedDirW + g_tetrahedron[i] * 0.003;
envColor += g_texEnv.SampleLevel(g_samEnv, dir, 0.0).rgb;
}
envColor *= 0.25f * fresnel;
envColor *= 0.25 * fresnel;
#endif
float4 color = float4(envColor, 0.f);
float4 color = float4(envColor, 0.0);
#ifdef DEF_SSR
const float originDepth = ToLinearDepth(rawDepth, g_ubSsrFS._zNearFarEx);
const float equalize = equalizeDist / originDepth;
const float invRadius = 1.f / radius;
const float invRadius = 1.0 / radius;
#if _SHADER_QUALITY <= _Q_LOW
const int maxSampleCount = 6;
#elif _SHADER_QUALITY <= _Q_MEDIUM
@ -138,23 +138,23 @@ FSO mainFS(VSO si)
{
float4 tcRaySample = mul(float4(kernelPosWV, 1), g_ubSsrFS._matPTex);
tcRaySample /= tcRaySample.w;
const float rawKernelDepth = g_texDepth.SampleLevel(g_samDepth, tcRaySample.xy, 0.f).r;
const float rawKernelDepth = g_texDepth.SampleLevel(g_samDepth, tcRaySample.xy, 0.0).r;
const float2 rayDepth_texDepth = ToLinearDepth(float2(tcRaySample.z, rawKernelDepth), g_ubSsrFS._zNearFarEx);
const float rayDeeper = rayDepth_texDepth.x - rayDepth_texDepth.y;
if (rayDeeper > 0.f && rayDeeper < thickness) // Ray deeper, but not too deep?
if (rayDeeper > 0.0 && rayDeeper < thickness) // Ray deeper, but not too deep?
{
const float ratio = prevRayDeeper / (prevRayDeeper + rayDeeper);
const float2 tcFinal = lerp(prevTcRaySample, tcRaySample.xy, ratio);
const float tcMask = SoftBorderMask(tcFinal);
const float distMask = 1.f - ((j + ratio) * stride * invRadius);
const float distMask = 1.0 - ((j + ratio) * stride * invRadius);
const float alpha = tcMask * AlphaBoost(distMask) * fresnel;
color.rgb = lerp(envColor, g_texColor.SampleLevel(g_samColor, tcFinal, 0.f).rgb, alpha);
color.rgb = lerp(envColor, g_texColor.SampleLevel(g_samColor, tcFinal, 0.0).rgb, alpha);
color.a = alpha;
break;
}

View File

@ -52,16 +52,16 @@ struct FSO
float4 color : SV_Target0;
};
static const float g_waterPatchTexelCenter = 0.5f / 1024.f;
static const float g_beachTexelCenter = 0.5f / 16.f;
static const float g_beachMip = 6.f;
static const float g_beachHeightScale = 3.f;
static const float g_adjustHeightBy = 0.7f;
static const float g_foamScale = 8.f;
static const float g_shadeScale = 1.f / 32.f;
static const float g_wavesZoneMaskCenter = -10.f;
static const float g_wavesZoneMaskContrast = 0.12f;
static const float g_wavesMaskScaleBias = 20.f;
static const float g_waterPatchTexelCenter = 0.5 / 1024.0;
static const float g_beachTexelCenter = 0.5 / 16.0;
static const float g_beachMip = 6.0;
static const float g_beachHeightScale = 3.0;
static const float g_adjustHeightBy = 0.7;
static const float g_foamScale = 8.0;
static const float g_shadeScale = 1.0 / 32.0;
static const float g_wavesZoneMaskCenter = -10.0;
static const float g_wavesZoneMaskContrast = 0.12;
static const float g_wavesMaskScaleBias = 20.0;
float2 GetWaterHeightAt(
Texture2D texTerrainHeightmap, SamplerState samTerrainHeightmap,
@ -70,19 +70,19 @@ float2 GetWaterHeightAt(
float distToEye, float distToMipScale, float landDistToMipScale)
{
const float2 tc = pos * waterScale;
const float2 tcLand = pos * mapSideInv + 0.5f;
const float2 tcLand = pos * mapSideInv + 0.5;
float landHeight;
{
const float mip = log2(max(1.f, distToEye * landDistToMipScale));
const float texelCenter = 0.5f * mapSideInv * exp2(mip);
const float mip = log2(max(1.0, distToEye * landDistToMipScale));
const float texelCenter = 0.5 * mapSideInv * exp2(mip);
landHeight = UnpackTerrainHeight(texTerrainHeightmap.SampleLevel(samTerrainHeightmap, tcLand + texelCenter, mip).r);
}
const float landMask = ToLandMask(landHeight);
float seaWaterHeight;
{
const float mip = log2(max(1.f, distToEye * distToMipScale));
const float mip = log2(max(1.0, distToEye * distToMipScale));
const float texelCenter = g_waterPatchTexelCenter * exp2(mip);
seaWaterHeight = texGenHeightmap.SampleLevel(samGenHeightmap, tc + texelCenter, mip).r;
}
@ -124,20 +124,20 @@ VSO mainVS(VSI si)
// <Waves>
float wave;
{
const float phaseShift = saturate(g_texFoamVS.SampleLevel(g_samFoamVS, tc0 * g_shadeScale, 4.f).r * 2.f);
const float wavesZoneMask = saturate(1.f - g_wavesZoneMaskContrast * abs(height_landHeight.y - g_wavesZoneMaskCenter));
const float2 wavesMaskCenter = frac(wavePhase + phaseShift + float2(0.f, 0.5f)) * g_wavesMaskScaleBias - g_wavesMaskScaleBias;
const float2 absDeltaAsym = AsymAbs(height_landHeight.y - wavesMaskCenter, -1.f, 3.f);
const float wavesMask = smoothstep(0.f, 1.f, saturate(1.f - 0.15f * min(absDeltaAsym.x, absDeltaAsym.y)));
const float phaseShift = saturate(g_texFoamVS.SampleLevel(g_samFoamVS, tc0 * g_shadeScale, 4.0).r * 2.0);
const float wavesZoneMask = saturate(1.0 - g_wavesZoneMaskContrast * abs(height_landHeight.y - g_wavesZoneMaskCenter));
const float2 wavesMaskCenter = frac(wavePhase + phaseShift + float2(0.0, 0.5)) * g_wavesMaskScaleBias - g_wavesMaskScaleBias;
const float2 absDeltaAsym = AsymAbs(height_landHeight.y - wavesMaskCenter, -1.0, 3.0);
const float wavesMask = smoothstep(0.0, 1.0, saturate(1.0 - 0.15 * min(absDeltaAsym.x, absDeltaAsym.y)));
wave = wavesMask * wavesZoneMask;
}
// </Waves>
posW.y = height_landHeight.x + wave * 2.f * saturate(1.f / (distToEye * 0.01f));
posW.y = height_landHeight.x + wave * 2.0 * saturate(1.0 / (distToEye * 0.01));
so.pos = mul(float4(posW, 1), g_ubWaterVS._matVP);
so.tc0 = tc0;
so.tcLand_height.xy = (posW.xz + 0.5f) * mapSideInv + 0.5f;
so.tcLand_height.xy = (posW.xz + 0.5) * mapSideInv + 0.5;
so.tcLand_height.z = height_landHeight.x;
so.tcScreen = mul(float4(posW, 1), g_ubWaterVS._matScreen);
so.dirToEye_depth.xyz = dirToEye;
@ -161,7 +161,7 @@ FSO mainFS(VSO si)
const float3 dirToEye = normalize(si.dirToEye_depth.xyz);
const float depth = si.dirToEye_depth.w;
const float4 tcScreenInv = 1.f / si.tcScreen;
const float4 tcScreenInv = 1.0 / si.tcScreen;
const float perspectScale = tcScreenInv.z;
const float2 tcScreen = si.tcScreen.xy * tcScreenInv.w;
@ -174,25 +174,25 @@ FSO mainFS(VSO si)
beachWaterHeight = g_texGenHeightmap.SampleLevel(g_samGenHeightmap, si.tc0 + g_beachTexelCenter, g_beachMip).r * g_beachHeightScale + g_adjustHeightBy;
landHeight = UnpackTerrainHeight(g_texTerrainHeightmap.Sample(g_samTerrainHeightmap, si.tcLand_height.xy).r);
landMask = ToLandMask(landHeight - beachWaterHeight);
landMaskStatic = lerp(saturate((ToLandMask(landHeight) - 0.8f) * 5.f), landMask, 0.1f);
landMaskStatic = lerp(saturate((ToLandMask(landHeight) - 0.8) * 5.0), landMask, 0.1);
}
const float alpha = saturate((1.f - landMask) * 20.f);
const float alpha = saturate((1.0 - landMask) * 20.0);
// </Land>
// <Waves>
float wave;
float fresnelDimmer; // A trick to make waves look more 3D.
{
const float phaseShift = saturate(g_texFoam.SampleLevel(g_samFoam, si.tc0 * g_shadeScale, 4.f).r * 2.f);
const float wavesZoneMask = saturate(1.f - g_wavesZoneMaskContrast * abs(landHeight - g_wavesZoneMaskCenter));
const float2 wavesMaskCenter = frac(wavePhase + phaseShift + float2(0.f, 0.5f)) * g_wavesMaskScaleBias - g_wavesMaskScaleBias;
const float phaseShift = saturate(g_texFoam.SampleLevel(g_samFoam, si.tc0 * g_shadeScale, 4.0).r * 2.0);
const float wavesZoneMask = saturate(1.0 - g_wavesZoneMaskContrast * abs(landHeight - g_wavesZoneMaskCenter));
const float2 wavesMaskCenter = frac(wavePhase + phaseShift + float2(0.0, 0.5)) * g_wavesMaskScaleBias - g_wavesMaskScaleBias;
const float2 delta = landHeight - wavesMaskCenter;
const float2 absDelta = abs(delta);
const float2 absDeltaAsym = AsymAbs(delta, -1.f, 3.5f);
const float wavesMask = saturate(1.f - 0.5f * min(absDeltaAsym.x, absDeltaAsym.y));
const float2 absDeltaAsym = AsymAbs(delta, -1.0, 3.5);
const float wavesMask = saturate(1.0 - 0.5 * min(absDeltaAsym.x, absDeltaAsym.y));
wave = wavesMask * wavesZoneMask;
const float biggerWavesMask = saturate(1.f - 0.5f * min(absDelta.x, absDelta.y));
fresnelDimmer = saturate(1.f - biggerWavesMask * wavesZoneMask * 1.5f);
const float biggerWavesMask = saturate(1.0 - 0.5 * min(absDelta.x, absDelta.y));
fresnelDimmer = saturate(1.0 - biggerWavesMask * wavesZoneMask * 1.5);
}
// </Waves>
@ -200,7 +200,7 @@ FSO mainFS(VSO si)
float3 normal;
{
const float3 rawNormal = g_texGenNormals.Sample(g_samGenNormals, si.tc0).rgb;
const float3 normalWithLand = lerp(rawNormal, float3(0.5f, 0.5f, 1), saturate(landMask * 0.8f + wave));
const float3 normalWithLand = lerp(rawNormal, float3(0.5, 0.5, 1), saturate(landMask * 0.8 + wave));
normal = normalize(normalWithLand.xzy * float3(-2, 2, -2) + float3(1, -1, 1));
}
// </Normal>
@ -208,35 +208,35 @@ FSO mainFS(VSO si)
// <Reflection>
float3 reflectColor;
{
const float fudgeFactor = 32.f;
const float fudgeFactor = 32.0;
const float3 flatReflect = reflect(-dirToEye, float3(0, 1, 0));
const float3 bumpReflect = reflect(-dirToEye, normal);
const float3 delta = bumpReflect - flatReflect;
const float2 viewSpaceOffsetPerMeter = mul(float4(delta, 0), g_ubWaterFS._matV).xy;
const float2 offset = viewSpaceOffsetPerMeter * saturate(perspectScale) * camScale * fudgeFactor;
reflectColor = g_texReflection.Sample(g_samReflection, tcScreen + max(offset, float2(-1, 0))).rgb;
reflectColor = ReflectionDimming(reflectColor, 0.8f);
reflectColor = ReflectionDimming(reflectColor, 0.8);
}
// </Reflection>
// <Refraction>
float3 refractColor;
{
const float fudgeFactor = (0.1f + 0.9f * abs(dirToEye.y) * abs(dirToEye.y)) * 2.5f;
const float fudgeFactor = (0.1 + 0.9 * abs(dirToEye.y) * abs(dirToEye.y)) * 2.5;
const float waterDepth = -landHeight;
const float2 tcScreen2 = tcScreen * 2.f - 1.f;
const float2 tcScreen2 = tcScreen * 2.0 - 1.0;
const float mask = saturate(dot(tcScreen2, tcScreen2));
const float3 bumpRefract = refract(-dirToEye, normal, 1.f / 1.33f);
const float3 bumpRefract = refract(-dirToEye, normal, 1.0 / 1.33);
const float3 delta = bumpRefract + dirToEye;
const float2 viewSpaceOffsetPerMeter = mul(float4(delta, 0), g_ubWaterFS._matV).xy * (1.f - mask);
const float2 viewSpaceOffsetPerMeter = mul(float4(delta, 0), g_ubWaterFS._matV).xy * (1.0 - mask);
const float2 offset = viewSpaceOffsetPerMeter * waterDepth * saturate(perspectScale) * camScale * fudgeFactor;
const float2 tcRefractR = tcScreen + offset * 0.9f;
const float2 tcRefractG = tcScreen + offset * 1.f;
const float2 tcRefractB = tcScreen + offset * 1.1f;
const float2 tcRefractR = tcScreen + offset * 0.9;
const float2 tcRefractG = tcScreen + offset * 1.0;
const float2 tcRefractB = tcScreen + offset * 1.1;
refractColor = float3(
g_texRefraction.SampleLevel(g_samRefraction, tcRefractR, 0.f).r,
g_texRefraction.SampleLevel(g_samRefraction, tcRefractG, 0.f).g,
g_texRefraction.SampleLevel(g_samRefraction, tcRefractB, 0.f).b);
g_texRefraction.SampleLevel(g_samRefraction, tcRefractR, 0.0).r,
g_texRefraction.SampleLevel(g_samRefraction, tcRefractG, 0.0).g,
g_texRefraction.SampleLevel(g_samRefraction, tcRefractB, 0.0).b);
}
// </Refraction>
@ -247,24 +247,24 @@ FSO mainFS(VSO si)
float foamHeightAlpha;
{
const float2 tcFoam = si.tc0 * g_foamScale;
const float2 tcFoamA = tcFoam + phase + float2(0.5f, 0.f);
const float2 tcFoamA = tcFoam + phase + float2(0.5, 0.0);
const float2 tcFoamB = tcFoam - phase;
const float3 foamColorA = g_texFoam.Sample(g_samFoam, tcFoamA).rgb;
const float3 foamColorB = g_texFoam.Sample(g_samFoam, tcFoamB).rgb;
foamColor.rgb = lerp(foamColorA, foamColorB, 0.5f);
foamColor.a = saturate(foamColor.b * 2.f);
foamColor.rgb = lerp(foamColorA, foamColorB, 0.5);
foamColor.a = saturate(foamColor.b * 2.0);
const float a = saturate(height - 0.1f);
const float a = saturate(height - 0.1);
const float a2 = a * a;
const float a4 = a2 * a2;
foamHeightAlpha = saturate(a4 * a4 + wave * 0.75f);
foamHeightAlpha = saturate(a4 * a4 + wave * 0.75);
const float complement = 1.f - shade;
const float mask = saturate((landMask - 0.9f) * 10.f * (1.f - shade * 3.f)) * complement * complement;
const float superfoam = saturate(mask * (1.f - mask) * 3.f);
foamColor = lerp(foamColor, 1.f, max(superfoam * superfoam, saturate(wave * 0.75f)));
const float complement = 1.0 - shade;
const float mask = saturate((landMask - 0.9) * 10.0 * (1.0 - shade * 3.0)) * complement * complement;
const float superfoam = saturate(mask * (1.0 - mask) * 3.0);
foamColor = lerp(foamColor, 1.0, max(superfoam * superfoam, saturate(wave * 0.75)));
}
const float foamAlpha = 0.002f + 0.998f * saturate(landMaskStatic + foamHeightAlpha) * foamColor.a;
const float foamAlpha = 0.002 + 0.998 * saturate(landMaskStatic + foamHeightAlpha) * foamColor.a;
// </Foam>
// <Plankton>
@ -273,22 +273,22 @@ FSO mainFS(VSO si)
{
const float diffuseMask = ToWaterDiffuseMask(landHeight);
planktonColor = lerp(g_ubWaterFS._diffuseColorDeep.rgb, g_ubWaterFS._diffuseColorShallow.rgb, diffuseMask);
planktonColor *= 0.1f + 0.2f * saturate(shade - wave);
refractMask = saturate((diffuseMask - 0.75f) * 4.f);
planktonColor *= 0.1 + 0.2 * saturate(shade - wave);
refractMask = saturate((diffuseMask - 0.75) * 4.0);
}
// </Plankton>
const float spec = lerp(1.f, 0.1f, foamAlpha);
const float gloss = lerp(1200.f, 4.f, foamAlpha);
const float spec = lerp(1.0, 0.1, foamAlpha);
const float gloss = lerp(1200.0, 4.0, foamAlpha);
const float2 lamScaleBias = float2(1, 0.2f);
const float2 lamScaleBias = float2(1, 0.2);
// <Shadow>
float shadowMask;
{
float4 shadowConfig = g_ubWaterFS._shadowConfig;
const float lamBiasMask = saturate(lamScaleBias.y * shadowConfig.y);
shadowConfig.y = 1.f - lamBiasMask; // Keep penumbra blurry.
shadowConfig.y = 1.0 - lamBiasMask; // Keep penumbra blurry.
const float3 posForShadow = AdjustPosForShadow(si.posW, normal, g_ubWaterFS._dirToSun.xyz, depth);
shadowMask = ShadowMapCSM(
g_texShadowCmp,
@ -311,9 +311,9 @@ FSO mainFS(VSO si)
gloss,
lamScaleBias,
float4(0, 0, 1, 0),
1.f);
1.0);
const float fresnelTerm = FresnelSchlick(0.03f, 0.6f * fresnelDimmer, litRet.w);
const float fresnelTerm = FresnelSchlick(0.03, 0.6 * fresnelDimmer, litRet.w);
const float3 diff = litRet.y * g_ubWaterFS._sunColor.rgb * shadowMask + g_ubWaterFS._ambientColor.rgb;
const float3 diffColorFoam = foamColor.rgb * diff;
@ -323,10 +323,10 @@ FSO mainFS(VSO si)
const float fog = ComputeFog(depth, g_ubWaterFS._fogColor.a);
so.color.rgb = lerp(diffColor * (1.f - fresnelTerm) + specColor, g_ubWaterFS._fogColor.rgb, fog);
so.color.rgb = lerp(diffColor * (1.0 - fresnelTerm) + specColor, g_ubWaterFS._fogColor.rgb, fog);
so.color.a = alpha;
clip(so.color.a - 0.01f);
clip(so.color.a - 0.01);
return so;
}

View File

@ -66,16 +66,16 @@ FSO mainGenHeightmapFS(VSO si)
float2(-1, +0),
float2(+0, -1)
};
const float4 offsets = float4(0, 0.3f, 0.5f, 0.7f);
float accHeight = 0.f;
const float4 offsets = float4(0, 0.3, 0.5, 0.7);
float accHeight = 0.0;
[unroll] for (uint i = 0; i < 4; ++i)
{
float height = g_texSourceHeightmap.SampleLevel(g_samSourceHeightmap, (si.tc0 + offsets[i]) * (i / 2 + 1) + g_ubGenHeightmapFS._phase.x * dirs[i], 0.f).r - 0.5f;
float height = g_texSourceHeightmap.SampleLevel(g_samSourceHeightmap, (si.tc0 + offsets[i]) * (i / 2 + 1) + g_ubGenHeightmapFS._phase.x * dirs[i], 0.0).r - 0.5;
height *= amplitudes[i]; // Must be local float4 to work in D3D12!
accHeight += height;
}
const float splash = max(0.f, accHeight);
so.color = accHeight * 2.f + splash * splash * splash * 16.f;
const float splash = max(0.0, accHeight);
so.color = accHeight * 2.0 + splash * splash * splash * 16.0;
return so;
}
@ -86,9 +86,9 @@ FSO mainGenNormalsFS(VSO si)
{
FSO so;
const float damp = (1.f / 512.f / 2.f) * g_ubGenNormalsFS._waterScale.x * g_ubGenNormalsFS._textureSize.x;
const float damp = (1.0 / 512.0 / 2.0) * g_ubGenNormalsFS._waterScale.x * g_ubGenNormalsFS._textureSize.x;
so.color.rgb = ComputeNormals(g_texGenHeightmap, g_samGenHeightmap, si.tc0, damp, 2);
so.color.a = 1.f;
so.color.a = 1.0;
return so;
}