Add Deformable material domain
This commit is contained in:
375
Content/Editor/MaterialTemplates/Deformable.shader
Normal file
375
Content/Editor/MaterialTemplates/Deformable.shader
Normal file
@@ -0,0 +1,375 @@
|
|||||||
|
// File generated by Flax Materials Editor
|
||||||
|
// Version: @0
|
||||||
|
|
||||||
|
#define MATERIAL 1
|
||||||
|
@3
|
||||||
|
#include "./Flax/Common.hlsl"
|
||||||
|
#include "./Flax/MaterialCommon.hlsl"
|
||||||
|
#include "./Flax/GBufferCommon.hlsl"
|
||||||
|
@7
|
||||||
|
// Primary constant buffer (with additional material parameters)
|
||||||
|
META_CB_BEGIN(0, Data)
|
||||||
|
float4x4 ViewProjectionMatrix;
|
||||||
|
float4x4 WorldMatrix;
|
||||||
|
float4x4 LocalMatrix;
|
||||||
|
float4x4 ViewMatrix;
|
||||||
|
float3 ViewPos;
|
||||||
|
float ViewFar;
|
||||||
|
float3 ViewDir;
|
||||||
|
float TimeParam;
|
||||||
|
float4 ViewInfo;
|
||||||
|
float4 ScreenSize;
|
||||||
|
float3 WorldInvScale;
|
||||||
|
float WorldDeterminantSign;
|
||||||
|
float MeshMinZ;
|
||||||
|
float Segment;
|
||||||
|
float ChunksPerSegment;
|
||||||
|
float PerInstanceRandom;
|
||||||
|
float4 TemporalAAJitter;
|
||||||
|
float3 GeometrySize;
|
||||||
|
float MeshMaxZ;
|
||||||
|
@1META_CB_END
|
||||||
|
|
||||||
|
// Shader resources
|
||||||
|
@2
|
||||||
|
// The spline deformation buffer (stored as 4x3, 3 float4 behind each other)
|
||||||
|
Buffer<float4> SplineDeformation : register(t0);
|
||||||
|
|
||||||
|
// Geometry data passed though the graphics rendering stages up to the pixel shader
|
||||||
|
struct GeometryData
|
||||||
|
{
|
||||||
|
float3 WorldPosition : TEXCOORD0;
|
||||||
|
float2 TexCoord : TEXCOORD1;
|
||||||
|
#if USE_VERTEX_COLOR
|
||||||
|
half4 VertexColor : COLOR;
|
||||||
|
#endif
|
||||||
|
float3 WorldNormal : TEXCOORD2;
|
||||||
|
float4 WorldTangent : TEXCOORD3;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Interpolants passed from the vertex shader
|
||||||
|
struct VertexOutput
|
||||||
|
{
|
||||||
|
float4 Position : SV_Position;
|
||||||
|
GeometryData Geometry;
|
||||||
|
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||||
|
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
||||||
|
#endif
|
||||||
|
#if USE_TESSELLATION
|
||||||
|
float TessellationMultiplier : TESS;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
// Interpolants passed to the pixel shader
|
||||||
|
struct PixelInput
|
||||||
|
{
|
||||||
|
float4 Position : SV_Position;
|
||||||
|
GeometryData Geometry;
|
||||||
|
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||||
|
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
||||||
|
#endif
|
||||||
|
bool IsFrontFace : SV_IsFrontFace;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Material properties generation input
|
||||||
|
struct MaterialInput
|
||||||
|
{
|
||||||
|
float3 WorldPosition;
|
||||||
|
float TwoSidedSign;
|
||||||
|
float2 TexCoord;
|
||||||
|
#if USE_VERTEX_COLOR
|
||||||
|
half4 VertexColor;
|
||||||
|
#endif
|
||||||
|
float3x3 TBN;
|
||||||
|
float4 SvPosition;
|
||||||
|
float3 PreSkinnedPosition;
|
||||||
|
float3 PreSkinnedNormal;
|
||||||
|
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||||
|
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT];
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
// Extracts geometry data to the material input
|
||||||
|
MaterialInput GetGeometryMaterialInput(GeometryData geometry)
|
||||||
|
{
|
||||||
|
MaterialInput output = (MaterialInput)0;
|
||||||
|
output.WorldPosition = geometry.WorldPosition;
|
||||||
|
output.TexCoord = geometry.TexCoord;
|
||||||
|
#if USE_VERTEX_COLOR
|
||||||
|
output.VertexColor = geometry.VertexColor;
|
||||||
|
#endif
|
||||||
|
output.TBN = CalcTangentBasis(geometry.WorldNormal, geometry.WorldTangent);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if USE_TESSELLATION
|
||||||
|
|
||||||
|
// Interpolates the geometry positions data only (used by the tessallation when generating vertices)
|
||||||
|
#define InterpolateGeometryPositions(output, p0, w0, p1, w1, p2, w2, offset) output.WorldPosition = p0.WorldPosition * w0 + p1.WorldPosition * w1 + p2.WorldPosition * w2 + offset
|
||||||
|
|
||||||
|
// Offsets the geometry positions data only (used by the tessallation when generating vertices)
|
||||||
|
#define OffsetGeometryPositions(geometry, offset) geometry.WorldPosition += offset
|
||||||
|
|
||||||
|
// Applies the Phong tessallation to the geometry positions (used by the tessallation when doing Phong tess)
|
||||||
|
#define ApplyGeometryPositionsPhongTess(geometry, p0, p1, p2, U, V, W) \
|
||||||
|
float3 posProjectedU = TessalationProjectOntoPlane(p0.WorldNormal, p0.WorldPosition, geometry.WorldPosition); \
|
||||||
|
float3 posProjectedV = TessalationProjectOntoPlane(p1.WorldNormal, p1.WorldPosition, geometry.WorldPosition); \
|
||||||
|
float3 posProjectedW = TessalationProjectOntoPlane(p2.WorldNormal, p2.WorldPosition, geometry.WorldPosition); \
|
||||||
|
geometry.WorldPosition = U * posProjectedU + V * posProjectedV + W * posProjectedW
|
||||||
|
|
||||||
|
// Interpolates the geometry data except positions (used by the tessallation when generating vertices)
|
||||||
|
GeometryData InterpolateGeometry(GeometryData p0, float w0, GeometryData p1, float w1, GeometryData p2, float w2)
|
||||||
|
{
|
||||||
|
GeometryData output = (GeometryData)0;
|
||||||
|
output.TexCoord = p0.TexCoord * w0 + p1.TexCoord * w1 + p2.TexCoord * w2;
|
||||||
|
#if USE_VERTEX_COLOR
|
||||||
|
output.VertexColor = p0.VertexColor * w0 + p1.VertexColor * w1 + p2.VertexColor * w2;
|
||||||
|
#endif
|
||||||
|
output.WorldNormal = p0.WorldNormal * w0 + p1.WorldNormal * w1 + p2.WorldNormal * w2;
|
||||||
|
output.WorldNormal = normalize(output.WorldNormal);
|
||||||
|
output.WorldTangent = p0.WorldTangent * w0 + p1.WorldTangent * w1 + p2.WorldTangent * w2;
|
||||||
|
output.WorldTangent.xyz = normalize(output.WorldTangent.xyz);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
MaterialInput GetMaterialInput(PixelInput input)
|
||||||
|
{
|
||||||
|
MaterialInput output = GetGeometryMaterialInput(input.Geometry);
|
||||||
|
output.TwoSidedSign = WorldDeterminantSign * (input.IsFrontFace ? 1.0 : -1.0);
|
||||||
|
output.SvPosition = input.Position;
|
||||||
|
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||||
|
output.CustomVSToPS = input.CustomVSToPS;
|
||||||
|
#endif
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removes the scale vector from the local to world transformation matrix
|
||||||
|
float3x3 RemoveScaleFromLocalToWorld(float3x3 localToWorld)
|
||||||
|
{
|
||||||
|
localToWorld[0] *= WorldInvScale.x;
|
||||||
|
localToWorld[1] *= WorldInvScale.y;
|
||||||
|
localToWorld[2] *= WorldInvScale.z;
|
||||||
|
return localToWorld;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transforms a vector from tangent space to world space
|
||||||
|
float3 TransformTangentVectorToWorld(MaterialInput input, float3 tangentVector)
|
||||||
|
{
|
||||||
|
return mul(tangentVector, input.TBN);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transforms a vector from world space to tangent space
|
||||||
|
float3 TransformWorldVectorToTangent(MaterialInput input, float3 worldVector)
|
||||||
|
{
|
||||||
|
return mul(input.TBN, worldVector);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transforms a vector from world space to view space
|
||||||
|
float3 TransformWorldVectorToView(MaterialInput input, float3 worldVector)
|
||||||
|
{
|
||||||
|
return mul(worldVector, (float3x3)ViewMatrix);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transforms a vector from view space to world space
|
||||||
|
float3 TransformViewVectorToWorld(MaterialInput input, float3 viewVector)
|
||||||
|
{
|
||||||
|
return mul((float3x3)ViewMatrix, viewVector);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transforms a vector from local space to world space
|
||||||
|
float3 TransformLocalVectorToWorld(MaterialInput input, float3 localVector)
|
||||||
|
{
|
||||||
|
float3x3 localToWorld = (float3x3)WorldMatrix;
|
||||||
|
//localToWorld = RemoveScaleFromLocalToWorld(localToWorld);
|
||||||
|
return mul(localVector, localToWorld);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transforms a vector from local space to world space
|
||||||
|
float3 TransformWorldVectorToLocal(MaterialInput input, float3 worldVector)
|
||||||
|
{
|
||||||
|
float3x3 localToWorld = (float3x3)WorldMatrix;
|
||||||
|
//localToWorld = RemoveScaleFromLocalToWorld(localToWorld);
|
||||||
|
return mul(localToWorld, worldVector);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets the current object position
|
||||||
|
float3 GetObjectPosition(MaterialInput input)
|
||||||
|
{
|
||||||
|
return WorldMatrix[3].xyz;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets the current object size
|
||||||
|
float3 GetObjectSize(MaterialInput input)
|
||||||
|
{
|
||||||
|
float4x4 world = WorldMatrix;
|
||||||
|
return GeometrySize * float3(world._m00, world._m11, world._m22);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the current object random value
|
||||||
|
float GetPerInstanceRandom(MaterialInput input)
|
||||||
|
{
|
||||||
|
return PerInstanceRandom;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the current object LOD transition dither factor
|
||||||
|
float GetLODDitherFactor(MaterialInput input)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets the interpolated vertex color (in linear space)
|
||||||
|
float4 GetVertexColor(MaterialInput input)
|
||||||
|
{
|
||||||
|
#if USE_VERTEX_COLOR
|
||||||
|
return input.VertexColor;
|
||||||
|
#else
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 SampleLightmap(Material material, MaterialInput materialInput)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@8
|
||||||
|
|
||||||
|
// Get material properties function (for vertex shader)
|
||||||
|
Material GetMaterialVS(MaterialInput input)
|
||||||
|
{
|
||||||
|
@5
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get material properties function (for domain shader)
|
||||||
|
Material GetMaterialDS(MaterialInput input)
|
||||||
|
{
|
||||||
|
@6
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get material properties function (for pixel shader)
|
||||||
|
Material GetMaterialPS(MaterialInput input)
|
||||||
|
{
|
||||||
|
@4
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculates the transform matrix from mesh tangent space to local space
|
||||||
|
float3x3 CalcTangentToLocal(ModelInput input)
|
||||||
|
{
|
||||||
|
float bitangentSign = input.Tangent.w ? -1.0f : +1.0f;
|
||||||
|
float3 normal = input.Normal.xyz * 2.0 - 1.0;
|
||||||
|
float3 tangent = input.Tangent.xyz * 2.0 - 1.0;
|
||||||
|
float3 bitangent = cross(normal, tangent) * bitangentSign;
|
||||||
|
return float3x3(tangent, bitangent, normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vertex Shader function for GBuffer Pass and Depth Pass (with full vertex data)
|
||||||
|
META_VS(true, FEATURE_LEVEL_ES2)
|
||||||
|
META_VS_IN_ELEMENT(POSITION, 0, R32G32B32_FLOAT, 0, 0, PER_VERTEX, 0, true)
|
||||||
|
META_VS_IN_ELEMENT(TEXCOORD, 0, R16G16_FLOAT, 1, 0, PER_VERTEX, 0, true)
|
||||||
|
META_VS_IN_ELEMENT(NORMAL, 0, R10G10B10A2_UNORM, 1, ALIGN, PER_VERTEX, 0, true)
|
||||||
|
META_VS_IN_ELEMENT(TANGENT, 0, R10G10B10A2_UNORM, 1, ALIGN, PER_VERTEX, 0, true)
|
||||||
|
META_VS_IN_ELEMENT(TEXCOORD, 1, R16G16_FLOAT, 1, ALIGN, PER_VERTEX, 0, true)
|
||||||
|
META_VS_IN_ELEMENT(COLOR, 0, R8G8B8A8_UNORM, 2, 0, PER_VERTEX, 0, USE_VERTEX_COLOR)
|
||||||
|
VertexOutput VS_SplineModel(ModelInput input)
|
||||||
|
{
|
||||||
|
VertexOutput output;
|
||||||
|
|
||||||
|
// Apply local transformation of the geometry before deformation
|
||||||
|
float3 position = mul(float4(input.Position, 1), LocalMatrix).xyz;
|
||||||
|
|
||||||
|
// Apply spline curve deformation
|
||||||
|
float splineAlpha = saturate((position.z - MeshMinZ) / (MeshMaxZ - MeshMinZ));
|
||||||
|
int splineIndex = (int)((Segment + splineAlpha) * ChunksPerSegment);
|
||||||
|
position.z = splineAlpha;
|
||||||
|
float3x4 splineMatrix = float3x4(SplineDeformation[splineIndex * 3], SplineDeformation[splineIndex * 3 + 1], SplineDeformation[splineIndex * 3 + 2]);
|
||||||
|
position = mul(splineMatrix, float4(position, 1));
|
||||||
|
|
||||||
|
// Compute world space vertex position
|
||||||
|
output.Geometry.WorldPosition = mul(float4(position, 1), WorldMatrix).xyz;
|
||||||
|
|
||||||
|
// Compute clip space position
|
||||||
|
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
||||||
|
|
||||||
|
// Pass vertex attributes
|
||||||
|
output.Geometry.TexCoord = input.TexCoord;
|
||||||
|
#if USE_VERTEX_COLOR
|
||||||
|
output.Geometry.VertexColor = input.Color;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Calculate tanget space to world space transformation matrix for unit vectors
|
||||||
|
float3x3 tangentToLocal = CalcTangentToLocal(input);
|
||||||
|
float3x3 localToWorld = RemoveScaleFromLocalToWorld((float3x3)WorldMatrix);
|
||||||
|
float3x3 tangentToWorld = mul(tangentToLocal, localToWorld);
|
||||||
|
output.Geometry.WorldNormal = tangentToWorld[2];
|
||||||
|
output.Geometry.WorldTangent.xyz = tangentToWorld[0];
|
||||||
|
output.Geometry.WorldTangent.w = input.Tangent.w ? -1.0f : +1.0f;
|
||||||
|
|
||||||
|
// Get material input params if need to evaluate any material property
|
||||||
|
#if USE_POSITION_OFFSET || USE_TESSELLATION || USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||||
|
MaterialInput materialInput = GetGeometryMaterialInput(output.Geometry);
|
||||||
|
materialInput.TwoSidedSign = WorldDeterminantSign;
|
||||||
|
materialInput.SvPosition = output.Position;
|
||||||
|
materialInput.PreSkinnedPosition = input.Position.xyz;
|
||||||
|
materialInput.PreSkinnedNormal = tangentToLocal[2].xyz;
|
||||||
|
Material material = GetMaterialVS(materialInput);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Apply world position offset per-vertex
|
||||||
|
#if USE_POSITION_OFFSET
|
||||||
|
output.Geometry.WorldPosition += material.PositionOffset;
|
||||||
|
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Get tessalation multiplier (per vertex)
|
||||||
|
#if USE_TESSELLATION
|
||||||
|
output.TessellationMultiplier = material.TessellationMultiplier;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Copy interpolants for other shader stages
|
||||||
|
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||||
|
output.CustomVSToPS = material.CustomVSToPS;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vertex Shader function for Depth Pass
|
||||||
|
META_VS(true, FEATURE_LEVEL_ES2)
|
||||||
|
META_VS_IN_ELEMENT(POSITION, 0, R32G32B32_FLOAT, 0, 0, PER_VERTEX, 0, true)
|
||||||
|
float4 VS_Depth(ModelInput_PosOnly input) : SV_Position
|
||||||
|
{
|
||||||
|
float3 worldPosition = mul(float4(input.Position.xyz, 1), WorldMatrix).xyz;
|
||||||
|
float4 position = mul(float4(worldPosition, 1), ViewProjectionMatrix);
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if USE_DITHERED_LOD_TRANSITION
|
||||||
|
|
||||||
|
void ClipLODTransition(PixelInput input)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Pixel Shader function for Depth Pass
|
||||||
|
META_PS(true, FEATURE_LEVEL_ES2)
|
||||||
|
void PS_Depth(PixelInput input)
|
||||||
|
{
|
||||||
|
#if MATERIAL_MASKED || MATERIAL_BLEND != MATERIAL_BLEND_OPAQUE
|
||||||
|
// Get material parameters
|
||||||
|
MaterialInput materialInput = GetMaterialInput(input);
|
||||||
|
Material material = GetMaterialPS(materialInput);
|
||||||
|
|
||||||
|
// Perform per pixel clipping
|
||||||
|
#if MATERIAL_MASKED
|
||||||
|
clip(material.Mask - MATERIAL_MASK_THRESHOLD);
|
||||||
|
#endif
|
||||||
|
#if MATERIAL_BLEND != MATERIAL_BLEND_OPAQUE
|
||||||
|
clip(material.Opacity - MATERIAL_OPACITY_THRESHOLD);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
@9
|
||||||
@@ -156,6 +156,7 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
case MaterialDomain.Surface:
|
case MaterialDomain.Surface:
|
||||||
case MaterialDomain.Terrain:
|
case MaterialDomain.Terrain:
|
||||||
case MaterialDomain.Particle:
|
case MaterialDomain.Particle:
|
||||||
|
case MaterialDomain.Deformable:
|
||||||
{
|
{
|
||||||
bool isNotUnlit = info.ShadingModel != MaterialShadingModel.Unlit;
|
bool isNotUnlit = info.ShadingModel != MaterialShadingModel.Unlit;
|
||||||
bool isTransparent = info.BlendMode == MaterialBlendMode.Transparent;
|
bool isTransparent = info.BlendMode == MaterialBlendMode.Transparent;
|
||||||
|
|||||||
@@ -172,6 +172,9 @@ namespace FlaxEditor.Viewport.Previews
|
|||||||
usePreviewActor = false;
|
usePreviewActor = false;
|
||||||
particleMaterial = _material;
|
particleMaterial = _material;
|
||||||
break;
|
break;
|
||||||
|
case MaterialDomain.Deformable:
|
||||||
|
// TODO: preview Deformable material (eg. by using Spline with Spline Model)
|
||||||
|
break;
|
||||||
default: throw new ArgumentOutOfRangeException();
|
default: throw new ArgumentOutOfRangeException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -392,12 +392,12 @@ void Material::InitCompilationOptions(ShaderCompilationOptions& options)
|
|||||||
auto& info = _shaderHeader.Material.Info;
|
auto& info = _shaderHeader.Material.Info;
|
||||||
const bool isSurfaceOrTerrain = info.Domain == MaterialDomain::Surface || info.Domain == MaterialDomain::Terrain;
|
const bool isSurfaceOrTerrain = info.Domain == MaterialDomain::Surface || info.Domain == MaterialDomain::Terrain;
|
||||||
const bool useCustomData = info.ShadingModel == MaterialShadingModel::Subsurface || info.ShadingModel == MaterialShadingModel::Foliage;
|
const bool useCustomData = info.ShadingModel == MaterialShadingModel::Subsurface || info.ShadingModel == MaterialShadingModel::Foliage;
|
||||||
const bool useForward = (info.Domain == MaterialDomain::Surface && info.BlendMode != MaterialBlendMode::Opaque) || info.Domain == MaterialDomain::Particle;
|
const bool useForward = ((info.Domain == MaterialDomain::Surface || info.Domain == MaterialDomain::Deformable) && info.BlendMode != MaterialBlendMode::Opaque) || info.Domain == MaterialDomain::Particle;
|
||||||
const bool useTess =
|
const bool useTess =
|
||||||
info.TessellationMode != TessellationMethod::None &&
|
info.TessellationMode != TessellationMethod::None &&
|
||||||
RenderTools::CanSupportTessellation(options.Profile) && isSurfaceOrTerrain;
|
RenderTools::CanSupportTessellation(options.Profile) && isSurfaceOrTerrain;
|
||||||
const bool useDistortion =
|
const bool useDistortion =
|
||||||
(info.Domain == MaterialDomain::Surface || info.Domain == MaterialDomain::Particle) &&
|
(info.Domain == MaterialDomain::Surface || info.Domain == MaterialDomain::Deformable || info.Domain == MaterialDomain::Particle) &&
|
||||||
info.BlendMode != MaterialBlendMode::Opaque &&
|
info.BlendMode != MaterialBlendMode::Opaque &&
|
||||||
(info.UsageFlags & MaterialUsageFlags::UseRefraction) != 0 &&
|
(info.UsageFlags & MaterialUsageFlags::UseRefraction) != 0 &&
|
||||||
(info.FeaturesFlags & MaterialFeaturesFlags::DisableDistortion) == 0;
|
(info.FeaturesFlags & MaterialFeaturesFlags::DisableDistortion) == 0;
|
||||||
@@ -455,6 +455,7 @@ void Material::InitCompilationOptions(ShaderCompilationOptions& options)
|
|||||||
options.Macros.Add({ "IS_DECAL", Numbers[info.Domain == MaterialDomain::Decal ? 1 : 0] });
|
options.Macros.Add({ "IS_DECAL", Numbers[info.Domain == MaterialDomain::Decal ? 1 : 0] });
|
||||||
options.Macros.Add({ "IS_TERRAIN", Numbers[info.Domain == MaterialDomain::Terrain ? 1 : 0] });
|
options.Macros.Add({ "IS_TERRAIN", Numbers[info.Domain == MaterialDomain::Terrain ? 1 : 0] });
|
||||||
options.Macros.Add({ "IS_PARTICLE", Numbers[info.Domain == MaterialDomain::Particle ? 1 : 0] });
|
options.Macros.Add({ "IS_PARTICLE", Numbers[info.Domain == MaterialDomain::Particle ? 1 : 0] });
|
||||||
|
options.Macros.Add({ "IS_DEFORMABLE", Numbers[info.Domain == MaterialDomain::Deformable ? 1 : 0] });
|
||||||
options.Macros.Add({ "USE_FORWARD", Numbers[useForward ? 1 : 0] });
|
options.Macros.Add({ "USE_FORWARD", Numbers[useForward ? 1 : 0] });
|
||||||
options.Macros.Add({ "USE_DEFERRED", Numbers[isSurfaceOrTerrain && info.BlendMode == MaterialBlendMode::Opaque ? 1 : 0] });
|
options.Macros.Add({ "USE_DEFERRED", Numbers[isSurfaceOrTerrain && info.BlendMode == MaterialBlendMode::Opaque ? 1 : 0] });
|
||||||
options.Macros.Add({ "USE_DISTORTION", Numbers[useDistortion ? 1 : 0] });
|
options.Macros.Add({ "USE_DISTORTION", Numbers[useDistortion ? 1 : 0] });
|
||||||
|
|||||||
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;
|
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>
|
/// <summary>
|
||||||
/// Returns true if material is ready for rendering.
|
/// Returns true if material is ready for rendering.
|
||||||
/// </summary>
|
/// </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.
|
/// The particle shader. Can be used only with particles geometry (sprites, trails and ribbons). Supports reading particle data on a GPU.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Particle = 5,
|
Particle = 5,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The deformable shader. Can be used only with objects that can be deformed (spline models).
|
||||||
|
/// </summary>
|
||||||
|
Deformable = 6,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
#include "GUIMaterialShader.h"
|
#include "GUIMaterialShader.h"
|
||||||
#include "TerrainMaterialShader.h"
|
#include "TerrainMaterialShader.h"
|
||||||
#include "ParticleMaterialShader.h"
|
#include "ParticleMaterialShader.h"
|
||||||
//#include "DeformableMaterialShader.h"
|
#include "DeformableMaterialShader.h"
|
||||||
|
|
||||||
GPUPipelineState* MaterialShader::PipelineStateCache::InitPS(CullMode mode, bool wireframe)
|
GPUPipelineState* MaterialShader::PipelineStateCache::InitPS(CullMode mode, bool wireframe)
|
||||||
{
|
{
|
||||||
@@ -62,9 +62,9 @@ MaterialShader* MaterialShader::Create(const String& name, MemoryReadStream& sha
|
|||||||
case MaterialDomain::Particle:
|
case MaterialDomain::Particle:
|
||||||
material = New<ParticleMaterialShader>(name);
|
material = New<ParticleMaterialShader>(name);
|
||||||
break;
|
break;
|
||||||
/*case MaterialDomain::Deformable:
|
case MaterialDomain::Deformable:
|
||||||
material = New<DeformableMaterialShader>(name);
|
material = New<DeformableMaterialShader>(name);
|
||||||
break;*/
|
break;
|
||||||
default:
|
default:
|
||||||
LOG(Fatal, "Unknown material type.");
|
LOG(Fatal, "Unknown material type.");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|||||||
@@ -350,7 +350,7 @@ bool Mesh::Intersects(const Ray& ray, const Matrix& world, float& distance, Vect
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mesh::GetDrawCallGeometry(DrawCall& drawCall)
|
void Mesh::GetDrawCallGeometry(DrawCall& drawCall) const
|
||||||
{
|
{
|
||||||
drawCall.Geometry.IndexBuffer = _indexBuffer;
|
drawCall.Geometry.IndexBuffer = _indexBuffer;
|
||||||
drawCall.Geometry.VertexBuffers[0] = _vertexBuffers[0];
|
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.
|
/// Gets the draw call geometry for this mesh. Sets the index and vertex buffers.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="drawCall">The draw call.</param>
|
/// <param name="drawCall">The draw call.</param>
|
||||||
void GetDrawCallGeometry(DrawCall& drawCall);
|
void GetDrawCallGeometry(DrawCall& drawCall) const;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Model instance drawing packed data.
|
/// Model instance drawing packed data.
|
||||||
|
|||||||
@@ -211,6 +211,17 @@ struct DrawCall
|
|||||||
} Ribbon;
|
} Ribbon;
|
||||||
} Particle;
|
} Particle;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
GPUBuffer* SplineDeformation;
|
||||||
|
Matrix LocalMatrix; // Geometry transformation applied before deformation.
|
||||||
|
Vector3 GeometrySize; // Object geometry size in the world (unscaled).
|
||||||
|
float Segment;
|
||||||
|
float ChunksPerSegment;
|
||||||
|
float MeshMinZ;
|
||||||
|
float MeshMaxZ;
|
||||||
|
} Deformable;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
byte Raw[96];
|
byte Raw[96];
|
||||||
|
|||||||
@@ -206,6 +206,14 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
|
|||||||
ADD_FEATURE(DistortionFeature);
|
ADD_FEATURE(DistortionFeature);
|
||||||
ADD_FEATURE(ForwardShadingFeature);
|
ADD_FEATURE(ForwardShadingFeature);
|
||||||
break;
|
break;
|
||||||
|
case MaterialDomain::Deformable:
|
||||||
|
if (materialInfo.TessellationMode != TessellationMethod::None)
|
||||||
|
ADD_FEATURE(TessellationFeature);
|
||||||
|
if (materialInfo.BlendMode == MaterialBlendMode::Opaque)
|
||||||
|
ADD_FEATURE(DeferredShadingFeature);
|
||||||
|
if (materialInfo.BlendMode != MaterialBlendMode::Opaque)
|
||||||
|
ADD_FEATURE(ForwardShadingFeature);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -228,7 +236,7 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
|
|||||||
{
|
{
|
||||||
materialVarPS = Value(VariantType::Void, baseLayer->GetVariableName(nullptr));
|
materialVarPS = Value(VariantType::Void, baseLayer->GetVariableName(nullptr));
|
||||||
_writer.Write(TEXT("\tMaterial {0} = (Material)0;\n"), materialVarPS.Value);
|
_writer.Write(TEXT("\tMaterial {0} = (Material)0;\n"), materialVarPS.Value);
|
||||||
if (baseLayer->Domain == MaterialDomain::Surface || baseLayer->Domain == MaterialDomain::Terrain || baseLayer->Domain == MaterialDomain::Particle)
|
if (baseLayer->Domain == MaterialDomain::Surface || baseLayer->Domain == MaterialDomain::Terrain || baseLayer->Domain == MaterialDomain::Particle || baseLayer->Domain == MaterialDomain::Deformable)
|
||||||
{
|
{
|
||||||
eatMaterialGraphBox(baseLayer, MaterialGraphBoxes::Emissive);
|
eatMaterialGraphBox(baseLayer, MaterialGraphBoxes::Emissive);
|
||||||
eatMaterialGraphBox(baseLayer, MaterialGraphBoxes::Normal);
|
eatMaterialGraphBox(baseLayer, MaterialGraphBoxes::Normal);
|
||||||
@@ -410,6 +418,9 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
|
|||||||
case MaterialDomain::Particle:
|
case MaterialDomain::Particle:
|
||||||
srv = 2; // Particles data + Sorted indices/Ribbon segments
|
srv = 2; // Particles data + Sorted indices/Ribbon segments
|
||||||
break;
|
break;
|
||||||
|
case MaterialDomain::Deformable:
|
||||||
|
srv = 1; // Mesh deformation buffer
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
for (auto f : features)
|
for (auto f : features)
|
||||||
{
|
{
|
||||||
@@ -489,6 +500,9 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
|
|||||||
case MaterialDomain::Particle:
|
case MaterialDomain::Particle:
|
||||||
path /= TEXT("Particle.shader");
|
path /= TEXT("Particle.shader");
|
||||||
break;
|
break;
|
||||||
|
case MaterialDomain::Deformable:
|
||||||
|
path /= TEXT("Deformable.shader");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
LOG(Warning, "Unknown material domain.");
|
LOG(Warning, "Unknown material domain.");
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
Reference in New Issue
Block a user