Add Deformable material domain
This commit is contained in:
195
Source/Engine/Graphics/Materials/DeformableMaterialShader.cpp
Normal file
195
Source/Engine/Graphics/Materials/DeformableMaterialShader.cpp
Normal file
@@ -0,0 +1,195 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
#include "DeformableMaterialShader.h"
|
||||
#include "MaterialShaderFeatures.h"
|
||||
#include "MaterialParams.h"
|
||||
#include "Engine/Graphics/RenderBuffers.h"
|
||||
#include "Engine/Graphics/RenderView.h"
|
||||
#include "Engine/Renderer/DrawCall.h"
|
||||
#include "Engine/Renderer/RenderList.h"
|
||||
#include "Engine/Graphics/GPUContext.h"
|
||||
#include "Engine/Graphics/Shaders/GPUConstantBuffer.h"
|
||||
#include "Engine/Graphics/GPUDevice.h"
|
||||
#include "Engine/Graphics/Shaders/GPUShader.h"
|
||||
#include "Engine/Graphics/GPULimits.h"
|
||||
#include "Engine/Engine/Time.h"
|
||||
#include "Engine/Graphics/RenderTask.h"
|
||||
|
||||
PACK_STRUCT(struct DeformableMaterialShaderData {
|
||||
Matrix ViewProjectionMatrix;
|
||||
Matrix WorldMatrix;
|
||||
Matrix LocalMatrix;
|
||||
Matrix ViewMatrix;
|
||||
Vector3 ViewPos;
|
||||
float ViewFar;
|
||||
Vector3 ViewDir;
|
||||
float TimeParam;
|
||||
Vector4 ViewInfo;
|
||||
Vector4 ScreenSize;
|
||||
Vector3 WorldInvScale;
|
||||
float WorldDeterminantSign;
|
||||
float MeshMinZ;
|
||||
float Segment;
|
||||
float ChunksPerSegment;
|
||||
float PerInstanceRandom;
|
||||
Vector4 TemporalAAJitter;
|
||||
Vector3 GeometrySize;
|
||||
float MeshMaxZ;
|
||||
});
|
||||
|
||||
DrawPass DeformableMaterialShader::GetDrawModes() const
|
||||
{
|
||||
return _drawModes;
|
||||
}
|
||||
|
||||
void DeformableMaterialShader::Bind(BindParameters& params)
|
||||
{
|
||||
// Prepare
|
||||
auto context = params.GPUContext;
|
||||
auto& view = params.RenderContext.View;
|
||||
auto& drawCall = *params.FirstDrawCall;
|
||||
byte* cb = _cbData.Get();
|
||||
auto materialData = reinterpret_cast<DeformableMaterialShaderData*>(cb);
|
||||
cb += sizeof(DeformableMaterialShaderData);
|
||||
int32 srv = 1;
|
||||
|
||||
// Setup features
|
||||
if (_info.BlendMode != MaterialBlendMode::Opaque)
|
||||
ForwardShadingFeature::Bind(params, cb, srv);
|
||||
|
||||
// Setup parameters
|
||||
MaterialParameter::BindMeta bindMeta;
|
||||
bindMeta.Context = context;
|
||||
bindMeta.Constants = cb;
|
||||
bindMeta.Input = nullptr;
|
||||
bindMeta.Buffers = nullptr;
|
||||
bindMeta.CanSampleDepth = false;
|
||||
bindMeta.CanSampleGBuffer = false;
|
||||
MaterialParams::Bind(params.ParamsLink, bindMeta);
|
||||
|
||||
// Setup material constants
|
||||
{
|
||||
Matrix::Transpose(view.Frustum.GetMatrix(), materialData->ViewProjectionMatrix);
|
||||
Matrix::Transpose(drawCall.World, materialData->WorldMatrix);
|
||||
Matrix::Transpose(drawCall.Deformable.LocalMatrix, materialData->LocalMatrix);
|
||||
Matrix::Transpose(view.View, materialData->ViewMatrix);
|
||||
materialData->ViewPos = view.Position;
|
||||
materialData->ViewFar = view.Far;
|
||||
materialData->ViewDir = view.Direction;
|
||||
materialData->TimeParam = Time::Draw.UnscaledTime.GetTotalSeconds();
|
||||
materialData->ViewInfo = view.ViewInfo;
|
||||
materialData->ScreenSize = view.ScreenSize;
|
||||
const float scaleX = Vector3(drawCall.World.M11, drawCall.World.M12, drawCall.World.M13).Length();
|
||||
const float scaleY = Vector3(drawCall.World.M21, drawCall.World.M22, drawCall.World.M23).Length();
|
||||
const float scaleZ = Vector3(drawCall.World.M31, drawCall.World.M32, drawCall.World.M33).Length();
|
||||
materialData->WorldInvScale = Vector3(
|
||||
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->Segment = drawCall.Deformable.Segment;
|
||||
materialData->ChunksPerSegment = drawCall.Deformable.ChunksPerSegment;
|
||||
materialData->MeshMinZ = drawCall.Deformable.MeshMinZ;
|
||||
materialData->MeshMaxZ = drawCall.Deformable.MeshMaxZ;
|
||||
materialData->PerInstanceRandom = drawCall.PerInstanceRandom;
|
||||
materialData->TemporalAAJitter = view.TemporalAAJitter;
|
||||
materialData->GeometrySize = drawCall.Deformable.GeometrySize;
|
||||
}
|
||||
|
||||
// Bind spline deformation buffer
|
||||
context->BindSR(0, drawCall.Deformable.SplineDeformation->View());
|
||||
|
||||
// Bind constants
|
||||
if (_cb)
|
||||
{
|
||||
context->UpdateCB(_cb, _cbData.Get());
|
||||
context->BindCB(0, _cb);
|
||||
}
|
||||
|
||||
// Select pipeline state based on current pass and render mode
|
||||
const bool wireframe = (_info.FeaturesFlags & MaterialFeaturesFlags::Wireframe) != 0 || view.Mode == ViewMode::Wireframe;
|
||||
CullMode cullMode = view.Pass == DrawPass::Depth ? CullMode::TwoSided : _info.CullMode;
|
||||
if (cullMode != CullMode::TwoSided && drawCall.WorldDeterminantSign < 0)
|
||||
{
|
||||
// Invert culling when scale is negative
|
||||
if (cullMode == CullMode::Normal)
|
||||
cullMode = CullMode::Inverted;
|
||||
else
|
||||
cullMode = CullMode::Normal;
|
||||
}
|
||||
PipelineStateCache* psCache = _cache.GetPS(view.Pass);
|
||||
ASSERT(psCache);
|
||||
GPUPipelineState* state = psCache->GetPS(cullMode, wireframe);
|
||||
|
||||
// Bind pipeline
|
||||
context->SetState(state);
|
||||
}
|
||||
|
||||
void DeformableMaterialShader::Unload()
|
||||
{
|
||||
// Base
|
||||
MaterialShader::Unload();
|
||||
|
||||
_cache.Release();
|
||||
}
|
||||
|
||||
bool DeformableMaterialShader::Load()
|
||||
{
|
||||
_drawModes = DrawPass::Depth;
|
||||
auto psDesc = GPUPipelineState::Description::Default;
|
||||
psDesc.DepthTestEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == 0;
|
||||
psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == 0;
|
||||
|
||||
// Check if use tessellation (both material and runtime supports it)
|
||||
const bool useTess = _info.TessellationMode != TessellationMethod::None && GPUDevice::Instance->Limits.HasTessellation;
|
||||
if (useTess)
|
||||
{
|
||||
psDesc.HS = _shader->GetHS("HS");
|
||||
psDesc.DS = _shader->GetDS("DS");
|
||||
}
|
||||
|
||||
if (_info.BlendMode == MaterialBlendMode::Opaque)
|
||||
{
|
||||
_drawModes = DrawPass::GBuffer;
|
||||
|
||||
// GBuffer Pass
|
||||
psDesc.VS = _shader->GetVS("VS_SplineModel");
|
||||
psDesc.PS = _shader->GetPS("PS_GBuffer");
|
||||
_cache.Default.Init(psDesc);
|
||||
}
|
||||
else
|
||||
{
|
||||
_drawModes = DrawPass::Forward;
|
||||
|
||||
// Forward Pass
|
||||
psDesc.VS = _shader->GetVS("VS_SplineModel");
|
||||
psDesc.PS = _shader->GetPS("PS_Forward");
|
||||
psDesc.DepthWriteEnable = false;
|
||||
psDesc.BlendMode = BlendingMode::AlphaBlend;
|
||||
switch (_info.BlendMode)
|
||||
{
|
||||
case MaterialBlendMode::Transparent:
|
||||
psDesc.BlendMode = BlendingMode::AlphaBlend;
|
||||
break;
|
||||
case MaterialBlendMode::Additive:
|
||||
psDesc.BlendMode = BlendingMode::Additive;
|
||||
break;
|
||||
case MaterialBlendMode::Multiply:
|
||||
psDesc.BlendMode = BlendingMode::Multiply;
|
||||
break;
|
||||
}
|
||||
_cache.Default.Init(psDesc);
|
||||
}
|
||||
|
||||
// Depth Pass
|
||||
psDesc.CullMode = CullMode::TwoSided;
|
||||
psDesc.DepthClipEnable = false;
|
||||
psDesc.DepthWriteEnable = true;
|
||||
psDesc.DepthTestEnable = true;
|
||||
psDesc.DepthFunc = ComparisonFunc::Less;
|
||||
psDesc.HS = nullptr;
|
||||
psDesc.DS = nullptr;
|
||||
_cache.Depth.Init(psDesc);
|
||||
|
||||
return false;
|
||||
}
|
||||
63
Source/Engine/Graphics/Materials/DeformableMaterialShader.h
Normal file
63
Source/Engine/Graphics/Materials/DeformableMaterialShader.h
Normal file
@@ -0,0 +1,63 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "MaterialShader.h"
|
||||
|
||||
/// <summary>
|
||||
/// Represents material that can be used to render objects that can be deformed.
|
||||
/// </summary>
|
||||
class DeformableMaterialShader : public MaterialShader
|
||||
{
|
||||
private:
|
||||
|
||||
struct Cache
|
||||
{
|
||||
PipelineStateCache Default;
|
||||
PipelineStateCache Depth;
|
||||
|
||||
FORCE_INLINE PipelineStateCache* GetPS(const DrawPass pass)
|
||||
{
|
||||
switch (pass)
|
||||
{
|
||||
case DrawPass::Depth:
|
||||
return &Depth;
|
||||
case DrawPass::GBuffer:
|
||||
case DrawPass::Forward:
|
||||
return &Default;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
FORCE_INLINE void Release()
|
||||
{
|
||||
Default.Release();
|
||||
Depth.Release();
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
Cache _cache;
|
||||
DrawPass _drawModes = DrawPass::None;
|
||||
|
||||
public:
|
||||
|
||||
DeformableMaterialShader(const String& name)
|
||||
: MaterialShader(name)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// [MaterialShader]
|
||||
DrawPass GetDrawModes() const override;
|
||||
void Bind(BindParameters& params) override;
|
||||
void Unload() override;
|
||||
|
||||
protected:
|
||||
|
||||
// [MaterialShader]
|
||||
bool Load() override;
|
||||
};
|
||||
@@ -74,6 +74,14 @@ public:
|
||||
return GetInfo().Domain == MaterialDomain::Particle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether material is a deformable shader.
|
||||
/// </summary>
|
||||
FORCE_INLINE bool IsDeformable() const
|
||||
{
|
||||
return GetInfo().Domain == MaterialDomain::Deformable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if material is ready for rendering.
|
||||
/// </summary>
|
||||
|
||||
@@ -39,6 +39,11 @@ API_ENUM() enum class MaterialDomain : byte
|
||||
/// The particle shader. Can be used only with particles geometry (sprites, trails and ribbons). Supports reading particle data on a GPU.
|
||||
/// </summary>
|
||||
Particle = 5,
|
||||
|
||||
/// <summary>
|
||||
/// The deformable shader. Can be used only with objects that can be deformed (spline models).
|
||||
/// </summary>
|
||||
Deformable = 6,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include "GUIMaterialShader.h"
|
||||
#include "TerrainMaterialShader.h"
|
||||
#include "ParticleMaterialShader.h"
|
||||
//#include "DeformableMaterialShader.h"
|
||||
#include "DeformableMaterialShader.h"
|
||||
|
||||
GPUPipelineState* MaterialShader::PipelineStateCache::InitPS(CullMode mode, bool wireframe)
|
||||
{
|
||||
@@ -62,9 +62,9 @@ MaterialShader* MaterialShader::Create(const String& name, MemoryReadStream& sha
|
||||
case MaterialDomain::Particle:
|
||||
material = New<ParticleMaterialShader>(name);
|
||||
break;
|
||||
/*case MaterialDomain::Deformable:
|
||||
material = New<DeformableMaterialShader>(name);
|
||||
break;*/
|
||||
case MaterialDomain::Deformable:
|
||||
material = New<DeformableMaterialShader>(name);
|
||||
break;
|
||||
default:
|
||||
LOG(Fatal, "Unknown material type.");
|
||||
return nullptr;
|
||||
|
||||
@@ -350,7 +350,7 @@ bool Mesh::Intersects(const Ray& ray, const Matrix& world, float& distance, Vect
|
||||
#endif
|
||||
}
|
||||
|
||||
void Mesh::GetDrawCallGeometry(DrawCall& drawCall)
|
||||
void Mesh::GetDrawCallGeometry(DrawCall& drawCall) const
|
||||
{
|
||||
drawCall.Geometry.IndexBuffer = _indexBuffer;
|
||||
drawCall.Geometry.VertexBuffers[0] = _vertexBuffers[0];
|
||||
|
||||
@@ -377,7 +377,7 @@ public:
|
||||
/// Gets the draw call geometry for this mesh. Sets the index and vertex buffers.
|
||||
/// </summary>
|
||||
/// <param name="drawCall">The draw call.</param>
|
||||
void GetDrawCallGeometry(DrawCall& drawCall);
|
||||
void GetDrawCallGeometry(DrawCall& drawCall) const;
|
||||
|
||||
/// <summary>
|
||||
/// Model instance drawing packed data.
|
||||
|
||||
Reference in New Issue
Block a user