1 // Copyright 2001-2018 Crytek GmbH / Crytek Group. All rights reserved.
5 #include "RootOpticsElement.h"
6 #include "FlareSoftOcclusionQuery.h"
7 #include "../Textures/Texture.h"
8 #include "D3DPostProcess.h"
11 #include <Common/RenderDisplayContext.h>
20 const float RootOpticsElement::kExtendedFlareRadiusRatio
= 1.3f
;
22 #if defined(FLARES_SUPPORT_EDITING)
23 #define MFPtr(FUNC_NAME) (Optics_MFPtr)(&RootOpticsElement::FUNC_NAME)
24 void RootOpticsElement::InitEditorParamGroups(DynArray
<FuncVariableGroup
>& groups
)
26 COpticsGroup::InitEditorParamGroups(groups
);
28 FuncVariableGroup rootGroup
;
29 rootGroup
.SetName("GlobalSettings", "Global Settings");
30 rootGroup
.AddVariable(new OpticsMFPVariable(e_BOOL
, "Enable Occlusion", "Enable Occlusion", this, MFPtr(SetOcclusionEnabled
), MFPtr(IsOcclusionEnabled
)));
31 rootGroup
.AddVariable(new OpticsMFPVariable(e_VEC2
, "Occlusion Size", "The size for occlusion plane", this, MFPtr(SetOccSize
), MFPtr(GetOccSize
)));
32 rootGroup
.AddVariable(new OpticsMFPVariable(e_BOOL
, "Enable Invert Fade", "Enable Invert Fade", this, MFPtr(SetInvertFade
), MFPtr(IsInvertFade
)));
33 rootGroup
.AddVariable(new OpticsMFPVariable(e_FLOAT
, "Flare fade time", "The duration of flare afterimage fading in seconds", this, MFPtr(SetFlareFadingDuration
), MFPtr(GetFlareFadingDuration
)));
34 rootGroup
.AddVariable(new OpticsMFPVariable(e_FLOAT
, "Shaft fade time", "The duration of shaft afterimage fading in seconds", this, MFPtr(SetShaftFadingDuration
), MFPtr(GetShaftFadingDuration
)));
35 rootGroup
.AddVariable(new OpticsMFPVariable(e_BOOL
, "Affected by light color", "light color can affect flare color", this, MFPtr(SetAffectedByLightColor
), MFPtr(IsAffectedByLightColor
)));
36 rootGroup
.AddVariable(new OpticsMFPVariable(e_BOOL
, "Affected by light radius", "light radius can affect flare fading", this, MFPtr(SetAffectedByLightRadius
), MFPtr(IsAffectedByLightRadius
)));
37 rootGroup
.AddVariable(new OpticsMFPVariable(e_BOOL
, "Affected by light FOV", "light projection FOV can affect flare fading", this, MFPtr(SetAffectedByLightFOV
), MFPtr(IsAffectedByLightFOV
)));
38 rootGroup
.AddVariable(new OpticsMFPVariable(e_BOOL
, "Multiply Color", "Select one of between Multiply and Addition about color calculation. If true, Multiply will be chosen.", this, MFPtr(SetMultiplyColor
), MFPtr(IsMultiplyColor
)));
39 groups
.push_back(rootGroup
);
41 FuncVariableGroup sensorGroup
;
42 sensorGroup
.SetName("Sensor");
43 sensorGroup
.AddVariable(new OpticsMFPVariable(e_BOOL
, "Custom Sensor Variation Map", "Enable Custom Sensor Variation Map", this, MFPtr(SetCustomSensorVariationMapEnabled
), MFPtr(IsCustomSensorVariationMapEnabled
)));
44 sensorGroup
.AddVariable(new OpticsMFPVariable(e_FLOAT
, "Effective Sensor Size", "The size of image-able part of the sensor", this, MFPtr(SetEffectiveSensorSize
), MFPtr(GetEffectiveSensorSize
)));
45 groups
.push_back(sensorGroup
);
50 void RootOpticsElement::Load(IXmlNode
* pNode
)
52 COpticsElement::Load(pNode
);
54 XmlNodeRef pGloabalSettingsNode
= pNode
->findChild("GlobalSettings");
55 if (pGloabalSettingsNode
)
57 bool bOcclusionEnabled(m_bOcclusionEnabled
);
58 if (pGloabalSettingsNode
->getAttr("EnableOcclusion", bOcclusionEnabled
))
59 SetOcclusionEnabled(bOcclusionEnabled
);
61 Vec2
occlusionSize(m_OcclusionSize
);
62 if (pGloabalSettingsNode
->getAttr("OcclusionSize", occlusionSize
))
63 SetOccSize(occlusionSize
);
65 bool bInvertFade(m_bEnableInvertFade
);
66 if (pGloabalSettingsNode
->getAttr("EnableInvertFade", bInvertFade
))
67 SetInvertFade(bInvertFade
);
69 float fFlareTimelineDuration(m_fFlareTimelineDuration
);
70 if (pGloabalSettingsNode
->getAttr("Flarefadetime", fFlareTimelineDuration
))
71 SetFlareFadingDuration(fFlareTimelineDuration
);
73 float fShaftTimelineDuration(m_fShaftTimelineDuration
);
74 if (pGloabalSettingsNode
->getAttr("Flarefadetime", fShaftTimelineDuration
))
75 SetShaftFadingDuration(fShaftTimelineDuration
);
77 bool bAffectedByLightColor(m_bAffectedByLightColor
);
78 if (pGloabalSettingsNode
->getAttr("Affectedbylightcolor", bAffectedByLightColor
))
79 SetAffectedByLightColor(bAffectedByLightColor
);
81 bool bAffectedByLightRadius(m_bAffectedByLightRadius
);
82 if (pGloabalSettingsNode
->getAttr("Affectedbylightradius", bAffectedByLightRadius
))
83 SetAffectedByLightRadius(bAffectedByLightRadius
);
85 bool bAffectedByLightFOV(m_bAffectedByLightFOV
);
86 if (pGloabalSettingsNode
->getAttr("AffectedbylightFOV", bAffectedByLightFOV
))
87 SetAffectedByLightFOV(bAffectedByLightFOV
);
89 bool bMultiplyColor(m_bMultiplyColor
);
90 if (pGloabalSettingsNode
->getAttr("MultiplyColor", bMultiplyColor
))
91 SetMultiplyColor(bMultiplyColor
);
94 XmlNodeRef pSensorNode
= pNode
->findChild("Sensor");
97 bool bCustomSensorVariationMap(m_bCustomSensorVariationMap
);
98 if (pSensorNode
->getAttr("CustomSensorVariationMap", bCustomSensorVariationMap
))
99 SetCustomSensorVariationMapEnabled(bCustomSensorVariationMap
);
101 float fEffectiveSensorSize(m_fEffectiveSensorSize
);
102 if (pSensorNode
->getAttr("EffectiveSensorSize", fEffectiveSensorSize
))
103 SetEffectiveSensorSize(fEffectiveSensorSize
);
107 void RootOpticsElement::SetOcclusionQuery(CFlareSoftOcclusionQuery
* query
)
112 float RootOpticsElement::GetFlareVisibilityFactor() const
114 CSoftOcclusionVisiblityFader
* pFader
= m_pOccQuery
? m_pOccQuery
->GetVisibilityFader(VISFADER_FLARE
) : NULL
;
115 return pFader
? pFader
->m_fVisibilityFactor
: 0.0f
;
118 float RootOpticsElement::GetShaftVisibilityFactor() const
120 CSoftOcclusionVisiblityFader
* pFader
= m_pOccQuery
? m_pOccQuery
->GetVisibilityFader(VISFADER_SHAFT
) : NULL
;
121 return pFader
? pFader
->m_fVisibilityFactor
: 0.0f
;
124 void RootOpticsElement::SetVisibilityFactor(float f
)
126 f
= clamp_tpl(f
, 0.f
, 1.f
);
130 for (uint i
= 0; i
< VISFADER_NUM
; ++i
)
132 if (CSoftOcclusionVisiblityFader
* pFader
= m_pOccQuery
->GetVisibilityFader(i
))
134 pFader
->m_fVisibilityFactor
= f
;
140 CTexture
* RootOpticsElement::GetOcclusionPattern()
142 return m_pOccQuery
->GetGatherTexture();
145 void RootOpticsElement::validateGlobalVars(const SAuxParams
& aux
)
147 m_globalPerspectiveFactor
= m_fPerspectiveFactor
;
148 m_globalDistanceFadingFactor
= m_flareLight
.m_bAttachToSun
? 0.0f
: m_fDistanceFadingFactor
;
149 m_globalSensorBrightnessFactor
= m_fSensorBrightnessFactor
;
150 m_globalSensorSizeFactor
= m_fSensorSizeFactor
;
151 m_globalSize
= m_fSize
;
152 m_globalFlareBrightness
= GetBrightness();
153 m_globalMovement
= m_vMovement
;
155 if (m_bAffectedByLightColor
)
157 if (aux
.bMultiplyColor
)
158 m_globalColor
= ColorF(m_Color
.r
* m_flareLight
.m_cLdrClr
.r
, m_Color
.g
* m_flareLight
.m_cLdrClr
.g
, m_Color
.b
* m_flareLight
.m_cLdrClr
.b
, m_Color
.a
);
160 m_globalColor
= ColorF(m_Color
.r
+ m_flareLight
.m_cLdrClr
.r
, m_Color
.g
+ m_flareLight
.m_cLdrClr
.g
, m_Color
.b
+ m_flareLight
.m_cLdrClr
.b
, m_Color
.a
);
162 m_globalFlareBrightness
*= m_flareLight
.m_fClrMultiplier
;
166 m_globalColor
= m_Color
;
169 if (m_bAffectedByLightRadius
)
171 if (m_bEnableInvertFade
)
173 const float kRedundantRadiusRatio
= kExtendedFlareRadiusRatio
; //1.0f;
174 const float fExtendedRadius
= m_flareLight
.m_fRadius
* kRedundantRadiusRatio
;
176 if (aux
.distance
> m_flareLight
.m_fRadius
&& aux
.distance
< fExtendedRadius
)
178 const float fDistFromRadius
= aux
.distance
- m_flareLight
.m_fRadius
;
179 const float fRedundantLength
= fExtendedRadius
- m_flareLight
.m_fRadius
;
180 m_globalFlareBrightness
*= clamp_tpl(1.0f
- fDistFromRadius
/ fRedundantLength
, 0.0f
, 1.0f
);
184 m_globalFlareBrightness
*= clamp_tpl(aux
.distance
/ m_flareLight
.m_fRadius
, 0.0f
, 1.0f
);
189 m_globalFlareBrightness
*= clamp_tpl(1.0f
- aux
.distance
/ m_flareLight
.m_fRadius
, 0.0f
, 1.0f
);
193 if (m_bAffectedByLightFOV
)
195 m_globalFlareBrightness
*= aux
.viewAngleFalloff
;
198 float fShaftVisibilityFactor
= aux
.bForceRender
? 1.0f
: GetShaftVisibilityFactor();
199 float fFlareVisibilityFactor
= aux
.bForceRender
? 1.0f
: GetFlareVisibilityFactor();
201 m_globalShaftBrightness
= m_globalFlareBrightness
* fShaftVisibilityFactor
;
202 m_globalFlareBrightness
*= fFlareVisibilityFactor
;
204 m_globalOcclusionBokeh
= m_bOcclusionBokeh
& IsOcclusionEnabled();
205 m_globalOrbitAngle
= m_fOrbitAngle
;
206 m_globalTransform
= m_mxTransform
;
208 COpticsGroup::validateChildrenGlobalVars(aux
);
211 void RootOpticsElement::RenderPreview(const SLensFlareRenderParam
* pParam
, const Vec3
& vPos
)
215 if (!pParam
->IsValid())
218 _smart_ptr
<CRenderView
> pRenderView
= pParam
->passInfo
.GetRenderView();
220 if (gcpRendD3D
->m_pRT
->IsRenderThread())
222 return RT_RenderPreview(vPos
, pParam
);
225 gcpRendD3D
->m_pRT
->ExecuteRenderThreadCommand([=]
227 std::shared_ptr
<CGraphicsPipeline
> pGraphicsPipeline
= pRenderView
->GetGraphicsPipeline();
228 pGraphicsPipeline
->SetCurrentRenderView(pRenderView
.get());
229 RT_RenderPreview(vPos
, pParam
);
230 }, ERenderCommandFlags::None
);
233 void RootOpticsElement::RT_RenderPreview(const Vec3
& vPos
, const SLensFlareRenderParam
* pParam
)
235 CRY_PROFILE_REGION(PROFILE_RENDERER
, "RootOpticsElement::RT_RenderPreview")
239 light
.m_fRadius
= 10000.0f
;
240 light
.m_bAttachToSun
= false;
241 light
.m_cLdrClr
= ColorF(1, 1, 1, 1);
242 light
.m_fClrMultiplier
= 1;
243 light
.m_fViewAngleFalloff
= 1;
245 const bool bIgnoreOcclusionQueries
= true;
247 if (CTexture
* pDstRT
= gcpRendD3D
->GetActiveDisplayContext()->GetCurrentBackBuffer())
249 CClearSurfacePass::Execute(pDstRT
, Clr_Empty
);
251 D3DViewPort viewport
;
252 viewport
.TopLeftX
= viewport
.TopLeftY
= 0.0f
;
253 viewport
.Width
= float(pDstRT
->GetWidth());
254 viewport
.Height
= float(pDstRT
->GetHeight());
255 viewport
.MinDepth
= 0.0f
;
256 viewport
.MaxDepth
= 1.0f
;
258 _smart_ptr
<CRenderView
> pRenderView
= pParam
->passInfo
.GetRenderView();
259 SRenderViewInfo viewInfo
[CCamera::eEye_eCount
];
260 size_t viewInfoCount
= pRenderView
->GetGraphicsPipeline()->GenerateViewInfo(viewInfo
);
262 std::vector
<CPrimitiveRenderPass
*> prePasses
;
264 CPrimitiveRenderPass previewPass
;
265 previewPass
.SetRenderTarget(0, pDstRT
);
266 previewPass
.SetViewport(viewport
);
267 previewPass
.BeginAddingPrimitives();
269 if (ProcessAll(previewPass
, prePasses
, light
, viewInfo
, viewInfoCount
, true, bIgnoreOcclusionQueries
))
270 previewPass
.Execute();
274 bool RootOpticsElement::ProcessAll(CPrimitiveRenderPass
& targetPass
, std::vector
<CPrimitiveRenderPass
*>& prePasses
, const SFlareLight
& light
, const SRenderViewInfo
* pViewInfo
, int viewInfoCount
, bool bForceRender
, bool bUpdateOcclusion
)
276 CRY_ASSERT(IsGroupEnabled() && (viewInfoCount
> 0) && (viewInfoCount
<= CCamera::eEye_eCount
));
278 Vec3 vSrcWorldPos
= light
.m_vPos
;
281 m_flareLight
= light
;
282 float linearDepth
= 0;
285 // Ideally we'd use the center camera here
286 const SRenderViewInfo
& viewInfo
= pViewInfo
[0];
288 if (!CFlareSoftOcclusionQuery::ComputeProjPos(vSrcWorldPos
, viewInfo
.viewMatrix
, viewInfo
.projMatrix
, vSrcProjPos
))
291 if (viewInfo
.flags
& SRenderViewInfo::eFlags_ReverseDepth
)
292 vSrcProjPos
.z
= 1.0f
- vSrcProjPos
.z
;
294 linearDepth
= clamp_tpl(CFlareSoftOcclusionQuery::ComputeLinearDepth(vSrcWorldPos
, viewInfo
.viewMatrix
, viewInfo
.nearClipPlane
, viewInfo
.farClipPlane
), -1.0f
, 0.99f
);
295 distance
= viewInfo
.cameraOrigin
.GetDistance(vSrcWorldPos
);
297 if (!bForceRender
&& (linearDepth
<= 0 || !IsVisibleBasedOnLight(light
, distance
)))
300 float fFade
= 1 - 1000.f
* m_fDistanceFadingFactor
* linearDepth
;
301 if (!light
.m_bAttachToSun
&& fFade
<= 0.001f
)
304 if (!bForceRender
&& IsOcclusionEnabled())
306 float curTargetVisibility
= 0.0f
;
307 m_fFlareVisibilityFactor
= m_fShaftVisibilityFactor
= 0.0f
;
311 curTargetVisibility
= m_pOccQuery
->GetVisibility();
313 if (CSoftOcclusionVisiblityFader
* pFader
= m_pOccQuery
->GetVisibilityFader(VISFADER_FLARE
))
314 m_fFlareVisibilityFactor
= bUpdateOcclusion
? pFader
->UpdateVisibility(curTargetVisibility
, m_fFlareTimelineDuration
) : pFader
->m_fVisibilityFactor
;
316 if (CSoftOcclusionVisiblityFader
* pFader
= m_pOccQuery
->GetVisibilityFader(VISFADER_SHAFT
))
317 m_fShaftVisibilityFactor
= bUpdateOcclusion
? pFader
->UpdateVisibility(curTargetVisibility
, m_fShaftTimelineDuration
) : pFader
->m_fVisibilityFactor
;
324 SPreparePrimitivesContext
context(targetPass
, prePasses
);
325 context
.pViewInfo
= pViewInfo
;
326 context
.viewInfoCount
= viewInfoCount
;
327 context
.lightWorldPos
= vSrcWorldPos
;
328 context
.lightScreenPos
[0] = vSrcProjPos
;
330 for (int i
= 1; i
< viewInfoCount
; ++i
)
333 if (CFlareSoftOcclusionQuery::ComputeProjPos(vSrcWorldPos
, pViewInfo
[i
].viewMatrix
, pViewInfo
[i
].projMatrix
, projPos
))
335 if (pViewInfo
[i
].flags
& SRenderViewInfo::eFlags_ReverseDepth
)
336 projPos
.z
= 1.0f
- projPos
.z
;
338 PREFAST_ASSUME(i
> 0 && i
< CCamera::eEye_eCount
);
339 context
.lightScreenPos
[i
] = projPos
;
343 context
.auxParams
.linearDepth
= linearDepth
;
344 context
.auxParams
.distance
= distance
;
345 float x
= vSrcProjPos
.x
* 2 - 1;
346 float y
= vSrcProjPos
.y
* 2 - 1;
347 float unitLenSq
= (x
* x
+ y
* y
);
348 context
.auxParams
.sensorVariationValue
= clamp_tpl((1 - powf(unitLenSq
, 0.25f
)) * 2 - 1, -1.0f
, 1.0f
);
349 context
.auxParams
.perspectiveShortening
= clamp_tpl(10.f
* (1.f
- vSrcProjPos
.z
), 0.0f
, 2.0f
);
350 context
.auxParams
.viewAngleFalloff
= light
.m_fViewAngleFalloff
;
351 context
.auxParams
.attachToSun
= light
.m_bAttachToSun
;
352 context
.auxParams
.bMultiplyColor
= IsMultiplyColor();
353 context
.auxParams
.bForceRender
= bForceRender
;
354 context
.auxParams
.bIgnoreOcclusionQueries
= bUpdateOcclusion
;
356 validateGlobalVars(context
.auxParams
);
357 if (bForceRender
|| m_globalFlareBrightness
> 0.001f
|| m_globalShaftBrightness
> 0.001f
)
358 COpticsGroup::PreparePrimitives(context
);