LightRendering.h
TShaderMapRef<TDeferredLightVS<true> > VertexShader(View.ShaderMap);
VertexShader->SetParameters(RHICmdList, View, LightSceneInfo);
TDefferredLightVS:
/** A vertex shader for rendering the light in a deferred pass. */
template<bool bRadialLight>
class TDeferredLightVS : public FGlobalShader
{
DECLARE_SHADER_TYPE(TDeferredLightVS,Global);
public:
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
if (bRadialLight)
{
return IsFeatureLevelSupported(Parameters.Platform, ERHIFeatureLevel::SM5) || IsMobileDeferredShadingEnabled(Parameters.Platform);
}
// used with FPrefilterPlanarReflectionPS on mobile
return true;
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("SHADER_RADIAL_LIGHT"), bRadialLight ? 1 : 0);
}
TDeferredLightVS() {}
TDeferredLightVS(const ShaderMetaType::CompiledShaderInitializerType& Initializer):
FGlobalShader(Initializer)
{
StencilingGeometryParameters.Bind(Initializer.ParameterMap);
}
void SetParameters(FRHICommandList& RHICmdList, const FViewInfo& View, const FLightSceneInfo* LightSceneInfo)
{
FGlobalShader::SetParameters<FViewUniformShaderParameters>(RHICmdList, RHICmdList.GetBoundVertexShader(), View.ViewUniformBuffer);
StencilingGeometryParameters.Set(RHICmdList, this, View, LightSceneInfo);
}
void SetSimpleLightParameters(FRHICommandList& RHICmdList, const FViewInfo& View, const FSphere& LightBounds)
{
FGlobalShader::SetParameters<FViewUniformShaderParameters>(RHICmdList, RHICmdList.GetBoundVertexShader(), View.ViewUniformBuffer);
FVector4 StencilingSpherePosAndScale;
StencilingGeometry::GStencilSphereVertexBuffer.CalcTransform(StencilingSpherePosAndScale, LightBounds, View.ViewMatrices.GetPreViewTranslation());
StencilingGeometryParameters.Set(RHICmdList, this, StencilingSpherePosAndScale);
}
private:
LAYOUT_FIELD(FStencilingGeometryShaderParameters, StencilingGeometryParameters);
};
FStencilingGeometryShaderParameters:
/**
* Stencil geometry parameters used by multiple shaders.
*/
class FStencilingGeometryShaderParameters
{
DECLARE_TYPE_LAYOUT(FStencilingGeometryShaderParameters, NonVirtual);
public:
void Bind(const FShaderParameterMap& ParameterMap)
{
StencilGeometryPosAndScale.Bind(ParameterMap, TEXT("StencilingGeometryPosAndScale"));
StencilConeParameters.Bind(ParameterMap, TEXT("StencilingConeParameters"));
StencilConeTransform.Bind(ParameterMap, TEXT("StencilingConeTransform"));
StencilPreViewTranslation.Bind(ParameterMap, TEXT("StencilingPreViewTranslation"));
}
void Set(FRHICommandList& RHICmdList, FShader* Shader, const FVector4& InStencilingGeometryPosAndScale) const
{
SetShaderValue(RHICmdList, RHICmdList.GetBoundVertexShader(), StencilGeometryPosAndScale, InStencilingGeometryPosAndScale);
SetShaderValue(RHICmdList, RHICmdList.GetBoundVertexShader(), StencilConeParameters, FVector4(0.0f, 0.0f, 0.0f, 0.0f));
}
void Set(FRHICommandList& RHICmdList, FShader* Shader, const FSceneView& View, const FLightSceneInfo* LightSceneInfo) const
{
FVector4 GeometryPosAndScale;
if( LightSceneInfo->Proxy->GetLightType() == LightType_Point ||
LightSceneInfo->Proxy->GetLightType() == LightType_Rect )
{
StencilingGeometry::GStencilSphereVertexBuffer.CalcTransform(GeometryPosAndScale, LightSceneInfo->Proxy->GetBoundingSphere(), View.ViewMatrices.GetPreViewTranslation());
SetShaderValue(RHICmdList, RHICmdList.GetBoundVertexShader(), StencilGeometryPosAndScale, GeometryPosAndScale);
SetShaderValue(RHICmdList, RHICmdList.GetBoundVertexShader(), StencilConeParameters, FVector4(0.0f, 0.0f, 0.0f, 0.0f));
}
else if(LightSceneInfo->Proxy->GetLightType() == LightType_Spot)
{
SetShaderValue(RHICmdList, RHICmdList.GetBoundVertexShader(), StencilConeTransform, LightSceneInfo->Proxy->GetLightToWorld());
SetShaderValue(
RHICmdList,
RHICmdList.GetBoundVertexShader(),
StencilConeParameters,
FVector4(
StencilingGeometry::FStencilConeIndexBuffer::NumSides,
StencilingGeometry::FStencilConeIndexBuffer::NumSlices,
LightSceneInfo->Proxy->GetOuterConeAngle(),
LightSceneInfo->Proxy->GetRadius()));
SetShaderValue(RHICmdList, RHICmdList.GetBoundVertexShader(), StencilPreViewTranslation, View.ViewMatrices.GetPreViewTranslation());
}
}
/** Serializer. */
friend FArchive& operator<<(FArchive& Ar,FStencilingGeometryShaderParameters& P)
{
Ar << P.StencilGeometryPosAndScale;
Ar << P.StencilConeParameters;
Ar << P.StencilConeTransform;
Ar << P.StencilPreViewTranslation;
return Ar;
}
private:
LAYOUT_FIELD(FShaderParameter, StencilGeometryPosAndScale)
LAYOUT_FIELD(FShaderParameter, StencilConeParameters)
LAYOUT_FIELD(FShaderParameter, StencilConeTransform)
LAYOUT_FIELD(FShaderParameter, StencilPreViewTranslation)
};
ShaderParameterUtils.h
/**
* Sets the value of a shader parameter. Template'd on shader type
* A template parameter specified the type of the parameter value.
* NOTE: Shader should be the param ref type, NOT the param type, since Shader is passed by value.
* Otherwise AddRef/ReleaseRef will be called many times.
*/
template<typename ShaderRHIParamRef, class ParameterType, typename TRHICmdList>
void SetShaderValue(
TRHICmdList& RHICmdList,
const ShaderRHIParamRef& Shader,
const FShaderParameter& Parameter,
const ParameterType& Value,
uint32 ElementIndex = 0
)
{
static_assert(!TIsPointer<ParameterType>::Value, "Passing by value is not valid.");
const uint32 AlignedTypeSize = Align(sizeof(ParameterType), SHADER_PARAMETER_ARRAY_ELEMENT_ALIGNMENT);
const int32 NumBytesToSet = FMath::Min<int32>(sizeof(ParameterType),Parameter.GetNumBytes() - ElementIndex * AlignedTypeSize);
// This will trigger if the parameter was not serialized
checkSlow(Parameter.IsInitialized());
if(NumBytesToSet > 0)
{
RHICmdList.SetShaderParameter(
Shader,
Parameter.GetBufferIndex(),
Parameter.GetBaseIndex() + ElementIndex * AlignedTypeSize,
(uint32)NumBytesToSet,
&Value
);
}
}