You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/CryEngine/RenderDll/Common/RendElements/RootOpticsElement.cpp

352 lines
13 KiB
C++

/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "RenderDll_precompiled.h"
#include "RootOpticsElement.h"
#include "FlareSoftOcclusionQuery.h"
#include "../Textures/Texture.h"
#include "DriverD3D.h"
#include "D3DPostProcess.h"
#include "stdarg.h"
enum EVisFader
{
VISFADER_FLARE = 0,
VISFADER_SHAFT,
VISFADER_NUM
};
#if defined(FLARES_SUPPORT_EDITING)
#define MFPtr(FUNC_NAME) (Optics_MFPtr)(&RootOpticsElement::FUNC_NAME)
void RootOpticsElement::InitEditorParamGroups(AZStd::vector<FuncVariableGroup>& groups)
{
COpticsGroup::InitEditorParamGroups(groups);
FuncVariableGroup rootGroup;
rootGroup.SetName("GlobalSettings", "Global Settings");
rootGroup.AddVariable(new OpticsMFPVariable(e_BOOL, "Enable Occlusion", "Enable Occlusion", this, MFPtr(SetOcclusionEnabled), MFPtr(IsOcclusionEnabled)));
rootGroup.AddVariable(new OpticsMFPVariable(e_VEC2, "Occlusion Size", "The size for occlusion plane", this, MFPtr(SetOccSize), MFPtr(GetOccSize)));
rootGroup.AddVariable(new OpticsMFPVariable(e_FLOAT, "Flare fade time", "The duration of flare afterimage fading in seconds", this, MFPtr(SetFlareFadingDuration), MFPtr(GetFlareFadingDuration)));
rootGroup.AddVariable(new OpticsMFPVariable(e_FLOAT, "Shaft fade time", "The duration of shaft afterimage fading in seconds", this, MFPtr(SetShaftFadingDuration), MFPtr(GetShaftFadingDuration)));
rootGroup.AddVariable(new OpticsMFPVariable(e_BOOL, "Affected by light color", "light color can affect flare color", this, MFPtr(SetAffectedByLightColor), MFPtr(IsAffectedByLightColor)));
rootGroup.AddVariable(new OpticsMFPVariable(e_BOOL, "Affected by light radius", "light radius can affect flare fading", this, MFPtr(SetAffectedByLightRadius), MFPtr(IsAffectedByLightRadius)));
rootGroup.AddVariable(new OpticsMFPVariable(e_BOOL, "Affected by light FOV", "light projection FOV can affect flare fading", this, MFPtr(SetAffectedByLightFOV), MFPtr(IsAffectedByLightFOV)));
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)));
groups.push_back(rootGroup);
FuncVariableGroup sensorGroup;
sensorGroup.SetName("Sensor");
sensorGroup.AddVariable(new OpticsMFPVariable(e_BOOL, "Custom Sensor Variation Map", "Enable Custom Sensor Variation Map", this, MFPtr(SetCustomSensorVariationMapEnabled), MFPtr(IsCustomSensorVariationMapEnabled)));
sensorGroup.AddVariable(new OpticsMFPVariable(e_FLOAT, "Effective Sensor Size", "The size of image-able part of the sensor", this, MFPtr(SetEffectiveSensorSize), MFPtr(GetEffectiveSensorSize)));
groups.push_back(sensorGroup);
}
#undef MFPtr
#endif
void RootOpticsElement::Load(IXmlNode* pNode)
{
COpticsElement::Load(pNode);
XmlNodeRef pGloabalSettingsNode = pNode->findChild("GlobalSettings");
if (pGloabalSettingsNode)
{
bool bOcclusionEnabled(m_bOcclusionEnabled);
if (pGloabalSettingsNode->getAttr("EnableOcclusion", bOcclusionEnabled))
{
SetOcclusionEnabled(bOcclusionEnabled);
}
Vec2 occlusionSize(m_OcclusionSize);
if (pGloabalSettingsNode->getAttr("OcclusionSize", occlusionSize))
{
SetOccSize(occlusionSize);
}
float fFlareTimelineDuration(m_fFlareTimelineDuration);
if (pGloabalSettingsNode->getAttr("Flarefadetime", fFlareTimelineDuration))
{
SetFlareFadingDuration(fFlareTimelineDuration);
}
float fShaftTimelineDuration(m_fShaftTimelineDuration);
if (pGloabalSettingsNode->getAttr("Flarefadetime", fShaftTimelineDuration))
{
SetShaftFadingDuration(fShaftTimelineDuration);
}
bool bAffectedByLightColor(m_bAffectedByLightColor);
if (pGloabalSettingsNode->getAttr("Affectedbylightcolor", bAffectedByLightColor))
{
SetAffectedByLightColor(bAffectedByLightColor);
}
bool bAffectedByLightRadius(m_bAffectedByLightRadius);
if (pGloabalSettingsNode->getAttr("Affectedbylightradius", bAffectedByLightRadius))
{
SetAffectedByLightRadius(bAffectedByLightRadius);
}
bool bAffectedByLightFOV(m_bAffectedByLightFOV);
if (pGloabalSettingsNode->getAttr("AffectedbylightFOV", bAffectedByLightFOV))
{
SetAffectedByLightFOV(bAffectedByLightFOV);
}
bool bMultiplyColor(m_bMultiplyColor);
if (pGloabalSettingsNode->getAttr("MultiplyColor", bMultiplyColor))
{
SetMultiplyColor(bMultiplyColor);
}
}
XmlNodeRef pSensorNode = pNode->findChild("Sensor");
if (pSensorNode)
{
bool bCustomSensorVariationMap(m_bCustomSensorVariationMap);
if (pSensorNode->getAttr("CustomSensorVariationMap", bCustomSensorVariationMap))
{
SetCustomSensorVariationMapEnabled(bCustomSensorVariationMap);
}
float fEffectiveSensorSize(m_fEffectiveSensorSize);
if (pSensorNode->getAttr("EffectiveSensorSize", fEffectiveSensorSize))
{
SetEffectiveSensorSize(fEffectiveSensorSize);
}
}
}
void RootOpticsElement::SetOcclusionQuery(CFlareSoftOcclusionQuery* query)
{
m_pOccQuery = query;
}
float RootOpticsElement::GetFlareVisibilityFactor() const
{
CSoftOcclusionVisiblityFader* pFader = m_pOccQuery ? m_pOccQuery->GetVisibilityFader(VISFADER_FLARE) : NULL;
return pFader ? pFader->m_fVisibilityFactor : 0.0f;
}
float RootOpticsElement::GetShaftVisibilityFactor() const
{
CSoftOcclusionVisiblityFader* pFader = m_pOccQuery ? m_pOccQuery->GetVisibilityFader(VISFADER_SHAFT) : NULL;
return pFader ? pFader->m_fVisibilityFactor : 0.0f;
}
void RootOpticsElement::SetVisibilityFactor(float f)
{
f = clamp_tpl(f, 0.f, 1.f);
if (m_pOccQuery)
{
for (uint i = 0; i < VISFADER_NUM; ++i)
{
if (CSoftOcclusionVisiblityFader* pFader = m_pOccQuery->GetVisibilityFader(i))
{
pFader->m_fVisibilityFactor = f;
}
}
}
}
CTexture* RootOpticsElement::GetOcclusionPattern()
{
return m_pOccQuery->GetGatherTexture();
}
void RootOpticsElement::validateGlobalVars(SAuxParams& aux)
{
m_globalPerpectiveFactor = m_fPerpectiveFactor;
m_globalDistanceFadingFactor = m_flareLight.m_bAttachToSun ? 0.0f : m_fDistanceFadingFactor;
m_globalSensorBrightnessFactor = m_fSensorBrightnessFactor;
m_globalSensorSizeFactor = m_fSensorSizeFactor;
m_globalSize = m_fSize;
m_globalFlareBrightness = GetBrightness();
m_globalMovement = m_vMovement;
if (m_bAffectedByLightColor)
{
if (aux.bMultiplyColor)
{
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);
}
else
{
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);
}
m_globalFlareBrightness *= m_flareLight.m_fClrMultiplier;
}
else
{
m_globalColor = m_Color;
}
if (m_bAffectedByLightRadius)
{
m_globalFlareBrightness *= clamp_tpl(1 - aux.distance / m_flareLight.m_fRadius, 0.0f, 1.0f);
}
if (m_bAffectedByLightFOV)
{
m_globalFlareBrightness *= aux.viewAngleFalloff;
}
float fShaftVisibilityFactor = aux.bForceRender ? 1.0f : GetShaftVisibilityFactor();
float fFlareVisibilityFactor = aux.bForceRender ? 1.0f : GetFlareVisibilityFactor();
m_globalShaftBrightness = m_globalFlareBrightness * fShaftVisibilityFactor;
m_globalFlareBrightness *= fFlareVisibilityFactor;
m_globalOcclusionBokeh = m_bOcclusionBokeh & IsOcclusionEnabled();
m_globalCorrectAspectRatio = m_globalCorrectAspectRatio;
m_globalAutoRotation = m_globalAutoRotation;
m_globalOrbitAngle = m_fOrbitAngle;
m_globalTransform = m_mxTransform;
COpticsGroup::validateChildrenGlobalVars(aux);
}
void RootOpticsElement::Render(SLensFlareRenderParam* pParam, const Vec3& vPos)
{
if (pParam == NULL)
{
return;
}
if (!pParam->IsValid())
{
return;
}
SFlareLight light;
light.m_vPos = vPos;
light.m_fRadius = 10000.0f;
light.m_bAttachToSun = false;
light.m_cLdrClr = ColorF(1, 1, 1, 1);
light.m_fClrMultiplier = 1;
light.m_fViewAngleFalloff = 1;
ProcessAll((CShader*)pParam->pShader, light, true, pParam->pCamera);
}
bool RootOpticsElement::ProcessAll(CShader* shader, SFlareLight& light, bool bForceRender, CCamera* pCamera)
{
CD3D9Renderer* pRD = gcpRendD3D;
Vec3 vSrcWorldPos = light.m_vPos;
Vec3 vSrcProjPos;
m_flareLight = light;
float linearDepth = 0;
float distance = 0;
if (pCamera)
{
Matrix44A mProj, mView;
mathMatrixPerspectiveFov(&mProj, pCamera->GetFov(), pCamera->GetProjRatio(), pCamera->GetNearPlane(), pCamera->GetFarPlane());
mathMatrixLookAt(&mView, pCamera->GetPosition(), pCamera->GetPosition() + pCamera->GetViewdir(), Vec3(0, 0, 1));
if (!CFlareSoftOcclusionQuery::ComputeProjPos(vSrcWorldPos, mView, mProj, vSrcProjPos))
{
return false;
}
linearDepth = clamp_tpl(CFlareSoftOcclusionQuery::ComputeLinearDepth(vSrcWorldPos, mView, pCamera->GetNearPlane(), pCamera->GetFarPlane()), -1.0f, 0.99f);
distance = mView.GetTranslation().GetDistance(vSrcWorldPos);
}
else
{
if (!CFlareSoftOcclusionQuery::ComputeProjPos(vSrcWorldPos, pRD->m_ViewMatrix, pRD->m_ProjMatrix, vSrcProjPos))
{
return false;
}
if (pRD->m_RP.m_TI[pRD->m_RP.m_nProcessThreadID].m_PersFlags & RBPF_REVERSE_DEPTH)
{
vSrcProjPos.z = 1.0f - vSrcProjPos.z;
}
const CameraViewParameters& rc = gRenDev->GetViewParameters();
linearDepth = clamp_tpl(CFlareSoftOcclusionQuery::ComputeLinearDepth(vSrcWorldPos, pRD->m_CameraMatrix, rc.fNear, rc.fFar), -1.0f, 0.99f);
distance = pRD->GetViewParameters().vOrigin.GetDistance(vSrcWorldPos);
}
if (GetElementCount() <= 0 || !IsEnabled())
{
return false;
}
if (!bForceRender && (linearDepth <= 0 || !IsVisibleBasedOnLight(light, distance)))
{
return false;
}
bool bVisible(!IsOcclusionEnabled());
if (!bVisible && !bForceRender)
{
float curTargetVisibility = 0.0f;
m_fFlareVisibilityFactor = m_fShaftVisibilityFactor = 0.0f;
if (m_pOccQuery)
{
curTargetVisibility = m_pOccQuery->GetVisibility();
if (CSoftOcclusionVisiblityFader* pFader = m_pOccQuery->GetVisibilityFader(VISFADER_FLARE))
{
m_fFlareVisibilityFactor = pFader->UpdateVisibility(curTargetVisibility, m_fFlareTimelineDuration);
}
if (CSoftOcclusionVisiblityFader* pFader = m_pOccQuery->GetVisibilityFader(VISFADER_SHAFT))
{
m_fShaftVisibilityFactor = pFader->UpdateVisibility(curTargetVisibility, m_fShaftTimelineDuration);
}
}
bVisible = IsVisible();
}
if (bVisible || bForceRender)
{
SAuxParams aux;
aux.linearDepth = linearDepth;
aux.distance = distance;
float x = vSrcProjPos.x * 2 - 1;
float y = vSrcProjPos.y * 2 - 1;
float unitLenSq = (x * x + y * y);
aux.sensorVariationValue = clamp_tpl((1 - powf(unitLenSq, 0.25f)) * 2 - 1, -1.0f, 1.0f);
aux.perspectiveShortening = clamp_tpl(10.f * (1.f - vSrcProjPos.z), 0.0f, 2.0f);
aux.viewAngleFalloff = light.m_fViewAngleFalloff;
aux.attachToSun = light.m_bAttachToSun;
aux.bMultiplyColor = IsMultiplyColor();
aux.bForceRender = bForceRender;
// The legacy entity system does not allow for overriding the color, brightness and size of lens flares.
// The new component systems does allow for overriding these values so we apply them only when valid
if (light.m_opticsParams.m_isValid)
{
SetColor(light.m_opticsParams.m_color);
SetBrightness(light.m_opticsParams.m_brightness);
SetSize(light.m_opticsParams.m_size);
}
validateGlobalVars(aux);
if (bForceRender || m_globalFlareBrightness > 0.001f || m_globalShaftBrightness > 0.001f)
{
gcpRendD3D->m_RP.m_PersFlags2 |= RBPF2_LENS_OPTICS_COMPOSITE;
COpticsGroup::Render(shader, vSrcWorldPos, vSrcProjPos, aux);
}
}
return true;
}