2021.7
This commit is contained in:
parent
9e0b83d85d
commit
3a8e683f01
20
README.md
20
README.md
|
@ -3,21 +3,17 @@
|
|||
# Verus Engine
|
||||
|
||||
## What is Verus Engine?
|
||||
|
||||
Verus Engine is a modern, platform-agnostic 3D game engine. It is developed using **C++** and **HLSL**. It is based on **Direct3D 12** and **Vulkan** graphics APIs. The code is user friendly and well optimized. The engine is intended to be a full-featured solution for making games. It includes modules to handle input, audio, networking and other things. Hence there is no need to search for third-party libraries or write custom code.
|
||||
|
||||
## Supported systems
|
||||
|
||||
* **Windows 10**, 8, 8.1 *(via Vulkan renderer)*
|
||||
* **64-bit only**, 32-bit is not supported
|
||||
|
||||
## Supported graphics libraries
|
||||
|
||||
* Vulkan
|
||||
* Direct3D 12
|
||||
|
||||
## Features
|
||||
|
||||
* Native cross-platform code
|
||||
* Same HLSL shader code for all APIs
|
||||
* Deferred shading
|
||||
|
@ -31,11 +27,18 @@ Verus Engine is a modern, platform-agnostic 3D game engine. It is developed usin
|
|||
* Filesystem abstraction
|
||||
* Other things
|
||||
|
||||
## VerusEdit
|
||||
VerusEdit is an official editor for Verus Engine.
|
||||
|
||||
You can download the latest version of VerusEdit here: https://verushub.com/page/verusedit.
|
||||
|
||||
![VerusEdit](https://en.verushub.com/img/verusedit/screenshot0_tn.jpg)
|
||||
![VerusEdit](https://en.verushub.com/img/verusedit/screenshot1_tn.jpg)
|
||||
|
||||
## Roadmap
|
||||
These features should be implemented in version **1.x**:
|
||||
|
||||
These features should be implemented in version 1.x:
|
||||
|
||||
- [ ] glTF file format support
|
||||
- [x] glTF file format support
|
||||
- [ ] Shadow maps for all lights
|
||||
- [ ] Triggers
|
||||
- [ ] Quest system, dialogue system
|
||||
|
@ -45,7 +48,7 @@ These features should be implemented in version 1.x:
|
|||
- [ ] Lua scripting
|
||||
- [ ] Linux support
|
||||
|
||||
These features should be implemented in version 2.x:
|
||||
These features should be implemented in version **2.x**:
|
||||
|
||||
- [ ] Signed distance field (SDF) fonts
|
||||
- [ ] Materials v2.0: separate textures for gloss, emission, etc.
|
||||
|
@ -56,5 +59,4 @@ These features should be implemented in version 2.x:
|
|||
- [ ] Android and iOS support
|
||||
|
||||
## License
|
||||
|
||||
Verus Engine is free for non-commercial use
|
||||
|
|
|
@ -303,6 +303,20 @@ void CommandBufferD3D12::Dispatch(int groupCountX, int groupCountY, int groupCou
|
|||
GetD3DGraphicsCommandList()->Dispatch(groupCountX, groupCountY, groupCountZ);
|
||||
}
|
||||
|
||||
void CommandBufferD3D12::DispatchMesh(int groupCountX, int groupCountY, int groupCountZ)
|
||||
{
|
||||
//GetD3DGraphicsCommandList()->DispatchMesh(groupCountX, groupCountY, groupCountZ);
|
||||
}
|
||||
|
||||
void CommandBufferD3D12::TraceRays(int width, int height, int depth)
|
||||
{
|
||||
//D3D12_DISPATCH_RAYS_DESC desc = {};
|
||||
//desc.Width = width;
|
||||
//desc.Height = height;
|
||||
//desc.Depth = depth;
|
||||
//GetD3DGraphicsCommandList()->DispatchRays(&desc);
|
||||
}
|
||||
|
||||
ID3D12GraphicsCommandList3* CommandBufferD3D12::GetD3DGraphicsCommandList() const
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
|
|
|
@ -47,8 +47,9 @@ namespace verus
|
|||
|
||||
virtual void Draw(int vertexCount, int instanceCount, int firstVertex, int firstInstance) override;
|
||||
virtual void DrawIndexed(int indexCount, int instanceCount, int firstIndex, int vertexOffset, int firstInstance) override;
|
||||
|
||||
virtual void Dispatch(int groupCountX, int groupCountY, int groupCountZ) override;
|
||||
virtual void DispatchMesh(int groupCountX, int groupCountY, int groupCountZ) override;
|
||||
virtual void TraceRays(int width, int height, int depth) override;
|
||||
|
||||
//
|
||||
// D3D12
|
||||
|
|
|
@ -26,11 +26,7 @@ void PipelineD3D12::Init(RcPipelineDesc desc)
|
|||
return;
|
||||
}
|
||||
|
||||
_vertexInputBindingsFilter = desc._vertexInputBindingsFilter;
|
||||
|
||||
RcGeometryD3D12 geo = static_cast<RcGeometryD3D12>(*desc._geometry);
|
||||
RcShaderD3D12 shader = static_cast<RcShaderD3D12>(*desc._shader);
|
||||
|
||||
// Attachment count according to blend equations:
|
||||
int attachmentCount = 0;
|
||||
for (const auto& x : desc._colorAttachBlendEqs)
|
||||
{
|
||||
|
@ -39,8 +35,12 @@ void PipelineD3D12::Init(RcPipelineDesc desc)
|
|||
attachmentCount++;
|
||||
}
|
||||
|
||||
RcGeometryD3D12 geo = static_cast<RcGeometryD3D12>(*desc._geometry);
|
||||
RcShaderD3D12 shader = static_cast<RcShaderD3D12>(*desc._shader);
|
||||
|
||||
_pRootSignature = shader.GetD3DRootSignature();
|
||||
_topology = ToNativePrimitiveTopology(desc._topology);
|
||||
_vertexInputBindingsFilter = desc._vertexInputBindingsFilter;
|
||||
|
||||
RP::RcD3DRenderPass renderPass = pRendererD3D12->GetRenderPass(desc._renderPassHandle);
|
||||
RP::RcD3DSubpass subpass = renderPass._vSubpasses[desc._subpass];
|
||||
|
@ -60,78 +60,9 @@ void PipelineD3D12::Init(RcPipelineDesc desc)
|
|||
gpsDesc.GS = ToBytecode(compiled._pBlobs[+BaseShader::Stage::gs].Get());
|
||||
gpsDesc.StreamOutput = {};
|
||||
|
||||
gpsDesc.BlendState = {};
|
||||
gpsDesc.BlendState.AlphaToCoverageEnable = FALSE;
|
||||
gpsDesc.BlendState.IndependentBlendEnable = TRUE;
|
||||
VERUS_FOR(i, attachmentCount)
|
||||
{
|
||||
CSZ p = _C(desc._colorAttachWriteMasks[i]);
|
||||
while (*p)
|
||||
{
|
||||
switch (*p)
|
||||
{
|
||||
case 'r': gpsDesc.BlendState.RenderTarget[i].RenderTargetWriteMask |= D3D12_COLOR_WRITE_ENABLE_RED; break;
|
||||
case 'g': gpsDesc.BlendState.RenderTarget[i].RenderTargetWriteMask |= D3D12_COLOR_WRITE_ENABLE_GREEN; break;
|
||||
case 'b': gpsDesc.BlendState.RenderTarget[i].RenderTargetWriteMask |= D3D12_COLOR_WRITE_ENABLE_BLUE; break;
|
||||
case 'a': gpsDesc.BlendState.RenderTarget[i].RenderTargetWriteMask |= D3D12_COLOR_WRITE_ENABLE_ALPHA; break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
if (desc._colorAttachBlendEqs[i] != "off")
|
||||
{
|
||||
gpsDesc.BlendState.RenderTarget[i].BlendEnable = TRUE;
|
||||
|
||||
static const D3D12_BLEND bfs[] =
|
||||
{
|
||||
D3D12_BLEND_ZERO,
|
||||
D3D12_BLEND_ONE,
|
||||
D3D12_BLEND_INV_DEST_ALPHA,
|
||||
D3D12_BLEND_INV_DEST_COLOR,
|
||||
D3D12_BLEND_INV_BLEND_FACTOR,
|
||||
D3D12_BLEND_INV_SRC_ALPHA,
|
||||
D3D12_BLEND_INV_SRC_COLOR,
|
||||
D3D12_BLEND_DEST_ALPHA,
|
||||
D3D12_BLEND_DEST_COLOR,
|
||||
D3D12_BLEND_BLEND_FACTOR,
|
||||
D3D12_BLEND_SRC_ALPHA,
|
||||
D3D12_BLEND_SRC_ALPHA_SAT,
|
||||
D3D12_BLEND_SRC_COLOR
|
||||
};
|
||||
static const D3D12_BLEND_OP ops[] =
|
||||
{
|
||||
D3D12_BLEND_OP_ADD,
|
||||
D3D12_BLEND_OP_SUBTRACT,
|
||||
D3D12_BLEND_OP_REV_SUBTRACT,
|
||||
D3D12_BLEND_OP_MIN,
|
||||
D3D12_BLEND_OP_MAX
|
||||
};
|
||||
|
||||
int colorBlendOp = -1;
|
||||
int alphaBlendOp = -1;
|
||||
int srcColorBlendFactor = -1;
|
||||
int dstColorBlendFactor = -1;
|
||||
int srcAlphaBlendFactor = -1;
|
||||
int dstAlphaBlendFactor = -1;
|
||||
|
||||
BaseRenderer::SetAlphaBlendHelper(
|
||||
_C(desc._colorAttachBlendEqs[i]),
|
||||
colorBlendOp,
|
||||
alphaBlendOp,
|
||||
srcColorBlendFactor,
|
||||
dstColorBlendFactor,
|
||||
srcAlphaBlendFactor,
|
||||
dstAlphaBlendFactor);
|
||||
|
||||
gpsDesc.BlendState.RenderTarget[i].SrcBlend = bfs[srcColorBlendFactor];
|
||||
gpsDesc.BlendState.RenderTarget[i].DestBlend = bfs[dstColorBlendFactor];
|
||||
gpsDesc.BlendState.RenderTarget[i].BlendOp = ops[colorBlendOp];
|
||||
gpsDesc.BlendState.RenderTarget[i].SrcBlendAlpha = bfs[srcAlphaBlendFactor];
|
||||
gpsDesc.BlendState.RenderTarget[i].DestBlendAlpha = bfs[dstAlphaBlendFactor];
|
||||
gpsDesc.BlendState.RenderTarget[i].BlendOpAlpha = ops[alphaBlendOp];
|
||||
gpsDesc.BlendState.RenderTarget[i].LogicOp = D3D12_LOGIC_OP_CLEAR;
|
||||
}
|
||||
}
|
||||
FillBlendStateRenderTargets(desc, attachmentCount, gpsDesc.BlendState);
|
||||
|
||||
gpsDesc.SampleMask = UINT_MAX;
|
||||
|
||||
|
@ -160,12 +91,11 @@ void PipelineD3D12::Init(RcPipelineDesc desc)
|
|||
gpsDesc.IBStripCutValue = desc._primitiveRestartEnable ? GetStripCutValue() : D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED;
|
||||
gpsDesc.PrimitiveTopologyType = ToNativePrimitiveTopologyType(desc._topology);
|
||||
|
||||
gpsDesc.NumRenderTargets = Utils::Cast32(subpass._vColor.size());
|
||||
VERUS_RT_ASSERT(gpsDesc.NumRenderTargets == attachmentCount);
|
||||
gpsDesc.NumRenderTargets = Utils::Cast32(subpass._vColor.size()); // According to subpass.
|
||||
VERUS_RT_ASSERT(gpsDesc.NumRenderTargets == attachmentCount); // These two must match.
|
||||
VERUS_U_FOR(i, gpsDesc.NumRenderTargets)
|
||||
{
|
||||
const int index = subpass._vColor[i]._index;
|
||||
RP::RcD3DAttachment attachment = renderPass._vAttachments[index];
|
||||
RP::RcD3DAttachment attachment = renderPass._vAttachments[subpass._vColor[i]._index];
|
||||
gpsDesc.RTVFormats[i] = ToNativeFormat(attachment._format, false);
|
||||
}
|
||||
if (subpass._depthStencil._index >= 0)
|
||||
|
@ -214,6 +144,88 @@ void PipelineD3D12::InitCompute(RcPipelineDesc desc)
|
|||
_pPipelineState->SetName(_C(Str::Utf8ToWide(String("PipelineState (") + _C(shader.GetSourceName()) + ", " + desc._shaderBranch + ")")));
|
||||
}
|
||||
|
||||
void PipelineD3D12::InitMeshShading(RcPipelineDesc desc)
|
||||
{
|
||||
VERUS_QREF_RENDERER_D3D12;
|
||||
HRESULT hr = 0;
|
||||
|
||||
// Attachment count according to blend equations:
|
||||
int attachmentCount = 0;
|
||||
for (const auto& x : desc._colorAttachBlendEqs)
|
||||
{
|
||||
if (x.empty())
|
||||
break;
|
||||
attachmentCount++;
|
||||
}
|
||||
|
||||
RcShaderD3D12 shader = static_cast<RcShaderD3D12>(*desc._shader);
|
||||
|
||||
_pRootSignature = shader.GetD3DRootSignature();
|
||||
_topology = ToNativePrimitiveTopology(desc._topology);
|
||||
|
||||
RP::RcD3DRenderPass renderPass = pRendererD3D12->GetRenderPass(desc._renderPassHandle);
|
||||
RP::RcD3DSubpass subpass = renderPass._vSubpasses[desc._subpass];
|
||||
|
||||
D3DX12_MESH_SHADER_PIPELINE_STATE_DESC mspsDesc = {};
|
||||
mspsDesc.pRootSignature = _pRootSignature;
|
||||
mspsDesc.AS = ToBytecode(nullptr);
|
||||
mspsDesc.MS = ToBytecode(nullptr);
|
||||
mspsDesc.PS = ToBytecode(nullptr);
|
||||
|
||||
mspsDesc.BlendState.AlphaToCoverageEnable = FALSE;
|
||||
mspsDesc.BlendState.IndependentBlendEnable = TRUE;
|
||||
FillBlendStateRenderTargets(desc, attachmentCount, mspsDesc.BlendState);
|
||||
|
||||
mspsDesc.SampleMask = UINT_MAX;
|
||||
|
||||
mspsDesc.RasterizerState.FillMode = ToNativePolygonMode(desc._rasterizationState._polygonMode);
|
||||
mspsDesc.RasterizerState.CullMode = ToNativeCullMode(desc._rasterizationState._cullMode);
|
||||
mspsDesc.RasterizerState.FrontCounterClockwise = TRUE;
|
||||
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.MultisampleEnable = FALSE;
|
||||
mspsDesc.RasterizerState.AntialiasedLineEnable = (desc._colorAttachBlendEqs[0] == VERUS_COLOR_BLEND_ALPHA) ? TRUE : FALSE;
|
||||
mspsDesc.RasterizerState.ForcedSampleCount = 0;
|
||||
mspsDesc.RasterizerState.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
|
||||
|
||||
if (subpass._depthStencil._index >= 0)
|
||||
{
|
||||
mspsDesc.DepthStencilState.DepthEnable = desc._depthTestEnable;
|
||||
mspsDesc.DepthStencilState.DepthWriteMask = desc._depthWriteEnable ? D3D12_DEPTH_WRITE_MASK_ALL : D3D12_DEPTH_WRITE_MASK_ZERO;
|
||||
mspsDesc.DepthStencilState.DepthFunc = ToNativeCompareOp(desc._depthCompareOp);
|
||||
mspsDesc.DepthStencilState.StencilEnable = desc._stencilTestEnable;
|
||||
}
|
||||
|
||||
mspsDesc.PrimitiveTopologyType = ToNativePrimitiveTopologyType(desc._topology);
|
||||
|
||||
mspsDesc.NumRenderTargets = Utils::Cast32(subpass._vColor.size()); // According to subpass.
|
||||
VERUS_RT_ASSERT(mspsDesc.NumRenderTargets == attachmentCount); // These two must match.
|
||||
VERUS_U_FOR(i, mspsDesc.NumRenderTargets)
|
||||
{
|
||||
RP::RcD3DAttachment attachment = renderPass._vAttachments[subpass._vColor[i]._index];
|
||||
mspsDesc.RTVFormats[i] = ToNativeFormat(attachment._format, false);
|
||||
}
|
||||
if (subpass._depthStencil._index >= 0)
|
||||
{
|
||||
RP::RcD3DAttachment attachment = renderPass._vAttachments[subpass._depthStencil._index];
|
||||
mspsDesc.DSVFormat = ToNativeFormat(attachment._format, false);
|
||||
}
|
||||
|
||||
mspsDesc.SampleDesc.Count = desc._sampleCount;
|
||||
mspsDesc.NodeMask = 0;
|
||||
mspsDesc.CachedPSO = { nullptr, 0 };
|
||||
mspsDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
|
||||
|
||||
auto meshStateStream = CD3DX12_PIPELINE_MESH_STATE_STREAM(mspsDesc);
|
||||
D3D12_PIPELINE_STATE_STREAM_DESC streamDesc = {};
|
||||
streamDesc.SizeInBytes = sizeof(meshStateStream);
|
||||
streamDesc.pPipelineStateSubobjectStream = &meshStateStream;
|
||||
if (FAILED(hr = pRendererD3D12->GetD3DDevice()->CreatePipelineState(&streamDesc, IID_PPV_ARGS(&_pPipelineState))))
|
||||
throw VERUS_RUNTIME_ERROR << "CreatePipelineState(), hr=" << VERUS_HR(hr);
|
||||
}
|
||||
|
||||
D3D12_SHADER_BYTECODE PipelineD3D12::ToBytecode(ID3DBlob* pBlob)
|
||||
{
|
||||
D3D12_SHADER_BYTECODE bytecode = {};
|
||||
|
@ -224,3 +236,76 @@ D3D12_SHADER_BYTECODE PipelineD3D12::ToBytecode(ID3DBlob* pBlob)
|
|||
}
|
||||
return bytecode;
|
||||
}
|
||||
|
||||
void PipelineD3D12::FillBlendStateRenderTargets(RcPipelineDesc desc, int attachmentCount, D3D12_BLEND_DESC& blendDesc)
|
||||
{
|
||||
VERUS_FOR(i, attachmentCount)
|
||||
{
|
||||
CSZ p = _C(desc._colorAttachWriteMasks[i]);
|
||||
while (*p)
|
||||
{
|
||||
switch (*p)
|
||||
{
|
||||
case 'r': blendDesc.RenderTarget[i].RenderTargetWriteMask |= D3D12_COLOR_WRITE_ENABLE_RED; break;
|
||||
case 'g': blendDesc.RenderTarget[i].RenderTargetWriteMask |= D3D12_COLOR_WRITE_ENABLE_GREEN; break;
|
||||
case 'b': blendDesc.RenderTarget[i].RenderTargetWriteMask |= D3D12_COLOR_WRITE_ENABLE_BLUE; break;
|
||||
case 'a': blendDesc.RenderTarget[i].RenderTargetWriteMask |= D3D12_COLOR_WRITE_ENABLE_ALPHA; break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
if (desc._colorAttachBlendEqs[i] != "off")
|
||||
{
|
||||
blendDesc.RenderTarget[i].BlendEnable = TRUE;
|
||||
|
||||
static const D3D12_BLEND bfs[] =
|
||||
{
|
||||
D3D12_BLEND_ZERO,
|
||||
D3D12_BLEND_ONE,
|
||||
D3D12_BLEND_INV_DEST_ALPHA,
|
||||
D3D12_BLEND_INV_DEST_COLOR,
|
||||
D3D12_BLEND_INV_BLEND_FACTOR,
|
||||
D3D12_BLEND_INV_SRC_ALPHA,
|
||||
D3D12_BLEND_INV_SRC_COLOR,
|
||||
D3D12_BLEND_DEST_ALPHA,
|
||||
D3D12_BLEND_DEST_COLOR,
|
||||
D3D12_BLEND_BLEND_FACTOR,
|
||||
D3D12_BLEND_SRC_ALPHA,
|
||||
D3D12_BLEND_SRC_ALPHA_SAT,
|
||||
D3D12_BLEND_SRC_COLOR
|
||||
};
|
||||
static const D3D12_BLEND_OP ops[] =
|
||||
{
|
||||
D3D12_BLEND_OP_ADD,
|
||||
D3D12_BLEND_OP_SUBTRACT,
|
||||
D3D12_BLEND_OP_REV_SUBTRACT,
|
||||
D3D12_BLEND_OP_MIN,
|
||||
D3D12_BLEND_OP_MAX
|
||||
};
|
||||
|
||||
int colorBlendOp = -1;
|
||||
int alphaBlendOp = -1;
|
||||
int srcColorBlendFactor = -1;
|
||||
int dstColorBlendFactor = -1;
|
||||
int srcAlphaBlendFactor = -1;
|
||||
int dstAlphaBlendFactor = -1;
|
||||
|
||||
BaseRenderer::SetAlphaBlendHelper(
|
||||
_C(desc._colorAttachBlendEqs[i]),
|
||||
colorBlendOp,
|
||||
alphaBlendOp,
|
||||
srcColorBlendFactor,
|
||||
dstColorBlendFactor,
|
||||
srcAlphaBlendFactor,
|
||||
dstAlphaBlendFactor);
|
||||
|
||||
blendDesc.RenderTarget[i].SrcBlend = bfs[srcColorBlendFactor];
|
||||
blendDesc.RenderTarget[i].DestBlend = bfs[dstColorBlendFactor];
|
||||
blendDesc.RenderTarget[i].BlendOp = ops[colorBlendOp];
|
||||
blendDesc.RenderTarget[i].SrcBlendAlpha = bfs[srcAlphaBlendFactor];
|
||||
blendDesc.RenderTarget[i].DestBlendAlpha = bfs[dstAlphaBlendFactor];
|
||||
blendDesc.RenderTarget[i].BlendOpAlpha = ops[alphaBlendOp];
|
||||
blendDesc.RenderTarget[i].LogicOp = D3D12_LOGIC_OP_CLEAR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,11 +24,13 @@ namespace verus
|
|||
//
|
||||
|
||||
VERUS_P(void InitCompute(RcPipelineDesc desc));
|
||||
VERUS_P(void InitMeshShading(RcPipelineDesc desc));
|
||||
D3D12_SHADER_BYTECODE ToBytecode(ID3DBlob* pBlob);
|
||||
bool IsCompute() const { return _compute; }
|
||||
ID3D12PipelineState* GetD3DPipelineState() const { return _pPipelineState.Get(); }
|
||||
ID3D12RootSignature* GetD3DRootSignature() const { return _pRootSignature; }
|
||||
D3D_PRIMITIVE_TOPOLOGY GetPrimitiveTopology() const { return _topology; }
|
||||
void FillBlendStateRenderTargets(RcPipelineDesc desc, int attachmentCount, D3D12_BLEND_DESC& blendDesc);
|
||||
};
|
||||
VERUS_TYPEDEFS(PipelineD3D12);
|
||||
}
|
||||
|
|
|
@ -301,6 +301,8 @@ void ShaderD3D12::CreatePipelineLayout()
|
|||
case ShaderStageFlags::ds: visibility = D3D12_SHADER_VISIBILITY_DOMAIN; break;
|
||||
case ShaderStageFlags::gs: visibility = D3D12_SHADER_VISIBILITY_GEOMETRY; break;
|
||||
case ShaderStageFlags::fs: visibility = D3D12_SHADER_VISIBILITY_PIXEL; break;
|
||||
case ShaderStageFlags::ts: visibility = D3D12_SHADER_VISIBILITY_AMPLIFICATION; break;
|
||||
case ShaderStageFlags::ms: visibility = D3D12_SHADER_VISIBILITY_MESH; break;
|
||||
}
|
||||
|
||||
CD3DX12_DESCRIPTOR_RANGE1 descRange;
|
||||
|
@ -373,6 +375,10 @@ void ShaderD3D12::CreatePipelineLayout()
|
|||
rootSignatureFlags |= D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS;
|
||||
if (!(stageFlags & ShaderStageFlags::fs))
|
||||
rootSignatureFlags |= D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS;
|
||||
if (!(stageFlags & ShaderStageFlags::ts))
|
||||
rootSignatureFlags |= D3D12_ROOT_SIGNATURE_FLAG_DENY_AMPLIFICATION_SHADER_ROOT_ACCESS;
|
||||
if (!(stageFlags & ShaderStageFlags::ms))
|
||||
rootSignatureFlags |= D3D12_ROOT_SIGNATURE_FLAG_DENY_MESH_SHADER_ROOT_ACCESS;
|
||||
}
|
||||
|
||||
UpdateDebugInfo(vRootParams, vStaticSamplers, rootSignatureFlags);
|
||||
|
@ -633,6 +639,8 @@ void ShaderD3D12::UpdateDebugInfo(
|
|||
case D3D12_SHADER_VISIBILITY_DOMAIN: ss << "D"; break;
|
||||
case D3D12_SHADER_VISIBILITY_GEOMETRY: ss << "G"; break;
|
||||
case D3D12_SHADER_VISIBILITY_PIXEL: ss << "P"; break;
|
||||
case D3D12_SHADER_VISIBILITY_AMPLIFICATION: ss << "A"; break;
|
||||
case D3D12_SHADER_VISIBILITY_MESH: ss << "M"; break;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -721,6 +729,10 @@ void ShaderD3D12::UpdateDebugInfo(
|
|||
ss << "[ASO]";
|
||||
if (rootSignatureFlags & D3D12_ROOT_SIGNATURE_FLAG_LOCAL_ROOT_SIGNATURE)
|
||||
ss << "[LRS]";
|
||||
if (rootSignatureFlags & D3D12_ROOT_SIGNATURE_FLAG_DENY_AMPLIFICATION_SHADER_ROOT_ACCESS)
|
||||
ss << "[DASRA]";
|
||||
if (rootSignatureFlags & D3D12_ROOT_SIGNATURE_FLAG_DENY_MESH_SHADER_ROOT_ACCESS)
|
||||
ss << "[DMSRA]";
|
||||
|
||||
_debugInfo = ss.str();
|
||||
}
|
||||
|
|
|
@ -352,6 +352,11 @@ void CommandBufferVulkan::Dispatch(int groupCountX, int groupCountY, int groupCo
|
|||
vkCmdDispatch(GetVkCommandBuffer(), groupCountX, groupCountY, groupCountZ);
|
||||
}
|
||||
|
||||
void CommandBufferVulkan::TraceRays(int width, int height, int depth)
|
||||
{
|
||||
//vkCmdTraceRaysKHR(GetVkCommandBuffer(), nullptr, nullptr, nullptr, nullptr, width, height, depth);
|
||||
}
|
||||
|
||||
VkCommandBuffer CommandBufferVulkan::GetVkCommandBuffer() const
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
|
|
|
@ -42,8 +42,8 @@ namespace verus
|
|||
|
||||
virtual void Draw(int vertexCount, int instanceCount, int firstVertex, int firstInstance) override;
|
||||
virtual void DrawIndexed(int indexCount, int instanceCount, int firstIndex, int vertexOffset, int firstInstance) override;
|
||||
|
||||
virtual void Dispatch(int groupCountX, int groupCountY, int groupCountZ) override;
|
||||
virtual void TraceRays(int width, int height, int depth) override;
|
||||
|
||||
//
|
||||
// Vulkan
|
||||
|
|
|
@ -143,6 +143,18 @@ VkShaderStageFlags CGI::ToNativeStageFlags(ShaderStageFlags stageFlags)
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,11 +26,7 @@ void PipelineVulkan::Init(RcPipelineDesc desc)
|
|||
return;
|
||||
}
|
||||
|
||||
_vertexInputBindingsFilter = desc._vertexInputBindingsFilter;
|
||||
|
||||
RcGeometryVulkan geo = static_cast<RcGeometryVulkan>(*desc._geometry);
|
||||
RcShaderVulkan shader = static_cast<RcShaderVulkan>(*desc._shader);
|
||||
|
||||
// Attachment count according to blend equations:
|
||||
int attachmentCount = 0;
|
||||
for (const auto& x : desc._colorAttachBlendEqs)
|
||||
{
|
||||
|
@ -39,6 +35,10 @@ void PipelineVulkan::Init(RcPipelineDesc desc)
|
|||
attachmentCount++;
|
||||
}
|
||||
|
||||
RcGeometryVulkan geo = static_cast<RcGeometryVulkan>(*desc._geometry);
|
||||
RcShaderVulkan shader = static_cast<RcShaderVulkan>(*desc._shader);
|
||||
|
||||
_vertexInputBindingsFilter = desc._vertexInputBindingsFilter;
|
||||
const bool tess = desc._topology >= PrimitiveTopology::patchList3 && desc._topology <= PrimitiveTopology::patchList4;
|
||||
|
||||
ShaderVulkan::RcCompiled compiled = shader.GetCompiled(desc._shaderBranch);
|
||||
|
@ -97,7 +97,6 @@ void PipelineVulkan::Init(RcPipelineDesc desc)
|
|||
rasterizationState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
||||
rasterizationState.pNext = &rasterizationLineState;
|
||||
rasterizationState.depthClampEnable = desc._rasterizationState._depthClampEnable;
|
||||
rasterizationState.rasterizerDiscardEnable = desc._rasterizationState._rasterizerDiscardEnable;
|
||||
rasterizationState.polygonMode = ToNativePolygonMode(desc._rasterizationState._polygonMode);
|
||||
rasterizationState.cullMode = ToNativeCullMode(desc._rasterizationState._cullMode);
|
||||
rasterizationState.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
|
||||
|
@ -119,74 +118,7 @@ void PipelineVulkan::Init(RcPipelineDesc desc)
|
|||
depthStencilState.stencilTestEnable = desc._stencilTestEnable;
|
||||
|
||||
VkPipelineColorBlendAttachmentState vkpcbas[VERUS_MAX_RT] = {};
|
||||
VERUS_FOR(i, attachmentCount)
|
||||
{
|
||||
CSZ p = _C(desc._colorAttachWriteMasks[i]);
|
||||
while (*p)
|
||||
{
|
||||
switch (*p)
|
||||
{
|
||||
case 'r': vkpcbas[i].colorWriteMask |= VK_COLOR_COMPONENT_R_BIT; break;
|
||||
case 'g': vkpcbas[i].colorWriteMask |= VK_COLOR_COMPONENT_G_BIT; break;
|
||||
case 'b': vkpcbas[i].colorWriteMask |= VK_COLOR_COMPONENT_B_BIT; break;
|
||||
case 'a': vkpcbas[i].colorWriteMask |= VK_COLOR_COMPONENT_A_BIT; break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
if (desc._colorAttachBlendEqs[i] != "off")
|
||||
{
|
||||
vkpcbas[i].blendEnable = VK_TRUE;
|
||||
|
||||
static const VkBlendFactor bfs[] =
|
||||
{
|
||||
VK_BLEND_FACTOR_ZERO,
|
||||
VK_BLEND_FACTOR_ONE,
|
||||
VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA,
|
||||
VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR,
|
||||
VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR,
|
||||
VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
|
||||
VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR,
|
||||
VK_BLEND_FACTOR_DST_ALPHA,
|
||||
VK_BLEND_FACTOR_DST_COLOR,
|
||||
VK_BLEND_FACTOR_CONSTANT_COLOR,
|
||||
VK_BLEND_FACTOR_SRC_ALPHA,
|
||||
VK_BLEND_FACTOR_SRC_ALPHA_SATURATE,
|
||||
VK_BLEND_FACTOR_SRC_COLOR
|
||||
};
|
||||
static const VkBlendOp ops[] =
|
||||
{
|
||||
VK_BLEND_OP_ADD,
|
||||
VK_BLEND_OP_SUBTRACT,
|
||||
VK_BLEND_OP_REVERSE_SUBTRACT,
|
||||
VK_BLEND_OP_MIN,
|
||||
VK_BLEND_OP_MAX
|
||||
};
|
||||
|
||||
int colorBlendOp = -1;
|
||||
int alphaBlendOp = -1;
|
||||
int srcColorBlendFactor = -1;
|
||||
int dstColorBlendFactor = -1;
|
||||
int srcAlphaBlendFactor = -1;
|
||||
int dstAlphaBlendFactor = -1;
|
||||
|
||||
BaseRenderer::SetAlphaBlendHelper(
|
||||
_C(desc._colorAttachBlendEqs[i]),
|
||||
colorBlendOp,
|
||||
alphaBlendOp,
|
||||
srcColorBlendFactor,
|
||||
dstColorBlendFactor,
|
||||
srcAlphaBlendFactor,
|
||||
dstAlphaBlendFactor);
|
||||
|
||||
vkpcbas[i].srcColorBlendFactor = bfs[srcColorBlendFactor];
|
||||
vkpcbas[i].dstColorBlendFactor = bfs[dstColorBlendFactor];
|
||||
vkpcbas[i].colorBlendOp = ops[colorBlendOp];
|
||||
vkpcbas[i].srcAlphaBlendFactor = bfs[srcAlphaBlendFactor];
|
||||
vkpcbas[i].dstAlphaBlendFactor = bfs[dstAlphaBlendFactor];
|
||||
vkpcbas[i].alphaBlendOp = ops[alphaBlendOp];
|
||||
}
|
||||
}
|
||||
FillColorBlendAttachmentStates(desc, attachmentCount, vkpcbas);
|
||||
VkPipelineColorBlendStateCreateInfo colorBlendState = {};
|
||||
colorBlendState.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
|
||||
colorBlendState.logicOpEnable = VK_FALSE;
|
||||
|
@ -255,3 +187,75 @@ void PipelineVulkan::InitCompute(RcPipelineDesc desc)
|
|||
if (VK_SUCCESS != (res = vkCreateComputePipelines(pRendererVulkan->GetVkDevice(), VK_NULL_HANDLE, 1, &vkcpci, pRendererVulkan->GetAllocator(), &_pipeline)))
|
||||
throw VERUS_RUNTIME_ERROR << "vkCreateComputePipelines(), res=" << res;
|
||||
}
|
||||
|
||||
void PipelineVulkan::FillColorBlendAttachmentStates(RcPipelineDesc desc, int attachmentCount, VkPipelineColorBlendAttachmentState vkpcbas[])
|
||||
{
|
||||
VERUS_FOR(i, attachmentCount)
|
||||
{
|
||||
CSZ p = _C(desc._colorAttachWriteMasks[i]);
|
||||
while (*p)
|
||||
{
|
||||
switch (*p)
|
||||
{
|
||||
case 'r': vkpcbas[i].colorWriteMask |= VK_COLOR_COMPONENT_R_BIT; break;
|
||||
case 'g': vkpcbas[i].colorWriteMask |= VK_COLOR_COMPONENT_G_BIT; break;
|
||||
case 'b': vkpcbas[i].colorWriteMask |= VK_COLOR_COMPONENT_B_BIT; break;
|
||||
case 'a': vkpcbas[i].colorWriteMask |= VK_COLOR_COMPONENT_A_BIT; break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
if (desc._colorAttachBlendEqs[i] != "off")
|
||||
{
|
||||
vkpcbas[i].blendEnable = VK_TRUE;
|
||||
|
||||
static const VkBlendFactor bfs[] =
|
||||
{
|
||||
VK_BLEND_FACTOR_ZERO,
|
||||
VK_BLEND_FACTOR_ONE,
|
||||
VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA,
|
||||
VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR,
|
||||
VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR,
|
||||
VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
|
||||
VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR,
|
||||
VK_BLEND_FACTOR_DST_ALPHA,
|
||||
VK_BLEND_FACTOR_DST_COLOR,
|
||||
VK_BLEND_FACTOR_CONSTANT_COLOR,
|
||||
VK_BLEND_FACTOR_SRC_ALPHA,
|
||||
VK_BLEND_FACTOR_SRC_ALPHA_SATURATE,
|
||||
VK_BLEND_FACTOR_SRC_COLOR
|
||||
};
|
||||
static const VkBlendOp ops[] =
|
||||
{
|
||||
VK_BLEND_OP_ADD,
|
||||
VK_BLEND_OP_SUBTRACT,
|
||||
VK_BLEND_OP_REVERSE_SUBTRACT,
|
||||
VK_BLEND_OP_MIN,
|
||||
VK_BLEND_OP_MAX
|
||||
};
|
||||
|
||||
int colorBlendOp = -1;
|
||||
int alphaBlendOp = -1;
|
||||
int srcColorBlendFactor = -1;
|
||||
int dstColorBlendFactor = -1;
|
||||
int srcAlphaBlendFactor = -1;
|
||||
int dstAlphaBlendFactor = -1;
|
||||
|
||||
BaseRenderer::SetAlphaBlendHelper(
|
||||
_C(desc._colorAttachBlendEqs[i]),
|
||||
colorBlendOp,
|
||||
alphaBlendOp,
|
||||
srcColorBlendFactor,
|
||||
dstColorBlendFactor,
|
||||
srcAlphaBlendFactor,
|
||||
dstAlphaBlendFactor);
|
||||
|
||||
vkpcbas[i].srcColorBlendFactor = bfs[srcColorBlendFactor];
|
||||
vkpcbas[i].dstColorBlendFactor = bfs[dstColorBlendFactor];
|
||||
vkpcbas[i].colorBlendOp = ops[colorBlendOp];
|
||||
vkpcbas[i].srcAlphaBlendFactor = bfs[srcAlphaBlendFactor];
|
||||
vkpcbas[i].dstAlphaBlendFactor = bfs[dstAlphaBlendFactor];
|
||||
vkpcbas[i].alphaBlendOp = ops[alphaBlendOp];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace verus
|
|||
VERUS_P(void InitCompute(RcPipelineDesc desc));
|
||||
bool IsCompute() const { return _compute; }
|
||||
VkPipeline GetVkPipeline() const { return _pipeline; }
|
||||
void FillColorBlendAttachmentStates(RcPipelineDesc desc, int attachmentCount, VkPipelineColorBlendAttachmentState vkpcbas[]);
|
||||
};
|
||||
VERUS_TYPEDEFS(PipelineVulkan);
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
<ImportGroup Label="PropertySheets" />
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<IncludePath>C:\Compressonator_3.2.4691\include;C:\Home\Projects\Verus\verus\Verus\src;C:\Home\Middleware\AMD Tootle 2.3\include;C:\Home\Middleware\bullet3-2.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.20.1-bin\include;C:\Home\Middleware\SDL2-2.0.14\include;C:\VulkanSDK\1.2.176.1\Include;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>C:\Compressonator_3.2.4691\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.20.1-bin\libs\Win64;C:\Home\Middleware\SDL2-2.0.14\lib\x64;C:\VulkanSDK\1.2.176.1\Lib;$(LibraryPath)</LibraryPath>
|
||||
<IncludePath>C:\Compressonator_3.2.4691\include;C:\Home\Projects\Verus\verus\Verus\src;C:\Home\Middleware\AMD Tootle 2.3\include;C:\Home\Middleware\bullet3-2.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.20.1-bin\include;C:\Home\Middleware\SDL2-2.0.14\include;C:\VulkanSDK\1.2.182.0\Include;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>C:\Compressonator_3.2.4691\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.20.1-bin\libs\Win64;C:\Home\Middleware\SDL2-2.0.14\lib\x64;C:\VulkanSDK\1.2.182.0\Lib;$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup />
|
||||
<ItemGroup />
|
||||
|
|
|
@ -29,6 +29,11 @@ bool QualitySettings::operator==(RcQualitySettings that) const
|
|||
_sceneWaterQuality == that._sceneWaterQuality;
|
||||
}
|
||||
|
||||
bool QualitySettings::operator!=(RcQualitySettings that) const
|
||||
{
|
||||
return !(*this == that);
|
||||
}
|
||||
|
||||
void QualitySettings::SetQuality(OverallQuality q)
|
||||
{
|
||||
if (OverallQuality::custom == q)
|
||||
|
|
|
@ -62,6 +62,7 @@ namespace verus
|
|||
WaterQuality _sceneWaterQuality = WaterQuality::solidColor;
|
||||
|
||||
bool operator==(const QualitySettings& that) const;
|
||||
bool operator!=(const QualitySettings& that) const;
|
||||
|
||||
void SetQuality(OverallQuality q);
|
||||
OverallQuality DetectQuality() const;
|
||||
|
|
|
@ -43,8 +43,10 @@ namespace verus
|
|||
|
||||
virtual void Draw(int vertexCount, int instanceCount = 1, int firstVertex = 0, int firstInstance = 0) = 0;
|
||||
virtual void DrawIndexed(int indexCount, int instanceCount = 1, int firstIndex = 0, int vertexOffset = 0, int firstInstance = 0) = 0;
|
||||
|
||||
virtual void Dispatch(int groupCountX, int groupCountY, int groupCountZ = 1) = 0;
|
||||
virtual void DispatchIndirect() {} // WIP.
|
||||
virtual void DispatchMesh(int groupCountX, int groupCountY, int groupCountZ) {} // WIP.
|
||||
virtual void TraceRays(int width, int height, int depth) {} // WIP.
|
||||
|
||||
RcVector4 GetViewportSize() const { return _viewportSize; }
|
||||
};
|
||||
|
|
|
@ -52,7 +52,6 @@ namespace verus
|
|||
float _depthBiasSlopeFactor = 0;
|
||||
bool _depthClampEnable = false;
|
||||
bool _depthBiasEnable = false;
|
||||
bool _rasterizerDiscardEnable = false;
|
||||
};
|
||||
|
||||
enum class CompareOp : int
|
||||
|
@ -69,12 +68,27 @@ namespace verus
|
|||
|
||||
enum class ShaderStageFlags : UINT32
|
||||
{
|
||||
vs = (1 << 0),
|
||||
hs = (1 << 1),
|
||||
ds = (1 << 2),
|
||||
gs = (1 << 3),
|
||||
fs = (1 << 4),
|
||||
cs = (1 << 5),
|
||||
// Classic pipeline:
|
||||
vs = (1 << 0), // Vertex shader.
|
||||
hs = (1 << 1), // Hull shader. Also known as tessellation control shader.
|
||||
ds = (1 << 2), // Domain shader. Also known as tessellation evaluation shader.
|
||||
gs = (1 << 3), // Geometry shader.
|
||||
fs = (1 << 4), // Fragment shader. Also known as pixel shader.
|
||||
|
||||
cs = (1 << 5), // Compute shader. Also known as kernel shader.
|
||||
|
||||
// Raytracing:
|
||||
rtrg = (1 << 6), // Ray generation shader.
|
||||
rtah = (1 << 7), // Any hit shader.
|
||||
rtch = (1 << 8), // Closest hit shader.
|
||||
rtm = (1 << 9), // Miss shader.
|
||||
rti = (1 << 10), // Intersection shader.
|
||||
rtc = (1 << 11), // Callable shader.
|
||||
|
||||
// Mesh shading pipeline:
|
||||
ts = (1 << 12), // Task shader. Also known as amplification shader.
|
||||
ms = (1 << 13), // Mesh shader.
|
||||
|
||||
vs_fs = vs | fs,
|
||||
vs_hs_ds = vs | hs | ds,
|
||||
vs_hs_ds_fs = vs | hs | ds | fs
|
||||
|
|
|
@ -47,8 +47,9 @@ void ConvertGLTF::ParseData(CSZ pathname)
|
|||
|
||||
LoadFromFile(pathname);
|
||||
|
||||
const String baseDir = IO::FileSystem::ReplaceFilename(pathname, "");
|
||||
std::string err, warn;
|
||||
if (!_context.LoadASCIIFromString(&_model, &err, &warn, _vData.data(), Utils::Cast32(_vData.size()), ""))
|
||||
if (!_context.LoadASCIIFromString(&_model, &err, &warn, _vData.data(), Utils::Cast32(_vData.size()), _C(baseDir)))
|
||||
throw VERUS_RECOVERABLE << "LoadASCIIFromString() failed, err=" << err << ", warn=" << warn;
|
||||
|
||||
_vNodeExtraData.resize(_model.nodes.size());
|
||||
|
@ -265,7 +266,7 @@ void ConvertGLTF::ProcessMesh(const tinygltf::Mesh& mesh, int nodeIndex, int ski
|
|||
OnProgressText(_C(ss.str()));
|
||||
}
|
||||
|
||||
const UINT16* p = reinterpret_cast<const UINT16*>(&buffer.data[bufferView.byteOffset]);
|
||||
const BYTE* p = &buffer.data[accessor.byteOffset + bufferView.byteOffset];
|
||||
|
||||
const int faceCount = static_cast<int>(accessor.count / 3);
|
||||
_pCurrentMesh->SetFaceCount(faceCount);
|
||||
|
@ -274,7 +275,12 @@ void ConvertGLTF::ProcessMesh(const tinygltf::Mesh& mesh, int nodeIndex, int ski
|
|||
{
|
||||
Mesh::Face face;
|
||||
VERUS_FOR(i, 3)
|
||||
face._indices[i] = p[faceIndex * 3 + i];
|
||||
{
|
||||
const UINT16* pSrc = reinterpret_cast<const UINT16*>(p + byteStride * (faceIndex * 3 + i));
|
||||
face._indices[i] = *pSrc;
|
||||
}
|
||||
if (_desc._flipFaces)
|
||||
std::swap(face._indices[1], face._indices[2]);
|
||||
_pCurrentMesh->GetSetFaceAt(faceIndex) = face;
|
||||
}
|
||||
_pCurrentMesh->AddFoundFlag(Mesh::Found::faces);
|
||||
|
@ -301,13 +307,14 @@ void ConvertGLTF::ProcessMesh(const tinygltf::Mesh& mesh, int nodeIndex, int ski
|
|||
OnProgressText(_C(ss.str()));
|
||||
}
|
||||
|
||||
const float* p = reinterpret_cast<const float*>(&buffer.data[bufferView.byteOffset]);
|
||||
const BYTE* p = &buffer.data[accessor.byteOffset + bufferView.byteOffset];
|
||||
|
||||
const int vertCount = Utils::Cast32(accessor.count);
|
||||
TryResizeVertsArray(vertCount);
|
||||
VERUS_FOR(vertIndex, vertCount)
|
||||
{
|
||||
glm::vec3 pos = glm::make_vec3(p + vertIndex * 3);
|
||||
const float* pSrc = reinterpret_cast<const float*>(p + byteStride * vertIndex);
|
||||
glm::vec3 pos = glm::make_vec3(pSrc);
|
||||
pos = glm::vec3(_pCurrentMesh->GetGlobalMatrix() * glm::vec4(pos, 1));
|
||||
_pCurrentMesh->GetSetVertexAt(vertIndex)._pos = pos;
|
||||
}
|
||||
|
@ -327,15 +334,18 @@ void ConvertGLTF::ProcessMesh(const tinygltf::Mesh& mesh, int nodeIndex, int ski
|
|||
OnProgressText(_C(ss.str()));
|
||||
}
|
||||
|
||||
const float* p = reinterpret_cast<const float*>(&buffer.data[bufferView.byteOffset]);
|
||||
const BYTE* p = &buffer.data[accessor.byteOffset + bufferView.byteOffset];
|
||||
|
||||
const int vertCount = Utils::Cast32(accessor.count);
|
||||
TryResizeVertsArray(vertCount);
|
||||
VERUS_FOR(vertIndex, vertCount)
|
||||
{
|
||||
glm::vec3 nrm = glm::make_vec3(p + vertIndex * 3);
|
||||
const float* pSrc = reinterpret_cast<const float*>(p + byteStride * vertIndex);
|
||||
glm::vec3 nrm = glm::make_vec3(pSrc);
|
||||
nrm = glm::vec3(_pCurrentMesh->GetGlobalMatrix() * glm::vec4(nrm, 0));
|
||||
nrm = glm::normalize(nrm);
|
||||
if (_desc._flipNormals)
|
||||
nrm = -nrm;
|
||||
_pCurrentMesh->GetSetVertexAt(vertIndex)._nrm = nrm;
|
||||
}
|
||||
_pCurrentMesh->AddFoundFlag(Mesh::Found::normals);
|
||||
|
@ -355,13 +365,14 @@ void ConvertGLTF::ProcessMesh(const tinygltf::Mesh& mesh, int nodeIndex, int ski
|
|||
OnProgressText(_C(ss.str()));
|
||||
}
|
||||
|
||||
const float* p = reinterpret_cast<const float*>(&buffer.data[bufferView.byteOffset]);
|
||||
const BYTE* p = &buffer.data[accessor.byteOffset + bufferView.byteOffset];
|
||||
|
||||
const int vertCount = Utils::Cast32(accessor.count);
|
||||
TryResizeVertsArray(vertCount);
|
||||
VERUS_FOR(vertIndex, vertCount)
|
||||
{
|
||||
const glm::vec2 tc = glm::make_vec2(p + vertIndex * 2);
|
||||
const float* pSrc = reinterpret_cast<const float*>(p + byteStride * vertIndex);
|
||||
const glm::vec2 tc = glm::make_vec2(pSrc);
|
||||
_pCurrentMesh->GetSetVertexAt(vertIndex)._tc0 = tc;
|
||||
}
|
||||
_pCurrentMesh->AddFoundFlag(Mesh::Found::posAndTexCoord0);
|
||||
|
@ -381,7 +392,7 @@ void ConvertGLTF::ProcessMesh(const tinygltf::Mesh& mesh, int nodeIndex, int ski
|
|||
OnProgressText(_C(ss.str()));
|
||||
}
|
||||
|
||||
const BYTE* p = reinterpret_cast<const BYTE*>(&buffer.data[bufferView.byteOffset]);
|
||||
const BYTE* p = &buffer.data[accessor.byteOffset + bufferView.byteOffset];
|
||||
|
||||
const int vertCount = Utils::Cast32(accessor.count);
|
||||
TryResizeVertsArray(vertCount);
|
||||
|
@ -389,7 +400,7 @@ void ConvertGLTF::ProcessMesh(const tinygltf::Mesh& mesh, int nodeIndex, int ski
|
|||
VERUS_FOR(vertIndex, vertCount)
|
||||
{
|
||||
VERUS_FOR(i, 4)
|
||||
vBlendIndices[vertIndex][i] = p[vertIndex * 4 + i] + _pCurrentMesh->GetBoneCount();
|
||||
vBlendIndices[vertIndex][i] = p[byteStride * vertIndex + i] + _pCurrentMesh->GetBoneCount();
|
||||
}
|
||||
}
|
||||
if (attr.first == "WEIGHTS_0")
|
||||
|
@ -407,13 +418,16 @@ void ConvertGLTF::ProcessMesh(const tinygltf::Mesh& mesh, int nodeIndex, int ski
|
|||
OnProgressText(_C(ss.str()));
|
||||
}
|
||||
|
||||
const float* p = reinterpret_cast<const float*>(&buffer.data[bufferView.byteOffset]);
|
||||
const BYTE* p = &buffer.data[accessor.byteOffset + bufferView.byteOffset];
|
||||
|
||||
const int vertCount = Utils::Cast32(accessor.count);
|
||||
TryResizeVertsArray(vertCount);
|
||||
vBlendWeights.resize(vertCount);
|
||||
VERUS_FOR(vertIndex, vertCount)
|
||||
vBlendWeights[vertIndex] = glm::make_vec4(p + vertIndex * 4);
|
||||
{
|
||||
const float* pSrc = reinterpret_cast<const float*>(p + byteStride * vertIndex);
|
||||
vBlendWeights[vertIndex] = glm::make_vec4(pSrc);
|
||||
}
|
||||
}
|
||||
|
||||
if (!vBlendIndices.empty() && !vBlendWeights.empty())
|
||||
|
@ -566,6 +580,16 @@ void ConvertGLTF::ProcessAnimation(const tinygltf::Animation& an)
|
|||
progress++;
|
||||
}
|
||||
|
||||
// Remove empty:
|
||||
_vAnimSets[animSetIndex]._vAnimations.erase(std::remove_if(
|
||||
_vAnimSets[animSetIndex]._vAnimations.begin(),
|
||||
_vAnimSets[animSetIndex]._vAnimations.end(),
|
||||
[](const Animation& anim)
|
||||
{
|
||||
return anim._vAnimKeys.empty();
|
||||
}),
|
||||
_vAnimSets[animSetIndex]._vAnimations.end());
|
||||
|
||||
// Convert data to bone space:
|
||||
progress = 0;
|
||||
for (Animation& animWithKeys : _vAnimSets[animSetIndex]._vAnimations)
|
||||
|
|
|
@ -14,6 +14,8 @@ namespace verus
|
|||
float _scaleFactor = 1;
|
||||
float _angle = 0;
|
||||
float _areaBasedNormals = 0;
|
||||
bool _flipNormals = false;
|
||||
bool _flipFaces = false;
|
||||
bool _useRigidBones = false;
|
||||
bool _convertAsScene = false;
|
||||
};
|
||||
|
|
|
@ -323,7 +323,7 @@ void BaseGame::Run(bool relativeMouseMode)
|
|||
case CGI::Gapi::vulkan: gapi = "Vulkan"; break;
|
||||
case CGI::Gapi::direct3D12: gapi = "Direct3D 12"; break;
|
||||
}
|
||||
sprintf_s(title, "[%s] - %.1f FPS", gapi, renderer.GetFps());
|
||||
sprintf_s(title, "GAPI: %s, FPS: %.1f", gapi, renderer.GetFps());
|
||||
SDL_SetWindowTitle(renderer.GetMainWindow()->GetSDL(), title);
|
||||
}
|
||||
} while (!quit); // The Game Loop.
|
||||
|
|
|
@ -69,6 +69,7 @@ namespace verus
|
|||
|
||||
static float GetMouseScale();
|
||||
|
||||
bool IsRestartAppRequested() const { return _restartApp; }
|
||||
void RestartApp();
|
||||
void RequestAppRestart();
|
||||
};
|
||||
|
|
|
@ -38,7 +38,7 @@ void Utils::FreeEx(PBaseAllocator pAlloc)
|
|||
void Utils::InitPaths()
|
||||
{
|
||||
if (_companyFolderName.empty())
|
||||
_companyFolderName = "VerusEngine";
|
||||
_companyFolderName = "Verus Engine";
|
||||
|
||||
wchar_t pathname[MAX_PATH] = {};
|
||||
if (_modulePath.empty())
|
||||
|
|
|
@ -622,8 +622,8 @@ void Math::Test()
|
|||
Scene::Camera camera;
|
||||
camera.MoveEyeTo(Point3(0, 0, 3));
|
||||
camera.MoveAtTo(Point3(0, 0, 4));
|
||||
camera.SetAspectRatio(1);
|
||||
camera.SetYFov(VERUS_PI * 0.25f);
|
||||
camera.SetAspectRatio(1);
|
||||
camera.SetZNear(0.5f);
|
||||
camera.SetZFar(100);
|
||||
camera.Update();
|
||||
|
|
|
@ -27,8 +27,8 @@ namespace verus
|
|||
VERUS_PD(Point3 _atPos = Point3(0, 0, -1));
|
||||
VERUS_PD(Vector3 _upDir = Vector3(0, 1, 0));
|
||||
VERUS_PD(Vector3 _frontDir = Vector3(0, 0, -1));
|
||||
float _aspectRatio = 1;
|
||||
float _yFov = VERUS_PI / 4; // Zero FOV means ortho.
|
||||
float _aspectRatio = 1;
|
||||
float _zNear = 0.1f; // 10 cm.
|
||||
float _zFar = 10000; // 10 km.
|
||||
float _xMag = 80;
|
||||
|
@ -70,11 +70,11 @@ namespace verus
|
|||
RcMatrix4 GetMatrixVP() const { return _matVP; }
|
||||
|
||||
// Perspective:
|
||||
float GetAspectRatio() const { return _aspectRatio; }
|
||||
void SetAspectRatio(float x) { _update |= Update::p; _aspectRatio = x; }
|
||||
float GetYFov() const { return _yFov; }
|
||||
void SetYFov(float x) { _update |= Update::p; _yFov = x; }
|
||||
void SetXFov(float x);
|
||||
void SetXFov(float x); // Set correct aspect ratio before calling this method.
|
||||
float GetAspectRatio() const { return _aspectRatio; }
|
||||
void SetAspectRatio(float x) { _update |= Update::p; _aspectRatio = x; }
|
||||
float GetZNear() const { return _zNear; }
|
||||
void SetZNear(float x) { _update |= Update::p; _zNear = x; }
|
||||
float GetZFar() const { return _zFar; }
|
||||
|
|
|
@ -90,8 +90,8 @@ void CubeMap::BeginEnvMap(CGI::CubeMapFace cubeMapFace, RcPoint3 center)
|
|||
_camera.MoveEyeTo(center);
|
||||
_camera.MoveAtTo(center - facePos); // Looking at center.
|
||||
_camera.SetUpDirection(up);
|
||||
_camera.SetAspectRatio(1);
|
||||
_camera.SetYFov(VERUS_PI * -0.5f); // Using left-handed coordinate system!
|
||||
_camera.SetAspectRatio(1);
|
||||
_camera.SetZNear(1);
|
||||
_camera.SetZFar(200);
|
||||
_camera.Update();
|
||||
|
|
|
@ -58,7 +58,7 @@ void Forest::DoneStatic()
|
|||
s_shader.Done();
|
||||
}
|
||||
|
||||
void Forest::Init(PTerrain pTerrain)
|
||||
void Forest::Init(PTerrain pTerrain, CSZ url)
|
||||
{
|
||||
VERUS_INIT();
|
||||
|
||||
|
@ -86,6 +86,52 @@ void Forest::Init(PTerrain pTerrain)
|
|||
_vDrawPlants.resize(_capacity);
|
||||
|
||||
_vCollisionPool.Resize(1000);
|
||||
|
||||
if (url)
|
||||
{
|
||||
Vector<BYTE> vData;
|
||||
IO::FileSystem::LoadResource(url, vData, IO::FileSystem::LoadDesc(true));
|
||||
|
||||
pugi::xml_document doc;
|
||||
const pugi::xml_parse_result result = doc.load_buffer_inplace(vData.data(), vData.size());
|
||||
if (!result)
|
||||
throw VERUS_RECOVERABLE << "load_buffer_inplace(), " << result.description();
|
||||
pugi::xml_node root = doc.first_child();
|
||||
|
||||
for (auto layerNode : root.children("layer"))
|
||||
{
|
||||
const int id = layerNode.attribute("id").as_int();
|
||||
LayerDesc layerDesc;
|
||||
for (auto typeNode : layerNode.children("type"))
|
||||
{
|
||||
const int typeID = typeNode.attribute("id").as_int();
|
||||
SCATTER_TYPE scatterType = SCATTER_TYPE_COUNT;
|
||||
switch (typeID)
|
||||
{
|
||||
case 100: scatterType = SCATTER_TYPE_100; break;
|
||||
case 50: scatterType = SCATTER_TYPE_50; break;
|
||||
case 25: scatterType = SCATTER_TYPE_25; break;
|
||||
case 20: scatterType = SCATTER_TYPE_20; break;
|
||||
case 15: scatterType = SCATTER_TYPE_15; break;
|
||||
case 10: scatterType = SCATTER_TYPE_10; break;
|
||||
case 5: scatterType = SCATTER_TYPE_5; break;
|
||||
case 3: scatterType = SCATTER_TYPE_3; break;
|
||||
}
|
||||
if (SCATTER_TYPE_COUNT == scatterType)
|
||||
throw VERUS_RECOVERABLE << "Invalid scatterType";
|
||||
|
||||
layerDesc._forType[scatterType].Set(
|
||||
typeNode.text().as_string(),
|
||||
typeNode.attribute("alignToNormal").as_float(1),
|
||||
typeNode.attribute("minScale").as_float(0.5f),
|
||||
typeNode.attribute("maxScale").as_float(1.5f),
|
||||
typeNode.attribute("windBending").as_float(1),
|
||||
typeNode.attribute("allowedNormal").as_int(116));
|
||||
}
|
||||
|
||||
SetLayer(id, layerDesc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Forest::Done()
|
||||
|
@ -982,8 +1028,8 @@ void Forest::BakeSprite(RPlant plant, CSZ url)
|
|||
Camera cam;
|
||||
cam.MoveEyeTo(Vector3(0, size * 0.5f / _margin, 0) + offset);
|
||||
cam.MoveAtTo(Vector3(0, size * 0.5f / _margin, 0));
|
||||
cam.SetAspectRatio(1);
|
||||
cam.SetYFov(0);
|
||||
cam.SetAspectRatio(1);
|
||||
cam.SetZNear(0);
|
||||
cam.SetZFar(size * 2);
|
||||
cam.SetXMag(size * _margin);
|
||||
|
@ -1041,7 +1087,7 @@ void Forest::BakeSprite(RPlant plant, CSZ url)
|
|||
|
||||
String pathname = _C(plant._mesh.GetUrl());
|
||||
char filename[20];
|
||||
sprintf_s(filename, "GB%d%s.psd", i, ext[i]);
|
||||
sprintf_s(filename, "GB%d%s.tga", i, ext[i]);
|
||||
Str::ReplaceFilename(pathname, filename);
|
||||
pathname = Str::ToPakFriendlyUrl(_C(pathname));
|
||||
pathname = String(url) + '/' + pathname;
|
||||
|
|
|
@ -214,7 +214,7 @@ namespace verus
|
|||
static void InitStatic();
|
||||
static void DoneStatic();
|
||||
|
||||
void Init(PTerrain pTerrain);
|
||||
void Init(PTerrain pTerrain, CSZ url = nullptr);
|
||||
void Done();
|
||||
|
||||
void ResetInstanceCount();
|
||||
|
|
|
@ -442,6 +442,24 @@ void Grass::ResetAllTextures()
|
|||
_bushMask = 0;
|
||||
}
|
||||
|
||||
void Grass::LoadLayersFromFile(CSZ url)
|
||||
{
|
||||
if (!url)
|
||||
url = "[Misc]:TerrainLayers.xml";
|
||||
Vector<BYTE> vData;
|
||||
IO::FileSystem::LoadResource(url, vData);
|
||||
pugi::xml_document doc;
|
||||
const pugi::xml_parse_result result = doc.load_buffer_inplace(vData.data(), vData.size());
|
||||
if (!result)
|
||||
throw VERUS_RECOVERABLE << "load_buffer_inplace(), " << result.description();
|
||||
pugi::xml_node root = doc.first_child();
|
||||
for (auto node : root.children("grass"))
|
||||
{
|
||||
const int id = node.attribute("id").as_int();
|
||||
SetTexture(id, node.attribute("url").value(), node.attribute("urlEx").value());
|
||||
}
|
||||
}
|
||||
|
||||
void Grass::SetTexture(int layer, CSZ url, CSZ url2)
|
||||
{
|
||||
if (_vTextureSubresData.empty()) // Using DDS?
|
||||
|
|
|
@ -104,6 +104,7 @@ namespace verus
|
|||
VERUS_P(void CreateBuffers());
|
||||
|
||||
void ResetAllTextures();
|
||||
void LoadLayersFromFile(CSZ url = nullptr);
|
||||
void SetTexture(int layer, CSZ url, CSZ url2 = nullptr);
|
||||
VERUS_P(void OnTextureLoaded(int layer));
|
||||
void SaveTexture(CSZ url);
|
||||
|
|
|
@ -423,11 +423,17 @@ void Terrain::Init(RcDesc desc)
|
|||
VERUS_QREF_CONST_SETTINGS;
|
||||
VERUS_QREF_RENDERER;
|
||||
|
||||
if (!Math::IsPowerOfTwo(desc._mapSide))
|
||||
throw VERUS_RECOVERABLE << "Init(), mapSide must be power of two";
|
||||
|
||||
_mapSide = desc._mapSide;
|
||||
_mapShift = Math::HighestBit(desc._mapSide);
|
||||
IO::Image image;
|
||||
if (desc._heightmapUrl)
|
||||
{
|
||||
image.Init(desc._heightmapUrl);
|
||||
_mapSide = image._width;
|
||||
}
|
||||
_mapShift = Math::HighestBit(_mapSide);
|
||||
|
||||
if (!Math::IsPowerOfTwo(_mapSide))
|
||||
throw VERUS_RECOVERABLE << "Init(), mapSide must be power of two";
|
||||
|
||||
const int patchSide = _mapSide >> 4;
|
||||
const int patchShift = _mapShift - 4;
|
||||
|
@ -449,7 +455,30 @@ void Terrain::Init(RcDesc desc)
|
|||
patch._layerForChannel[0] = desc._layer;
|
||||
}
|
||||
});
|
||||
if (desc._debugHills)
|
||||
|
||||
if (desc._heightmapUrl)
|
||||
{
|
||||
VERUS_P_FOR(i, _mapSide)
|
||||
{
|
||||
VERUS_FOR(j, _mapSide)
|
||||
{
|
||||
const BYTE pix = image._p[((i << _mapShift) + j) * image._bytesPerPixel];
|
||||
const float h = Convert::Uint8ToUnorm(pix) * desc._heightmapScale + desc._heightmapBias;
|
||||
const short hs = Math::Clamp(ConvertHeight(h), -SHRT_MAX, SHRT_MAX);
|
||||
const int ij[] = { i, j };
|
||||
SetHeightAt(ij, hs);
|
||||
}
|
||||
});
|
||||
|
||||
VERUS_FOR(lod, 5)
|
||||
{
|
||||
VERUS_P_FOR(i, Utils::Cast32(_vPatches.size()))
|
||||
{
|
||||
_vPatches[i].UpdateNormals(this, lod);
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (desc._debugHills)
|
||||
{
|
||||
if (desc._debugHills < 0)
|
||||
{
|
||||
|
|
|
@ -181,6 +181,9 @@ namespace verus
|
|||
|
||||
struct Desc
|
||||
{
|
||||
CSZ _heightmapUrl = nullptr;
|
||||
float _heightmapScale = 1;
|
||||
float _heightmapBias = 0;
|
||||
int _mapSide = 256;
|
||||
int _layer = 0;
|
||||
short _height = 0;
|
||||
|
|
Loading…
Reference in New Issue