@@ -89,6 +89,7 @@ void ViewportIconsRenderer::DrawIcons(RenderContext& renderContext, Actor* actor
|
||||
draw.Flags = StaticFlags::Transform;
|
||||
draw.DrawModes = DrawPass::Forward;
|
||||
draw.PerInstanceRandom = 0;
|
||||
draw.StencilValue = 0;
|
||||
draw.LODBias = 0;
|
||||
draw.ForcedLOD = -1;
|
||||
draw.SortOrder = 0;
|
||||
|
||||
@@ -323,6 +323,7 @@ void Foliage::DrawCluster(RenderContext& renderContext, FoliageCluster* cluster,
|
||||
draw.Bounds = sphere;
|
||||
draw.PerInstanceRandom = instance.Random;
|
||||
draw.DrawModes = type._drawModes;
|
||||
draw.SetStencilValue(_layer);
|
||||
type.Model->Draw(renderContext, draw);
|
||||
|
||||
//DebugDraw::DrawSphere(instance.Bounds, Color::YellowGreen);
|
||||
@@ -1182,6 +1183,7 @@ void Foliage::Draw(RenderContext& renderContext)
|
||||
draw.Bounds = instance.Bounds;
|
||||
draw.PerInstanceRandom = instance.Random;
|
||||
draw.DrawModes = type.DrawModes & view.Pass & view.GetShadowsDrawPassMask(type.ShadowsMode);
|
||||
draw.SetStencilValue(_layer);
|
||||
type.Model->Draw(renderContext, draw);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
|
||||
// Default depth buffer pixel format
|
||||
#ifndef GPU_DEPTH_BUFFER_PIXEL_FORMAT
|
||||
#define GPU_DEPTH_BUFFER_PIXEL_FORMAT PixelFormat::D32_Float
|
||||
#define GPU_DEPTH_BUFFER_PIXEL_FORMAT PixelFormat::D24_UNorm_S8_UInt
|
||||
#endif
|
||||
|
||||
// Enable/disable gpu resources naming
|
||||
|
||||
@@ -85,13 +85,10 @@ void DeferredMaterialShader::Bind(BindParameters& params)
|
||||
if (IsRunningRadiancePass)
|
||||
cullMode = CullMode::TwoSided;
|
||||
#endif
|
||||
if (cullMode != CullMode::TwoSided && drawCall.WorldDeterminantSign < 0)
|
||||
if (cullMode != CullMode::TwoSided && drawCall.WorldDeterminant)
|
||||
{
|
||||
// Invert culling when scale is negative
|
||||
if (cullMode == CullMode::Normal)
|
||||
cullMode = CullMode::Inverted;
|
||||
else
|
||||
cullMode = CullMode::Normal;
|
||||
cullMode = cullMode == CullMode::Normal ? CullMode::Inverted : CullMode::Normal;
|
||||
}
|
||||
ASSERT_LOW_LAYER(!(useSkinning && params.Instanced)); // No support for instancing skinned meshes
|
||||
const auto cache = params.Instanced ? &_cacheInstanced : &_cache;
|
||||
@@ -101,6 +98,7 @@ void DeferredMaterialShader::Bind(BindParameters& params)
|
||||
|
||||
// Bind pipeline
|
||||
context->SetState(state);
|
||||
context->SetStencilRef(drawCall.StencilValue);
|
||||
}
|
||||
|
||||
void DeferredMaterialShader::Unload()
|
||||
@@ -137,6 +135,10 @@ bool DeferredMaterialShader::Load()
|
||||
}
|
||||
#endif
|
||||
|
||||
psDesc.StencilEnable = true;
|
||||
psDesc.StencilReadMask = 0;
|
||||
psDesc.StencilPassOp = StencilOperation::Replace;
|
||||
|
||||
// GBuffer Pass
|
||||
psDesc.VS = _shader->GetVS("VS");
|
||||
failed |= psDesc.VS == nullptr;
|
||||
@@ -160,6 +162,9 @@ bool DeferredMaterialShader::Load()
|
||||
psDesc.PS = _shader->GetPS("PS_GBuffer");
|
||||
_cache.DefaultSkinned.Init(psDesc);
|
||||
|
||||
psDesc.StencilEnable = false;
|
||||
psDesc.StencilPassOp = StencilOperation::Keep;
|
||||
|
||||
#if USE_EDITOR
|
||||
if (_shader->HasShader("PS_QuadOverdraw"))
|
||||
{
|
||||
|
||||
@@ -62,7 +62,7 @@ void DeformableMaterialShader::Bind(BindParameters& params)
|
||||
{
|
||||
Matrix::Transpose(drawCall.World, materialData->WorldMatrix);
|
||||
Matrix::Transpose(drawCall.Deformable.LocalMatrix, materialData->LocalMatrix);
|
||||
materialData->WorldDeterminantSign = drawCall.WorldDeterminantSign;
|
||||
materialData->WorldDeterminantSign = drawCall.WorldDeterminant ? -1.0f : 1.0f;
|
||||
materialData->Segment = drawCall.Deformable.Segment;
|
||||
materialData->ChunksPerSegment = drawCall.Deformable.ChunksPerSegment;
|
||||
materialData->MeshMinZ = drawCall.Deformable.MeshMinZ;
|
||||
@@ -84,13 +84,10 @@ void DeformableMaterialShader::Bind(BindParameters& params)
|
||||
// Select pipeline state based on current pass and render mode
|
||||
const bool wireframe = (_info.FeaturesFlags & MaterialFeaturesFlags::Wireframe) != MaterialFeaturesFlags::None || view.Mode == ViewMode::Wireframe;
|
||||
CullMode cullMode = view.Pass == DrawPass::Depth ? CullMode::TwoSided : _info.CullMode;
|
||||
if (cullMode != CullMode::TwoSided && drawCall.WorldDeterminantSign < 0)
|
||||
if (cullMode != CullMode::TwoSided && drawCall.WorldDeterminant)
|
||||
{
|
||||
// Invert culling when scale is negative
|
||||
if (cullMode == CullMode::Normal)
|
||||
cullMode = CullMode::Inverted;
|
||||
else
|
||||
cullMode = CullMode::Normal;
|
||||
cullMode = cullMode == CullMode::Normal ? CullMode::Inverted : CullMode::Normal;
|
||||
}
|
||||
PipelineStateCache* psCache = _cache.GetPS(view.Pass);
|
||||
ASSERT(psCache);
|
||||
@@ -98,6 +95,7 @@ void DeformableMaterialShader::Bind(BindParameters& params)
|
||||
|
||||
// Bind pipeline
|
||||
context->SetState(state);
|
||||
context->SetStencilRef(drawCall.StencilValue);
|
||||
}
|
||||
|
||||
void DeformableMaterialShader::Unload()
|
||||
@@ -139,10 +137,17 @@ bool DeformableMaterialShader::Load()
|
||||
{
|
||||
_drawModes |= DrawPass::GBuffer | DrawPass::GlobalSurfaceAtlas;
|
||||
|
||||
psDesc.StencilEnable = true;
|
||||
psDesc.StencilReadMask = 0;
|
||||
psDesc.StencilPassOp = StencilOperation::Replace;
|
||||
|
||||
// GBuffer Pass
|
||||
psDesc.VS = _shader->GetVS("VS_SplineModel");
|
||||
psDesc.PS = _shader->GetPS("PS_GBuffer");
|
||||
_cache.Default.Init(psDesc);
|
||||
|
||||
psDesc.StencilEnable = false;
|
||||
psDesc.StencilPassOp = StencilOperation::Keep;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -80,13 +80,10 @@ void ForwardMaterialShader::Bind(BindParameters& params)
|
||||
if (IsRunningRadiancePass)
|
||||
cullMode = CullMode::TwoSided;
|
||||
#endif
|
||||
if (cullMode != CullMode::TwoSided && drawCall.WorldDeterminantSign < 0)
|
||||
if (cullMode != CullMode::TwoSided && drawCall.WorldDeterminant)
|
||||
{
|
||||
// Invert culling when scale is negative
|
||||
if (cullMode == CullMode::Normal)
|
||||
cullMode = CullMode::Inverted;
|
||||
else
|
||||
cullMode = CullMode::Normal;
|
||||
cullMode = cullMode == CullMode::Normal ? CullMode::Inverted : CullMode::Normal;
|
||||
}
|
||||
ASSERT_LOW_LAYER(!(useSkinning && params.Instanced)); // No support for instancing skinned meshes
|
||||
const auto cacheObj = params.Instanced ? &_cacheInstanced : &_cache;
|
||||
|
||||
@@ -76,7 +76,7 @@ void TerrainMaterialShader::Bind(BindParameters& params)
|
||||
scaleX > 0.00001f ? 1.0f / scaleX : 0.0f,
|
||||
scaleY > 0.00001f ? 1.0f / scaleY : 0.0f,
|
||||
scaleZ > 0.00001f ? 1.0f / scaleZ : 0.0f);
|
||||
materialData->WorldDeterminantSign = drawCall.WorldDeterminantSign;
|
||||
materialData->WorldDeterminantSign = drawCall.WorldDeterminant ? -1.0f : 1.0f;
|
||||
materialData->PerInstanceRandom = drawCall.PerInstanceRandom;
|
||||
materialData->CurrentLOD = drawCall.Terrain.CurrentLOD;
|
||||
materialData->ChunkSizeNextLOD = drawCall.Terrain.ChunkSizeNextLOD;
|
||||
@@ -109,13 +109,10 @@ void TerrainMaterialShader::Bind(BindParameters& params)
|
||||
if (IsRunningRadiancePass)
|
||||
cullMode = CullMode::TwoSided;
|
||||
#endif
|
||||
if (cullMode != CullMode::TwoSided && drawCall.WorldDeterminantSign < 0)
|
||||
if (cullMode != CullMode::TwoSided && drawCall.WorldDeterminant)
|
||||
{
|
||||
// Invert culling when scale is negative
|
||||
if (cullMode == CullMode::Normal)
|
||||
cullMode = CullMode::Inverted;
|
||||
else
|
||||
cullMode = CullMode::Normal;
|
||||
cullMode = cullMode == CullMode::Normal ? CullMode::Inverted : CullMode::Normal;
|
||||
}
|
||||
const PipelineStateCache* psCache = _cache.GetPS(view.Pass, useLightmap);
|
||||
ASSERT(psCache);
|
||||
@@ -123,6 +120,7 @@ void TerrainMaterialShader::Bind(BindParameters& params)
|
||||
|
||||
// Bind pipeline
|
||||
context->SetState(state);
|
||||
context->SetStencilRef(drawCall.StencilValue);
|
||||
}
|
||||
|
||||
void TerrainMaterialShader::Unload()
|
||||
@@ -139,6 +137,10 @@ bool TerrainMaterialShader::Load()
|
||||
psDesc.DepthEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
|
||||
psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == MaterialFeaturesFlags::None;
|
||||
|
||||
psDesc.StencilEnable = true;
|
||||
psDesc.StencilReadMask = 0;
|
||||
psDesc.StencilPassOp = StencilOperation::Replace;
|
||||
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
// Check if use tessellation (both material and runtime supports it)
|
||||
const bool useTess = _info.TessellationMode != TessellationMethod::None && GPUDevice::Instance->Limits.HasTessellation;
|
||||
|
||||
@@ -218,7 +218,7 @@ bool Mesh::Load(uint32 vertices, uint32 triangles, const void* vb0, const void*
|
||||
return Init(vertices, triangles, vbData, ib, use16BitIndexBuffer, vbLayout);
|
||||
}
|
||||
|
||||
void Mesh::Draw(const RenderContext& renderContext, MaterialBase* material, const Matrix& world, StaticFlags flags, bool receiveDecals, DrawPass drawModes, float perInstanceRandom, int8 sortOrder) const
|
||||
void Mesh::Draw(const RenderContext& renderContext, MaterialBase* material, const Matrix& world, StaticFlags flags, bool receiveDecals, DrawPass drawModes, float perInstanceRandom, int8 sortOrder, uint8 stencilValue) const
|
||||
{
|
||||
if (!material || !material->IsSurface() || !IsInitialized())
|
||||
return;
|
||||
@@ -240,8 +240,8 @@ void Mesh::Draw(const RenderContext& renderContext, MaterialBase* material, cons
|
||||
drawCall.ObjectRadius = (float)_sphere.Radius * drawCall.World.GetScaleVector().GetAbsolute().MaxValue();
|
||||
drawCall.Surface.GeometrySize = _box.GetSize();
|
||||
drawCall.Surface.PrevWorld = world;
|
||||
drawCall.WorldDeterminantSign = RenderTools::GetWorldDeterminantSign(drawCall.World);
|
||||
drawCall.PerInstanceRandom = perInstanceRandom;
|
||||
drawCall.StencilValue = stencilValue;
|
||||
#if USE_EDITOR
|
||||
const ViewMode viewMode = renderContext.View.Mode;
|
||||
if (viewMode == ViewMode::LightmapUVsDensity || viewMode == ViewMode::LODPreview)
|
||||
@@ -307,8 +307,8 @@ void Mesh::Draw(const RenderContext& renderContext, const DrawInfo& info, float
|
||||
drawCall.Surface.Lightmap = (info.Flags & StaticFlags::Lightmap) != StaticFlags::None ? info.Lightmap : nullptr;
|
||||
drawCall.Surface.LightmapUVsArea = info.LightmapUVs ? *info.LightmapUVs : Rectangle::Empty;
|
||||
drawCall.Surface.LODDitherFactor = lodDitherFactor;
|
||||
drawCall.WorldDeterminantSign = RenderTools::GetWorldDeterminantSign(drawCall.World);
|
||||
drawCall.PerInstanceRandom = info.PerInstanceRandom;
|
||||
drawCall.StencilValue = info.StencilValue;
|
||||
#if USE_EDITOR
|
||||
const ViewMode viewMode = renderContext.View.Mode;
|
||||
if (viewMode == ViewMode::LightmapUVsDensity || viewMode == ViewMode::LODPreview)
|
||||
@@ -370,8 +370,8 @@ void Mesh::Draw(const RenderContextBatch& renderContextBatch, const DrawInfo& in
|
||||
drawCall.Surface.Lightmap = (info.Flags & StaticFlags::Lightmap) != StaticFlags::None ? info.Lightmap : nullptr;
|
||||
drawCall.Surface.LightmapUVsArea = info.LightmapUVs ? *info.LightmapUVs : Rectangle::Empty;
|
||||
drawCall.Surface.LODDitherFactor = lodDitherFactor;
|
||||
drawCall.WorldDeterminantSign = RenderTools::GetWorldDeterminantSign(drawCall.World);
|
||||
drawCall.PerInstanceRandom = info.PerInstanceRandom;
|
||||
drawCall.StencilValue = info.StencilValue;
|
||||
#if USE_EDITOR
|
||||
const ViewMode viewMode = renderContextBatch.GetMainContext().View.Mode;
|
||||
if (viewMode == ViewMode::LightmapUVsDensity || viewMode == ViewMode::LODPreview)
|
||||
|
||||
@@ -142,7 +142,8 @@ public:
|
||||
/// <param name="drawModes">The draw passes to use for rendering this object.</param>
|
||||
/// <param name="perInstanceRandom">The random per-instance value (normalized to range 0-1).</param>
|
||||
/// <param name="sortOrder">Object sorting key.</param>
|
||||
API_FUNCTION() void Draw(API_PARAM(Ref) const RenderContext& renderContext, MaterialBase* material, API_PARAM(Ref) const Matrix& world, StaticFlags flags = StaticFlags::None, bool receiveDecals = true, DrawPass drawModes = DrawPass::Default, float perInstanceRandom = 0.0f, int8 sortOrder = 0) const;
|
||||
/// <param name="stencilValue">Object stencil value.</param>
|
||||
API_FUNCTION() void Draw(API_PARAM(Ref) const RenderContext& renderContext, MaterialBase* material, API_PARAM(Ref) const Matrix& world, StaticFlags flags = StaticFlags::None, bool receiveDecals = true, DrawPass drawModes = DrawPass::Default, float perInstanceRandom = 0.0f, int8 sortOrder = 0, uint8 stencilValue = 0) const;
|
||||
|
||||
/// <summary>
|
||||
/// Draws the mesh.
|
||||
|
||||
@@ -404,6 +404,11 @@ public:
|
||||
/// </summary>
|
||||
float PerInstanceRandom;
|
||||
|
||||
/// <summary>
|
||||
/// The 8-bit stencil value to write into Depth-Stencil Buffer.
|
||||
/// </summary>
|
||||
uint8 StencilValue;
|
||||
|
||||
/// <summary>
|
||||
/// The LOD bias value.
|
||||
/// </summary>
|
||||
@@ -422,6 +427,12 @@ public:
|
||||
#if USE_EDITOR
|
||||
float LightmapScale = -1.0f;
|
||||
#endif
|
||||
|
||||
// Packs object layer into the stencil bits.
|
||||
FORCE_INLINE void SetStencilValue(int32 layer)
|
||||
{
|
||||
StencilValue = uint8(layer & 0x1f);
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -314,8 +314,8 @@ void SkinnedMesh::Draw(const RenderContext& renderContext, const DrawInfo& info,
|
||||
drawCall.Surface.PrevWorld = info.DrawState->PrevWorld;
|
||||
drawCall.Surface.Skinning = info.Skinning;
|
||||
drawCall.Surface.LODDitherFactor = lodDitherFactor;
|
||||
drawCall.WorldDeterminantSign = RenderTools::GetWorldDeterminantSign(drawCall.World);
|
||||
drawCall.PerInstanceRandom = info.PerInstanceRandom;
|
||||
drawCall.StencilValue = info.StencilValue;
|
||||
|
||||
// Push draw call to the render list
|
||||
renderContext.List->AddDrawCall(renderContext, drawModes, StaticFlags::None, drawCall, entry.ReceiveDecals, info.SortOrder);
|
||||
@@ -355,8 +355,8 @@ void SkinnedMesh::Draw(const RenderContextBatch& renderContextBatch, const DrawI
|
||||
drawCall.Surface.PrevWorld = info.DrawState->PrevWorld;
|
||||
drawCall.Surface.Skinning = info.Skinning;
|
||||
drawCall.Surface.LODDitherFactor = lodDitherFactor;
|
||||
drawCall.WorldDeterminantSign = RenderTools::GetWorldDeterminantSign(drawCall.World);
|
||||
drawCall.PerInstanceRandom = info.PerInstanceRandom;
|
||||
drawCall.StencilValue = info.StencilValue;
|
||||
|
||||
// Push draw call to the render lists
|
||||
const auto shadowsMode = entry.ShadowsMode & slot.ShadowsMode;
|
||||
|
||||
@@ -13,6 +13,17 @@
|
||||
#define GBUFFER2_FORMAT PixelFormat::R8G8B8A8_UNorm
|
||||
#define GBUFFER3_FORMAT PixelFormat::R8G8B8A8_UNorm
|
||||
|
||||
// Stencil bits usage (must match GBuffer.hlsl)
|
||||
// [0] | Object Layer
|
||||
// [1] | Object Layer
|
||||
// [2] | Object Layer
|
||||
// [3] | Object Layer
|
||||
// [4] | Object Layer
|
||||
// [5] | <unsued>
|
||||
// [6] | <unsued>
|
||||
// [7] | <unsued>
|
||||
#define STENCIL_BUFFER_OBJECT_LAYER(value) uint8(value & 0x1f)
|
||||
|
||||
/// <summary>
|
||||
/// The scene rendering buffers container.
|
||||
/// </summary>
|
||||
|
||||
@@ -437,6 +437,12 @@ public:
|
||||
/// <returns>The view to the depth-stencil resource descriptor as read-only depth.</returns>
|
||||
API_FUNCTION() virtual GPUTextureView* ViewReadOnlyDepth() const = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the view to the texture as stencil buffer.
|
||||
/// </summary>
|
||||
/// <returns>The view to the stencil resource descriptor.</returns>
|
||||
API_FUNCTION() virtual GPUTextureView* ViewStencil() const = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Implicit conversion to the first surface (only for 2D textures).
|
||||
/// </summary>
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "GPUSamplerDX11.h"
|
||||
#include "GPUVertexLayoutDX11.h"
|
||||
#include "Engine/GraphicsDevice/DirectX/RenderToolsDX.h"
|
||||
#include "Engine/Graphics/PixelFormatExtensions.h"
|
||||
#include "Engine/Core/Math/Viewport.h"
|
||||
#include "Engine/Core/Math/Rectangle.h"
|
||||
#include "Engine/Profiler/RenderStats.h"
|
||||
@@ -216,7 +217,10 @@ void GPUContextDX11::ClearDepth(GPUTextureView* depthBuffer, float depthValue, u
|
||||
if (depthBufferDX11)
|
||||
{
|
||||
ASSERT(depthBufferDX11->DSV());
|
||||
_context->ClearDepthStencilView(depthBufferDX11->DSV(), D3D11_CLEAR_DEPTH, depthValue, stencilValue);
|
||||
UINT clearFlags = D3D11_CLEAR_DEPTH;
|
||||
if (PixelFormatExtensions::HasStencil(depthBufferDX11->GetFormat()))
|
||||
clearFlags |= D3D11_CLEAR_STENCIL;
|
||||
_context->ClearDepthStencilView(depthBufferDX11->DSV(), clearFlags, depthValue, stencilValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -150,6 +150,7 @@ void GPUTextureDX11::OnReleaseGPU()
|
||||
_handleArray.Release();
|
||||
_handleVolume.Release();
|
||||
_handleReadOnlyDepth.Release();
|
||||
_handleStencil.Release();
|
||||
DX_SAFE_RELEASE_CHECK(_resource, 0);
|
||||
|
||||
// Base
|
||||
@@ -547,6 +548,41 @@ void GPUTextureDX11::initHandles()
|
||||
}
|
||||
_handleReadOnlyDepth.Init(this, rtView, srView, dsView, nullptr, format, msaa);
|
||||
}
|
||||
|
||||
// Stencil view
|
||||
if (useDSV && useSRV && PixelFormatExtensions::HasStencil(format))
|
||||
{
|
||||
PixelFormat stencilFormat;
|
||||
switch (_dxgiFormatDSV)
|
||||
{
|
||||
case PixelFormat::D24_UNorm_S8_UInt:
|
||||
srDesc.Format = DXGI_FORMAT_X24_TYPELESS_G8_UINT;
|
||||
stencilFormat = PixelFormat::X24_Typeless_G8_UInt;
|
||||
break;
|
||||
case PixelFormat::D32_Float_S8X24_UInt:
|
||||
srDesc.Format = DXGI_FORMAT_X32_TYPELESS_G8X24_UINT;
|
||||
stencilFormat = PixelFormat::X32_Typeless_G8X24_UInt;
|
||||
break;
|
||||
}
|
||||
if (isCubeMap)
|
||||
{
|
||||
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
|
||||
srDesc.TextureCube.MostDetailedMip = 0;
|
||||
srDesc.TextureCube.MipLevels = mipLevels;
|
||||
}
|
||||
else if (isMsaa)
|
||||
{
|
||||
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
|
||||
}
|
||||
else
|
||||
{
|
||||
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
srDesc.Texture2D.MostDetailedMip = 0;
|
||||
srDesc.Texture2D.MipLevels = mipLevels;
|
||||
}
|
||||
VALIDATE_DIRECTX_CALL(device->CreateShaderResourceView(_resource, &srDesc, &srView));
|
||||
_handleStencil.Init(this, nullptr, srView, nullptr, nullptr, stencilFormat, msaa);
|
||||
}
|
||||
}
|
||||
|
||||
bool GPUTextureDX11::GetData(int32 arrayIndex, int32 mipMapIndex, TextureMipData& data, uint32 mipRowPitch)
|
||||
|
||||
@@ -158,6 +158,7 @@ private:
|
||||
GPUTextureViewDX11 _handleArray;
|
||||
GPUTextureViewDX11 _handleVolume;
|
||||
GPUTextureViewDX11 _handleReadOnlyDepth;
|
||||
GPUTextureViewDX11 _handleStencil;
|
||||
Array<GPUTextureViewDX11> _handlesPerSlice; // [slice]
|
||||
Array<Array<GPUTextureViewDX11>> _handlesPerMip; // [slice][mip]
|
||||
|
||||
@@ -225,6 +226,11 @@ public:
|
||||
ASSERT(_desc.Flags & GPUTextureFlags::ReadOnlyDepthView);
|
||||
return (GPUTextureView*)&_handleReadOnlyDepth;
|
||||
}
|
||||
GPUTextureView* ViewStencil() const override
|
||||
{
|
||||
ASSERT(_desc.Flags & GPUTextureFlags::DepthStencil);
|
||||
return (GPUTextureView*)&_handleStencil;
|
||||
}
|
||||
void* GetNativePtr() const override
|
||||
{
|
||||
return static_cast<void*>(_resource);
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "CommandSignatureDX12.h"
|
||||
#include "Engine/Profiler/RenderStats.h"
|
||||
#include "Engine/Graphics/GPUResourceAccess.h"
|
||||
#include "Engine/Graphics/PixelFormatExtensions.h"
|
||||
#include "Engine/Graphics/Shaders/GPUShader.h"
|
||||
#include "Engine/Threading/Threading.h"
|
||||
|
||||
@@ -823,7 +824,10 @@ void GPUContextDX12::ClearDepth(GPUTextureView* depthBuffer, float depthValue, u
|
||||
SetResourceState(depthBufferDX12->GetResourceOwner(), D3D12_RESOURCE_STATE_DEPTH_WRITE, depthBufferDX12->SubresourceIndex);
|
||||
flushRBs();
|
||||
|
||||
_commandList->ClearDepthStencilView(depthBufferDX12->DSV(), D3D12_CLEAR_FLAG_DEPTH, depthValue, stencilValue, 0, nullptr);
|
||||
D3D12_CLEAR_FLAGS clearFlags = D3D12_CLEAR_FLAG_DEPTH;
|
||||
if (PixelFormatExtensions::HasStencil(depthBufferDX12->GetFormat()))
|
||||
clearFlags |= D3D12_CLEAR_FLAG_STENCIL;
|
||||
_commandList->ClearDepthStencilView(depthBufferDX12->DSV(), clearFlags, depthValue, stencilValue, 0, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -227,6 +227,8 @@ void GPUTextureDX12::OnReleaseGPU()
|
||||
_handlesPerSlice.Resize(0, false);
|
||||
_handleArray.Release();
|
||||
_handleVolume.Release();
|
||||
_handleReadOnlyDepth.Release();
|
||||
_handleStencil.Release();
|
||||
_srv.Release();
|
||||
_uav.Release();
|
||||
releaseResource();
|
||||
@@ -721,6 +723,45 @@ void GPUTextureDX12::initHandles()
|
||||
_handleReadOnlyDepth.SetSRV(srDesc);
|
||||
}
|
||||
}
|
||||
|
||||
// Stencil view
|
||||
if (useDSV && useSRV && PixelFormatExtensions::HasStencil(format))
|
||||
{
|
||||
PixelFormat stencilFormat;
|
||||
switch (_dxgiFormatDSV)
|
||||
{
|
||||
case PixelFormat::D24_UNorm_S8_UInt:
|
||||
srDesc.Format = DXGI_FORMAT_X24_TYPELESS_G8_UINT;
|
||||
stencilFormat = PixelFormat::X24_Typeless_G8_UInt;
|
||||
break;
|
||||
case PixelFormat::D32_Float_S8X24_UInt:
|
||||
srDesc.Format = DXGI_FORMAT_X32_TYPELESS_G8X24_UINT;
|
||||
stencilFormat = PixelFormat::X32_Typeless_G8X24_UInt;
|
||||
break;
|
||||
}
|
||||
if (isCubeMap)
|
||||
{
|
||||
srDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
|
||||
srDesc.TextureCube.MostDetailedMip = 0;
|
||||
srDesc.TextureCube.MipLevels = mipLevels;
|
||||
srDesc.TextureCube.ResourceMinLODClamp = 0;
|
||||
}
|
||||
else if (isMsaa)
|
||||
{
|
||||
srDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMS;
|
||||
}
|
||||
else
|
||||
{
|
||||
srDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
srDesc.Texture2D.MostDetailedMip = 0;
|
||||
srDesc.Texture2D.MipLevels = mipLevels;
|
||||
srDesc.Texture2D.ResourceMinLODClamp = 0;
|
||||
srDesc.Texture2D.PlaneSlice = 1;
|
||||
}
|
||||
_handleStencil.Init(this, _device, this, stencilFormat, msaa);
|
||||
_handleStencil.ReadOnlyDepthView = true;
|
||||
_handleStencil.SetSRV(srDesc);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -91,7 +91,7 @@ public:
|
||||
// [IShaderResourceDX12]
|
||||
bool IsDepthStencilResource() const override
|
||||
{
|
||||
return _dsv.IsValid();
|
||||
return ReadOnlyDepthView || _dsv.IsValid();
|
||||
}
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE SRV() const override
|
||||
{
|
||||
@@ -117,6 +117,7 @@ private:
|
||||
GPUTextureViewDX12 _handleArray;
|
||||
GPUTextureViewDX12 _handleVolume;
|
||||
GPUTextureViewDX12 _handleReadOnlyDepth;
|
||||
GPUTextureViewDX12 _handleStencil;
|
||||
Array<GPUTextureViewDX12> _handlesPerSlice; // [slice]
|
||||
Array<Array<GPUTextureViewDX12>> _handlesPerMip; // [slice][mip]
|
||||
|
||||
@@ -165,6 +166,11 @@ public:
|
||||
ASSERT(_desc.Flags & GPUTextureFlags::ReadOnlyDepthView);
|
||||
return (GPUTextureView*)&_handleReadOnlyDepth;
|
||||
}
|
||||
GPUTextureView* ViewStencil() const override
|
||||
{
|
||||
ASSERT(_desc.Flags & GPUTextureFlags::DepthStencil);
|
||||
return (GPUTextureView*)&_handleStencil;
|
||||
}
|
||||
void* GetNativePtr() const override
|
||||
{
|
||||
return (void*)_resource;
|
||||
|
||||
@@ -33,6 +33,10 @@ public:
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
GPUTextureView* ViewStencil() const override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
void* GetNativePtr() const override
|
||||
{
|
||||
return nullptr;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include "Engine/Graphics/Textures/TextureData.h"
|
||||
#include "Engine/Scripting/Enums.h"
|
||||
|
||||
void GPUTextureViewVulkan::Init(GPUDeviceVulkan* device, ResourceOwnerVulkan* owner, VkImage image, int32 totalMipLevels, PixelFormat format, MSAALevel msaa, VkExtent3D extent, VkImageViewType viewType, int32 mipLevels, int32 firstMipIndex, int32 arraySize, int32 firstArraySlice, bool readOnlyDepth)
|
||||
void GPUTextureViewVulkan::Init(GPUDeviceVulkan* device, ResourceOwnerVulkan* owner, VkImage image, int32 totalMipLevels, PixelFormat format, MSAALevel msaa, VkExtent3D extent, VkImageViewType viewType, int32 mipLevels, int32 firstMipIndex, int32 arraySize, int32 firstArraySlice, bool readOnlyDepth, bool stencilView)
|
||||
{
|
||||
ASSERT(View == VK_NULL_HANDLE);
|
||||
|
||||
@@ -57,7 +57,13 @@ void GPUTextureViewVulkan::Init(GPUDeviceVulkan* device, ResourceOwnerVulkan* ow
|
||||
SubresourceIndex = RenderTools::CalcSubresourceIndex(firstMipIndex, firstArraySlice, totalMipLevels);
|
||||
}
|
||||
|
||||
if (PixelFormatExtensions::IsDepthStencil(format))
|
||||
if (stencilView)
|
||||
{
|
||||
range.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
LayoutRTV = readOnlyDepth ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
LayoutSRV = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
|
||||
}
|
||||
else if (PixelFormatExtensions::IsDepthStencil(format))
|
||||
{
|
||||
range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
#if 0
|
||||
@@ -157,13 +163,23 @@ void GPUTextureViewVulkan::DescriptorAsImage(GPUContextVulkan* context, VkImageV
|
||||
imageView = View;
|
||||
layout = LayoutSRV;
|
||||
const VkImageAspectFlags aspectMask = Info.subresourceRange.aspectMask;
|
||||
if (aspectMask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
|
||||
if (aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
|
||||
{
|
||||
// Transition depth-only when binding depth buffer with stencil
|
||||
// Transition depth-only when binding depth buffer with stencil (or stencil-only without depth)
|
||||
if (ViewSRV == VK_NULL_HANDLE)
|
||||
{
|
||||
VkImageViewCreateInfo createInfo = Info;
|
||||
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
if (aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
|
||||
{
|
||||
// Stencil
|
||||
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
createInfo.components.g = VK_COMPONENT_SWIZZLE_R; // Map .g component in shader to .r of stencil plane
|
||||
}
|
||||
else
|
||||
{
|
||||
// Depth
|
||||
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
}
|
||||
VALIDATE_VULKAN_RESULT(vkCreateImageView(Device->Device, &createInfo, nullptr, &ViewSRV));
|
||||
}
|
||||
imageView = ViewSRV;
|
||||
@@ -434,6 +450,26 @@ void GPUTextureVulkan::initHandles()
|
||||
{
|
||||
_handleReadOnlyDepth.Init(_device, this, _image, mipLevels, format, msaa, extent, VK_IMAGE_VIEW_TYPE_2D, mipLevels, 0, 1, 0, true);
|
||||
}
|
||||
|
||||
// Stencil view
|
||||
if (IsDepthStencil() && IsShaderResource() && PixelFormatExtensions::HasStencil(format))
|
||||
{
|
||||
PixelFormat stencilFormat;
|
||||
switch (format)
|
||||
{
|
||||
case PixelFormat::D24_UNorm_S8_UInt:
|
||||
case PixelFormat::R24_UNorm_X8_Typeless:
|
||||
case PixelFormat::R24G8_Typeless:
|
||||
stencilFormat = PixelFormat::X24_Typeless_G8_UInt;
|
||||
break;
|
||||
case PixelFormat::D32_Float_S8X24_UInt:
|
||||
case PixelFormat::R32_Float_X8X24_Typeless:
|
||||
case PixelFormat::R32G8X24_Typeless:
|
||||
stencilFormat = PixelFormat::X32_Typeless_G8X24_UInt;
|
||||
break;
|
||||
}
|
||||
_handleStencil.Init(_device, this, _image, mipLevels, stencilFormat, msaa, extent, VK_IMAGE_VIEW_TYPE_2D, mipLevels, 0, 1, 0, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
void GPUTextureVulkan::OnResidentMipsChanged()
|
||||
@@ -457,6 +493,7 @@ void GPUTextureVulkan::OnReleaseGPU()
|
||||
_handleVolume.Release();
|
||||
_handleUAV.Release();
|
||||
_handleReadOnlyDepth.Release();
|
||||
_handleStencil.Release();
|
||||
for (int32 i = 0; i < _handlesPerMip.Count(); i++)
|
||||
{
|
||||
for (int32 j = 0; j < _handlesPerMip[i].Count(); j++)
|
||||
|
||||
@@ -45,7 +45,7 @@ public:
|
||||
#endif
|
||||
|
||||
public:
|
||||
void Init(GPUDeviceVulkan* device, ResourceOwnerVulkan* owner, VkImage image, int32 totalMipLevels, PixelFormat format, MSAALevel msaa, VkExtent3D extent, VkImageViewType viewType, int32 mipLevels = 1, int32 firstMipIndex = 0, int32 arraySize = 1, int32 firstArraySlice = 0, bool readOnlyDepth = false);
|
||||
void Init(GPUDeviceVulkan* device, ResourceOwnerVulkan* owner, VkImage image, int32 totalMipLevels, PixelFormat format, MSAALevel msaa, VkExtent3D extent, VkImageViewType viewType, int32 mipLevels = 1, int32 firstMipIndex = 0, int32 arraySize = 1, int32 firstArraySlice = 0, bool readOnlyDepth = false, bool stencilView = false);
|
||||
|
||||
VkImageView GetFramebufferView();
|
||||
|
||||
@@ -79,6 +79,7 @@ private:
|
||||
GPUTextureViewVulkan _handleVolume;
|
||||
GPUTextureViewVulkan _handleUAV;
|
||||
GPUTextureViewVulkan _handleReadOnlyDepth;
|
||||
GPUTextureViewVulkan _handleStencil;
|
||||
Array<GPUTextureViewVulkan> _handlesPerSlice; // [slice]
|
||||
Array<Array<GPUTextureViewVulkan>> _handlesPerMip; // [slice][mip]
|
||||
|
||||
@@ -140,6 +141,11 @@ public:
|
||||
ASSERT(_desc.Flags & GPUTextureFlags::ReadOnlyDepthView);
|
||||
return (GPUTextureView*)&_handleReadOnlyDepth;
|
||||
}
|
||||
GPUTextureView* ViewStencil() const override
|
||||
{
|
||||
ASSERT(_desc.Flags & GPUTextureFlags::DepthStencil);
|
||||
return (GPUTextureView*)&_handleStencil;
|
||||
}
|
||||
void* GetNativePtr() const override
|
||||
{
|
||||
return (void*)_image;
|
||||
|
||||
@@ -1027,6 +1027,7 @@ void AnimatedModel::Draw(RenderContext& renderContext)
|
||||
draw.LODBias = LODBias;
|
||||
draw.ForcedLOD = ForcedLOD;
|
||||
draw.SortOrder = SortOrder;
|
||||
draw.SetStencilValue(_layer);
|
||||
|
||||
SkinnedModel->Draw(renderContext, draw);
|
||||
}
|
||||
@@ -1068,6 +1069,7 @@ void AnimatedModel::Draw(RenderContextBatch& renderContextBatch)
|
||||
draw.LODBias = LODBias;
|
||||
draw.ForcedLOD = ForcedLOD;
|
||||
draw.SortOrder = SortOrder;
|
||||
draw.SetStencilValue(_layer);
|
||||
|
||||
PRAGMA_DISABLE_DEPRECATION_WARNINGS
|
||||
if (ShadowsMode != ShadowsCastingMode::All)
|
||||
|
||||
@@ -374,6 +374,7 @@ void Camera::Draw(RenderContext& renderContext)
|
||||
BoundingSphere::FromBox(_previewModelBox, draw.Bounds);
|
||||
draw.Bounds.Center -= renderContext.View.Origin;
|
||||
draw.PerInstanceRandom = GetPerInstanceRandom();
|
||||
draw.StencilValue = 0;
|
||||
draw.LODBias = 0;
|
||||
draw.ForcedLOD = -1;
|
||||
draw.SortOrder = 0;
|
||||
|
||||
@@ -107,7 +107,6 @@ void Skybox::ApplySky(GPUContext* context, RenderContext& renderContext, const M
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.ObjectRadius = (float)_sphere.Radius;
|
||||
drawCall.Surface.GeometrySize = _box.GetSize();
|
||||
drawCall.WorldDeterminantSign = RenderTools::GetWorldDeterminantSign(drawCall.World);
|
||||
drawCall.PerInstanceRandom = GetPerInstanceRandom();
|
||||
MaterialBase::BindParameters bindParams(context, renderContext, drawCall);
|
||||
bindParams.BindViewData();
|
||||
|
||||
@@ -407,12 +407,12 @@ void SplineModel::Draw(RenderContext& renderContext)
|
||||
drawCall.Deformable.MeshMaxZ = _meshMaxZ;
|
||||
drawCall.Deformable.GeometrySize = _box.GetSize();
|
||||
drawCall.PerInstanceRandom = GetPerInstanceRandom();
|
||||
drawCall.SetStencilValue(_layer);
|
||||
_preTransform.GetWorld(drawCall.Deformable.LocalMatrix);
|
||||
const Transform splineTransform = GetTransform();
|
||||
renderContext.View.GetWorldMatrix(splineTransform, drawCall.World);
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation() + drawCall.Deformable.LocalMatrix.GetTranslation();
|
||||
drawCall.ObjectRadius = (float)_sphere.Radius; // TODO: use radius for the spline chunk rather than whole spline
|
||||
const float worldDeterminantSign = drawCall.World.RotDeterminant() * drawCall.Deformable.LocalMatrix.RotDeterminant();
|
||||
for (int32 segment = 0; segment < _instances.Count(); segment++)
|
||||
{
|
||||
auto& instance = _instances[segment];
|
||||
@@ -468,7 +468,6 @@ void SplineModel::Draw(RenderContext& renderContext)
|
||||
// Submit draw call
|
||||
mesh->GetDrawCallGeometry(drawCall);
|
||||
drawCall.Material = material;
|
||||
drawCall.WorldDeterminantSign = Math::FloatSelect(worldDeterminantSign * instance.RotDeterminant, 1, -1);
|
||||
renderContext.List->AddDrawCall(renderContext, drawModes, _staticFlags, drawCall, entry.ReceiveDecals);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,6 +361,7 @@ void StaticModel::Draw(RenderContext& renderContext)
|
||||
draw.ForcedLOD = _forcedLod;
|
||||
draw.SortOrder = _sortOrder;
|
||||
draw.VertexColors = _vertexColorsCount ? _vertexColorsBuffer : nullptr;
|
||||
draw.SetStencilValue(_layer);
|
||||
#if USE_EDITOR
|
||||
if (HasStaticFlag(StaticFlags::Lightmap))
|
||||
draw.LightmapScale = _scaleInLightmap;
|
||||
@@ -397,6 +398,7 @@ void StaticModel::Draw(RenderContextBatch& renderContextBatch)
|
||||
draw.ForcedLOD = _forcedLod;
|
||||
draw.SortOrder = _sortOrder;
|
||||
draw.VertexColors = _vertexColorsCount ? _vertexColorsBuffer : nullptr;
|
||||
draw.SetStencilValue(_layer);
|
||||
#if USE_EDITOR
|
||||
if (HasStaticFlag(StaticFlags::Lightmap))
|
||||
draw.LightmapScale = _scaleInLightmap;
|
||||
|
||||
@@ -1168,9 +1168,6 @@ void Particles::DrawParticles(RenderContextBatch& renderContextBatch, ParticleEf
|
||||
Matrix worlds[2];
|
||||
Matrix::Translation(-viewOrigin, worlds[0]); // World
|
||||
renderContextBatch.GetMainContext().View.GetWorldMatrix(effect->GetTransform(), worlds[1]); // Local
|
||||
float worldDeterminantSigns[2];
|
||||
worldDeterminantSigns[0] = Math::FloatSelect(worlds[0].RotDeterminant(), 1, -1);
|
||||
worldDeterminantSigns[1] = Math::FloatSelect(worlds[1].RotDeterminant(), 1, -1);
|
||||
const StaticFlags staticFlags = effect->GetStaticFlags();
|
||||
const int8 sortOrder = effect->SortOrder;
|
||||
|
||||
@@ -1194,6 +1191,7 @@ void Particles::DrawParticles(RenderContextBatch& renderContextBatch, ParticleEf
|
||||
// Setup a draw call common data
|
||||
DrawCall drawCall;
|
||||
drawCall.PerInstanceRandom = effect->GetPerInstanceRandom();
|
||||
drawCall.SetStencilValue(effect->GetLayer());
|
||||
drawCall.ObjectPosition = bounds.Center;
|
||||
drawCall.ObjectRadius = (float)bounds.Radius;
|
||||
|
||||
@@ -1209,7 +1207,6 @@ void Particles::DrawParticles(RenderContextBatch& renderContextBatch, ParticleEf
|
||||
continue;
|
||||
|
||||
drawCall.World = worlds[(int32)emitter->SimulationSpace];
|
||||
drawCall.WorldDeterminantSign = worldDeterminantSigns[(int32)emitter->SimulationSpace];
|
||||
drawCall.Particle.Particles = buffer;
|
||||
|
||||
// Check if need to render any module
|
||||
|
||||
@@ -265,16 +265,23 @@ struct DrawCall
|
||||
/// </summary>
|
||||
float ObjectRadius;
|
||||
|
||||
/// <summary>
|
||||
/// The world matrix determinant sign (used for geometry that is two sided or has inverse scale - needs to flip normal vectors and change triangles culling).
|
||||
/// </summary>
|
||||
float WorldDeterminantSign;
|
||||
|
||||
/// <summary>
|
||||
/// The random per-instance value (normalized to range 0-1).
|
||||
/// </summary>
|
||||
float PerInstanceRandom;
|
||||
|
||||
/// <summary>
|
||||
/// The 8-bit stencil value to write into Depth-Stencil Buffer.
|
||||
/// </summary>
|
||||
uint8 StencilValue;
|
||||
|
||||
/// <summary>
|
||||
/// The world matrix determinant sign (used for geometry that is two sided or has inverse scale - needs to flip normal vectors and change triangles culling).
|
||||
/// 0 - sign is positive
|
||||
/// 1 - sign is negative (flips object surfaces)
|
||||
/// </summary>
|
||||
uint8 WorldDeterminant : 1;
|
||||
|
||||
/// <summary>
|
||||
/// The sorting key for the draw call calculate by RenderList.
|
||||
/// </summary>
|
||||
@@ -287,6 +294,12 @@ struct DrawCall
|
||||
{
|
||||
Platform::MemoryClear(this, sizeof(DrawCall));
|
||||
}
|
||||
|
||||
// Packs object layer into the stencil bits.
|
||||
FORCE_INLINE void SetStencilValue(int32 layer)
|
||||
{
|
||||
StencilValue = uint8(layer & 0x1f);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
|
||||
@@ -129,8 +129,6 @@ void MaterialComplexityMaterialShader::Draw(RenderContext& renderContext, GPUCon
|
||||
DrawCall drawCall;
|
||||
MaterialBase::BindParameters bindParams(context, renderContext, drawCall);
|
||||
bindParams.BindViewData();
|
||||
drawCall.WorldDeterminantSign = 1.0f;
|
||||
drawCall.PerInstanceRandom = 0.0f;
|
||||
context->SetRenderTarget(lightBuffer);
|
||||
for (int32 i = 0; i < decals.Count(); i++)
|
||||
{
|
||||
|
||||
@@ -50,8 +50,6 @@ void QuadOverdrawPass::Render(RenderContext& renderContext, GPUContext* context,
|
||||
context->BindUA(1, overdrawTexture->View());
|
||||
context->BindUA(2, liveCountTexture->View());
|
||||
DrawCall drawCall;
|
||||
drawCall.WorldDeterminantSign = 1.0f;
|
||||
drawCall.PerInstanceRandom = 0.0f;
|
||||
MaterialBase::BindParameters bindParams(context, renderContext, drawCall);
|
||||
bindParams.BindViewData();
|
||||
renderContext.View.Pass = DrawPass::QuadOverdraw;
|
||||
@@ -83,7 +81,6 @@ void QuadOverdrawPass::Render(RenderContext& renderContext, GPUContext* context,
|
||||
m1 *= m2;
|
||||
drawCall.World = m1;
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.WorldDeterminantSign = RenderTools::GetWorldDeterminantSign(drawCall.World);
|
||||
skyMaterial->Bind(bindParams);
|
||||
skyModel->Render(context);
|
||||
}
|
||||
|
||||
@@ -564,7 +564,8 @@ FORCE_INLINE void CalculateSortKey(const RenderContext& renderContext, DrawCall&
|
||||
IMaterial::InstancingHandler handler;
|
||||
if (drawCall.Material->CanUseInstancing(handler))
|
||||
handler.GetHash(drawCall, batchKey);
|
||||
uint32 drawKey = (uint32)(471 * drawCall.WorldDeterminantSign);
|
||||
batchKey = (batchKey * 397) ^ drawCall.StencilValue;
|
||||
uint32 drawKey = (uint32)(471 * drawCall.WorldDeterminant);
|
||||
drawKey = (drawKey * 397) ^ GetHash(drawCall.Geometry.VertexBuffers[0]);
|
||||
drawKey = (drawKey * 397) ^ GetHash(drawCall.Geometry.VertexBuffers[1]);
|
||||
drawKey = (drawKey * 397) ^ GetHash(drawCall.Geometry.VertexBuffers[2]);
|
||||
@@ -586,8 +587,11 @@ void RenderList::AddDrawCall(const RenderContext& renderContext, DrawPass drawMo
|
||||
ASSERT_LOW_LAYER(drawModes != DrawPass::None && ((uint32)drawModes & ~(uint32)materialDrawModes) == 0);
|
||||
#endif
|
||||
|
||||
// Append draw call data
|
||||
// Finalize draw call initialization
|
||||
drawCall.WorldDeterminant = drawCall.World.RotDeterminant() < 0 ? 1 : 0;
|
||||
CalculateSortKey(renderContext, drawCall, sortOrder);
|
||||
|
||||
// Append draw call data
|
||||
const int32 index = DrawCalls.Add(drawCall);
|
||||
|
||||
// Add draw call to proper draw lists
|
||||
@@ -625,8 +629,11 @@ void RenderList::AddDrawCall(const RenderContextBatch& renderContextBatch, DrawP
|
||||
#endif
|
||||
const RenderContext& mainRenderContext = renderContextBatch.Contexts.Get()[0];
|
||||
|
||||
// Append draw call data
|
||||
// Finalize draw call initialization
|
||||
drawCall.WorldDeterminant = drawCall.World.RotDeterminant() < 0 ? 1 : 0;
|
||||
CalculateSortKey(mainRenderContext, drawCall, sortOrder);
|
||||
|
||||
// Append draw call data
|
||||
const int32 index = DrawCalls.Add(drawCall);
|
||||
|
||||
// Add draw call to proper draw lists
|
||||
@@ -777,7 +784,8 @@ void RenderList::SortDrawCalls(const RenderContext& renderContext, bool reverseD
|
||||
other.InstanceCount != 0 &&
|
||||
drawCallHandler.CanBatch == otherHandler.CanBatch &&
|
||||
drawCallHandler.CanBatch(drawCall, other, pass) &&
|
||||
drawCall.WorldDeterminantSign * other.WorldDeterminantSign > 0;
|
||||
drawCall.WorldDeterminant == other.WorldDeterminant &&
|
||||
drawCall.StencilValue == other.StencilValue;
|
||||
if (!canBatch)
|
||||
break;
|
||||
batchSize++;
|
||||
|
||||
@@ -651,13 +651,15 @@ GPU_CB_STRUCT(ShaderObjectData
|
||||
|
||||
FORCE_INLINE void Store(const DrawCall& drawCall)
|
||||
{
|
||||
Store(drawCall.World, drawCall.Surface.PrevWorld, drawCall.Surface.LightmapUVsArea, drawCall.Surface.GeometrySize, drawCall.PerInstanceRandom, drawCall.WorldDeterminantSign, drawCall.Surface.LODDitherFactor);
|
||||
Store(drawCall.World, drawCall.Surface.PrevWorld, drawCall.Surface.LightmapUVsArea, drawCall.Surface.GeometrySize, drawCall.PerInstanceRandom, drawCall.WorldDeterminant ? -1.0f : 1.0f, drawCall.Surface.LODDitherFactor);
|
||||
}
|
||||
|
||||
FORCE_INLINE void Load(DrawCall& drawCall) const
|
||||
{
|
||||
Load(drawCall.World, drawCall.Surface.PrevWorld, drawCall.Surface.LightmapUVsArea, drawCall.Surface.GeometrySize, drawCall.PerInstanceRandom, drawCall.WorldDeterminantSign, drawCall.Surface.LODDitherFactor);
|
||||
float worldDeterminantSign;
|
||||
Load(drawCall.World, drawCall.Surface.PrevWorld, drawCall.Surface.LightmapUVsArea, drawCall.Surface.GeometrySize, drawCall.PerInstanceRandom, worldDeterminantSign, drawCall.Surface.LODDitherFactor);
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.WorldDeterminant = worldDeterminantSign < 0 ? 1 : 0;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -122,8 +122,8 @@ void TerrainChunk::Draw(const RenderContext& renderContext) const
|
||||
drawCall.Terrain.Lightmap = nullptr;
|
||||
drawCall.Terrain.LightmapUVsArea = Rectangle::Empty;
|
||||
}
|
||||
drawCall.WorldDeterminantSign = RenderTools::GetWorldDeterminantSign(drawCall.World);
|
||||
drawCall.PerInstanceRandom = _perInstanceRandom;
|
||||
drawCall.SetStencilValue(_patch->_terrain->GetLayer());
|
||||
#if USE_EDITOR
|
||||
if (renderContext.View.Mode == ViewMode::LightmapUVsDensity)
|
||||
drawCall.Surface.LODDitherFactor = 1.0f; // See LightmapUVsDensityMaterialShader
|
||||
@@ -183,8 +183,8 @@ void TerrainChunk::Draw(const RenderContext& renderContext, MaterialBase* materi
|
||||
drawCall.Terrain.Lightmap = nullptr;
|
||||
drawCall.Terrain.LightmapUVsArea = Rectangle::Empty;
|
||||
}
|
||||
drawCall.WorldDeterminantSign = RenderTools::GetWorldDeterminantSign(drawCall.World);
|
||||
drawCall.PerInstanceRandom = _perInstanceRandom;
|
||||
drawCall.SetStencilValue(_patch->_terrain->GetLayer());
|
||||
#if USE_EDITOR
|
||||
if (renderContext.View.Mode == ViewMode::LightmapUVsDensity)
|
||||
drawCall.Surface.LODDitherFactor = 1.0f; // See LightmapUVsDensityMaterialShader
|
||||
|
||||
@@ -390,8 +390,8 @@ void TextRender::Draw(RenderContext& renderContext)
|
||||
drawCall.ObjectRadius = (float)_sphere.Radius;
|
||||
drawCall.Surface.GeometrySize = _localBox.GetSize();
|
||||
drawCall.Surface.PrevWorld = _drawState.PrevWorld;
|
||||
drawCall.WorldDeterminantSign = RenderTools::GetWorldDeterminantSign(drawCall.World);
|
||||
drawCall.PerInstanceRandom = GetPerInstanceRandom();
|
||||
drawCall.SetStencilValue(_layer);
|
||||
drawCall.Geometry.IndexBuffer = _ib.GetBuffer();
|
||||
drawCall.Geometry.VertexBuffers[0] = _vb.GetBuffer();
|
||||
drawCall.InstanceCount = 1;
|
||||
|
||||
23
Source/Shaders/Stencil.hlsl
Normal file
23
Source/Shaders/Stencil.hlsl
Normal file
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) Wojciech Figat. All rights reserved.
|
||||
|
||||
#ifndef __STENCIL__
|
||||
#define __STENCIL__
|
||||
|
||||
#include "./Flax/Common.hlsl"
|
||||
|
||||
// Stencil bits usage (must match RenderBuffers.h)
|
||||
// [0] | Object Layer
|
||||
// [1] | Object Layer
|
||||
// [2] | Object Layer
|
||||
// [3] | Object Layer
|
||||
// [4] | Object Layer
|
||||
// [5] | <unsued>
|
||||
// [6] | <unsued>
|
||||
// [7] | <unsued>
|
||||
#define STENCIL_BUFFER_OBJECT_LAYER(stencil) uint(stencil & 0x1f)
|
||||
#ifndef STENCIL_BUFFER_SWIZZLE
|
||||
#define STENCIL_BUFFER_SWIZZLE .g
|
||||
#endif
|
||||
#define STENCIL_BUFFER_LOAD(rt, pos) rt.Load(int3(pos, 0)) STENCIL_BUFFER_SWIZZLE
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user