Refactor material shaders generator to use modular features as extensions
This commit is contained in:
44
Content/Editor/MaterialTemplates/Features/MotionVectors.hlsl
Normal file
44
Content/Editor/MaterialTemplates/Features/MotionVectors.hlsl
Normal 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);
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user