Refactor material shaders generator to use modular features as extensions

This commit is contained in:
Wojtek Figat
2021-02-05 14:54:29 +01:00
parent 300f948515
commit d8304a2178
16 changed files with 185 additions and 259 deletions

View File

@@ -0,0 +1,44 @@
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
@0// Motion Vectors: Defines
@1// Motion Vectors: Includes
@2// Motion Vectors: Constants
@3// Motion Vectors: Resources
@4// Motion Vectors: Utilities
@5// Motion Vectors: Shaders
// Pixel Shader function for Motion Vectors Pass
META_PS(true, FEATURE_LEVEL_ES2)
float4 PS_MotionVectors(PixelInput input) : SV_Target0
{
#if USE_DITHERED_LOD_TRANSITION
// LOD masking
ClipLODTransition(input);
#endif
#if MATERIAL_MASKED
// Perform per pixel clipping if material requries it
MaterialInput materialInput = GetMaterialInput(input);
Material material = GetMaterialPS(materialInput);
clip(material.Mask - MATERIAL_MASK_THRESHOLD);
#endif
// Calculate this and previosu frame pixel locations in clip space
float4 prevClipPos = mul(float4(input.Geometry.PrevWorldPosition, 1), PrevViewProjectionMatrix);
float4 curClipPos = mul(float4(input.Geometry.WorldPosition, 1), ViewProjectionMatrix);
float2 prevHPos = prevClipPos.xy / prevClipPos.w;
float2 curHPos = curClipPos.xy / curClipPos.w;
// Revert temporal jitter offset
prevHPos -= TemporalAAJitter.zw;
curHPos -= TemporalAAJitter.xy;
// Clip Space -> UV Space
float2 vPosPrev = prevHPos.xy * 0.5f + 0.5f;
float2 vPosCur = curHPos.xy * 0.5f + 0.5f;
vPosPrev.y = 1.0 - vPosPrev.y;
vPosCur.y = 1.0 - vPosCur.y;
// Calculate per-pixel motion vector
return float4(vPosCur - vPosPrev, 0, 1);
}

View File

@@ -32,14 +32,13 @@ struct TessalationDSToPS
MaterialInput GetMaterialInput(TessalationDSToPS input)
{
MaterialInput result = (MaterialInput)0;
result.SvPosition = input.Position;
GetGeometryMaterialInput(result, input.Geometry);
result.TwoSidedSign = WorldDeterminantSign;
MaterialInput output = GetGeometryMaterialInput(input.Geometry);
output.SvPosition = input.Position;
output.TwoSidedSign = WorldDeterminantSign;
#if USE_CUSTOM_VERTEX_INTERPOLATORS
result.CustomVSToPS = input.CustomVSToPS;
output.CustomVSToPS = input.CustomVSToPS;
#endif
return result;
return output;
}
struct TessalationPatch

View File

@@ -141,14 +141,11 @@ MaterialInput GetMaterialInput(PixelInput input)
}
// Gets the local to world transform matrix (supports instancing)
float4x4 GetInstanceTransform(ModelInput input)
{
return WorldMatrix;
}
float4x4 GetInstanceTransform(MaterialInput input)
{
return WorldMatrix;
}
#if USE_INSTANCING
#define GetInstanceTransform(input) float4x4(float4(input.InstanceTransform1.xyz, 0.0f), float4(input.InstanceTransform2.xyz, 0.0f), float4(input.InstanceTransform3.xyz, 0.0f), float4(input.InstanceOrigin.xyz, 1.0f))
#else
#define GetInstanceTransform(input) WorldMatrix;
#endif
// Removes the scale vector from the local to world transformation matrix (supports instancing)
float3x3 RemoveScaleFromLocalToWorld(float3x3 localToWorld)

View File

@@ -101,19 +101,21 @@ struct MaterialInput
};
// Extracts geometry data to the material input
void GetGeometryMaterialInput(inout MaterialInput result, in GeometryData geometry)
MaterialInput GetGeometryMaterialInput(GeometryData geometry)
{
result.WorldPosition = geometry.WorldPosition;
result.TexCoord = geometry.TexCoord;
MaterialInput output = (MaterialInput)0;
output.WorldPosition = geometry.WorldPosition;
output.TexCoord = geometry.TexCoord;
#if USE_LIGHTMAP
result.LightmapUV = geometry.LightmapUV;
output.LightmapUV = geometry.LightmapUV;
#endif
#if USE_VERTEX_COLOR
result.VertexColor = geometry.VertexColor;
output.VertexColor = geometry.VertexColor;
#endif
result.TBN = CalcTangentBasis(geometry.WorldNormal, geometry.WorldTangent);
result.InstanceOrigin = geometry.InstanceOrigin;
result.InstanceParams = geometry.InstanceParams;
output.TBN = CalcTangentBasis(geometry.WorldNormal, geometry.WorldTangent);
output.InstanceOrigin = geometry.InstanceOrigin;
output.InstanceParams = geometry.InstanceParams;
return output;
}
#if USE_TESSELLATION
@@ -157,111 +159,23 @@ GeometryData InterpolateGeometry(GeometryData p0, float w0, GeometryData p1, flo
#endif
MaterialInput GetMaterialInput(ModelInput input, VertexOutput output, float3 localNormal)
{
MaterialInput result = (MaterialInput)0;
result.WorldPosition = output.Geometry.WorldPosition;
result.TexCoord = output.Geometry.TexCoord;
#if USE_LIGHTMAP
result.LightmapUV = output.Geometry.LightmapUV;
#endif
#if USE_VERTEX_COLOR
result.VertexColor = output.Geometry.VertexColor;
#endif
result.TBN = CalcTangentBasis(output.Geometry.WorldNormal, output.Geometry.WorldTangent);
result.TwoSidedSign = WorldDeterminantSign;
result.SvPosition = output.Position;
result.PreSkinnedPosition = input.Position.xyz;
result.PreSkinnedNormal = localNormal;
#if USE_INSTANCING
result.InstanceOrigin = input.InstanceOrigin.xyz;
result.InstanceParams = float2(input.InstanceOrigin.w, input.InstanceTransform1.w);
result.InstanceTransform1 = input.InstanceTransform1.xyz;
result.InstanceTransform2 = input.InstanceTransform2.xyz;
result.InstanceTransform3 = input.InstanceTransform3.xyz;
#else
result.InstanceOrigin = WorldMatrix[3].xyz;
result.InstanceParams = float2(PerInstanceRandom, LODDitherFactor);
#endif
return result;
}
MaterialInput GetMaterialInput(VertexOutput output, float3 localPosition, float3 localNormal)
{
MaterialInput result = (MaterialInput)0;
result.WorldPosition = output.Geometry.WorldPosition;
result.TexCoord = output.Geometry.TexCoord;
#if USE_LIGHTMAP
result.LightmapUV = output.Geometry.LightmapUV;
#endif
#if USE_VERTEX_COLOR
result.VertexColor = output.Geometry.VertexColor;
#endif
result.TBN = CalcTangentBasis(output.Geometry.WorldNormal, output.Geometry.WorldTangent);
result.TwoSidedSign = WorldDeterminantSign;
result.InstanceOrigin = WorldMatrix[3].xyz;
result.InstanceParams = float2(PerInstanceRandom, LODDitherFactor);
result.SvPosition = output.Position;
result.PreSkinnedPosition = localPosition;
result.PreSkinnedNormal = localNormal;
return result;
}
MaterialInput GetMaterialInput(PixelInput input)
{
MaterialInput result = (MaterialInput)0;
result.WorldPosition = input.Geometry.WorldPosition;
result.TexCoord = input.Geometry.TexCoord;
#if USE_LIGHTMAP
result.LightmapUV = input.Geometry.LightmapUV;
#endif
#if USE_VERTEX_COLOR
result.VertexColor = input.Geometry.VertexColor;
#endif
result.TBN = CalcTangentBasis(input.Geometry.WorldNormal, input.Geometry.WorldTangent);
result.TwoSidedSign = WorldDeterminantSign * (input.IsFrontFace ? 1.0 : -1.0);
result.InstanceOrigin = input.Geometry.InstanceOrigin;
result.InstanceParams = input.Geometry.InstanceParams;
result.SvPosition = input.Position;
MaterialInput output = GetGeometryMaterialInput(input.Geometry);
output.TwoSidedSign = WorldDeterminantSign * (input.IsFrontFace ? 1.0 : -1.0);
output.SvPosition = input.Position;
#if USE_CUSTOM_VERTEX_INTERPOLATORS
result.CustomVSToPS = input.CustomVSToPS;
output.CustomVSToPS = input.CustomVSToPS;
#endif
return result;
return output;
}
// Gets the local to world transform matrix (supports instancing)
float4x4 GetInstanceTransform(ModelInput input)
{
#if USE_INSTANCING
return float4x4(float4(input.InstanceTransform1.xyz, 0.0f), float4(input.InstanceTransform2.xyz, 0.0f), float4(input.InstanceTransform3.xyz, 0.0f), float4(input.InstanceOrigin.xyz, 1.0f));
#define GetInstanceTransform(input) float4x4(float4(input.InstanceTransform1.xyz, 0.0f), float4(input.InstanceTransform2.xyz, 0.0f), float4(input.InstanceTransform3.xyz, 0.0f), float4(input.InstanceOrigin.xyz, 1.0f))
#else
return WorldMatrix;
#define GetInstanceTransform(input) WorldMatrix;
#endif
}
float4x4 GetInstanceTransform(ModelInput_Skinned input)
{
#if USE_INSTANCING
return float4x4(float4(input.InstanceTransform1.xyz, 0.0f), float4(input.InstanceTransform2.xyz, 0.0f), float4(input.InstanceTransform3.xyz, 0.0f), float4(input.InstanceOrigin.xyz, 1.0f));
#else
return WorldMatrix;
#endif
}
float4x4 GetInstanceTransform(ModelInput_PosOnly input)
{
#if USE_INSTANCING
return float4x4(float4(input.InstanceTransform1.xyz, 0.0f), float4(input.InstanceTransform2.xyz, 0.0f), float4(input.InstanceTransform3.xyz, 0.0f), float4(input.InstanceOrigin.xyz, 1.0f));
#else
return WorldMatrix;
#endif
}
float4x4 GetInstanceTransform(MaterialInput input)
{
#if USE_INSTANCING
return float4x4(float4(input.InstanceTransform1.xyz, 0.0f), float4(input.InstanceTransform2.xyz, 0.0f), float4(input.InstanceTransform3.xyz, 0.0f), float4(input.InstanceOrigin.xyz, 1.0f));
#else
return WorldMatrix;
#endif
}
// Removes the scale vector from the local to world transformation matrix (supports instancing)
float3x3 RemoveScaleFromLocalToWorld(float3x3 localToWorld)
@@ -453,7 +367,16 @@ VertexOutput VS(ModelInput input)
// Get material input params if need to evaluate any material property
#if USE_POSITION_OFFSET || USE_TESSELLATION || USE_CUSTOM_VERTEX_INTERPOLATORS
MaterialInput materialInput = GetMaterialInput(input, output, tangentToLocal[2].xyz);
MaterialInput materialInput = GetGeometryMaterialInput(output.Geometry);
materialInput.TwoSidedSign = WorldDeterminantSign;
materialInput.SvPosition = output.Position;
materialInput.PreSkinnedPosition = input.Position.xyz;
materialInput.PreSkinnedNormal = tangentToLocal[2].xyz;
#if USE_INSTANCING
materialInput.InstanceTransform1 = input.InstanceTransform1.xyz;
materialInput.InstanceTransform2 = input.InstanceTransform2.xyz;
materialInput.InstanceTransform3 = input.InstanceTransform3.xyz;
#endif
Material material = GetMaterialVS(materialInput);
#endif
@@ -626,7 +549,11 @@ VertexOutput VS_Skinned(ModelInput_Skinned input)
// Get material input params if need to evaluate any material property
#if USE_POSITION_OFFSET || USE_TESSELLATION || USE_CUSTOM_VERTEX_INTERPOLATORS
MaterialInput materialInput = GetMaterialInput(output, input.Position.xyz, tangentToLocal[2].xyz);
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
@@ -699,40 +626,4 @@ void PS_Depth(PixelInput input
#endif
}
// Pixel Shader function for Motion Vectors Pass
META_PS(USE_DEFERRED, FEATURE_LEVEL_ES2)
float4 PS_MotionVectors(PixelInput input) : SV_Target0
{
#if USE_DITHERED_LOD_TRANSITION
// LOD masking
ClipLODTransition(input);
#endif
#if MATERIAL_MASKED
// Perform per pixel clipping if material requries it
MaterialInput materialInput = GetMaterialInput(input);
Material material = GetMaterialPS(materialInput);
clip(material.Mask - MATERIAL_MASK_THRESHOLD);
#endif
// Calculate this and previosu frame pixel locations in clip space
float4 prevClipPos = mul(float4(input.Geometry.PrevWorldPosition, 1), PrevViewProjectionMatrix);
float4 curClipPos = mul(float4(input.Geometry.WorldPosition, 1), ViewProjectionMatrix);
float2 prevHPos = prevClipPos.xy / prevClipPos.w;
float2 curHPos = curClipPos.xy / curClipPos.w;
// Revert temporal jitter offset
prevHPos -= TemporalAAJitter.zw;
curHPos -= TemporalAAJitter.xy;
// Clip Space -> UV Space
float2 vPosPrev = prevHPos.xy * 0.5f + 0.5f;
float2 vPosCur = curHPos.xy * 0.5f + 0.5f;
vPosPrev.y = 1.0 - vPosPrev.y;
vPosCur.y = 1.0 - vPosCur.y;
// Calculate per-pixel motion vector
return float4(vPosCur - vPosPrev, 0, 1);
}
@9

View File

@@ -37,14 +37,16 @@ void DecalMaterialShader::Bind(BindParameters& params)
auto context = params.GPUContext;
auto& view = params.RenderContext.View;
auto& drawCall = *params.FirstDrawCall;
const auto cb0 = _shader->GetCB(0);
const bool hasCb0 = cb0->GetSize() != 0;
byte* cb = _cbData.Get();
auto materialData = reinterpret_cast<DecalMaterialShaderData*>(cb);
cb += sizeof(DecalMaterialShaderData);
int32 srv = 0;
const bool isCameraInside = OrientedBoundingBox(Vector3::Half, params.FirstDrawCall->World).Contains(view.Position) == ContainmentType::Contains;
// Setup parameters
MaterialParameter::BindMeta bindMeta;
bindMeta.Context = context;
bindMeta.Constants = hasCb0 ? _cb0Data.Get() + sizeof(DecalMaterialShaderData) : nullptr;
bindMeta.Constants = cb;
bindMeta.Input = nullptr;
bindMeta.Buffers = nullptr;
bindMeta.CanSampleDepth = true;
@@ -55,10 +57,7 @@ void DecalMaterialShader::Bind(BindParameters& params)
context->BindSR(0, GET_TEXTURE_VIEW_SAFE(params.RenderContext.Buffers->DepthBuffer));
// Setup material constants data
if (hasCb0)
{
const auto materialData = reinterpret_cast<DecalMaterialShaderData*>(_cb0Data.Get());
Matrix::Transpose(view.Frustum.GetMatrix(), materialData->ViewProjectionMatrix);
Matrix::Transpose(drawCall.World, materialData->WorldMatrix);
Matrix::Transpose(view.View, materialData->ViewMatrix);
@@ -85,10 +84,10 @@ void DecalMaterialShader::Bind(BindParameters& params)
}
// Bind constants
if (hasCb0)
if (_cb)
{
context->UpdateCB(cb0, _cb0Data.Get());
context->BindCB(0, cb0);
context->UpdateCB(_cb, _cbData.Get());
context->BindCB(0, _cb);
}
// Bind pipeline

View File

@@ -61,10 +61,7 @@ void DeferredMaterialShader::Bind(BindParameters& params)
auto context = params.GPUContext;
auto& view = params.RenderContext.View;
auto& drawCall = *params.FirstDrawCall;
const auto cb0 = _shader->GetCB(0);
const bool hasCb0 = cb0 && cb0->GetSize() != 0;
ASSERT(hasCb0 && "TODO: fix it"); // TODO: always make cb pointer valid even if cb is missing
byte* cb = _cb0Data.Get();
byte* cb = _cbData.Get();
auto materialData = reinterpret_cast<DeferredMaterialShaderData*>(cb);
cb += sizeof(DeferredMaterialShaderData);
int32 srv = 2;
@@ -82,8 +79,6 @@ void DeferredMaterialShader::Bind(BindParameters& params)
bindMeta.CanSampleGBuffer = false;
MaterialParams::Bind(params.ParamsLink, bindMeta);
// Setup material constants data
if (hasCb0)
{
Matrix::Transpose(view.Frustum.GetMatrix(), materialData->ViewProjectionMatrix);
Matrix::Transpose(drawCall.World, materialData->WorldMatrix);
@@ -131,10 +126,10 @@ void DeferredMaterialShader::Bind(BindParameters& params)
}
// Bind constants
if (hasCb0)
if (_cb)
{
context->UpdateCB(cb0, _cb0Data.Get());
context->BindCB(0, cb0);
context->UpdateCB(_cb, _cbData.Get());
context->BindCB(0, _cb);
}
// Select pipeline state based on current pass and render mode

View File

@@ -58,10 +58,7 @@ void ForwardMaterialShader::Bind(BindParameters& params)
auto context = params.GPUContext;
auto& view = params.RenderContext.View;
auto& drawCall = *params.FirstDrawCall;
const auto cb0 = _shader->GetCB(0);
const bool hasCb0 = cb0 && cb0->GetSize() != 0;
ASSERT(hasCb0 && "TODO: fix it"); // TODO: always make cb pointer valid even if cb is missing
byte* cb = _cb0Data.Get();
byte* cb = _cbData.Get();
auto materialData = reinterpret_cast<ForwardMaterialShaderData*>(cb);
cb += sizeof(ForwardMaterialShaderData);
int32 srv = 2;
@@ -89,7 +86,6 @@ void ForwardMaterialShader::Bind(BindParameters& params)
}
// Setup material constants data
if (hasCb0)
{
Matrix::Transpose(view.Frustum.GetMatrix(), materialData->ViewProjectionMatrix);
Matrix::Transpose(drawCall.World, materialData->WorldMatrix);
@@ -121,10 +117,10 @@ void ForwardMaterialShader::Bind(BindParameters& params)
}
// Bind constants
if (hasCb0)
if (_cb)
{
context->UpdateCB(cb0, _cb0Data.Get());
context->BindCB(0, cb0);
context->UpdateCB(_cb, _cbData.Get());
context->BindCB(0, _cb);
}
// Select pipeline state based on current pass and render mode

View File

@@ -28,15 +28,16 @@ void GUIMaterialShader::Bind(BindParameters& params)
{
// Prepare
auto context = params.GPUContext;
auto& view = params.RenderContext.View;
const auto cb0 = _shader->GetCB(0);
const bool hasCb0 = cb0->GetSize() != 0;
byte* cb = _cbData.Get();
auto materialData = reinterpret_cast<GUIMaterialShaderData*>(cb);
cb += sizeof(GUIMaterialShaderData);
int32 srv = 0;
const auto ps = context->IsDepthBufferBinded() ? _cache.Depth : _cache.NoDepth;
// Setup parameters
MaterialParameter::BindMeta bindMeta;
bindMeta.Context = context;
bindMeta.Constants = hasCb0 ? _cb0Data.Get() + sizeof(GUIMaterialShaderData) : nullptr;
bindMeta.Constants = cb;
bindMeta.Input = nullptr;
bindMeta.Buffers = nullptr;
bindMeta.CanSampleDepth = false;
@@ -44,10 +45,7 @@ void GUIMaterialShader::Bind(BindParameters& params)
MaterialParams::Bind(params.ParamsLink, bindMeta);
// Setup material constants data
if (hasCb0)
{
auto materialData = reinterpret_cast<GUIMaterialShaderData*>(_cb0Data.Get());
const auto viewProjectionMatrix = (Matrix*)params.CustomData;
Matrix::Transpose(*viewProjectionMatrix, materialData->ViewProjectionMatrix);
Matrix::Transpose(Matrix::Identity, materialData->WorldMatrix);
@@ -62,10 +60,10 @@ void GUIMaterialShader::Bind(BindParameters& params)
}
// Bind constants
if (hasCb0)
if (_cb)
{
context->UpdateCB(cb0, _cb0Data.Get());
context->BindCB(0, cb0);
context->UpdateCB(_cb, _cbData.Get());
context->BindCB(0, _cb);
}
// Bind pipeline

View File

@@ -14,18 +14,15 @@
#include "GUIMaterialShader.h"
#include "TerrainMaterialShader.h"
#include "ParticleMaterialShader.h"
//#include "DeformableMaterialShader.h"
GPUPipelineState* MaterialShader::PipelineStateCache::GetPS(CullMode mode, bool wireframe)
GPUPipelineState* MaterialShader::PipelineStateCache::InitPS(CullMode mode, bool wireframe)
{
const int32 index = static_cast<int32>(mode) + (wireframe ? 3 : 0);
if (PS[index])
return PS[index];
Desc.CullMode = mode;
Desc.Wireframe = wireframe;
PS[index] = GPUDevice::Instance->CreatePipelineState();
PS[index]->Init(Desc);
return PS[index];
auto ps = GPUDevice::Instance->CreatePipelineState();
ps->Init(Desc);
return ps;
}
MaterialShader::MaterialShader(const String& name)
@@ -65,6 +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;*/
default:
LOG(Fatal, "Unknown material type.");
return nullptr;
@@ -138,10 +138,17 @@ bool MaterialShader::Load(MemoryReadStream& shaderCacheStream, const MaterialInf
}
// Init memory for a constant buffer
const auto cb0 = _shader->GetCB(0);
if (cb0)
_cb = _shader->GetCB(0);
if (_cb)
{
_cb0Data.Resize(cb0->GetSize(), false);
int32 cbSize = _cb->GetSize();
if (cbSize == 0)
{
// Handle unused constant buffer (eg. postFx returning solid color)
cbSize = 1024;
_cb = nullptr;
}
_cbData.Resize(cbSize, false);
}
// Initialize the material based on type (create pipeline states and setup)
@@ -157,6 +164,7 @@ bool MaterialShader::Load(MemoryReadStream& shaderCacheStream, const MaterialInf
void MaterialShader::Unload()
{
_isLoaded = false;
_cb0Data.Resize(0, false);
_cb = nullptr;
_cbData.Resize(0, false);
_shader->ReleaseGPU();
}

View File

@@ -9,10 +9,11 @@
/// <summary>
/// Current materials shader version.
/// </summary>
#define MATERIAL_GRAPH_VERSION 146
#define MATERIAL_GRAPH_VERSION 147
class Material;
class GPUShader;
class GPUConstantBuffer;
class MemoryReadStream;
/// <summary>
@@ -37,7 +38,16 @@ protected:
Desc = desc;
}
GPUPipelineState* GetPS(CullMode mode, bool wireframe);
GPUPipelineState* GetPS(CullMode mode, bool wireframe)
{
const int32 index = static_cast<int32>(mode) + (wireframe ? 3 : 0);
auto ps = PS[index];
if (!ps)
PS[index] = ps = InitPS(mode, wireframe);
return ps;
}
GPUPipelineState* InitPS(CullMode mode, bool wireframe);
void Release()
{
@@ -52,7 +62,8 @@ protected:
bool _isLoaded;
GPUShader* _shader;
Array<byte> _cb0Data;
GPUConstantBuffer* _cb;
Array<byte> _cbData;
MaterialInfo _info;
protected:
@@ -89,10 +100,8 @@ public:
/// <returns>The created and loaded material or null if failed.</returns>
static MaterialShader* CreateDummy(MemoryReadStream& shaderCacheStream, const MaterialInfo& info);
public:
/// <summary>
/// Clear loaded data
/// Clears the loaded data.
/// </summary>
virtual void Unload();

View File

@@ -158,36 +158,31 @@ bool LightmapFeature::Bind(MaterialShader::BindParameters& params, byte*& cb, in
void ForwardShadingFeature::Generate(GeneratorData& data)
{
data.Template = TEXT("Features/ForwardShading.hlsl");
data.ConstantsSize = sizeof(Data);
data.ResourcesCount = SRVs;
}
void DeferredShadingFeature::Generate(GeneratorData& data)
{
data.Template = TEXT("Features/DeferredShading.hlsl");
data.ConstantsSize = 0;
data.ResourcesCount = 0;
}
void TessellationFeature::Generate(GeneratorData& data)
{
data.Template = TEXT("Features/Tessellation.hlsl");
data.ConstantsSize = 0;
data.ResourcesCount = 0;
}
void LightmapFeature::Generate(GeneratorData& data)
{
data.Template = TEXT("Features/Lightmap.hlsl");
data.ConstantsSize = sizeof(Data);
data.ResourcesCount = SRVs;
}
void DistortionFeature::Generate(GeneratorData& data)
{
data.Template = TEXT("Features/Distortion.hlsl");
data.ConstantsSize = 0;
data.ResourcesCount = 0;
}
void MotionVectorsFeature::Generate(GeneratorData& data)
{
data.Template = TEXT("Features/MotionVectors.hlsl");
}
#endif

View File

@@ -12,8 +12,6 @@ struct MaterialShaderFeature
struct GeneratorData
{
const Char* Template;
int32 ConstantsSize;
int32 ResourcesCount;
};
#endif;
};
@@ -82,3 +80,11 @@ struct DistortionFeature : MaterialShaderFeature
static void Generate(GeneratorData& data);
#endif
};
// Material shader feature that adds motion vectors rendering pass.
struct MotionVectorsFeature : MaterialShaderFeature
{
#if USE_EDITOR
static void Generate(GeneratorData& data);
#endif
};

View File

@@ -60,10 +60,7 @@ void ParticleMaterialShader::Bind(BindParameters& params)
auto& view = params.RenderContext.View;
auto& drawCall = *params.FirstDrawCall;
const uint32 sortedIndicesOffset = drawCall.Particle.Module->SortedIndicesOffset;
const auto cb0 = _shader->GetCB(0);
const bool hasCb0 = cb0->GetSize() != 0;
ASSERT(hasCb0 && "TODO: fix it"); // TODO: always make cb pointer valid even if cb is missing
byte* cb = _cb0Data.Get();
byte* cb = _cbData.Get();
auto materialData = reinterpret_cast<ParticleMaterialShaderData*>(cb);
cb += sizeof(ParticleMaterialShaderData);
int32 srv = 2;
@@ -86,7 +83,6 @@ void ParticleMaterialShader::Bind(BindParameters& params)
context->BindSR(1, drawCall.Particle.Particles->GPU.SortedIndices ? drawCall.Particle.Particles->GPU.SortedIndices->View() : nullptr);
// Setup particles attributes binding info
if (hasCb0)
{
const auto& p = *params.ParamsLink->This;
for (int32 i = 0; i < p.Count(); i++)
@@ -129,19 +125,16 @@ void ParticleMaterialShader::Bind(BindParameters& params)
static StringView ParticleRibbonTwist(TEXT("RibbonTwist"));
static StringView ParticleRibbonFacingVector(TEXT("RibbonFacingVector"));
if (hasCb0)
{
materialData->RibbonWidthOffset = drawCall.Particle.Particles->Layout->FindAttributeOffset(ParticleRibbonWidth, ParticleAttribute::ValueTypes::Float, -1);
materialData->RibbonTwistOffset = drawCall.Particle.Particles->Layout->FindAttributeOffset(ParticleRibbonTwist, ParticleAttribute::ValueTypes::Float, -1);
materialData->RibbonFacingVectorOffset = drawCall.Particle.Particles->Layout->FindAttributeOffset(ParticleRibbonFacingVector, ParticleAttribute::ValueTypes::Vector3, -1);
materialData->RibbonWidthOffset = drawCall.Particle.Particles->Layout->FindAttributeOffset(ParticleRibbonWidth, ParticleAttribute::ValueTypes::Float, -1);
materialData->RibbonTwistOffset = drawCall.Particle.Particles->Layout->FindAttributeOffset(ParticleRibbonTwist, ParticleAttribute::ValueTypes::Float, -1);
materialData->RibbonFacingVectorOffset = drawCall.Particle.Particles->Layout->FindAttributeOffset(ParticleRibbonFacingVector, ParticleAttribute::ValueTypes::Vector3, -1);
materialData->RibbonUVTilingDistance = drawCall.Particle.Ribbon.UVTilingDistance;
materialData->RibbonUVScale.X = drawCall.Particle.Ribbon.UVScaleX;
materialData->RibbonUVScale.Y = drawCall.Particle.Ribbon.UVScaleY;
materialData->RibbonUVOffset.X = drawCall.Particle.Ribbon.UVOffsetX;
materialData->RibbonUVOffset.Y = drawCall.Particle.Ribbon.UVOffsetY;
materialData->RibbonSegmentCount = drawCall.Particle.Ribbon.SegmentCount;
}
materialData->RibbonUVTilingDistance = drawCall.Particle.Ribbon.UVTilingDistance;
materialData->RibbonUVScale.X = drawCall.Particle.Ribbon.UVScaleX;
materialData->RibbonUVScale.Y = drawCall.Particle.Ribbon.UVScaleY;
materialData->RibbonUVOffset.X = drawCall.Particle.Ribbon.UVOffsetX;
materialData->RibbonUVOffset.Y = drawCall.Particle.Ribbon.UVOffsetY;
materialData->RibbonSegmentCount = drawCall.Particle.Ribbon.SegmentCount;
if (drawCall.Particle.Ribbon.SegmentDistances)
context->BindSR(1, drawCall.Particle.Ribbon.SegmentDistances->View());
@@ -153,7 +146,6 @@ void ParticleMaterialShader::Bind(BindParameters& params)
GPUPipelineState* state = psCache->GetPS(cullMode, wireframe);
// Setup material constants data
if (hasCb0)
{
static StringView ParticlePosition(TEXT("Position"));
static StringView ParticleSpriteSize(TEXT("SpriteSize"));
@@ -188,10 +180,10 @@ void ParticleMaterialShader::Bind(BindParameters& params)
}
// Bind constants
if (hasCb0)
if (_cb)
{
context->UpdateCB(cb0, _cb0Data.Get());
context->BindCB(0, cb0);
context->UpdateCB(_cb, _cbData.Get());
context->BindCB(0, _cb);
}
// Bind pipeline

View File

@@ -26,13 +26,15 @@ void PostFxMaterialShader::Bind(BindParameters& params)
// Prepare
auto context = params.GPUContext;
auto& view = params.RenderContext.View;
const auto cb0 = _shader->GetCB(0);
const bool hasCb0 = cb0->GetSize() != 0;
byte* cb = _cbData.Get();
auto materialData = reinterpret_cast<PostFxMaterialShaderData*>(cb);
cb += sizeof(PostFxMaterialShaderData);
int32 srv = 0;
// Setup parameters
MaterialParameter::BindMeta bindMeta;
bindMeta.Context = context;
bindMeta.Constants = hasCb0 ? _cb0Data.Get() + sizeof(PostFxMaterialShaderData) : nullptr;
bindMeta.Constants = cb;
bindMeta.Input = params.Input;
bindMeta.Buffers = params.RenderContext.Buffers;
bindMeta.CanSampleDepth = true;
@@ -40,10 +42,7 @@ void PostFxMaterialShader::Bind(BindParameters& params)
MaterialParams::Bind(params.ParamsLink, bindMeta);
// Setup material constants data
if (hasCb0)
{
const auto materialData = reinterpret_cast<PostFxMaterialShaderData*>(_cb0Data.Get());
Matrix::Transpose(view.View, materialData->ViewMatrix);
materialData->ViewPos = view.Position;
materialData->ViewFar = view.Far;
@@ -55,10 +54,10 @@ void PostFxMaterialShader::Bind(BindParameters& params)
}
// Bind constants
if (hasCb0)
if (_cb)
{
context->UpdateCB(cb0, _cb0Data.Get());
context->BindCB(0, cb0);
context->UpdateCB(_cb, _cbData.Get());
context->BindCB(0, _cb);
}
// Bind pipeline

View File

@@ -54,10 +54,7 @@ void TerrainMaterialShader::Bind(BindParameters& params)
auto context = params.GPUContext;
auto& view = params.RenderContext.View;
auto& drawCall = *params.FirstDrawCall;
const auto cb0 = _shader->GetCB(0);
const bool hasCb0 = cb0->GetSize() != 0;
ASSERT(hasCb0 && "TODO: fix it"); // TODO: always make cb pointer valid even if cb is missing
byte* cb = _cb0Data.Get();
byte* cb = _cbData.Get();
auto materialData = reinterpret_cast<TerrainMaterialShaderData*>(cb);
cb += sizeof(TerrainMaterialShaderData);
int32 srv = 3;
@@ -76,7 +73,6 @@ void TerrainMaterialShader::Bind(BindParameters& params)
MaterialParams::Bind(params.ParamsLink, bindMeta);
// Setup material constants data
if (hasCb0)
{
Matrix::Transpose(view.Frustum.GetMatrix(), materialData->ViewProjectionMatrix);
Matrix::Transpose(drawCall.World, materialData->WorldMatrix);
@@ -114,10 +110,10 @@ void TerrainMaterialShader::Bind(BindParameters& params)
context->BindSR(2, splatmap1);
// Bind constants
if (hasCb0)
if (_cb)
{
context->UpdateCB(cb0, _cb0Data.Get());
context->BindCB(0, cb0);
context->UpdateCB(_cb, _cbData.Get());
context->BindCB(0, _cb);
}
// Select pipeline state based on current pass and render mode

View File

@@ -185,6 +185,8 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
if (materialInfo.TessellationMode != TessellationMethod::None)
ADD_FEATURE(TessellationFeature);
if (materialInfo.BlendMode == MaterialBlendMode::Opaque)
ADD_FEATURE(MotionVectorsFeature);
if (materialInfo.BlendMode == MaterialBlendMode::Opaque)
ADD_FEATURE(LightmapFeature);
if (materialInfo.BlendMode == MaterialBlendMode::Opaque)
ADD_FEATURE(DeferredShadingFeature);