From 9e65e940d026ee158eaa3eb6a94280133ed789b7 Mon Sep 17 00:00:00 2001 From: Tim Barnes Date: Wed, 21 Nov 2018 15:53:02 +1000 Subject: [PATCH] lighting single buffer --- .../source/T3D/lighting/reflectionProbe.cpp | 8 +- Engine/source/T3D/lighting/reflectionProbe.h | 3 + Engine/source/T3D/lighting/skylight.cpp | 2 +- Engine/source/T3D/objectTypes.h | 5 +- Engine/source/gfx/D3D11/gfxD3D11Device.cpp | 57 ++------ Engine/source/gfx/D3D11/gfxD3D11Device.h | 13 +- Engine/source/gfx/D3D11/gfxD3D11Shader.cpp | 2 +- .../advanced/advancedLightBinManager.cpp | 36 +---- .../advanced/advancedLightBinManager.h | 2 - .../hlsl/deferredShadingFeaturesHLSL.cpp | 22 +++ .../hlsl/deferredShadingFeaturesHLSL.h | 12 ++ .../source/materials/materialFeatureTypes.cpp | 1 + .../source/materials/materialFeatureTypes.h | 1 + .../renderInstance/renderDeferredMgr.cpp | 52 +++---- .../source/renderInstance/renderDeferredMgr.h | 4 - .../renderInstance/renderFormatChanger.cpp | 28 ++-- .../source/renderInstance/renderProbeMgr.cpp | 33 +---- .../shaderGen/HLSL/shaderGenHLSLInit.cpp | 1 + .../game/core/art/{ => pbr}/brdfTexture.dds | Bin .../game/core/art/pbr/default_irradiance.dds | Bin 0 -> 131192 bytes .../game/core/art/pbr/default_prefilter.dds | Bin 0 -> 131192 bytes .../lighting/advanced/deferredShading.cs | 51 ------- .../client/lighting/advanced/lightViz.cs | 126 +--------------- .../client/lighting/advanced/shaders.cs | 20 ++- .../game/core/scripts/client/renderManager.cs | 2 +- Templates/Full/game/shaders/common/brdf.hlsl | 3 +- .../Full/game/shaders/common/lighting.hlsl | 96 +++++++----- .../advanced/dbgLightColorVisualizeP.hlsl | 32 ---- .../advanced/dbgLightSpecularVisualizeP.hlsl | 31 ---- .../lighting/advanced/deferredShadingP.hlsl | 54 ------- .../lighting/advanced/lightingUtils.hlsl | 51 ------- .../common/lighting/advanced/pointLightP.hlsl | 34 ++--- .../lighting/advanced/reflectionProbeP.hlsl | 124 +++++++--------- .../common/lighting/advanced/skylightP.hlsl | 37 +++-- .../common/lighting/advanced/spotLightP.hlsl | 137 +++++------------- .../lighting/advanced/vectorLightP.hlsl | 26 +--- .../shaders/common/shaderModelAutoGen.hlsl | 16 -- 37 files changed, 309 insertions(+), 813 deletions(-) rename Templates/Full/game/core/art/{ => pbr}/brdfTexture.dds (100%) create mode 100644 Templates/Full/game/core/art/pbr/default_irradiance.dds create mode 100644 Templates/Full/game/core/art/pbr/default_prefilter.dds delete mode 100644 Templates/Full/game/shaders/common/lighting/advanced/dbgLightColorVisualizeP.hlsl delete mode 100644 Templates/Full/game/shaders/common/lighting/advanced/dbgLightSpecularVisualizeP.hlsl delete mode 100644 Templates/Full/game/shaders/common/lighting/advanced/deferredShadingP.hlsl delete mode 100644 Templates/Full/game/shaders/common/lighting/advanced/lightingUtils.hlsl diff --git a/Engine/source/T3D/lighting/reflectionProbe.cpp b/Engine/source/T3D/lighting/reflectionProbe.cpp index 7ba6593b9..9a1767365 100644 --- a/Engine/source/T3D/lighting/reflectionProbe.cpp +++ b/Engine/source/T3D/lighting/reflectionProbe.cpp @@ -144,6 +144,8 @@ ReflectionProbe::ReflectionProbe() mEditPosOffset = false; mProbeInfoIdx = -1; + + mCaptureMask = REFLECTION_PROBE_CAPTURE_TYPEMASK; } ReflectionProbe::~ReflectionProbe() @@ -620,9 +622,9 @@ bool ReflectionProbe::createClientResources() //brdf lookup resources //make the brdf lookup texture the same size as the prefilter texture - String brdfPath = Con::getVariable("$Core::BRDFTexture", "core/art/brdfTexture.dds"); + String brdfPath = Con::getVariable("$Core::BRDFTexture", "core/art/pbr/brdfTexture.dds"); - mBrdfTexture = TEXMGR->createTexture(brdfPath, &GFXTexturePersistentProfile);// TEXMGR->createTexture(mPrefilterSize, mPrefilterSize, GFXFormatR16G16B16A16F, &GFXRenderTargetProfile, 1, 0); + mBrdfTexture = TEXMGR->createTexture(brdfPath, &GFXTexturePersistentProfile); if (!mBrdfTexture) { @@ -978,7 +980,7 @@ void ReflectionProbe::bake(String outputPath, S32 resolution, bool renderWithPro MathUtils::makeFrustum(&left, &right, &top, &bottom, M_HALFPI_F, 1.0f, nearPlane); Frustum frustum(false, left, right, top, bottom, nearPlane, farDist); - renderFrame(&baseTarget, matView, frustum, StaticObjectType | StaticShapeObjectType & EDITOR_RENDER_TYPEMASK, gCanvasClearColor); + renderFrame(&baseTarget, matView, frustum, mCaptureMask & EDITOR_RENDER_TYPEMASK, gCanvasClearColor); baseTarget->resolve(); } diff --git a/Engine/source/T3D/lighting/reflectionProbe.h b/Engine/source/T3D/lighting/reflectionProbe.h index 90100a020..e1d430016 100644 --- a/Engine/source/T3D/lighting/reflectionProbe.h +++ b/Engine/source/T3D/lighting/reflectionProbe.h @@ -169,6 +169,7 @@ protected: F32 mMaxDrawDistance; bool mResourcesCreated; + U32 mCaptureMask; public: ReflectionProbe(); @@ -242,6 +243,8 @@ public: String getPrefilterMapPath(); String getIrradianceMapPath(); void bake(String outputPath, S32 resolution, bool renderWithProbes = false); + + const U32 getProbeInfoIndex() { return mProbeInfoIdx; } }; typedef ProbeRenderInst::ProbeShapeType ReflectProbeType; diff --git a/Engine/source/T3D/lighting/skylight.cpp b/Engine/source/T3D/lighting/skylight.cpp index c55e43a5a..87823b904 100644 --- a/Engine/source/T3D/lighting/skylight.cpp +++ b/Engine/source/T3D/lighting/skylight.cpp @@ -78,7 +78,7 @@ ConsoleDocClass(Skylight, //----------------------------------------------------------------------------- Skylight::Skylight() : ReflectionProbe() { - + mCaptureMask = SKYLIGHT_CAPTURE_TYPEMASK; } Skylight::~Skylight() diff --git a/Engine/source/T3D/objectTypes.h b/Engine/source/T3D/objectTypes.h index 2b27a7171..8f1c4d69e 100644 --- a/Engine/source/T3D/objectTypes.h +++ b/Engine/source/T3D/objectTypes.h @@ -216,7 +216,10 @@ enum SceneObjectTypeMasks : U32 /// /// @note Terrains have their own means for rendering inside interior zones. OUTDOOR_OBJECT_TYPEMASK = ( TerrainObjectType | - EnvironmentObjectType ) + EnvironmentObjectType ), + + SKYLIGHT_CAPTURE_TYPEMASK = (EnvironmentObjectType), + REFLECTION_PROBE_CAPTURE_TYPEMASK = (StaticObjectType | StaticShapeObjectType) }; #endif diff --git a/Engine/source/gfx/D3D11/gfxD3D11Device.cpp b/Engine/source/gfx/D3D11/gfxD3D11Device.cpp index e2fec68e8..5f583450e 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Device.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Device.cpp @@ -38,12 +38,14 @@ #include "gfx/D3D11/screenshotD3D11.h" #include "materials/shaderData.h" #include "shaderGen/shaderGen.h" +#include //d3dperf #ifdef TORQUE_DEBUG #include "d3d11sdklayers.h" #endif #pragma comment(lib, "dxgi.lib") +#pragma comment(lib, "d3d9.lib") //d3dperf #pragma comment(lib, "d3d11.lib") class GFXPCD3D11RegisterDevice @@ -90,9 +92,6 @@ GFXD3D11Device::GFXD3D11Device(U32 index) mAdapterIndex = index; mD3DDevice = NULL; mD3DDeviceContext = NULL; - mD3DDevice1 = NULL; - mD3DDeviceContext1 = NULL; - mUserAnnotation = NULL; mVolatileVB = NULL; mCurrentPB = NULL; @@ -126,7 +125,6 @@ GFXD3D11Device::GFXD3D11Device(U32 index) mCurrentConstBuffer = NULL; mOcclusionQuerySupported = false; - mCbufferPartialSupported = false; mDebugLayers = false; @@ -166,8 +164,6 @@ GFXD3D11Device::~GFXD3D11Device() SAFE_RELEASE(mDeviceBackBufferView); SAFE_RELEASE(mDeviceDepthStencil); SAFE_RELEASE(mDeviceBackbuffer); - SAFE_RELEASE(mUserAnnotation); - SAFE_RELEASE(mD3DDeviceContext1); SAFE_RELEASE(mD3DDeviceContext); SAFE_DELETE(mCardProfiler); @@ -185,7 +181,6 @@ GFXD3D11Device::~GFXD3D11Device() #endif SAFE_RELEASE(mSwapChain); - SAFE_RELEASE(mD3DDevice1); SAFE_RELEASE(mD3DDevice); } @@ -439,6 +434,7 @@ void GFXD3D11Device::init(const GFXVideoMode &mode, PlatformWindow *window) AssertFatal(window, "GFXD3D11Device::init - must specify a window!"); HWND winHwnd = (HWND)window->getSystemWindow( PlatformWindow::WindowSystem_Windows ); + SetFocus(winHwnd); UINT createDeviceFlags = D3D11_CREATE_DEVICE_SINGLETHREADED | D3D11_CREATE_DEVICE_BGRA_SUPPORT; #ifdef TORQUE_DEBUG @@ -489,26 +485,6 @@ void GFXD3D11Device::init(const GFXVideoMode &mode, PlatformWindow *window) #endif } - // Grab DX 11.1 device and context if available and also ID3DUserDefinedAnnotation - hres = mD3DDevice->QueryInterface(__uuidof(ID3D11Device1), reinterpret_cast(&mD3DDevice1)); - if (SUCCEEDED(hres)) - { - //11.1 context - mD3DDeviceContext->QueryInterface(__uuidof(ID3D11DeviceContext1), reinterpret_cast(&mD3DDeviceContext1)); - // ID3DUserDefinedAnnotation - mD3DDeviceContext->QueryInterface(IID_PPV_ARGS(&mUserAnnotation)); - //Check what is supported, windows 7 supports very little from 11.1 - D3D11_FEATURE_DATA_D3D11_OPTIONS options; - mD3DDevice1->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &options, - sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS)); - - //Cbuffer partial updates - if (options.ConstantBufferOffsetting && options.ConstantBufferPartialUpdate) - mCbufferPartialSupported = true; - } - - - //set the fullscreen state here if we need to if(mode.fullScreen) { @@ -1875,28 +1851,27 @@ GFXCubemapArray * GFXD3D11Device::createCubemapArray() //------------------------------------------------------------------------------ void GFXD3D11Device::enterDebugEvent(ColorI color, const char *name) { - if (mUserAnnotation) - { - WCHAR eventName[260]; - MultiByteToWideChar(CP_ACP, 0, name, -1, eventName, 260); - mUserAnnotation->BeginEvent(eventName); - } + // BJGFIX + WCHAR eventName[260]; + MultiByteToWideChar(CP_ACP, 0, name, -1, eventName, 260); + + D3DPERF_BeginEvent(D3DCOLOR_ARGB(color.alpha, color.red, color.green, color.blue), + (LPCWSTR)&eventName); } //------------------------------------------------------------------------------ void GFXD3D11Device::leaveDebugEvent() { - if (mUserAnnotation) - mUserAnnotation->EndEvent(); + D3DPERF_EndEvent(); } //------------------------------------------------------------------------------ void GFXD3D11Device::setDebugMarker(ColorI color, const char *name) { - if (mUserAnnotation) - { - WCHAR eventName[260]; - MultiByteToWideChar(CP_ACP, 0, name, -1, eventName, 260); - mUserAnnotation->SetMarker(eventName); - } + // BJGFIX + WCHAR eventName[260]; + MultiByteToWideChar(CP_ACP, 0, name, -1, eventName, 260); + + D3DPERF_SetMarker(D3DCOLOR_ARGB(color.alpha, color.red, color.green, color.blue), + (LPCWSTR)&eventName); } \ No newline at end of file diff --git a/Engine/source/gfx/D3D11/gfxD3D11Device.h b/Engine/source/gfx/D3D11/gfxD3D11Device.h index 381589c0f..6385a39e1 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Device.h +++ b/Engine/source/gfx/D3D11/gfxD3D11Device.h @@ -23,7 +23,7 @@ #ifndef _GFXD3D11DEVICE_H_ #define _GFXD3D11DEVICE_H_ -#include +#include #include "platform/tmm_off.h" #include "platformWin32/platformWin32.h" @@ -39,9 +39,6 @@ #define D3D11 static_cast(GFX) #define D3D11DEVICE D3D11->getDevice() #define D3D11DEVICECONTEXT D3D11->getDeviceContext() -// DX 11.1 - always check these are not NULL, dodgy support with win 7 -#define D3D11DEVICE1 D3D11->getDevice1() -#define D3D11DEVICECONTEXT1 D3D11->getDeviceContext1() class PlatformWindow; class GFXD3D11ShaderConstBuffer; @@ -129,10 +126,6 @@ protected: IDXGISwapChain *mSwapChain; ID3D11Device* mD3DDevice; ID3D11DeviceContext* mD3DDeviceContext; - // DX 11.1 - ID3D11Device1* mD3DDevice1; - ID3D11DeviceContext1* mD3DDeviceContext1; - ID3DUserDefinedAnnotation* mUserAnnotation; GFXShaderRef mGenericShader[GS_COUNT]; GFXShaderConstBufferRef mGenericShaderBuffer[GS_COUNT]; @@ -153,7 +146,6 @@ protected: DXGI_SAMPLE_DESC mMultisampleDesc; bool mOcclusionQuerySupported; - bool mCbufferPartialSupported; U32 mDrawInstancesCount; @@ -300,9 +292,6 @@ public: ID3D11DeviceContext* getDeviceContext(){ return mD3DDeviceContext; } ID3D11Device* getDevice(){ return mD3DDevice; } IDXGISwapChain* getSwapChain() { return mSwapChain; } - //DX 11.1 - ID3D11DeviceContext1* getDeviceContext1() { return mD3DDeviceContext1; } - ID3D11Device1* getDevice1() { return mD3DDevice1; } /// Reset void reset( DXGI_SWAP_CHAIN_DESC &d3dpp ); diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index 8a53170e7..f70364d6c 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -561,7 +561,7 @@ const String GFXD3D11ShaderConstBuffer::describeSelf() const GenericConstBufferLayout::ParamDesc pd; mVertexConstBufferLayout->getDesc(i, pd); - ret += String::ToString(" Constant name: %s", pd.name); + ret += String::ToString(" Constant name: %s", pd.name.c_str()); } return ret; diff --git a/Engine/source/lighting/advanced/advancedLightBinManager.cpp b/Engine/source/lighting/advanced/advancedLightBinManager.cpp index 17a923f50..89443d28c 100644 --- a/Engine/source/lighting/advanced/advancedLightBinManager.cpp +++ b/Engine/source/lighting/advanced/advancedLightBinManager.cpp @@ -119,17 +119,8 @@ AdvancedLightBinManager::AdvancedLightBinManager( AdvancedLightManager *lm /* = : RenderBinManager( RIT_LightInfo, 1.0f, 1.0f ), mNumLightsCulled(0), mLightManager(lm), - mShadowManager(sm), - mConditioner(NULL) + mShadowManager(sm) { - // Create an RGB conditioner - NamedTexTarget* specLightTarg = NamedTexTarget::find(RenderDeferredMgr::SpecularLightBufferName); - - mConditioner = new AdvancedLightBufferConditioner(lightBufferFormat, - AdvancedLightBufferConditioner::RGB ); - - specLightTarg->setConditioner( mConditioner ); - mMRTLightmapsDuringDeferred = true; Con::NotifyDelegate callback( this, &AdvancedLightBinManager::_deleteLightMaterials ); @@ -143,8 +134,6 @@ AdvancedLightBinManager::~AdvancedLightBinManager() { _deleteLightMaterials(); - SAFE_DELETE(mConditioner); - Con::NotifyDelegate callback( this, &AdvancedLightBinManager::_deleteLightMaterials ); Con::removeVariableNotify( "$pref::shadows::filterMode", callback ); Con::removeVariableNotify( "$AL::PSSMDebugRender", callback ); @@ -274,16 +263,8 @@ void AdvancedLightBinManager::render( SceneRenderState *state ) //if ( !_onPreRender( state ) ) // return; - //GFX->clear(GFXClearTarget, ColorI(0, 0, 0, 0), 1.0f, 0); - - NamedTexTargetRef diffuseLightingTarget = NamedTexTarget::find("diffuseLighting"); - - if (diffuseLightingTarget.isNull()) - return; - - NamedTexTargetRef specularLightingTarget = NamedTexTarget::find("specularLighting"); - - if (specularLightingTarget.isNull()) + NamedTexTargetRef sceneColorTargetRef = NamedTexTarget::find("AL_FormatToken"); + if (sceneColorTargetRef.isNull()) return; GFXTextureTargetRef lightingTargetRef = GFX->allocRenderToTextureTarget(); @@ -294,13 +275,12 @@ void AdvancedLightBinManager::render( SceneRenderState *state ) //Do a quick pass to update our probes if they're dirty PROBEMGR->updateDirtyProbes(); - lightingTargetRef->attachTexture(GFXTextureTarget::Color0, specularLightingTarget->getTexture()); - lightingTargetRef->attachTexture(GFXTextureTarget::Color1, diffuseLightingTarget->getTexture()); + lightingTargetRef->attachTexture(GFXTextureTarget::Color0, sceneColorTargetRef->getTexture()); GFX->pushActiveRenderTarget(); GFX->setActiveRenderTarget(lightingTargetRef); - GFX->setViewport(specularLightingTarget->getViewport()); + GFX->setViewport(sceneColorTargetRef->getViewport()); // Restore transforms MatrixSet &matrixSet = getRenderPass()->getMatrixSet(); @@ -415,7 +395,6 @@ void AdvancedLightBinManager::render( SceneRenderState *state ) // Finish up the rendering //_onPostRender(); - lightingTargetRef->resolve(); GFX->popActiveRenderTarget(); } @@ -765,9 +744,8 @@ void AdvancedLightBinManager::LightMaterialInfo::setLightParameters( const Light 0.0f ); matParams->setSafe( lightSpotParams, spotParams ); - - VectorF lightDir = lightInfo->getDirection(); - matParams->setSafe( lightDirection, lightDir ); + matParams->setSafe( lightDirection, lightInfo->getDirection()); + matParams->setSafe( lightPosition, lightInfo->getPosition()); } // Fall through diff --git a/Engine/source/lighting/advanced/advancedLightBinManager.h b/Engine/source/lighting/advanced/advancedLightBinManager.h index 85e40c2cb..8751c0815 100644 --- a/Engine/source/lighting/advanced/advancedLightBinManager.h +++ b/Engine/source/lighting/advanced/advancedLightBinManager.h @@ -230,8 +230,6 @@ protected: /// void _onShadowFilterChanged(); - AdvancedLightBufferConditioner *mConditioner; - typedef GFXVertexPNTT FarFrustumQuadVert; GFXVertexBufferHandle mFarFrustumQuadVerts; diff --git a/Engine/source/lighting/advanced/hlsl/deferredShadingFeaturesHLSL.cpp b/Engine/source/lighting/advanced/hlsl/deferredShadingFeaturesHLSL.cpp index 59c5d8ce9..a998b2fc4 100644 --- a/Engine/source/lighting/advanced/hlsl/deferredShadingFeaturesHLSL.cpp +++ b/Engine/source/lighting/advanced/hlsl/deferredShadingFeaturesHLSL.cpp @@ -179,3 +179,25 @@ void DeferredSpecVarsHLSL::processPix( Vector &componentList, meta->addStatement(new GenOp(" @.a = @;\r\n", material, metalness)); output = meta; } + +//deferred emissive +void DeferredEmissiveHLSL::processPix(Vector &componentList, const MaterialFeatureData &fd) +{ + //for now emission just uses the diffuse color, we could plug in a separate texture for emission at some stage + Var *diffuseTargetVar = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::RenderTarget1)); + if (!diffuseTargetVar) + return; //oh dear something is not right, maybe we should just write 0's instead + + // search for scene color target var + Var *sceneColorVar = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::RenderTarget3)); + if (!sceneColorVar) + { + // create scene color target var + sceneColorVar = new Var; + sceneColorVar->setType("fragout"); + sceneColorVar->setName(getOutputTargetVarName(ShaderFeature::RenderTarget3)); + sceneColorVar->setStructName("OUT"); + } + + output = new GenOp("@ = float4(@.rgb,0);", sceneColorVar, diffuseTargetVar); +} \ No newline at end of file diff --git a/Engine/source/lighting/advanced/hlsl/deferredShadingFeaturesHLSL.h b/Engine/source/lighting/advanced/hlsl/deferredShadingFeaturesHLSL.h index 1c9ae8e76..4f76226fb 100644 --- a/Engine/source/lighting/advanced/hlsl/deferredShadingFeaturesHLSL.h +++ b/Engine/source/lighting/advanced/hlsl/deferredShadingFeaturesHLSL.h @@ -69,4 +69,16 @@ public: virtual U32 getOutputTargets( const MaterialFeatureData &fd ) const { return ShaderFeature::RenderTarget2; } }; + +class DeferredEmissiveHLSL : public ShaderFeatureHLSL +{ +public: + virtual String getName() { return "Deferred Shading: Emissive"; } + + virtual void processPix(Vector &componentList, + const MaterialFeatureData &fd); + + virtual U32 getOutputTargets(const MaterialFeatureData &fd) const { return ShaderFeature::RenderTarget3; } +}; + #endif \ No newline at end of file diff --git a/Engine/source/materials/materialFeatureTypes.cpp b/Engine/source/materials/materialFeatureTypes.cpp index fd6134381..921236ce3 100644 --- a/Engine/source/materials/materialFeatureTypes.cpp +++ b/Engine/source/materials/materialFeatureTypes.cpp @@ -106,6 +106,7 @@ ImplementFeatureType( MFT_SkyBox, MFG_Transform, 1.0f, false ); ImplementFeatureType( MFT_DeferredSpecMap, MFG_Texture, 8.2f, false ); ImplementFeatureType( MFT_DeferredSpecVars, MFG_Texture, 8.5f, false ); ImplementFeatureType( MFT_DeferredMatInfoFlags, MFG_Texture, 8.7f, false ); +ImplementFeatureType( MFT_DeferredEmissive, MFG_Texture, 8.9f, false); ImplementFeatureType( MFT_HardwareSkinning, MFG_Transform,-2.0, false ); diff --git a/Engine/source/materials/materialFeatureTypes.h b/Engine/source/materials/materialFeatureTypes.h index 89640292b..d976b0054 100644 --- a/Engine/source/materials/materialFeatureTypes.h +++ b/Engine/source/materials/materialFeatureTypes.h @@ -193,4 +193,5 @@ DeclareFeatureType( MFT_SkyBox ); DeclareFeatureType( MFT_DeferredSpecMap ); DeclareFeatureType( MFT_DeferredSpecVars ); DeclareFeatureType( MFT_DeferredMatInfoFlags ); +DeclareFeatureType( MFT_DeferredEmissive ); #endif // _MATERIALFEATURETYPES_H_ diff --git a/Engine/source/renderInstance/renderDeferredMgr.cpp b/Engine/source/renderInstance/renderDeferredMgr.cpp index e4bceab56..aad88e115 100644 --- a/Engine/source/renderInstance/renderDeferredMgr.cpp +++ b/Engine/source/renderInstance/renderDeferredMgr.cpp @@ -56,8 +56,6 @@ const String RenderDeferredMgr::BufferName("deferred"); const RenderInstType RenderDeferredMgr::RIT_Deferred("Deferred"); const String RenderDeferredMgr::ColorBufferName("color"); const String RenderDeferredMgr::MatInfoBufferName("matinfo"); -const String RenderDeferredMgr::DiffuseLightBufferName("diffuseLighting"); -const String RenderDeferredMgr::SpecularLightBufferName("specularLighting"); IMPLEMENT_CONOBJECT(RenderDeferredMgr); @@ -104,8 +102,6 @@ RenderDeferredMgr::RenderDeferredMgr( bool gatherDepth, mNamedTarget.registerWithName( BufferName ); mColorTarget.registerWithName( ColorBufferName ); mMatInfoTarget.registerWithName( MatInfoBufferName ); - mDiffuseLightTarget.registerWithName( DiffuseLightBufferName ); - mSpecularLightTarget.registerWithName(SpecularLightBufferName); _registerFeatures(); } @@ -116,8 +112,6 @@ RenderDeferredMgr::~RenderDeferredMgr() mColorTarget.release(); mMatInfoTarget.release(); - mDiffuseLightTarget.release(); - mSpecularLightTarget.release(); _unregisterFeatures(); SAFE_DELETE( mDeferredMatInstance ); } @@ -141,8 +135,6 @@ bool RenderDeferredMgr::setTargetSize(const Point2I &newTargetSize) mNamedTarget.setViewport( GFX->getViewport() ); mColorTarget.setViewport( GFX->getViewport() ); mMatInfoTarget.setViewport( GFX->getViewport() ); - mDiffuseLightTarget.setViewport( GFX->getViewport() ); - mSpecularLightTarget.setViewport(GFX->getViewport()); return ret; } @@ -183,35 +175,25 @@ bool RenderDeferredMgr::_updateTargets() mMatInfoTex.set(mTargetSize.x, mTargetSize.y, matInfoFormat, &GFXRenderTargetProfile, avar("%s() - (line %d)", __FUNCTION__, __LINE__), 1, GFXTextureManager::AA_MATCH_BACKBUFFER); - mMatInfoTarget.setTexture(mMatInfoTex); + mMatInfoTarget.setTexture(mMatInfoTex); for (U32 i = 0; i < mTargetChainLength; i++) mTargetChain[i]->attachTexture(GFXTextureTarget::Color2, mMatInfoTarget.getTexture()); } - if (mDiffuseLightTex.getFormat() != GFXFormatR16G16B16A16F || mDiffuseLightTex.getWidthHeight() != mTargetSize || GFX->recentlyReset()) + //scene color target + NamedTexTargetRef sceneColorTargetRef = NamedTexTarget::find("AL_FormatToken"); + if (sceneColorTargetRef.isValid()) { - mDiffuseLightTarget.release(); - mDiffuseLightTex.set(mTargetSize.x, mTargetSize.y, GFXFormatR16G16B16A16F, - &GFXRenderTargetProfile, avar("%s() - (line %d)", __FUNCTION__, __LINE__), - 1, GFXTextureManager::AA_MATCH_BACKBUFFER); - mDiffuseLightTarget.setTexture(mDiffuseLightTex); - for (U32 i = 0; i < mTargetChainLength; i++) - mTargetChain[i]->attachTexture(GFXTextureTarget::Color3, mDiffuseLightTarget.getTexture()); + mTargetChain[i]->attachTexture(GFXTextureTarget::Color3, sceneColorTargetRef->getTexture(0)); + } + else + { + Con::errorf("RenderDeferredMgr: Could not find AL_FormatToken"); + return false; } - if (mSpecularLightTex.getFormat() != GFXFormatR16G16B16A16F || mSpecularLightTex.getWidthHeight() != mTargetSize || GFX->recentlyReset()) - { - mSpecularLightTarget.release(); - mSpecularLightTex.set(mTargetSize.x, mTargetSize.y, GFXFormatR16G16B16A16F, - &GFXRenderTargetProfile, avar("%s() - (line %d)", __FUNCTION__, __LINE__), - 1, GFXTextureManager::AA_MATCH_BACKBUFFER); - mSpecularLightTarget.setTexture(mSpecularLightTex); - - for (U32 i = 0; i < mTargetChainLength; i++) - mTargetChain[i]->attachTexture(GFXTextureTarget::Color4, mSpecularLightTarget.getTexture()); - } GFX->finalizeReset(); return ret; @@ -337,12 +319,11 @@ void RenderDeferredMgr::render( SceneRenderState *state ) const bool isRenderingToTarget = _onPreRender(state); // Clear z-buffer and g-buffer. - GFX->clear(GFXClearZBuffer | GFXClearStencil, ColorI::ZERO, 1.0f, 0); + GFX->clear(GFXClearZBuffer | GFXClearStencil, LinearColorF::ZERO, 1.0f, 0); GFX->clearColorAttachment(0, LinearColorF::ONE);//normdepth GFX->clearColorAttachment(1, LinearColorF::ZERO);//albedo GFX->clearColorAttachment(2, LinearColorF::ZERO);//matinfo - GFX->clearColorAttachment(3, LinearColorF::ZERO);//diffuse - GFX->clearColorAttachment(4, LinearColorF::ZERO);//specular + //AL_FormatToken is cleared by it's own class // Restore transforms MatrixSet &matrixSet = getRenderPass()->getMatrixSet(); @@ -358,7 +339,7 @@ void RenderDeferredMgr::render( SceneRenderState *state ) mDeferredMatInstance->setTransforms(matrixSet, state); } - // Signal start of pre-pass + // Signal start of deferred getRenderSignal().trigger( state, this, true ); // First do a loop and render all the terrain... these are @@ -751,8 +732,11 @@ void ProcessedDeferredMaterial::_determineFeatures( U32 stageNum, } else { - // If this object isn't lightmapped, add a zero-output feature to it - newFeatures.addFeature( MFT_RenderTarget3_Zero ); + // If this object isn't lightmapped or emissive, add a zero-output feature for render target 3 + if (fd.features.hasFeature(MFT_IsEmissive)) + newFeatures.addFeature(MFT_DeferredEmissive); + else + newFeatures.addFeature( MFT_RenderTarget3_Zero ); } } diff --git a/Engine/source/renderInstance/renderDeferredMgr.h b/Engine/source/renderInstance/renderDeferredMgr.h index cdfe2755a..5b5faae1e 100644 --- a/Engine/source/renderInstance/renderDeferredMgr.h +++ b/Engine/source/renderInstance/renderDeferredMgr.h @@ -46,8 +46,6 @@ public: // andremwac: Deferred Rendering static const String ColorBufferName; static const String MatInfoBufferName; - static const String DiffuseLightBufferName; - static const String SpecularLightBufferName; // Generic Deferred Render Instance Type static const RenderInstType RIT_Deferred; @@ -106,8 +104,6 @@ protected: // Deferred Shading NamedTexTarget mColorTarget; NamedTexTarget mMatInfoTarget; - NamedTexTarget mDiffuseLightTarget; - NamedTexTarget mSpecularLightTarget; GFXTexHandle mColorTex; GFXTexHandle mMatInfoTex; GFXTexHandle mDiffuseLightTex; diff --git a/Engine/source/renderInstance/renderFormatChanger.cpp b/Engine/source/renderInstance/renderFormatChanger.cpp index 01e0ef8aa..8bdeaefd0 100644 --- a/Engine/source/renderInstance/renderFormatChanger.cpp +++ b/Engine/source/renderInstance/renderFormatChanger.cpp @@ -222,15 +222,12 @@ void RenderFormatToken::_updateTargets() if( !mTargetColorTexture[i] || mTargetColorTexture[i].getFormat() != mColorFormat || mTargetColorTexture[i].getWidthHeight() != rtSize) { - mTargetColorTexture[i].set( rtSize.x, rtSize.y, mColorFormat, - &GFXRenderTargetSRGBProfile, avar( "%s() - (line %d)", __FUNCTION__, __LINE__ ), - 1, mTargetAALevel ); - mTargetChain[i]->attachTexture( GFXTextureTarget::Color0, mTargetColorTexture[i] ); - } - } - - - + mTargetColorTexture[i].set( rtSize.x, rtSize.y, mColorFormat, + &GFXRenderTargetSRGBProfile, avar( "%s() - (line %d)", __FUNCTION__, __LINE__ ), + 1, mTargetAALevel ); + mTargetChain[i]->attachTexture( GFXTextureTarget::Color0, mTargetColorTexture[i] ); + } + } // Update depth target if(mDepthFormat != GFXFormat_COUNT) @@ -239,15 +236,16 @@ void RenderFormatToken::_updateTargets() if( !mTargetDepthStencilTexture[i] || mTargetDepthStencilTexture[i].getFormat() != mColorFormat || mTargetDepthStencilTexture[i].getWidthHeight() != rtSize) { - mTargetDepthStencilTexture[i].set( rtSize.x, rtSize.y, mDepthFormat, - &GFXZTargetProfile, avar( "%s() - (line %d)", __FUNCTION__, __LINE__ ), - 1, mTargetAALevel ); + mTargetDepthStencilTexture[i].set( rtSize.x, rtSize.y, mDepthFormat, + &GFXZTargetProfile, avar( "%s() - (line %d)", __FUNCTION__, __LINE__ ), + 1, mTargetAALevel ); mTargetChain[i]->attachTexture( GFXTextureTarget::DepthStencil, mTargetDepthStencilTexture[i] ); } - } - - + } } + + //set the texture for now as the first color target texture + mTarget.setTexture(mTargetColorTexture[0]); } void RenderFormatToken::_teardownTargets() diff --git a/Engine/source/renderInstance/renderProbeMgr.cpp b/Engine/source/renderInstance/renderProbeMgr.cpp index 13f5a4b97..96eafd4f0 100644 --- a/Engine/source/renderInstance/renderProbeMgr.cpp +++ b/Engine/source/renderInstance/renderProbeMgr.cpp @@ -156,12 +156,6 @@ void RenderProbeMgr::_setupPerFrameParameters(const SceneRenderState *state) PlaneF farPlane(wsFrustumPoints[Frustum::FarBottomLeft], wsFrustumPoints[Frustum::FarTopLeft], wsFrustumPoints[Frustum::FarTopRight]); PlaneF vsFarPlane(verts[0].normal, verts[1].normal, verts[2].normal); - MatrixSet &matrixSet = getRenderPass()->getMatrixSet(); - matrixSet.restoreSceneViewProjection(); - - const MatrixF &worldToCameraXfm = matrixSet.getCameraToWorld(); - - MatrixF inverseViewMatrix = worldToCameraXfm; // Parameters calculated, assign them to the materials ProbeManager::SkylightMaterialInfo* skylightMat = PROBEMGR->getSkylightMaterial(); @@ -198,9 +192,6 @@ void RenderProbeMgr::render( SceneRenderState *state ) if (!ProbeRenderInst::all.size()) return; - if (PROBEMGR->mRegisteredProbes.empty()) - return; - if (!ProbeManager::smRenderReflectionProbes) return; @@ -208,14 +199,8 @@ void RenderProbeMgr::render( SceneRenderState *state ) GFXDEBUGEVENT_SCOPE(RenderProbeMgr_render, ColorI::WHITE); - NamedTexTargetRef diffuseLightingTarget = NamedTexTarget::find("diffuseLighting"); - - if (diffuseLightingTarget.isNull()) - return; - - NamedTexTargetRef specularLightingTarget = NamedTexTarget::find("specularLighting"); - - if (specularLightingTarget.isNull()) + NamedTexTargetRef sceneColorTargetRef = NamedTexTarget::find("AL_FormatToken"); + if (sceneColorTargetRef.isNull()) return; GFXTextureTargetRef probeLightingTargetRef = GFX->allocRenderToTextureTarget(); @@ -226,14 +211,12 @@ void RenderProbeMgr::render( SceneRenderState *state ) //Do a quick pass to update our probes if they're dirty PROBEMGR->updateDirtyProbes(); - probeLightingTargetRef->attachTexture(GFXTextureTarget::Color0, specularLightingTarget->getTexture()); - probeLightingTargetRef->attachTexture(GFXTextureTarget::Color1, diffuseLightingTarget->getTexture()); + probeLightingTargetRef->attachTexture(GFXTextureTarget::Color0, sceneColorTargetRef->getTexture(0)); GFX->pushActiveRenderTarget(); GFX->setActiveRenderTarget(probeLightingTargetRef); - GFX->setViewport(specularLightingTarget->getViewport()); - //GFX->setViewport(specularLightingTarget->getViewport()); + GFX->setViewport(sceneColorTargetRef->getViewport()); // Restore transforms MatrixSet &matrixSet = getRenderPass()->getMatrixSet(); @@ -258,9 +241,9 @@ void RenderProbeMgr::render( SceneRenderState *state ) ProbeManager::SkylightMaterialInfo* skylightMat = PROBEMGR->getSkylightMaterial(); ProbeManager::ReflectProbeMaterialInfo* reflProbeMat = PROBEMGR->getReflectProbeMaterial(); - for (U32 i = 0; i < PROBEMGR->mRegisteredProbes.size(); i++) + for (U32 i = 0; i < ProbeRenderInst::all.size(); i++) { - ProbeRenderInst* curEntry = ProbeRenderInst::all[PROBEMGR->mRegisteredProbes[i]]; + ProbeRenderInst* curEntry = ProbeRenderInst::all[i]; if (!curEntry->mIsEnabled) continue; @@ -324,10 +307,6 @@ void RenderProbeMgr::render( SceneRenderState *state ) } } - //And clean us up - PROBEMGR->mRegisteredProbes.clear(); - - probeLightingTargetRef->resolve(); GFX->popActiveRenderTarget(); //PROBEMGR->unregisterAllProbes(); diff --git a/Engine/source/shaderGen/HLSL/shaderGenHLSLInit.cpp b/Engine/source/shaderGen/HLSL/shaderGenHLSLInit.cpp index 3c1512613..c20cb5a8d 100644 --- a/Engine/source/shaderGen/HLSL/shaderGenHLSLInit.cpp +++ b/Engine/source/shaderGen/HLSL/shaderGenHLSLInit.cpp @@ -108,6 +108,7 @@ void _initShaderGenHLSL( ShaderGen *shaderGen ) FEATUREMGR->registerFeature( MFT_DeferredSpecMap, new DeferredSpecMapHLSL ); FEATUREMGR->registerFeature( MFT_DeferredSpecVars, new DeferredSpecVarsHLSL ); FEATUREMGR->registerFeature( MFT_DeferredMatInfoFlags, new DeferredMatInfoFlagsHLSL ); + FEATUREMGR->registerFeature( MFT_DeferredEmissive, new DeferredEmissiveHLSL); FEATUREMGR->registerFeature( MFT_SkyBox, new NamedFeatureHLSL( "skybox" ) ); FEATUREMGR->registerFeature( MFT_HardwareSkinning, new HardwareSkinningFeatureHLSL ); } diff --git a/Templates/Full/game/core/art/brdfTexture.dds b/Templates/Full/game/core/art/pbr/brdfTexture.dds similarity index 100% rename from Templates/Full/game/core/art/brdfTexture.dds rename to Templates/Full/game/core/art/pbr/brdfTexture.dds diff --git a/Templates/Full/game/core/art/pbr/default_irradiance.dds b/Templates/Full/game/core/art/pbr/default_irradiance.dds new file mode 100644 index 0000000000000000000000000000000000000000..4cd4bdc6e38dd1b4c541eab745ee60ee7d86740c GIT binary patch literal 131192 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 CxNyiwwR4-n&V@Ww0T!9J2kW*5^{Vr6eV z{eYOSH`1k7-b(EQTUV#^JVcci~ zdC`>v7vK4UJl7NHji3A+`viMX?Bk`_K_{2)q*J#aq2sfE;cRw*v*=5Y-%F?Pw_Z4Z zH+*y4FOS35%E&R+a-`$FxmP0R;vhSu&d9_jSM*VEg-^|Oe#=qE<|G`>8Y#`|x60?t0+ESvLwd|oH$ z@BSx$D`La?CT7y(&%U1?y!%;t<&!V+Ij@~Ki`A6Z3phg-=5ai6e#n2}r%OM9ryM`Z z$YZa(AGK8WA`{!S(~)mLKZQN`(XHRolg_{QTg04w0spwD0;Wfdlga zXE<0x{OcgGp?AjtTPJV~1(L{?X1_Hq5$s0N=z> zbc5Z*=AM7?^_Yj7kYS#?kK)sDfH{5?zpJ~S{2-0;u5#_xD{qGEz5etg;<+ECgZMmO zdh$uyvgc4*y!vwB!2ZR7^@tbokySq(U|sx2@W|uOzL(D3e>vTG`Y|{;iypUt++*&@ z>%1fEL3`;hF7i*muf8%It^99)@=1mp;v+eec3*e(rKhpi>_xY>HkP@IJJ6qYN}dq|hf)MwI{ZH9aR7azWgzsLzm#1d%+vxq>u~c>^m#i2P%^yj}3CfG3j?U z&$@o?32~Ujp&qz^%s+P}ow{{DYH9YMAD;f;hs5#RO)q`)Y5MS|{}7+dSJTCW4qrt9cEvqvwaJ*@q+_<@DYP^V^WnT%8BXXDObX8rd!^pA5i^Bo7j^St+h zH&*6DfwOow-pStew|zM#aZ$q@8AK;Kbr;!&Pfjmq>Vxb>&%W{jIW6C0EhNt;_T1yF z3k&!y??0W{7H5|(!!s|XGwct}-+UomfG<8`z5M+5{xs&oG;8Ux7v4)xKKd;9KpnYt z0GWim3p@Gvu4Jv7lk}-Bw+vUnQoth){GNRp{}%Hbo;J7PG9Gd~6*SK9l)+ixCh$=3 z5AC>aIyXw;MSUyV8P61J_Q8Aj=Hs{7Or4O{o<8(r^7>%AGtR4ly{IuZEK26jIng-jZf43;gf;$_3T}y(D#`vupW?49C&b*X^c_HsT7Jb~u|zpk&@Gx&*nE=OD10{60K zJAUsmH2nZOHu3C?dxlu7R_Xv7->jXgow!}=$qY@+Qg;cTz+H#a5p?DQ>~p5!nfX&! zg17sqEr0XfZ=pAIg|4=a+C@9r2Ohw`btCo*_f!FY&c_kwx$1kw`sFY$!{&J=WA%JF zctQH-xRK^rdl??%KK~1Qz;D~~TF!47Ph|3SMJ_Z&oX)xXkMS4Ja{P-Q;oppopuXOM z?Q(d6{8rc|>Nv}3#uwjQDb}std-7tsjchyxZ*=w(+cAv&_`|;*`nbGi{;xgg9rNrr z_p|0k?z>p~a@xdPE#$qhG54Wo&{-Qn0YCen@T&-Xj@&<#VUMlF*SOewxj%OwYHk2?LzHRrWo*W-G-InM#}@5AcsJ{bI*{;w z?+^X~d4sN_>;8>szk+85utjt*f9@hTT>paZ%**VP-@ugdg5QCkcBEO*78=L=V7&3J zv}Mf2^C2h118sP&T)b2G!(?;I_@`oy!4oltoDXatJc$csrQeko#eTy*M|QC%&tZ36 z(Ow}g;$pmw)T>$|-^UndBnQZmd5AcnH-Ga7(QX5_`?C+8M$Uv~m>Ki(+$?b6xM*AW zGx*#Stz5zy{NpF@#BZKAMsyh;1>J zFTo#h3O{2cmL;C!UIsJc62=@C#dkjooMd^@GhBI3*!|4%9WeIb4em#qdHdo}nB!Af zQRocLkBkQj_=7KaHp4?^oAA3lUyWUN3o>CGfAKw6??p{|Z4_mkE!1PD`EP&c9|R6u z|Aj#tknqQvB~0{N&@W&te)}m;#FfG3cjZ9jii>ww{SUm64~+ZE{2#hjh6`zJpV4o? zn(=+c6SQmF-sjUx*qw(34q{H^^F+R{r^cFg%RY4JJ@|w_`Qpdu1ee+O??|WbypS$k zzn9+p?oY@edndj3gFlG5kc}U@2?K3^#acb`LV*YRjo-n?`G5W&xX8!OxS}0-MVNfn z_VRawFXRnj$l;Imqky0LnOuYx$hX*g+CJBR3>VT~yaXQj?x%Eb1b){`YwS(4F3u4P za_iMMsb4sjZt}T=PW{gJf136Z`*i-^%V~uDQ}iL7gtve-U|$8Jzk`+;Ou^#;KhFp| z-{o)dl+l#&6>UnhylwBr|Kd6Dk^L7i@?6+ppkv_H_PMhEcwQLs+lu+(`_b+Se~1rp zP~gOvL;0hG^-3G}-qYm0*n61xUSeCYF=#8UN2khQR(2Ke({Jqm^ZxPgUxr1z+i&24 zPx^?tFF)isD|k70AcuQpZqQFIBQjhRc*s9#$9$KuuN3wIe(o>xL4H4*6O4i1#rK#a zj4{>?#wjk83FWN$8~VwEJ35K2uP*Y#w@~|W>DCJw{PG{;%4nR!#d|@AWwuE;&;DG`cIX;BbaTGk{-X!>8 z6>e7W0&aQ!S#go$#=INyidWEIzGpm+t&~``2jnw_%Z*0 zIkhvI`Y8@FJgk<#fqVD7j$Jwj+~AGz$A6AFV9GxOhWxwu@%g}yFt3^m${2Aczeqbj zea^9oE8lZW`4#Z{yqCD+zB*(^_e^$rU!HK@uYSJZiRGLNv|)ViGvL7I3VKCf`M8RH zV}8(A@6o;K<`2FRzM2^wfxj3_PTLq)j4dA{@HocEjq3e?Zv{8cXtPCkEA-@yuYo=A zmdU?tOn#?LFZ*OXaq&HHm47;K!tXfn2d{_^z8j+z^1*lGS?5e9A2a%7v@Gm-h5TK{ zhyC%Mzcasac&!+tFxj8*(Prq%_EX>lehBy-dvPzG=N+Ca@*tW!L0XDa&tGG1*rqY$ z%AkPV-_kgHH=dy_VGBO@8NQ2$;Bm*}|6a5kd=US0-+90lyv~0aZ?EuMCg=DqKLEFv zZI=@Zuiti&_feWY!#+)!;643rYKUXbaFXGB_50oz#%xbPyU};nzI$Z-WBsoh-vVKe zewRNBdV>eX68t1QJikKU4E`_CImc1RLg~(BZUNtk{$st*ZT`!+$Z@0ne;NJ^?`!c( zY{0)GU;*d;|95`zFT$TQ>NSdg){m&GjZaeaQM8-m(=j_n=_-!nyT2K$SE>7Jab8^c zvjKO=9C;zbZ@}++#r>QoS8$R)C$8ekXdmzk8|`E~pTq3E0`BO8z8tT8fH!$%i?w=~ z+vWI&`dhvBS^W6Tf#Vn#9$s6P;vT<+!TZIhJ{TFz>638;&Fq^ti#Z>2 zK{%WTe8xJ6-WboseQ_(DSNI}>JHuJ5A<91CjLR{I2gVrm$?*_4DE^~9Cq9Gr;j>j+ z$mj03a(tN2P8h22laeo^y_~ONT>0G2`pa-0^aFPHgs}$DcHme#azFBr(O2y8$PE$y z@jKw>|ImMYhyEgWs&XR#ZJr8ouuSjbKgL+#LYWY_cf1AMfd}r33%_#}a;ew{ua(A* z5%_m~^WE@WFUNnhiCE7KC-;XQAMHh(ncN84J9gWp-=a;wyI&1l$X|}%d-&W)d%yc^ zcAx)jLw=FR`7g%7bMj*37RurG`QVHA4;kfW-d?l;{gne5PdX;$Qb9N2&Uiro5c^t# zy=nRX=>HjV98<3}`eR(IW6~%1TYToY%RX0)*KrrLpq)B==6uF>T9B>EjZAi6X9Vs> ze4V}oXS|#7ZqOYXWb0?qF8?XpY{yT>C!Y9R{?6}gT@Y?@kii>k8vkXuD0qN;=Gfcp zD|m{0b@IBk?`rU|vLE9YHj%euc}~;Ufve>IrryIc9&A^<<^8SMKs^-4<;C;HTewdC z_Y!hYl~k6cx&xEc6XIMvr+d7!8W-ND4dEBI z3=fVmo14nNXRK`}ZI<_BISk<3Ik1K`J8JmYhP(wXY^#hIsEt!Q!>>Q)rTyeIR#vNL zuILXL9D~&Rmgk%BGZfF|*lPL)hE{MSE`&RWy}*OdhRzp!kkS0v2K;o4-Ow*UIHi65 zS>QbGx&F)NK@;g9-{y0I`;pU{_SMm1{GNT$jxxS=jC^YN*_!iR`o*5fKH%9B_Ly-m zhud7QRrtTg{0Lr?-|df!XKY6pwBb0;(+}@)R#`^<_OX1v^E}TjU*fX(&G(GPz-TT- z#=3^OD^>V(dwNwr-~(`*&GDRG@RMU+Pt1UGtOg%T>v5T*v(mMW zyq^Pmc9QdKU1}Rg=K+5Kw=hCuX}#&&k5k2DU#glN$Y>WZOaGi_%$-Ibz87AkOko5(4{kxGqwbOQsr|ok7C@wrcCmCE&im! zZrzjek?!=(pZ_c!{N4vqFGc;Yp4sH-HL zQA3SS=SM;F*z@=-{R_MG70u`3T>r{iYu7r*+_Om^-UY77$M}fh(_l?bW5xV0oAdZO zkPn~~+`RJ54}#X_&9!b@!TSZxvi36gqh18OVZOKwH?04R(MvjR+R~QEKKX&)J`*yw zfP;G>6UB>sAU_p2;=gk8?v%4GMVsNfx3Ufj^Rv)i-8b}K-p_3E=A(9w)24as+3%{m zO8d3sZR#B!jyOr@f^k!o=zMF4)2Sh+rZrC5-h4KrAW zuaP_uK^NL|ZPu2*V}3DUkFhaE;W9Q*c)eGSA9$t%LW3OszybLZLk^mYnRP@t;yF>= zX9-k<$x z`rZHcUq{UDzFXJvd+m%|Sms8n-vKP}n)r#iEZpES+UEPSo5&fiO!yW2N_ggP{^DP! z`g`Xx+5%h9#rJ(j-Yc#gf5LAL^i3~c3E!iP_w7p_VeN#EE6Fh-zt$1AV;-^48FRi8 zzv86eGjmk=j`_J<$A5)-tu^?q8Otx-V;yHs7{_Z)Ph&@O%+5$6oAC?nTk=W>pRQ+b6KDOKfBd_|Pm|vi9t-%@1$ZuUoH7n+syvT5%KZxB z>N5JQ;uYQzE@`%!_LIjoAFzs8xR6~w%kRijK%386Yl`^1wdP{ij^OjLrt%-S zTc$hTm3fZ8f*6z6$w5}EcaC{|TN`aWMK|z*Q|ekoV-7;Cr4o2D!1d4gd50 z%+D?Ir~(_GA&TrM$`sxS9K`d$4oo4d{G_j- zGw%jY#F0FZzbB2eIi9_ftylEn_@QyEV35aJ zcF&|LVl-@T4eLXuf8@GH&=XjkxAy68@gm&3FTV!=Gp68a+vd5jQ*$rI$}{S8!dW%i zOMYF~IOdr$-)G=~vH{@Ycf;jFsdBtK)t#7&JcD%|_#)az z$S3$P)@A9Dk1^IS=n?dHtT`_H3|Y_T`mUZhgRdrD%6rDEOPgxzU17h`Ca0VVS!KJ@ zl|JI0eBgiFbL|WN2W7N#C+=nXNyv&Ez7p~*JLTA#EMOg zX~UJ1Y13=?!7!%w_wXedA0h`Cv3mS2Xa0NkVQl?ZkR5CK%-zgfWgPNswpL~IDdxF& zi8ITbZuP|5Wbz5z0mm9}n(3Fc!Mvy>N18I-E8qvFIGY3K!OylA_+TH6d@Sf4XI9|d z@p*=4JpglunHRiA$1S zRrqJbJf>aoo#`FYRhaXOXG0ffyg@Hu^LGinT?*YR(KV~#x5|-@RO++9QC!i6zkQx( zg{_Ww-DnS-m%v;0dOobuF&3jE^h;?ISVqF z*O1$=E92`N=8VqS{0g`WnB@b$8z&?D@~7jdCf2YN8^7a&N++ZgXA>{;sB zu|By*#oR9DcShrar01<*i++7D|km*R|0!8`3CCHBf7^%Q}YBh-PvE(pj#QoU1eU5 z91oSWSwv=F+RRKUU^;FS7W|f#w7d|>><1#a06pT`&DbGa26NsiGz&BD{$LKV;A|`iT|yn zJ^4<(%RB&e{H`eA2M6oXVXJ^Ga3ZfmyBgqXLU(N)>?7{+aH<2wb*z6IID2bCzHMYa zHPKEp{Ot#4`<~24cml zfYF>UHNYZ`>%i9*YQgtCyqMMlXCrf@jac>#%!5{9u3M?KunAnW6JOoLe~rLAGtiq_ zfV-ag(#Sit<`H0yDJx>_i1Fp{D+93k3A_6w_xRecK7$;j zRt$7phwR(&kN;NceR7NVdfqc%3GiTouokvIds+k*^n+^$$@;R3^o~S$>i4 zfiIi?8Luz%zw->Ajcj!+)O>8cHsQmPamc}^ucjx-`m-q&hJ}DV?zVv z>}g5u<|2SMI;c7Ium0M9le*}mkuk^v%FjA*>-t&91@k4C6J--|oaSoUN{*BcV%E$X zG)kPzBr!tPl$au)Y+TQMmHaa2BTu&VHRhJS7CDEFOFVq>R$97pCoK_Iec;qZ>SUZw zv(IrI{c6Og?0WtRwJW|(jPtLhgTx;ly7KFhug-i8>&RPY{=UYo9psztOWOvCpPVLl zIk|JpW9&F4iG`bV9E@Rx*oayBH($50FS}1)B^Lb-`Pv^6<8dz?A&z4A(z&$rxl@ec zOys%VMJ`+WKk&6X(f1+ZC(YMq{sZIwtEhQmE`U06AvBU_b_@70H^tDxA>#CofsYdr z<7{4?zybZv;$tcv^t(U$s}G1tc_AGkKI`xW`XOF>f!Ok$N2tZhbHcyptJJI@KII@j z`p@yac~7iErR~x9azD+#5IGsZi}@Ei$sN>79x3tBPyT?By-Puh8QQe}Ibs?1(ysVC zc!~HH@ODx9Qcf5WUTI~fBDMlJtKn|TN%Eq#(X#q^A9+d7V>~}jm`vJ zrorvP^OuPs{M8tT^#FE*_kHwR;9>t)ucyW5$&oD|ii;c%@eYB5mZ6D#o#nxUS9274vy)pV^)Ixw_z$F5-Ur z;9F~eO)?&10*o!2WL)Ngo;24tciKu0l=l8nVuEMVAaQG>yADPEe#c>+_E~5bdrb7tunQGq@Kf8-sw?QT znl|}3O3|^6X_H6H2_s&r`K)11TkorpxMSmlx~P9W46Ve6{fmPga;BP z>t36_vx{|^e!adlmR}mfGOreR;nV%7aZnLM#8~wGu7O64o41lHV0-EyuT0+r@}2lo zujqeOzlB}rOa1=m#!=v8)u(p9$SJ}&-2aM;O8lB?$)mEK^Q4XN$R^@5^ub=~U;MJ> zqEi$(DVN6*aQ_l6iZSK?h3$=d*c*53^<39RlZHyeK z=rP4OiqEi%*EiN+nvpE}m*gyAU3<0-vSiwOyzWf>6UUe8brIY-G_l{nJn6ca^4Iww?Fy7>a)7E%VSz^T>lrUqw#P<^CCm zzNe9wJ@`}~7xNd9qX^x%npi<|mIe;gUt^5)58p&iWA-+YAC55;GzfU@7v5ZB-Z##- z%|j~A%b|NEHs=cT>G1bqOl#Pe6*-c#-2dz``M-KSvR69MM%a3V+lzgL_W8)^O#e~e zjqzxMR*!y$GZ*U|n;W&1Jxe9+R13>SYN(kTlRQ@y+>1F$JMPnjMO(h(b8Hp*Qh*2R zMU?=*dGqWia@g88I4g2!m+)>p!*k-wnkLpV67F*IfiH-Sn6%FY?Dh}ul(JVVhlUl< zQ#@3$zpdoE`S9#h{*ji#7BF%z@L1rJPxH4{ftMQg#pRBJKCMku&c3poa}nzbmU|DJ znHR9&H)$WT200_2$9U+sRDQ63;FK@J4j}KX>eKIGzhzwJE0iB<*uVH$4(t`!EGoBd zOjXngsbtTq?~u0H;#^&roL64azHJMm{3w3C921{mUtiU?bKd=SMWUmiKgl?$t6!}1skngX|by12l3(O>k*{m5Ah+}f$D zfvXxE$ERc9dlh)le(6=kSgLr&XT^Wkzp$^!rVPj6Am9WK0bjOe$m8;j=hqeRQYCy} zMLX^@>!5i(c&`J#I(WdmciO{h8AEYthlo9?W0n5meHs7E)tm-lx95J~7nohI%*SZH zJ#$f3(@u@;0%I+GnL~Cx^_`l?H`qu%SMwK|H_!cS>}mPbo>9+u3j2mRCFQ^Dg7)+m zb2j>=?}D!2IC4R<|Mv{6b|dy3_UaAT_sk=@p8a$qS2OuUTd*Uw;G4CD`&+oT1-n5D za%3}OGEd(I#|56&GiEPkX~^aLGv=`KxaeD+6360^_pNQTzH1vbO**N2*G*2-E^@AI zW1rSa{=qKt5225fv#<;Q_-@XFd)TjcV^iqdwl#HNx7o&+%_ZoVyp$`k*2er(Hp%z$ z8#tHN@-uzcF#dJqVr(3srrP9CYMmZSZL<^9QyONk+)KUdZt@1AV^TA2U~DiA4{cAQ z*bc`A`NU2#+}E9kwV5!ko{nv)n=|2VKFu}OLQcf3>}A@C6YV0ORUh%;){!0|ufRC_ z1@{lr?DeMEcA98}6 zHY;tJyR(k{gY`Vz+ih&?frbOIw{nlyw_{ftWGurA2gwCQT|eysd3zJ&%`gwFdu8iz zx-YYCt2q)kk{8r=+Q{|go~VZ$Q`@H&$iKFm9DKA#4vi7^BeDO+U(>n))^oGH!UkZ@ zq7CFp*v$T6EBbpIdzlV$0J@*)Lzmx<{%r16bI`h9wzju>Guv`MQq8zx-|CoXOTBk9 zamZWo8_U`nXO6ojx?Z`C6m1dvPh0M99BgvS?T~|dJ$r&8*X@ez2Nu?%$iqrIWqdDZ4X9vk%JQNj%c%WY zyWa6+^#F@^T_>{jB3m))em}f1JnIuhp3XZu;?Eb(u1C4?g94*Y%J!=oRr! zyr;ZDzOgpeQD@sV!SQDAU^`J?<*F=Xl)8~}5xJp_bse&!!Hc=Po-6VL)3@tk_8xsX z-;|&EJIb>S$dQfA-DYgf&B&JG62{0kt6U73n7@b3GGvl@j>)Ck%3Nz>?sar~b)bAMOVf_Bag zvR~F7w}HLs$kLjXd7qS={#a12=Nds}Wjn0w-hEV=X-VDmF$66}#)gqG{lwRkyO#0v4-Xkf@?UiB zCAXn@K*#rfIW=>?f?rJe6uDp*NAds8eGxsw)_*}C z1=jUa_{y3KWz5|*=tKIQS0Q)D@zvNu-o_ey`kqCWtwolVLDLp;x4DmteW5mj!bgkt z!WV))oBu2S>Uu}hdg=tWQh&XuSyqnUXBD*{8xBmQ+JneC{A@}my3!@iHd~JGroJ)j z(-+@JHTW%6?HSH|pn)fRWPvq&%J}UW?Xz{6k77}4+k5&X``OBx_*eeNzp;#?nj<^1 zJvC#FvwiIQP2|g|?Z?iI{iAiqR4T(i^I3EteK#u_@Es%>Uz%d9OH*p(tiznuK#B( zv?>{HUFLOtp4&Ow({@ph+_tWGM(51t6}Tt|_u_;;>%mVQ>uS>gbrM<2hA-U%zM&YC z@krI=JZePVwxHiDKOA=%=R1vE!^nH`;}7kOTA{V9f1R9NwsFq1Wo{u=F;DdQUduUk zCHm`HbmS&h)ob!;Kk&JR)F794QN3(r=#*M-kZ zfrb55DSM}9knhj70Rw*QAs>))bqml3_`XufUJ$>Jn1krL!SeyP@k*?3@P0eBaVwEQ zJFeVJSAX=srkkJscG^I`bnPqUoatG&+xcm%Lq@Y_QVqIKGkL?Sx1dY2&uQJYC)J`; zm$42!i%)zdy2!K8eyuv>1hu$#PU2VH9&<&W({ChV76N{KB$=Pg4QtwZeP@Y$O!(}c zp}s{Gu`)Nu`vdMh_%yAjhN$sVYp_++5gX+`w5gAJ(d^5FxduI_!FWhucV4I?WiiO$ zTAqjIfrnfUXcw(S_SR4b&RpnaoMlS)GWJDb;|m$i7>%*W$NnsQFHTOp@i}?H&wz){ z)W`W)RaaNMQ`6m)mNjpg z55Sjojh=zlj>Fgm<+*u{JufqcRp0G~)`85QnK7H&!(1?t!~2u(GXHwhhT)y5249P* z3%7$u>d>=m$T_!`HN)7ZwdnW7nT&8te|-bH$+GS_M?KvwoFO|$ zYVb8H>+MR%zW1F}H$D>m7!PBA4LfI`JMGY(a0l`5%`tR`Gar7QHjGZD zpIkZ|wOxPv0`*ypd}jI`V{$%-7x1x$z3RftZ_!>|n&WJGV0u?JUdAqNT9Iva z=)GmgGW|XpI4`Y3?zf&lliE+8O_k7c-Oe%Uc~i5A{ZlocYp~0fP+uhIp3~mFYdJRJ zjpSIJMc&q<1ODaT`Jbq5do=z2l_Tl*xPF@B;>X}Zd|2~$A8of2f3bl*UC1|ZVEkSK zKI)~tThPVOO`)0cPTp99ex1=<+@o_a=8TS+{EP3vp3#K3JnRm`$g>Lc7HtFSXc4~w z>=DBN9!k)6)r+L(TGoL|{H!+56E8r`3)e9(=W`>vN$b*?RL*{~w2PQ8>L-cA`nJw= zjJ)Tkp1zBZ+75I-Y6P>Mwo@bSPi`!wKe~QA{o%D^>1SL8J_=lnu^+9&f2EFC-&nJO zv6K4M^?Mi78uqeluva_BtpV47O)2&PJfqyncrTlK1s?_vtm4Z>azK_fZjQQ`#XMbp z7T(o9CETIc(oZ92!)?2$H-LXZIeSI*pEdAKJ+_)Ebgy#ibhJ~?YYTa;kG=WL^v1vX z1v%DFVdLIH9{M#_`W@pG-f;ck9n?o``zKe{utSTtAjxL@(Y# z9qkRo57&Xy8t@)*#OMNjH?O3oU98W@N$DNy9XOB{!3#N$$2`vGpnj^WVXI;fcjOW| zfvNNCocGLe<^N1p3%fLovnSg2chkVGv|;yrDhJ*QWPtOouBQime0N&ciVq@n#fGRq zGe}*x(h6-f?7O?Eb%^b6hCJ&H13S>E*fUb&=+7UVOMia*N@F{0*sLtRHy;&hb&IWp7=9O;z1aeZGNpOx{>e47B5SJ~+R#yhAzt ze+l+B>=jkmDmG#pJ5Fvd<$LJmt9T<|&uL%R-X3kL=a#bvEMbi;t-)U1Ka`r;18!zd zTc-aec~{Hp$xF()y}D98b&qQ72YxSQpSTHoU?qM;#Zv69q@J_a9T`4w{6kFU4Sc`ofbCLcY^K0)21ZGIm) z%8_&UAZY_=Bv)`1w5=kK`!K#;8@iZ>$p1R%;{LEic+sJ&v1R((JpYZ@Sk;yP)ytRD zzkBsc`oCYfoc;~p|BpwP(!YFkA$@^N*uuQuK#jM0;4bU$NG15VZ9Kl8^%GqeJD+;L zbdU9n&yWwmuI>?hoXcM06ayCcSKjEO{$%seY({hTa7)y{*hQXW?XNLkggyAhIl$as z#S`XAH+O2p_i%rWdJ#H#4uU$+3?(tQ0&F<7dZlH#-k<@x%Z>q&USG~Zz8KQq|Q|gGqYi&qB z!#AHfFPzH5h*4tR#&_;jLyI!xPP6qtUi>iazV~+O*g*|OYp)$Sllt)6lh(`fB8T7K z&i}Y?dtT_p`mNYkW*0y%h>Zbqr(d1sp%^1~1t@ z{g{(WJu>0};(z2M_twBu?g`9o5%ZC86*w?A_d00M1Rr^C4ju9ma{d<|JWNlnpH7=O z6B=f1ubyGuqt4xy*=hDt`2S7}r>cS8khj&?C0mXkjI-a6bBrbElJk4OpMS4{?#=iD zIu6(KM)U>$4|xt=X3%+VQ19d>wLe;2>xwqSL0r&Z{003oyr?6WRyQpFpXJ2hKi{=& z=b3vV_+TybqZ-*DtlC#>$Nk_sa(H{M8a=lO`tBnRX%n%E8@jr&_4VTSJ45Y7&U;u- z+fE-Rh7r3lYfde8&@Rr28po!B{y|&%tRkLOeu(`>;9H($E~w|xpJS9K*CKP`UOe+G zcH^G33*XPP4 zE6a0BS&A%hU(rA;dL40TO(Vb#zqhcDZDM_EKev=Nj$wb?vnTcvCHV9<&*P&F?=<6A z*+tE*Uh11f|ME6EfqFp3yDM`bWFg~Judijj4|s$foQS)1*xASD_K;8gY1(_~cGRXT z=pJ*QXM_K9d}X-I=p22o!invvLz*X{n*G1_pyobwWBS!@QpuTJ(YA9|9IPL}4m}9X z$;D9*jM`gU59~nCCTICYa+x0`fBXGQspHOB@^y5fJ4~SyVIPKaz z4~^9TZuS30eAI=db!0y0dvGN@{NIa>W0Z43&jY8AoC-g`prvpDPvFTluz74TB^6S(q;*3e2ksGGuq|+z&vQAW4FEMUD{IidBr}G=N+SaOaCt}+k2L0?8i7n<1no) zT#fCj1byCklGvjguZ+#Bq!GI>a=&lK9P_s-)sx@7XsZ~jpK&iAV>XAOi9USHnR3o3 zf-gdDt21Zts}FSHKfZ_$`uO4jdcY;V<%G zwIElsoWG87)rFp6ysrL9jhuaywlq=;YdSTOH>U+VPZjif2K=b!Sr4{rVUan~8Ftt# z?k-#BV@&cwzUPTK51f&g0UocT4nhsGc$t3E1zJgKuXb$l3rpwI4t$K|-(rk~4jJ^P zo$NE?-RP5h86AKfxV6QIPrpZ=HvYH$>^tw-ukH8=5BRR}$nNdda@MpSou&qz-+g@p zwx1ecRmZPqPu+F+NP71l{h#>DP>V*Vt!C!_4+h2h_)?0Zw*N@}VXZam)Gbe;uT_a>6 zpP@tN{f7MXefgAkYKZe`pkDDt_WAYH_1%n}s}b0>^Oi7X&)`~)5)X3X4Es)M6Ytoc zwGWPCEYct!OV;)({sI>x=y%$$v$?T?t4vO3IJo`6=lExw4jB-+F>SNp(`Y-#LC`Mm z&-;150XuLO?*zRI90$$ix2&(=L1E8vP{$rxKb|ev_{>98&Hk?c^8VDkIKm#A{Stc6 zy3tYgQ`i=v`3esf{bys%cssk-xVS51Tm>>+f4ySe%Xn5EBvwn=#T@Ya0KORummj7h z_g|;Z+TM)bF-F_VXe+LzYw$+kCc|ampuh#6>L1ZI@7s29Ww^@U5q2*5r3O2md)w+Z z_D7s|wNlrn1pTxDUmM#}*0&nJfd9E`T_#hC{rC#b3tru{c#v_b3oyTFzmm1Lj+(XE zyvzE}zSBldGwYxaP*<@Z`D)&8#~k#@c_8GVu*ky&OzKqyPxD#yA9e`jfS)lBL*mvN3jMp=TZ2g2b zjL-3iN87c{fXREgy-(ko?70H=j3(Z5zwf(U_%o=djNmgg!9GZz9O2LCojo5oq1_D5 ztnX;IzyZ7wZ7TcoIUoPWI~l!;^nlytm~oYf?M>R%np;u+rXbVbsXTz zJ(&9V=|^u;d-4wTxTxLw^mX<+?by-=;w-L~b3$#8jo1^)pkoC#8e>M{?2NHHrh-pH z=F5}7ZXfGdJG4*l+k5i@ouO`Rk*j5@38I5q6k#t#vTbN`Lh zz&Vre2!FiGm>pZ;XJFgHEWQi7Lv&c_ZYMP)nthTC7=7_pvz?{#`0;k2N`iI}E;rlH+_oo_cvW?8^rs4UOG1~v~ zm5pCpMj^9fehHU21|LP+e#SlIn()SVc_D`xff&n3h}cusf9gV z-@c2f1%J#I>PFV!YgN2g%vXQ=UIX()xMO``%~_^%(5T>VX$F6=w=d*Rte-p+&&RlO zc=Poz!(p~&WU$i~IC0-rP7UL)aHcTG+I#fkjkJfFJ9{`6IY{lwDe68?9lMhDKYTY$ z6F2$vxBfmns%&8`0r#P!@Tu%7&Xt8jnXi9r1#_qC^d;awotlYjYsM~IiEXkN_c9)G z`gk_4tT3KYztZe~VOgPHf$PG);4>@mxmM(GazEp*3~#nS2?yn!{GJgbb3y-j5?*(r1HsU+a6m4dBE8t%> z&wMxdBbQUqX{|AdoIShu=%ps(7&hf*)~vhle-<_Crm5rI#vGnLewBKR_tNIR32Gwa z`{o=7T)VetjRAJgZ9T(mVP9w*rhEQ+Y_3hvvSslY{u$^P?0+ZmNnSnHpa-xyuY6Db zvTfneuDZOo7BuyfE8dIm8IMSVW!U{*$QQqBlL;K<@}%ew+oL?Y0sGM0xjXE?E~N=- zFV3I28EgH1>hFwDk5nINeR^lupS}Czzt0#m-AXtd?>gp@_xffR(iZ66h2GQyKOMl9 z(=&gHy5UE$$zP{N;$iA~Ux~3to~DBSIsF{V=6?Lou-V#nIX)Bt6W=qKGrVN57xRM8 z;{Skq6&^TS4LtaN@g3Nmv+|R?=|0&yi(9b84^bn0@x(>=U_W{ob?V^R7JNH}?k;8OI0N_?`6v335A;4`jIRwL`U>)9l8p$2=m=Mb&vHDmj%d&wCLZ3GYG z@W*#$7?(a2Z4>*`I%?;x#SgWDIaI(`$O50su51ks905=EDbHtcdse#)zq~I`fQ#T= z+Hj1n^Rr9W@bj~-?<_n%PM%GCfU)K4kdyLE zE&Vj&|GtiK32%%)=X3S9a&Xf;y*qo~`OSYZ4+8!SAFdC9KVknR{;*AXVCvZA)IGHu z`j)2NxkJgigU$NB<707<+OO7kKmE#w>E$2%JYAq3@=dFu(a z3}4`x_p#xhN}Kw2P`CCne!%OACmyEW;U4NhFTn#dsgoLC>SyaY?^;bmX(9isca+F8 z@R(!so__Y3ZU7(Wa0Jd6e?2mHZ6)@-T6_p|90Z&Ntohsu{N=bS_(U3n-bJ0=$s?Dd z9$Qn_P#QaMhM4s0X?W+})B`^^BiC+y{?n+%eB}14=>hWb5IGADp(~t!_1*Nr&;BCq zr;hZsx4xOC&p%4@=k8G>^}TfBwa>%Px_5FmO)p*GyrwEG66dd+_uNI;j9)0?59Lew zrVP317=u3icC8-Uw-oy$$GnUK;4k*{<{)UtF40C^^9|5VSuc+C^$mD^uYiB`ckt73 z@IG`qnRX!OyQyJ3I5wI3sm(ro_;MOXe|26AQ`>U{+8w+5BrQFDpL(3P$R}`?nDk53 zuz!?xvp!t;?6;|3b~E)a9H)-+sq}4X8a_b&1?pT69z2bHK&~I; zhVWY_vWYd<@v7TA%Nn_sHMbg@iT9+Dz7OsXl{p~?q^t0A4p#7v{zJ9Q*GXz+jm}}G zXCGmWPX8Al&P#2cjp!NTS^g52yRW}W-MPo)8MvIfSl>Jw86F-Atnlf<*^XWw+};XCP_-~X5C;*(FweX*3zF;{x$kEBn4fAs3@ zG=K4hwEzA)_$2Jcws<6M1}D4kzZX2P1-oY#^P->p9S5i(?p$4qj9JIJxe?vjI``VG zO#M_iGr@Ds7mvG=hdhx^W0P88_;AF^(QFPfQ_C&icy_8P9^dWUyzeR21 zD^dUX47{N--emk9c`GYimL;mh{#e>cz34;uYYpxJcj%ezLsQrr z#;9@nQW`k>6r1a@nEP$ay9U+~&*|&2Q5g4GO)bEJmckVJknraIUx3)PyN)zUc7iW4Rb!;J_)^`{S;>+C7kmYFa|ur zpRaiZeKXqUusb)zi=WFrlq>Qg{<95a<`^`;^5moR@bjOfg_}>(+?B`Vu(}kyGBP@m zdUu~qU9-T*S=WhIK20MBFTyM4G&!AiQmb_A;N>)iEErx~O2hk3Q3Lu8bDcA7>?Jop z{$ZM+2K25=kJ4*D{pV?vcW0?%IeP3S-!H)XyV7y?7&Dh2M_u@q{wZ=%vJYo1ojP^{ z`G9{Z>xDL<=}YXtl#9#}#~*T#`5Uq_hb4o#fIG*5JW^cZ!|#EY?EBo6SJRP4AEs0A z=q!FsBYV!VUY(*YBk>f>xuL;fXlcFXTj?0JI;Y@=!98cv=nQ#$uvHFoO|gd_IRYN` zolNJbhdp)jHge%zWGeYn$Yaxke(~UopE94D(&-o9CBBY0J@!~5;6VST&G_c@?L3%z z=8mxE98aVB$%l$e?7`^xVmyT^Rypb zcb*!B3*?bGdgoPQ5f7zfw;!b|Z+?~zKmI%&W1gGqXFq$(@uOF%ZHc^n;R&!`N_%N@ z5Wczi!56GwyJDUkefb-y9sR236z7fWnz2j0!5mqNJw_M!>0?aooIl3;9qXKXGhkyM zQs8142dn5DG+)IB&VTWt%$_-MGo5_vyYT9*G_dyqb(*Qm%G~asT14NiB-bQ!6+K~K zc7IwteLW2*@T{Ptp|qcd>ro`Szcs`LlP@F0L0p{(hP`b~Vmz zyO0wD)L(ba>SJx~pWI3O=OnR_tk1016T1&EUs=zB2h{zTBf?(5%ct^jneSKOW%%d~ z=IZs-J+V7YpG6Mu!JmA1Azgj)A@soZIlC`pYA=2p{rkypMVAB5*- zkDQ<`{l3&cF%$5IT*zg_G7fS)EW;oAPmUkvz|j5+?0rs0UGg2w$)n_%I)t7!cJg8B zng-V0OR1MwA^iq>2bibu-vT}x!@PI$)sNEbxrfNBdud?bg*1R4@cGw1Ah*%wbnoMD zu|B?+<}W?Kzw;Ej#Ovh1x|Ck{&X3Wrj-`FqAEg(*^~2CRCh2#Ey+j8&-6ycSbWQ9@ z^VgrI$rCqH$IO1}VNSCz=q0bz-q3-XuuJWJ^<(OL00J`zvOPtY7rN)k7&T7Zf zDEjiD2k#>1%nNlh4YQ{innBm&>_feIh&|*U&N7c92iitxF9pwK@%)c9H2-!Na|6H0qaSa{gK|1Tc0{ZmJ1IU*3ZT;Bk zUP2c3uzoDypUD1oY(DmBG4F*fUl*2nK=|{ku$cuvATwV4?1$<02j5K(&~v8ouWp|> z$Ucbm?aYHT_vj<+|BuqldFV_3%9(C_CR@=Bj=uUCHQ8T*e=epz_O&CxJ;vI#4_UW( z=^=XGOYqS3)W3L^wdK7u2fRavF0+_|Zb%DocHMX@e7xWO zy`M9uj;1~5Z>Rmxa)R}CXxCBvvXK|erNdY6uqWM{b}U_qHMF^RhC1-j09;*q>r-US zH#k>4m!AHezl*J@A}yY~g}!ts?P3n~K_~a1=3vYALD;GE+b?)u*ujN&pUVY zY}#}4HTe2U>Oudz_5OFUcXJ;;9fw|{&_LN^Jo*6gKz-a?SsmP)x&BTXKXW@xUw9qc z(G6gI%>MYzGz08A$#Zw_{coq%{RdgIX44(UzU$2ObnK2hid&a{#|M4~+zV>oD`u>kN zYdAozh1PWPH~$5`-8tj7T{qA?u zID5b`bhIPbyZhM3jiUcg9K$}ca3bhAgibreeyFCAcs%yp%AFzBj(O(C{`=_rv^BZ+ z7&gPp=`eeog&X)ZoxPFbh{0eJ3%D#G>fq(uCi!c<7irkFD-zI)3lf;KlL7SFl^- z?=*ig4Zve_$i~5gSK-$~Y2fhn)H6Pp`mwtx3p%Ip2N)cOMwimzdvB%v*ntkC@65ut zqkG96ckWT@2cD7H#faM-M?Svz$#>zACux*^?tc6|@O?hk{zIHQ?KyKXU3mLj=^#4K z(HA~U`yRfQ$wKx`1IR`3HNZN!m;c+5eTVPA#rk|OwK0ZyY?yXC5pXnz3{kdDvkw|SafjIT-RZz> zd;<=%w?J1|y!bH9;5WJtowB8GHtoB3i+qMRusLnOerin|YG-3>n1+W2*jrDN&#!mS zY2rxQiQPOxji~0d^JUIAK1UBbbS2GEV|*4{#`xh2$iF+0_b*__FYP3BaXlE=dyX|| zf9U#i=U*UBWs!Z*sn|zav)wcDJ?MgC7oK7Z_$>8tc0SGAHGiD&@4(-78a#SE{NOvp zKrW^yKm0j!?pnaVaPC@q@a-R`6Zc;Y+2~Zx?o73?t_u-A1G>1%T$Bx;F+;%N%CkANg8?U0< z_h4&08@jl1X@ND{`K#^PIGj1wuO0C4;*HnS%!QZXt&^Qr^ zb7ZKu4-#M1%bAKgfpG}4<{;r3Kxg%=y%jr-Ywn$QznKo-d4j%6>?3>p9fwb*Q!hT@ z41!wU$OzYi{dXTRw)3e2-AX-WjOy_$pqX3>tWuSH*^3w*)@$Wv2>7g?U8hC=SVtB9M^M`{b?7zKT{(; z8Feb;Q=8vWO{G6r%Y)YEtUwodXG zZzC_(X7X|o13;{G8L_YS@9!$kvK}o?q`Qpa;*P;|0N6+H1@6Gtv89vzHNaN4ksK?; zb5#&eS4RASxw*{mRzbdvYVs@8wsU5We^|s{@mbTdHPw+*GWzE{skW8%2RnELK4azN zMJeEq{_*vDm00tKyC%}F&J3qx;C}+R+wnna-i8kv`KM~hkre$CZ(!b$5@Jxz?^a<> z5@2rV>H)`X`0lg-Cpo}2LI?V9AjYkMJQ#K4rKo01mHbzXp@6*xx;)uGo&M6^sdRg8 zG@TsZo@TZalS%yS#;wixBV_%X*Q=bkWb;~?+sph~WyGk~fY*BHTPuC>^QZtmV?65c zeP|@sqM?WLLU^HiD>T3dwi3BxOm_`qt!Iq##~Z|1KjnH6JY0Yecj1fMLvEyv&DKMcCi3&x z_Xf_FUO6Qy=X3f)>!;~{xeQyf=MEA3hVEB^J=GZG zY3RL|IG0_sV`*&1D1InIX*0QM8u0_GC6|hP9{J>mX&Y;61M@KY2X^f=amK*@N*kg!JZWNo z*6{MXV{)wP$qU~|ZlOkU2TAkBo^Iv_`PZ2@<;ZIDfh_k8e5Lg57^H*e1NPsJ{$(C5 z&sOa#Y+LkQ?0FqeoUKTkf_y-4DIUBZSJtoN5U$PGS2uIsvWd@){mO-Y_Bg~>BTt=Y&L?po z%<`RA@HS&IW_TTQ$$UqCdd8+5tg!8^9z)P0AA|gv<+7?y-LvGMz;>|>AEzxNlhg(# zHxBc;iuq)|G2!&GUu(=&AZNwBzADn&TxRy|e#$n5aiw2vu9@BSKh^)xUhJ*JfA(jp+(!r}-S(5Wg z@P9sr3>Pc5AIGr*Km5n|&Cfoxh~0aE_^80z z#uw+f%2oQU08i#JaBj$(D|1X)s2o}?53;$C&Bta^ANFW)5uQN zP|oS<@o{#K=@{e{Z3895d4$nbTj#Htjjs z^J)9yapvxGF&1s48__8|zpauMu5+$A^q=*uEO#v_`Y(??>eSJ%L1*@1wC5Pcuw_i} zd+Nvq&L*z1N4gp3g2pS0i#g5-r%zssbGp$(=dmH32|IN+dz)>eJMm)~OO5QK^r`dQ zG#iKTXYo<{o(pJK_ZATEPqSKP(;?!=(M6Bv(KE?*{jKF5L$g(BZ4M(@yTq z;5RwN`{PHxhJEiG<2a4o=m;`o5&pmjlDV^yJoC;K{a?&s^Cf&hj~VQ|`j~0U90QhN z>_S7>!A7tzOgzWF54*t3NpbLX&X|5J`krS`HwRzN;;S|N{B_O}t}q5@$nzuMEo}Dl z&vDj*PsG?<+Cte2E$l}__(Kdqi&1PzhhQ2n>DLvN|}wX~DmH12F~b@U3yb zP|e=UJ>U#`Z2Q;WGVq8EHN!zZ2H=^Xy&d!+EyTsnQ`f);^OCX12Rq;q|DR$E`tXXg zNv<*IH_RTqA0CxA+9&W)3t#&oa)9(OmiFj-dg)hr7hhlO`r1H7SB*hC&)C7Q^52E9 z2~8mzX0VkwFXqHQW7@&_|Mc=0kQ4OnrG0-4JV=v4c*;53;~Il);s0ap&7IYn^om-Ftt(z0aQaK6|Ss zERy`8U@z?8H*^o+Ah%`6a@YsalddgVSf)qft0x@ZPtF|aPQu`dd=H(x07F~$kt@yk&3~TrY7L?CE$0)SsJ}!HG}0&{OSl+_;ze; zdclUpGV26CH#Cl!rLnOVf}bC9Cw)g)#rP_Pd_Nl-GKJnqvG`4q_)THN8bj#|wB=6e zFZ@(|;}HBXeJ3dTPGsitDx@cEKHtye`$=(k+MW3G;rM-9=tme5As;Z3g)c@g53NA? z*U-=E%H{hxtTgqi2t6h zTXZXDeuMe0`h^DJud0_-0JQ3dJtmvXEn*qIEI)j#By7h-?8dmnc-QMOlzY~91Nf|J zWrOeybp~Ryd?Cdh^vK#QUm0GE^>}Q1atzJortDfB2zVm3}Ju@~V-F#x{j7WXLIOtz}*S?MCTcrKqcPW>RsY2CRa6FZVx zBy7Je^3CxlB)9Y%vhidG$sYT?@AI39xuwotQ0yxP+a!vZc!d005vwf4!(X-TB!L-tP`wX(7|BB&XbEf|7638Y_z^u1=_NS12pTyt9a zT`P-RC4En{c9b?^C)8LRF|RwRGuei2l)WGssNV@7Ht5f9X-W4lFY(#$mU2BQ{7#~D zY&NzrvV0roK=eE6_YsW$D%i4#&r4UhM|5}g%F3#Hm#g#H!Tlv8hvRdxv9TGVm|3)q z+6LiAza_n=`VnvA-7AmFuk}0njSTKD75m6TY+vDqnyn%FAE^;P^ z=Wgk@kbC+K$&L)-(rNsL;7Km31*S@HTsX@C9;Q(#-It=p;5&4x1vXcJJs6CW|iHX zLT!TZ6VK;GJNlgHQ1p=w?1Dd)-c%mJ51lFhw4Ki-CnZ`EbGZ^&u{@7U<{UKsUj%W? zZSYe(zMb+5ItQWqOU6D<27d`$N8eAxSB+;Sa7J!Bx`mwM|D&1-)yK;xxdXp_BQwL+ z(N}(Xwk|!4=#{0}Wa^2o8Fj1kUDr{wtC?NP^Z$6{Gj7%^xpYnHJvZo$OuQix|n(Hm}?&i2vEB$AkBa!0id z{OBJo4Y?PMtc)YhQo-ju?7xRz56Sd0EYHcdg8UpSEvG)7*U8LmOQG*y2WRD?>E9bl zJZ=m9y8?*`Y8IzvJBAUXjp59A0J1~5N1d;7=Ou_8$q!sd9Cdk49kq_Yx;(Fr&+%OA z){I8s0N6F7O*1H6FMFPAMwu_T+(vJzKwwF@al*rvAIRoz!y^uO41nKu^S2S1Y|oIQO0aY#u(7MjS-&rK1OO>8Dr@>|W?0 zJ1N03p!alWSC7f)hgfDlXl`3LaluG%r&)&noRbZtC)hS{a0l_xJBZi0m?Sbrw6F%> zc)fbKD~_{{v$?=0_#Nz=L3T5Md35tQ$<5xP0Y1Bdv$%f5WP_PS7estCjJ|~N4;-?@ zhfY|`6!mG3U8Gk-s#Sjf1#5WWQG0Oj2y}@)qGv?}aq<}Y*TfK8PR`G=s#$V*?D4{A zFZqrp2lHrKz18J=EtCDvA_h}gkYm@Uv9pK+WrMrS*f=YrAFbdo^HL85%_O3qg|A3x zAs9Lif(``if~TbTIqj zW;KciSn36?*@K(ty%&G|q(vXzZDGU=bDnvC^HrQnKfB+e>0gvsS7BpId&!@5SpxK) zhE35|U5xyphc&oJCeA$njmK@Ej(T2t8l~}m1~Au`Ke_idn zD!*I(vo*g^b2;1`bkV(F2gZ%W^)>5$-6n9PM`VO%{%L+gP+Gi$J^I|dMNDz72>K47 zC-7eAUcHHgwK;$Io0*nb8xREU>7CQv#RLyoSmB;vm#(D zqPLZ3y*N9=is|c9K_9(y3$s>2zwRPpki}UUR+yf~BYFlLWCOPsdRU@2i0~kpp!t27 z*iGr+(O!SXetYG(>s{;m{%Zf}gW+%htU4d(=pLBWD|B6u;#JG=Yri+pXJI{kCVlA* z?gLJJ=$RYbTw>vSdn|!oR2hwxmN?c;?;3h)cURN1gn0(scLetvh71gYzq-ok6VBdy z*q3O2Cyt&TN!W&Ee8xkMi_)hr+uQ%~uMX}aWL#HGnN{W!chB)!1HEqc^>$b_c&YSe zSp|Gh!TUuS>6QmC6cHOO0AF5cM||OhS3F$T9==Gm^Y>Y=vR;Dj>HC1JmaMyD9dNJU zLG!w`|Eqhxj{djmhrW&;6KkP~jZwsO;H53dlmP7UEuB@^XyiHQog7wA-;vQa^FRZ! z6TRk{>9^#)oHKy$V#rZxCZlA08*%Iy&N9aUdnz(54m&&%T!>E7!C?#iU2^DSR7*eg zU2TolU0Z1#wbi^|YCSbo)>TzuT@_{4*-&det&P@PS`2QotpS`Y^|hJiIC{~QLoM~z z%J1cZ1GAS|uQ~YN{?C7L@Vk9y@9$7gP~ia?=;p-(|ML70@Bp2wHp8Di(hQYN+`mr} zx~#g$Lg+K5e(F)DXDzydI_bfBi~srq*xb}+Un3WOW{w`Ndzl%kS;EW#JH2R}9SC?6LeYNfCpwHdtuub)M+uTqetJfAs z2JGDFV|HMC#C8JbB>jK(bvDBX>2B|bkRSHKBf$GJmSF!e>venk?SF%hQkH3+y>>Xz zBXqClf?s;y&2!q~&uk285MuBXI?LRgBK^-F8L@$!OGv4g{0BPw)Lz^B;QbcXKtG}+ zX4j$nVovX|q+{b2LoGwZM2~GnP6Z=(6Jn#FRnFVc%Oi&GiU*SM=hE1tZ2IX=zxN?bQAmyK(W1-8_BR9=mYbp1XD#Sbq0+`M?Zty=~>}|J9i>8vt)+ zzhV7~^(IR=c%Ai{?M9CzB4<<^;^wr9?pfk{^+j~_FCO5%4b)z&W6w6QPaEmMyG!ym1*y_g3$}1;7qerVu3jUxg3Y? z_n@Cd_ww=bGSjW3AlI6a>;3HI{O&=!e)hP%{_N9cZ*l*>eFJb<|Ha=hd~h8ZYHxje z<-fn>@z<=kSb|^s|C-ezV_NCeFF4gdb|blR>Az*T)t7ON+Mcz>q~Pj^Kx5$I*`{@1ctp0_-7NCzKrd zHf$sDdpfc`2D$7l%0bSjnHQN=fE;UVuC(EvHaoruEH6H7zy9X4-1mRyZxw#g!0P_L zYH$DNzgj*pt3t(_2?7TiYL;o@Gdrx`3vuQKP zspVtW7NFB>u>)@2f5HyVjN5NtU){(54($4l;9uQ)(Z1yVckS8Zb5;ufYX*Y)VY$6t z*?*mL(ww5T+^_iGKc4d`)a8Xi_rCPsS|7c|79M`cV(7!Zk^ZuQ$i(o*LW{+g@rOr( z3Ot-c;5_y?zTk7$nURak<8vY4Ac@aL(4$hh#5DT1_0p#=3A|>o7e%#Y*0QtBx?Ahb z-gwcz@r2~o|MXA%FWwj3OYb2Ae+y1ueiE_p4M)p@JqR0g84v0WzzSim3VD0Y3W{M) z{95>2%O5=((CD=&^w}2pRd!%#4SoJSX)Sx=u$G)%SJ~!eoxLE{}6Mp2BvH3Qm2SZy+ZF6FTC4AwG`DQV9vbBtvoaET} zP9(iq!^zc)?&EG8vuI>NBDFcu;3a-5eQLG_GeZg)$%>_BCJmhA=VvlICD*#T8vhp& zpuHE*FY9~zEwKLv*n!*LV!io1dyf6eJ_|<80K7x`z%BeB<)D!N&h7*5HP{ETef;UI zAA-Es+y%eXSlbjseGWL;2rY=mBaci{KM`ReMbvE!)G~J)y$}88F)JY&n;;@An3+|~ zs)i4e@bfb0WmJGKT#X)m>-h)&m*Bsh?w5Jq(fzMq1ojs|%X9YjkDj)*G0Qb8f>UzN z*?+Qu)@rTlgEcmD^d#{^l7tZ_9)QLrK?I?IZ5q*+{9x&0pc+$zL{|Wqm0K4Se3cU;V8Ro@jA$zCmO05vS z)4tzY;&s8lviz{sHv{uJaIjADA0JS5Z#c1qaN-Kucg1`nh`|Yd{ZDbA$i38`&JR;x z7i#{%><{gzKYb8#AQ&0B4W5WahQuho1-^=Nv&_EzImlHuj(Alv>%a4No359RbM*c^ zKgaLBj_vpwI`7rTQU6@)rAO@TFI{!}t(ed6;XtxLI#B!oOb&ixL5gok7Rol*O#N68 zGd+W<^DLyT5MO}W3vi(soZ-l}@}Xu6rWa$xSc~~08ypUx71{pb@JTGZ-(6K`eYMn( z!~bsoU*_JB$+AzDb@u;X90+g1A4_sxbnjq)3ibEI?_mEncEyVi*#ndG0Fb_O`@TZ| z!i8SL6N+zbW?zL1&0o!e{}uC5ENEjSwWieiZNpy+hL$&>L;Uz`^zmt8_v8@hO<9Ue zkD^X%8#a%Y;*XK+eFpY&263+6oY`-7?U)@K>M(oin%UQG0QzGqIFQbg{1QF?-~P1c z`diWQPR=dsHpzJVG5h{H@W0IOzVxWsHy?Je+cVd!YjJV~_7$EN-HV0=GkYXHNJdVl zA=}(6OI|y>ko^>$i!L;~(L=l;x{@CI+o*Tq`(bURH zxe>d6u+8l3yqVFcJY7jm3 zHX!Sr9}G=69&x;}5(ff)$;b8Rbl>t+3*Xa$?2oZ%@YPUPY%lE_vTx4~+v|(t_A~sV zpBIYH0i^Sv&PDa&2ex*Y|qXeSjNHCqu_x35Dp%@2rpb+#)I}sG%KEv{1QE{=rG6E z!i#7`{}X>peh6l_*TAdqYpueKFJixWgFeAU7ROA42f>Txk~-f<`|I`={jQt`yege9 z+f+Jl8*}9aw`_xOXhSp+g`E>j48Rv17mBUxM?55u7)dB|X!f;M+Oxy}Zs7nrci$ZWiKlOe z^>%m#^Ro{uucxnp+spPmerir%yS>ddoNkByCF3+JP%y58CN!Vc`M}V({Qr&EIf0T3 zzEGc1U-|cN@F~&4IkV3}3y(`KaR0jZ=fK4(YG?mOV`sVjE>iFtcu z@2KOo-#m838mBn7N$fFxXAANU`d7^^w7zWjpznxJYYu^W|R_7He@bXS`_KGI=N?(VW@S9sx@dxz}1bMV3{9UKuI%&zdl z3JxwUAs1I@;l^oXBlPgdd2n$XO|XZKM?@dMXHP;aPw<{-Ml$3{o(pfRg^2+>^2X~{ zFvA(EG0xUZ58Hp~F2V~=9!ww)z`=2F zAekt=AX<=axODh;co01Z7m^R6iASIf@rYaC=F!`i-WR@BKF4=riN&{*Z}HZbTk06~ zXg$=n0DnYvfo(IANq`YkNsn<~ahd`p#}f*RMw=iXSv%d^7&*8D#xAWZi|^aNy_w z96Z>!Ob3q)wK`sSVzkqqnLsb>>9cRF(80^H4;FVj{U}QSx-Nbo&nk;5#BYCH2i(>9pR0XvSHFfkWVP+z7 z-p##d4yxc>2Tf~st!P`Xb&kZ3b2jR^teJA_$ocqS8%fvs;^SvBAMY$UIPY*!<>=rt zyl@p>kW3T~Zb}}k^1@h`Jw4uoT-<5jm>w`E6ZVhTtH^{OV<$Nq!N~>gf0Z6&CkhuA zR%FEe;t$aV3w*qEZprE%K@af!#Qrh+^@%w2mS^zDnxTMu7ohL7@IqWvKJN6lb6-B@O) znMZiGx!lgRtk6MwwO#522VHfyaB!o)*&ZHhv(N2n|DA5Y{(fP4nIFE5On4bQ$WBpNgzzBwuxc}$7cN-XPi?<4%eZ*nJgrSOaN>~7Elyd=;RBq3Cx<-I&pALZ zaoRZY{^Y2LHH6}82I~A5w5(annrkJyPI^H75Y;PO{O|k%>|OD@aN~3zJm7=8+WMSd=fLrJcp+_%ZrYtw#Wy2&MkP^<$hLpUa+pgo(bZNnezRTf0`+%xQ8$Lzz>;s zw5HIG)fU=uY~16_Aw7XTaFW?;r&yu~(SrCvIJmz996$%FICu~`5Dp$$p#|wj@q^^T z^Vo}DBUdP!@!R``oV_4=aCm?gWIKu;ezS@T=;Ak`30B&X1sh`}jiTE-+U*4SzxZ+L zZ67$zx$qi`BySp#mTr;g0)O^DG={hx^UPYPDU=QCd|=?!e*3}?&gX>=6dzhoELgf= z19sm&&K)h*6xdGLZm^-VpL3v;HSN5yR1F_F~^nqTq6zh~P z=*ylf*A)-0!s)?Yirugu-65I;O1 zI{_R>CTKl^Y;^V#HskN%0eTQmIDLuj`0D&9@zifokn0Jd z*Z8Iwa(?K+aN>DE#H)N{1M>b7v~XB>aJVRRxHt?Bj=~R~ZsY(sh+<~)KIWDlLqDEh zr3J}G^pb2P=?B?M52GWcBbMc3r?Z`(!GCxTT9Axf<_TovyznrB{WNN?OI9xIc6wvy zFg>4Me1iFc%*dXZA@|yC;Vn(f5~FqxSrCxOys5%U{8?bfwpV?Y4>26&`~IK}JG>;#94{m{cvWWs6q;oPczz+RM&T(z5*Z3X1Qiml*$2V}xiPCj-cAK_ta zRmIi^Fm;+)dL0BEZp|U)oW{AlYv_^S`>Z&YV%dUQ@awta7K&%x z9^;oU92mh_TFz4n-i^or&CHa~w-J7bB^D5d{!1cnwFvynILP}QEx-@L!#QIA;Z@nT z2rg#&T5JIwaRj+|vI!bk(UHqGW0hS350Z_N3$mFm!56{AXG1mXhyAz=KAsrsbaG)c z`bRN|;9}^Dy0*M0K4)8t@;NgaVL4Ac%K2{eI{T{L5!>iB6i6MfVAZ}0HpMI*{Jai~ zXWkNLlbwIVXLM$GGxnel@p{EFRMX?mi<75T?*$)tp`Li2;sFQH{aS+mz-@RCEl3s| z1rNu0oJBTH3Mc4@{E1dOf_^+9Isgy1+lKv?$2>Q$Sk5C4S@!XxoTuje2ysZsHSM{t;KiQb2<*#y4(;5~7p ziGAFbmS)ZKbKo|aI0iWk_IiCt0QHg7CXkzn<8hGd%?sw+mcs$B^|=4{a3Pvl#>2r1 z^aAxRvX|ETvk&A#ik)2Oq~0;VG}AJn`3>Y+ zR70v5%Q|Rq6LLttmM^wPkm_sLv!wb8ONIAC8apf)`U%YDZ0fEdWR+yxvV0TlIs+m3 zwGN(%N~h;Fu??RL<}Xu=w+_4pAVZx$3k_(VR3P-e6?(rNZax1!*l)vu@Sx@B030lo z=h`^0qSEADdY%&XN3I>sL!#J(1W{wzOQ*l zy5G&xL+qPyqWM1&!=v;qk9W0|fynx(eG}%F1w7D;bi4RlwC?C09Bd9Gk56pRhx%9X zy7bsuJ(7#@jfK{cvwh^>)z6`YGyQ^hx+MD+4%~j@N3G()y3Vg5Qriv4Fx%+eG~+ zlMih(GcW_V*P^%SwTEvLP|A6FW?)C|9b;dqG2=YWs;t);q)mb3ao`8px31P_HNWL@ z-D^2}0DjTyiP%s9$POX|edQzNl9n7C;y zaVB8(DMFrO7p#dQ_s;*<1Z=XHxNXEG^06H`gF$>e@tFtBpPGS9^utOzy=aNlt_Bjn z3a2h?T?9S~=L<5v@CoLXF^8Ud4E26jA9EkhajwPQ+kmaMf%<067A{@CX9&{#vQjpjYBhi5lY9~atIM;*;He$8>q ze*Jm+Vxhm0tLxDf>r}tbK06x+c_%whw7&rzueipczxt%3e;3bQ&GkBepK~9`{muAy zf=hbrpk&wz?1KOIaDWVO@avH^ciURUOLTFn2_Jzi`Hsee##@**iC-Cltp#o0K@3fF zAA%noIDp&+|J(5K0zLHQfcMs7djvAiP<8if*(1%l^P?tuOEvK-^mZ`zL*m&53n7mf zR^&xLAj{Abj+X_ua?{e^p#T7M)rBL&b`3v8HXHy(1s=S0bhOrj5v)Q&bS6L|j&wAn&KG13aHsw0(aM8G8b!*Aj zs9&;P`*R-9okdYE68W^iE*v|7-H*hpS2xUboQsI%M1d7X%fQQJuUjAXmw zlfLnZ%#8=<=!wL<9C%^t>kz-3*z^=871Mh!H2dn&jiw>kS zR`4;$^L;#@g(n4nkSEgZ`8$278w;m?w8UfUlBhRkFBD%}PwiYVa&0|!&06%Z^u&7d z3!!C&7C3gLfIcasx=1+df4_O~dJ|~3uxj+7%A7|Fo^F;7(qV7n2S7a~A z1`Nc9+Ze2Q4_psj>gs&t=YuEFgkFmVj>u{b_Sr5L{3fvLkV_{3fJg1LM2|7^mrY*!fW$ofs_vMBk<*mjEP zi|=Lkt@6J3-NC*h18>0(?1xw3m+i7b2ZCR`pmn<(biA-a|I4(nj0e&Gy2v2A1KIsf zbobg&_8r-JM;JZ0N~kqM&nbSsHVU6IlQ>i&`6TRnoj=pu59MDpmv#-ZJB;}x>!}OZ z{;LOsFLv(+VlYv;1(w#@jV(mav(8p0Cw-82&W@LThs}|(Yo|NYyOubW@-}Yosc%@u zgW^4k`7X;r`KsFgTkwky;0H$oJeN%TJvsmvw`gF6_8ktu#}sx-J#;8}|4!__%_W*W zkI&MCJsgUEiCwS!n$C`F#2<8a0eqkysCQr+h&G%L3QdP_rX!-am6>;y^nvnV+l6qB zG?zMiY6`cJlc!Hc2EFQ1hK6hdbzHvq{yMWaeCh=8zbgENSgr-GrAN>U@^539^QB%I z>SwfC%OUuWtm1%p&N2`D0S<203Ae$23lG4)9vf~Gbs!P=QsVKreDW-u`CNlekEkzP z*6+|l+E_a>n=_a2yLA3$^rd>6>Kxh~+~*p8Lv*kKxfVn1;b!KZ2ZS>ZojvnG{^`6$ z5NDr#(QoPvv6b`GTARVa2F?;xEnQ@GLBG|E&g0{AmJ?st)iPlt#8lS+H!^_ufO@s4 zugNiB7Y-a9+|CCpJRteFtQVyVe&042D#^1s@ZpoHy+qdH?`a>k|Ld`9*5Hc^&dIY& z&JS2i%tE%WA2M%Kexie4^sfD1&-o(%=3EQf$$oQYHl7{`y3etx{mcB1T<{Bn&w)9S zJ~-=;5oJsCCg(iy7Vx1yGYK^{>^;2#nS&8T4;sz0luhh(ANw9if3cLx8h8TVo;kZ~ z*84bLeVGRGeqRa);NlgQY9g zo5?>S0oxedU_&TYbwuzJyH#94F>J-Pg@-wG%x2C;HgK*d2|cyI-fNAP)5A-$8~zQ8 zr%x?1e~sIF`ZTlug6;Md*i&q=#DvwyIFq=S_&~BwIP<~Z75z&G1auZ6xA5bsFI8W_ z&Cq;gE42#sZ8pMr;c#Lcp~%E7^cQcW$4dw^A2-pXKs}744@4uuDVY}AKk9f}{q!VD z)^na${}aC_Ktt<^f$9Bl{y*4K=4M8Rrlr~jWVJ7~+|9-5b{Ltkw;Vm25@kNQ^jPbw zr2i)83)%Zw>ZkHJ6LE+38F+h`$tzgaW8bXBFOmFv2TT7GKD7VpWh}kuSB&gJ|F8FQ zzsL*m|9WiX^;_t*5E-{D3!v3?*e>f?;l%Odn6(;HQH6gRWA*e?QU4}q*KR=1V$X&{ z_rk4Yq*!f8eI1{zh?g94K z<#xb`X=c#>J_$lu_^dYM1HYV%uQGT=UmI^ zpSv*tyMjI4NN|tARwr!_oH?gkVJjCEUoMBD!rqc^L-7-pY zEw8G`3eXG1#AHh4&*anZm|Bx!&NUTfXIOq_s^wfck6F>oc7B#!=+g;_jla0eReXRz^AYP+pd0ael0j^Fvj{2Wo1{tf8uu zbCc!PT2sL}x^ip4f2c1jvO4VR`tl-ct}VBYrs|dJFZT&`*CxlH__wR?AQtUUZ&A&f z4$Vz<^+I>vRnF|dQse>iWw>@$AwBl-OAE>htcDtkws+lS-R*bTz`NRP*Uop@$lYC> zW9zhgI@@fZv&9C9*^Ui#+r96($EL>mm+{XY$X8Qsjk`AS81)X&wF8s3LjyZ(D{?rB zv-C0K5o2qZ&qZ!O4Ib3lfjq8X0nF{hMRpDM+RVg=ec+Gw*azP~YezmXXG`zjYxm9G zYYV)0cz)LY^p6kNsXsYj2j4&GuD{wRReeL%uU7H)0D8JA))<_g$hj~2U2ujyx|M$V z#HwSFjS1O1-1)5>_P(?@&stg=Y?PSX!4K@U^QVs4CqDWS`}D^z+l>dV+Jk?2$v%GZ zoIUWdkMR1EedhW{?dtu1YJYNY*1_#yXYbv1U$U?K<1_Z$m;T$$k57M*=a1RnKmHl}%qKr$r~hQ$)%%Fry_<+3`T@UkP+`P_!pJ*>Q|B0g zZFncw-p;wEIB3Dc|FW}oSOw=udcpf2fAD~P_R|m8KYjTr``3T@y1o3JZ`-Ti`wr_R zdxhuUd+9~{&bPm6-}>h-+4IjlVxPPDQTvMzFSLvLF87Rr~P|e_%g( z{WZ6K{KN0t>#u#+e(>r)+xNcxCHvYx{_AM#E=8&51@X! zq0m4WIqz`Kc8em{8jBuGz`ozXV-7S~mY-ogEj4zOxYQT_=CABK-~5`r{)1QSr$734 z`#Cj-KY!y#?(t_o`GLLh`giR0fBUMv@~tQBt51L09{$9K?N1MpmxcDVHn4oafiHXD zFB=!W-$G0-oO{^DUTnu#_7r76^Qq<~PE{^iSmYd`$nKif}# z_^Q46lYh5g{PcBu>u0a?`0u>to__eE{pjT{+bduHTl>o6AGe1uAGb4y?nO5en`G&n zo6fTMq8t5%1N70BZRDNsL+?!9ZaZ@5vw`k!fe*WR96=5pBo^_P)K>iyao8V#(>K2J zoW1$lx9zPTzhb}q$-l8)<@tB*O|JdZSD&@lzxBAi{M={ktDpOreg5i)>|@9Gxoh8o zUDsCrhS*III0(Zhj)o4@-@24~ocF;0$M0^m3xln8otl|1&X3twPrct>y?)Am@^_!G zH^2I~_SQ>J+b{p^EB4DDe2w*0`^CTgll}a=|6o7)m(Sa4|MVIA&XXUv=N~$6kACc^ zee6SX4(}V;`%T(=a328d!CX5W__rg2l_hkMaWQ%A`|9-te+WFFGeQ~ceLeDLm^j1xf&JXhdi%_~+wFE1yJ~NI@rwQX=P%iJ9{z|u z2cB+T_@JHn~3@%vR-@-?`;H5GP4eVK*)98lY-cOy+N#yQFsXzD> z^$DMU4|QAj_S-kW!OMrIa(7W@@m_q}gIxavdhaax z*^iQ+f1v*^yU9H~1|I%_Sk&{>DZNPT-b>W7z5-3WdhCzvyC?VA^BLZ9C(jCcksRT*wU0;gvQ>tZ`|&l z+{L^*`qEJ+<-rEnjx7?2ALOo${M9+FVCDYU_XOy!1bd^8>rdn7?Z*zB2M40T`?!Y_ z;Nc_e#btQ$6X4>npo!1G7k>>t9(nIhy9rJ{aqm5LVS31x_6*wa_&rvGUiPB@lkuCj z=hE+q+-o>B2%CZ354sBi@8b6;U{8kUO6e;v`0oY(??d0t;FpY{gZFR`i{uDD1U>#4 zwRIn%cH%s>6K7Z-rhejdFTNVJuH*gK8-wq%wwW9t6#WL37c>(2|ii`NZT~&@UtOr??m1n`I9sxrZTqq#c^jDn*cWMeP)*+vaWc})qu|LQHPjTr;A^bpJgW^$G4%@;zSy$l7vfzMX3i1N(c6GF@J78vQ@YeYBQlS#3qO-Bp=Gubey^BY>z!6r(otFk+(eGd2FH^k&X9>_gx#m0+=*Szq09echr z%VY26+7sw}<*k($+{3zu*Olm?EH5($3b0>G(ygdG%gReK(SvE0PELM1c4BmTvTdg( zIIgbs*`>#!HAi6a--mNfDW z_!9o)|NY3t`l{wzi+=6tz+J(2yH?<9S$X1gbAG_=M{fo7$lpY4POBK4 zwQ0YRvlD`wYfp1cttr+xuLpp=4&3kH+S_(ulj1K1^E@Pn-tg@E7V(&$&80e$7s zhYz156uT&dvv+~ig!n_}{_MMIhSZ~e6L~Qoa%?{22Ak0@gE^@-j(!!+r`=k<_ItVZ z2ywh_%^JWC+wQp&zn>g@60;OI_Z6t-#y`aIhKtZ^EzM#F=M3 zu3meU)+V|3IBRs}+L8kW*ne@1Sf(gdPWA&OVc-8z3jCQEFSkj-;=Cy)_b__2x|~}yBj`eh9(QScEWb@ z!ko7Z!VeE1zU|Lz#SnGoeiN@Z<0tvW!rKX&ddQFL6ZI6O)?Q_cBvt6#g2-w(Jv~LkF!~yB-^}5E-oV+1qq&;#Pj-T6NyT?@s6# zJS<-yc!^0KiAgW3(XeM{0YtT@Y@<`Bfxz( z*X`uGP4JlHSSi=eg)Wm4>6Z?C!MZjvvrSsM2k_u093U@M8?q^q`VjalfZnGe;5sw~ z_=yQ?u1OI6*;nU^=-Qflu{!(0k3OTm*n0k3=vju(u?0A`LQ8j2Tao}TrNX;8*a)Q+ z#a35eY0c=6_SQzXT6x~oP|caKKynTARl{crP@a&)&P+ z4$Mv4eea*acH3h!dq#QxZVTZ1!Ptu7)TKtp(}R)Poh)it%J2Kcx_wZK03FXiJqXP?P`X``*KG zl>6+Vzc^u^z4T%G}fHLGVZy=Fq?U9 z%pUraIs2PGJH&C-!*=yg@3Rjdnzi|vQ5zkmpAxu>0rxwwS&G43JFt&qFCF6h=Y~7% z8g|Hy4@}snmuBqh2mi><9N1$E)9<$T@ZGM?CW{32cwo;&4^)D?9{B#f=DhpemDAfiW;}~ z^BW7;NeB3yIqE>)OYE|rK7P%2Ra<#gvE^U`CPBZM*gGZE`7|PHI^n&Y@I)`aaSt)m zd+@V*iMMn$mRmD=rMiZ5`=$BJ-pFEZ6SIV%nF3-3)#%SA;U4~J;y3EJk7{H|CGo1V z65^Kl>3J;0Yj$|)3yAHxof^QrgcvJFf7QWnx_%wMQO?TKd>!<027YcTXT{W;GMSaY zHDj@3?!<j0dI|cqxi_WF)=tB9ZM8tZm5HaK0PHcSD(bQO zOJR@GsU68go@H=eDHU75vm?opc91K={*FaACi45sVV${UAH)ux1n&tDj z>T9MyeW$W_(n^>$P(QKc=74t29A-Y(5i4ij?a=-s*0Jxjr4uu6-L=Qk^NH2c&o`}( z8HHWDnG3Ls+6jNF-Z{p7vHQl_)YbWA>TvnI?-E6Pw!DX^Tdlbb>gB;U3$od z4ji?*ox7kvVwSbcV&k&~%n(guCSJ?LqSY~H&&!Oqp1nsnuhHY?)$6xhe>P&+s%Ks} za?FH>1@13AhJDN_r&liX$;ovl6n9wr*sK+kD=DmNvBtr1t7z+?UjcIim{-=nXRl>5 z4>E%O%5~&N8g~vc|97vo?q)t*Ua>XsUI{ZK-Rr6zJ9_Cl=R*7K;w%5@=EC`gMp^yN zL299kZ0{$&WToU0H0Re#&*MCL;a31}baI9b9X?GT<8C|h&@;Ah`KIkXbH(b3*SC(% zxVr4j+MUb{o}$ljJ8`@UdZOc(?$X>gX3@Pq7mQqk{dCa2|{BBkXbf9{M z7;0jKgSViCeCF|H(@Q>^nF0r|Jk0E7W)E~Qx0~9TQf84i?4-AR)1dv`5C4n;deZs^hFS)F z=vB|E+Q!Y~@mBevXa5=N8fCV7(-8Qq1b%Yg-Ges1bkfy1v;$L4+obC|t=S0?N%(BL z4zNeeIPRQePCWDPDwtzV|NF&jPq>*DnYF!+4>PMZ1F*+3pi|BDQ;+_gduHi@KWO{T zT(VSp@24;aq;+Nq_&8t3^)=sP&&m63j(lC)$h37#%v%$W{?Q50Y74(xZYj`gJpA4~ zbAtJ!Cv4y_pTBs+9(eXe+r4zg`t}{R_FWU!w|GB2s^ggVK~HRGaWlD_<(gjVIic%S z9C%yVXYkiEOCQLymzfLL;^amWeWT;D=uw`9{@j0-eQULjz2FOZ(J^z}YM9yUfd)M} zg_hFNV5yu9EQOxZnMc_(f6j{9n9~6LY(oyD6*JcwTCdwZZ}ae&KHniF4$G^rt9=4w8gVr*(m)LfItOMGK|8lK4K931|ALx+_xQ=@u#&dsk)sp+(_ zOOM;hr+>$fwz0(n{|ejl2%_Wc)Z_~2Sb+y)j-SV`xwWz-M2d#@*d+&slB$WG>opl@nNHRl8!25x(%7p;%aS0M|k zS)ItSu*3{_U@!fgtF2~euT=wke(R7`O`f!|gD33D^Do=}^VebB?>2sWLEcWkUyu_vBdvyc*1&G_ZH|^VhAUwb$y0r>M!Kwj6r& zqEoY(jnQ}b0oOym`}jlF$@OMVUa--HlXmjqr!1$e2K_|OdwS+)psTBxnc6UQf?2Ws z$i<6R%FOjyX4LEd(%YIflR~floU&S5qdYe{QgvOcGQq>_-^AQn>Vm_pcIUW7dzcwl zQEz$G#N()sX&+%8bauX_u-CFns;R-$e1-J(DdhT2W`Qyf1v<)L-tj(UQw8%wG$*Eh z@{n~OIB7?3JYm_rGZsbftFoR6D<3~jpZ*GJvZky8+aZmdyk-GQKUVcmBb%$?hgo#Z zoDD4;XRr5IL*J;)96yiDqaRro^`O)>wCz7_v-dx4EzDfk4CSa)&e6q@Z{m0Q7tT1j z-pK6Mn$7`BDr~d}`g9~BdnFfL-)}>MZgR{u=9A}fI)%05-_$cpWjy*h~e#tS|X_Mz3 zLT(P*?gK~M%;WK!udq+Yt+IRAYKLd7W#4%lUOel5Bc-UGS{CNxU?&XiTe27a-?tqs z%>%#!{b}!_QVOjdTj=YUdUX?rn8OU6BYztQr|j5`#~qCp)pt1kmJ1Af&OGRJ_-1BS zsD?y!z^=9#TJWd7MYN#bFM`)gkXN0P^d6^HDxY39F^L{)MaH*H9kj&KHcPMS<~}Pq z-%G#fw%yEKZ9v}*+u-R3Ehf8)*~_iuCxhLb_!9WIsB@e%$Ng4;-IB;WgX&$=cIlx=IFjwz@ z?YPPhyZ0Yt2Js%?tFf5mOh+$C`NXD~q2*zQcuF}v!kO7Tj{Z-kHlhUkEIy}_-VPPW zedetmzJ@$)u+EuzX3{X%y}AWIFrQi2@H>2-*Rh-Ws|IL$FLR}_rI|%kGqBu?xC%PT z>Dpseyk8CNH4IMJ(EJhGwRqgw!?MMTduMI<dXcFOz0BKg??pdQC(RsrFLRiL!&c@A`%^2pp1FmR2g|gu#{T|aUa=EbZZa!- zr=4Suijf`Pfi{YonZFBPYOb;NTlQg9AM>hu=~s>3@?_>Y+jtn;y`rt(2Imi1E}tDc zdD&u^t6koMFTx!4q88>3p|fRI=fiWUrJ7yQz}dkFW=uCDHxD~qP>U_t2t9V}o@H+Q z9!HDmz?+AR_O^}@1Jc}`B%8eWq>Y|>kU2)Y-@o75MyIU`-1T7}*TRE~=Po;YE(RY< zGm2IBvn3*yJjWRGxjFZVEOxc7D>6a#G;zekmd;;s^HZ|g_CUYPae@ytTSIf*HA_9W zdj?u=wj5>-mF?Q^=r9ZUnp@q3|H8QobV&Iiy#}Dq`n@O6k?1F2ZCp6-{HiqgA-=c; zpToy`v3mW9(oUZm{Z-1EdmXfR6F@Qcn~>p=B6FK_Bb-L+sPlz zc&ZpbY8_+KR_9?pgEDqp%|+ z&y&jAtbg$oe&@W^pj!)So3L{_sX3$fJTfe;g_-owep&@I%$`Ohai*+sr!C!l27D~w z*X~3&_Ask@2)PCyVOtf#J4Lk}HhuCuIx5@FJjPrIS+9K?nA55AbXMoBKzwkLjh398SP@5RJuiO&{iY$D|c9 zV|xJ_+->6rPdRx%eeA5YPA}=uTqt`5{q|NgC4%qmSbCz3)9B%G* zGu#Ur+ATS+j?X1P+Z|3u-j0K9%&OEik_&6Cc=!-9ycwHz7TI6nbWtevbVb<3dC+y! z&=~yRiQTu~*~Owy4|~ysKh(-T6>$IIIVEoP-pr*Z?bM^s*%LoAo4@v$o6+7dG)b*P zfP+7!7`p|%l8tP1IK(HByqEuzjQq&2X|h~w!MZNyDnf(3&_G&QGjb%`^=xX}OHUJK zzlTP9ER%ci;)h;+?q!=khR@bMYOTZpYPxq>73T!<(Lb_>y};oq>!QYiIk40QOE-ug zBs<&thAahJIviP=kXel1H)P2b-BvoZ-*WJMM~+>v{`tf7twr8uS2L4|++s=|_U}Bn z;k(F%6m&;AGCY>pPe^2fRiOW7PG6-b%@bD3{xuHlhVQAlxc)s$DQmT6Y~_yq*hct( z`At1`;E|UcZxs-`$*-(q54)_Cv%S0K4l!3O8vQV0TgaLC1~X@X*^RLo#I@j8>FUSd zFk8HI!*Yw5lR(U&ocLLJ*O0|#aaJ&n8Pz4ski#CytY>B+GrZ#SYq7)WeZL|T-to>g z)b4cv60W!aO{4n#T;;g8Dj$C*tI%u~QQ^PFSvRfyJ_taYn zv6~WL&qX(Rsn6Eju{3JoqsZfwb&W7fiaabd*Z{AUxAxo2l_!yt=+nV5n>}^Oyy&hL zXifG>BEG`twdb4+kAoj&gQ_lE^TJ{>OI=N{lZz`dAu%fl-?z$Av2jwcJqz)3vUcvb zxWYPOCFtvnGGYkWO6WlkH0*5|h5uWK3n4#{=T)PJuqSG*eVRU0kNq>X`Ot6glocXh z2Nq6QdEX>4%1P!B?#9M{#M-#;{-yKI=PKk3e-=JaN^XhMkHzqAEjlHmcF;=7sJTop z!iQ?ZZ#(X6>XfoJJNd|S&W38j?ieE8&_(=j@!IF`VUa`l<+a1a{D>tAkJ0!Mxxi4` z-p|~{QRuE7y$)R<`(!IPxd=aOqAs?eik@NME;OSQdag!~^iem0%{6)2QmfH3?5Scw z9&Cz4=Awa?Z&vKAqvb}0{E!xnoQRlbG7e09Nc^9WW_v{;%+X0MyyRD4a zru>aQ?224s7V@{_io4j8JnAp#e^u6kuUump=#cA+m(@Pb-uL56Gsg)ZIyDX60tXrJQ~_~m%~Y+NIAx`S z)69^oMc(;iV-$jiS!}*(Y=b_Vzx1H@y`YB0(_fHY@&SlAQ$^* z>DX~6XVU87yYUlF2F7@6u`i%Mez%L5>L@nV(7r>&80IV+x>j70TQ@LEUb7GxP)Sawz{SQD7fI%v#U}jZ5MrRKa#1=mrwkdub&@0#h*kEUx`Dl& zW4ZZ-mdxyH`JE}?H?L`wS#0Dd@Y&?Y$nVI=DRPe|uYZ9YPNw6Nsy=*c?6l&6IU6|n zpn1x>Exoi3U4;y%hC2tDUxdt)Onv1SKgYh=KwOzQso-tk$OFWh_B)@y2Oppl*kjP8 zdfr5=+l!A-)Hi6c_$_(p$=&#Eefy8Xm)K>sqgDhzn(;9lZPyb_KDg+IB0(Pe^8uV$%z;9S6w0oQ6)A$;@@d zo7w$~F19awR{p>2y;R~L8WAV{HL9G_tN!8U5s_)Fm@Dt znt+WKhwYk=yq&uEDEtGjvS%H{ueuj5K_`n=NNyy%1fLR`&ceP;U|!(B5p)J}T)BwA zBro+*^wuB`m4FQtL;Up?KY)*PXeSCAAr<)_m70ehgC6;!PGv?Vu;(LVv+?P&n4w;aKJMOs9($mHd0qG<(BMNqB<6&CPDDN@qKo`FgQU39 zJKpgQXE&#KnQevrol-~shrCZ2@#|RVA}Asrc|DJe*-f5km&3sZ&Y8tz7h7B3F5+Zq z#9xV-qQf5hr6IG&h^L~Ph_h-|b!}6tvrkhB>(RUTG>yy#?jx_!JY*xXqkBi-+iG%L zGuBMbCbfVXEAlg2sqsk4ufdmrSFpcQuw~0f=Ey06J90ji=$op}LHK01m6IDPM6W7W zlU&yBeA&}ayo7u}r=ib1d^Z!@J}D2Kw{rr2q=ufbtNgI+KS?fzawbjoQ#^E1g8d?0 z)OYMMv(brHwG9&!nQ`>2_)`G(i{zo?lW-?{N;Hy7{xTU@>&e|^5_6G%k^y{i(DA;D z597;BSVk+njjSwf?jcsuL#$}Tc0unY?Zg;r(8<6UNsUcj4{^KVawmH$u~{`E)!RH` zNkz?0er6Pw=Umxpd`)uU4(K!y+K<5ZO(A9)!+obz({E5QC2|)zHOsQ+$rrxiXkjg% zm&{9phW$gBd&E7a5c7=YEK(}D70q1@#ZU1PSF336wozC1grAGbz)+=-Kyu&1xM zd|Ehpu`=RGlb4?&UeQLqPbT}xtQ~kMtpRxtj;luSOR$H^$V1dala1Jm@{RI4Ml1(8 zp5DZ3=xp}USFP>v4d>&f5PN7_dcdZZ&RX%vQFJnM<~f5Ji(XG9-V;ZxJ0-trnIB{` zI+;*p+t6>x__0aI3{QCvH9++7A>JLyeWoEBuH1Nd83)8C6-SGSPo@sG*Q$Dl9c^e% zZg?zpTM6(Tai|XB51HuHz5^$0^ymdQ=YDwcB)T5|rf=FR$rUTd+I!%f!?$E!9A^N- z(T8>205(pl^dIrEB4E$!o3pONH?avvn916JY|Fu# z?mh6~gv#_;D(p5-Hg&1gg~esT%h=^T_!!}dUU+n;bQb=QnZnY0KkUW&N|zRhP};uPOi3Jt^Kn?qSo%lCw%? zf9fWWT46u5ar6=A(=-gt;O8*M9(?8xE`fjIqQq0u#H+~GRPHe=2Va6d70KxOWOSTn z%M1S7ed%EGHkz9*|1VLnBR?Xr6GTJOEvfKCHuv!lU->#`Etb#ZR+2wb4kw!&!}-U) zN-Uc*O~j6d$ce;ytI#jdJvon>{t0Rtj$`|FSUfs9F}KRn(Tnx7m#lX8AzQltGC1y~ zhN9HT?n-=L$$P~OBr}C)5w>`B z4>6x?&a+`BWtCtj6%zlzUQH|lH%;hmd?cMuUQ3QgGI3cZke^34cet3zG zr8qyInyrKPQ|r*o@59UJbLC3Yuum)4d({*aK=wsrCNNpj-&sK}=dVn*HML~2JC(aZRC$n7lr;;qCGQpiiyke8{)-c(IVIeVNz z+&nRx^OmczC1gU&zB87OEQ*0AJisjZseMo`Tj$YJ@R8ex#~nW?{t!T;GcpM;*#>C zQt(;EiHT+dLmobMDsoYiBodjyoI~w|?Ddq2omPe(P#(Ggz3J^C?+4EowDegzvRX1T zihb}9qdEQT&+v8X$f2Khc7FnN9)tgv)x4V;$Zfac3A>R~ikB+SrnpK}67^$wCC;YJ zqBlWo7JaLTu?a_C`1>zAn@8vIOBy;|J|`C)l!A{{P}fKtGt|oPTQZQ%iVY`{w@88p zbBUoBB2u2^$nKRNdUH?056Lsr?(EJkpsctZ+) z)X^tiCO^E#Y8zX*XUD$t0dzfZgrI7w^Q5&d1kMY;xxQhn-)aDZd6=GYNYzA&c4p zWOix)jEl!K!t2raZaMIl% zEC4@VzMo%<3?$B@SXc&rNGY~zBKkU|ZqTY`&N-P>K`f+`Ty0E#r*%!vGxHKX#(ix| zrG~Dn&!UJK$!8LOD<2~nq51F$E9Q`mZ&chfVT<^ zSh}Nk%+Zj1;cRT1ine9nqJ8!hw%a5#yDwU_Vn@UWV$fCc*W$1lobQYe7soy-hN+$= zN$^(;byyL^Y&`H+68Xto^!nK3w99#K4pvO&4&+FQi^FsxmqW;NNv`Uzw0k$XZDN+v zHTZK`)I<~lS1EQ)zGOT)Bd6~Ww!tLz8+|Uf-9VjSGJaBV`>^FhKh+}()HEHid};%V z(IrLFC)gFal@ExOfV_q~w5bUO+yx5xaeuoLCM1d<}Y5^ioYuzKr-q0AVq zwQ>#Z_`}@?sH@;R%28%wgSSuM&lcB{%i2wxe~$PWwF1bUTy({?pS}&Q7R^)DN8KGc zPw-nq4+iCPE67QfqvLakGo~T~Jj8>WCa~G2=B#&i(baIIga1JK8>ly395zBCdoTSU z{ix?!8+?Q5QOWsva#E>^BU4LNL~Ug>_TfhIJgVpNKu^kh##4(?p%?`Djl53!d_za6 zjl19@;zitZHgH#Rzp;6()CUr?!^XT`0&i72KAG0>>@o4fb6~v#UXKUrJqDM;5F~v>T9_`?STB3Grhcsd~slYG#m^k%- zHNmfn6~rUYQ_AaIeAkmltOB1UCIy>P_8hi*0d`^vayF72M>;VS$(M>Jg!|)x^Ney{`ENoxN?QC!@JthCr+cR&)S65-{Nq!f%4&ZwdQ<^$$6Q`-!9T=tN?0}0`7b;c>Zz#Vxi7!?L%<`pG zt5<{_R*yU%JaV3U-s$k)NIX6VJ6`sBJvLL{;u&;z1O6FsViQzQdlyGdmugI6k%!xm z2XX9a3Uad^x>8+&{OXu&_!}CLkGwgIGbG#M$Y~&3;Ga0`55bwh-nhIgvFU>Uud6c+ zvGY97FtoUK($dt8>!h)*$kOP{cJ_TgGv~~9X3=OgT4p58j7E#4u_bFP*%J#3*}}$1 z$QTJ>BOHW-BaBUHO`T#yC|yDbA$1|4rTtfG`oH~=e=YRub-iaqN`8EdN7gy-_AK{v zKll3y|1WX&_Rr(wiptuX=uS3*)^I;PiZ&cTj&sPtfmm19d1lwqaGky$J@~Kx!B5`~ z{9^~q)n30sy*d}I-+mBHUw9Yo-y3M5HlrF?a+Kaw7yfDjE@2v7k6ID+5cY=T{IrDz zyu+DyKIZ-V%ha764=lXx)gEo z5O|<3RgCiW5$=xtDYnnQH}~xwfxq+pNcQ0S;ORZT7T6_D4qv_V1wH6fVEs3u16%L% zU9;5DmjZ_+zA9k<;@~oUH2IdnF*G}CSEJSUej4TXZ$_{E^w&{-`Y3hwHF#yTv=`q4 zH*8Qx?hBlPwr_21uc>+PBz9}`ol$F8a2xEAe0 z*V$S=7ySr+L|h%`{cgL;HOcAcEi`^9Al=p7lh)%*I z?%jHyys{ouS=%(6rG7tm{_SXT^Hy{StT3{0oZ5o3K-)Y7ZZU3;5^rjJuYHuA^jpLQ z=ilbv8pRLN=%tR`{FMIJM8JZ5d3$pEz?alwb^7%1RDVD&O~Os6X%XxF9PLz&zSCfH zAv%8R0h-vGyqlxL`x4OCTgz9$ci^%LXFoz-ND{9K#0&Rr|BWxARdhy2u74aIx^_SG zZaU}hfNx$!e{vkn8o3p$JGpi~^jOs#RgPYb@&~t~!`Su$IH*H^Y6t633%qvuCL9~S zMUKo;U(Rk`BbK1|;`jACp9ij>L;s;mFMI)vC@<8H?Z(QJQ5ya)RvhI$8`Z$$<-i+p z`w-ZHx}XI4zC?{9z7i{H505 ztaL8)&yT_#shcfwb}jhOGxT&%J?W=c9lV+MLZaT7)Jw z^dy>;Q8=M7a{Uy2y9RoJ%Iq>akM~1;Z%@E}cxgYJG`P0Q8Sj8AABEd*@VTMsOXw%i z7|}y(p|NSNfl<*%7Ql>s)PnmizaNdRpM@u(H;qO-LA)QNcIac>yUCNTJ%%mh+1DE% z+~+>VK-lwsVr>kZ-N(7R2Woy2CGP)PKTv}7 zw;udEvF1J;68dZEgDUlJx-}Je*Y3u(Xc_%Vf^p{2nB@<>7Tx&O|1#&hV5GHZKU$~) z=fD5WPuTZW`a7qi3bo=HbRS*#sS4Q0zRUpq^Z|1E-1+O&X6UXOlk{`1Gv;Q<>(zNU zaWwh`>RB}|#<^IMf2WNc8Ry(%YztOjtzxq*h{==U{-K~4@%d5n6 zv~1MlUE*EfljtGHsdmm>i7vv)%E?q0PDkr#n2W^g5qP>X7-1CcO9@{c>MWC+*c z-h~*bc0(+%W|dEBEK|#qFL%Z>>{;*KS876%^zip!KdX2CCTgGOEH-cBcju!oIe7cR zeT9i=>cVaM!dF-qTC=x4hi^g4aPBJW;EoKqrH=lxL+opj=e6a|x!chd`p~C{%kmHF z_vq!I&s0xV*ncW$f9)q7`?G%qS5T9Il`F(awE*Y8|5@Os=U)9V@Qh6`(gZr$G42B# zd;K<=jv}?fLGHMT4dIkIe{0Ccc#q#G98F^XLNrhPATF1aP7)7u@E}>V*(r1{gXEPM zxWc&b$YcDw!%sdHIG}IRzt)yc-TFK_{q{ZV`vQH7jd15^4((BeK0+Pe9XtC5nsM+N z^`v&wBCof}btCw19$u(PKVFg>sd)}sC7DRpFO;H_uu zb1q-I8*P2@Pl2E8$5+KlN$S%w*i_wOg*aR0&*Wxz(K8x5{Z_Dn$G`nl4?DyC^i#tW z(Vy3rd%ZR>lDv$%o3YcxPH?jvj{U$Gwb!HDcd`=n=i|hLabo-ncOOLa7p}vF&4oH~ z?e+JfDSU7WyPjZgyZCpL^-huF+SJ8a^2`Jnp-o?MDH{ z`e8MCKNE0hyU_+bHIRww=nclG6Uy+Bul(p&)Zb{PZ`>iy-=I$6o)W#{dGg6EYO5Ny zR^hw9K|X&P&ea;!I;tNo-F{RV?nvGJZsNE)^k;Y%XmNTOEx%grtzbuW>be-(o&;QT zlD=^ty!=5Vj;O!}5`3U*6%Gr&htuSuyAs>&ZrKM)DUfC^vB`@wG zuI(vLqZ3BkM}J~q-z<02E=R9_@*wmO#_uUr8Syg}V~nwXS}N@#>;FTKfm(6fR&*hwFA4;<0c zaHR=iP#R6d4*K*dIM^8c^A512In8`5z8iuoNzkVlK!dTHJO1_&)N9AZdBn~bIA`G^ z*d4vXPWo2;<_7j4GjTBF))+pvaqs6LhnDF@jueJ<x$PYuQ9Cvx)*?4!hnw&QGY1D7clY?{Q$z8<1-Q4fwPv_|6*V?j6$75wIJ*#OD5WG)tTG4(OTBUkLGOeW5x{Wwkw113$lbu@7 zp0s_5I=S}`pWxqm=)yC@m&R)QqE&h$3omSOSMWbWP5i_&v1oT+4BK6c;;em$cTEfq zatBw8$7kdj#hZIK-wM3>?Z5vj#El*BBwt7C6Ji4PX&u@}jPQO_iaav5ag*mAeC-M` ziJzNy@m2Z);K|IwC4L@38$pk&egMtw8=U10dP;AG`#O2nA@5c~bMy>#-TPmD75(rZ zzKSyNNl&0dKKkYdK`Wf29u^m=&l+qU4R@MKjS6^oj zQedndVB{U(!d_hD9u+uQUr$q`su^h>SMz+98u0z-z|B7=-oqgfcc<2<8R*M*So86> z?qCa-sPkXNx54qOI}e8=E=th*zWCwa2H&lN2_~qg%!l?a_MO?J_64utBbf>6iL>|^ zHn3-EGP?WYFN3ap^88y-cjGdBVED!5Gtud*H_6MdW3${Xzy5vh>7I_}_&rXq?&+s@ zQ1i5i1FQ*u$j+UiH_X|9VQbi51)ejrAACYAl($Sbr+9DVv9JgBv&DFz6}rm%UET zhn{589Kjy#%v8{cvIoRP`vM8>dwCDCd+timLC7PH!vS>BEd>n~aj35dhgV0Z$9;i~ z8~4zOufe&jhkJD;dPO;FOX~b^=N!&aZORz9B8N?=#k42-;NN~7Ex+?w)ID=G>VOZj z^e1xMDK?*ZKWhQKOLFoQz5*XaTrI)}$yq1B{U zya)F~U$c)Mz#e-?#BT4edWTrv!XBA-!t4+3gi{r3evO#mJqo|?N$#Ko{C4a@(7{i$ z2YLJ^$2^{)Hf_>3ut##3`aTDbQsGWvi=OiwJeYTEy2mdBj$r)Q^HFE%Ik3S=FywmF zT3icS()tYC(exsBSK=TX9#I@jGeC_KE6`&jpFQh+S$b>sODEA@jURoUTz)2MFQEqq+lb&E3q>dbD?ieyBMRY$K=T{r1Mb6)+uhAddFNK1^K&*E_QW?nWC821&x5C&|OZ z*v=riq@VeW!(Wauc1JwL6L@m=Wcma>HEg;CpHRkD3fM}SnAw_HjJn)ynL*=Z&)%L& zlbW%KZG}Bx{T0?;nOo|O&+pzV$MLd+-5T+|D6z+N5hwv17;Os>5c zILeumFGZ6p&xf<9u?{g#iG6Smb#O>$9zOWsO4NbNwP)XC{Z;nczgL+-gT!aN6J6rZ zitIsghIveL9z1#GlVv{X@x?H1o3UN{_zF6;?X`E0zZgxdus6(YdXRm zl!yC}^Kb8kSKPZ4HNhb@Vz+x$X8f@C*h2x{uE5xiU*v3xV6MV!@5#;3SLDpYzO#16 z*B+*@he^hsz$UfJHonzaqHX~5)fpoGEy^_}aW{6!Rv%Zz@hF9;&%0aW3WV zVi;e&SeASd^xTfme)|sa(r=BOXCFpfo8w~#+P-yM^8mg@-f$lJq)(f%mAB-ZeGmP%scTPBm zobTnJ{&Boee}gG<{O&VO&e7(bN9)jY#6#L5AD+}bfUhTkySEK_Pjm4^h*e!`BJ+K9ekGi*++n;q1NKBSVQd@D!V#1MFKQoB zO}zX^3ay#_t+aEZz8hhWJ@XOPJ^~-pWc)gNAJ&dN8~;3a=i~p=SB;Hh%g=E}^f9pI zg8S`1&mC-$C!^yTj=6sDu0A zh^=R}iwtwk!^PO+2{D{l)#N+1yBb*2^ERH<`E%_-+t5Gs1?!Abh$W1_h+dpIRM{Wz z=IDFH8EgVONf7Ui@jJoz)??3duSA}DxG}wL6HDApJxUBcN(`enj;+;*StW8-9&A`3 zZ`gZoa-Vz@9B8a+a9$<+NZZwyDscIZ?VQbhVz>ref$y)8A5`Dj&w1>G18^UnO>qYU zPJFn@doHnoI`-upyd!R|HO6PfX3V`n?5HooX$K#b<9I&2$Dzua9ow__o=tO+p0>G{ zd3oo%35KXrPkH~}zFra?;{aT|{GB@KXH&eByTDms3nli;cLy|Q4@J!xatC=<9h~pc zDH1oUVf{VZtYaG$G?{g3gc|lx#!ejD+$+xao_`A+Tx0n~`nKErC~MFrv`g>wxc|G* zulqQM0`V+QJ}iK_O5^m9!RG28OJG!eu83_HiC6My+E@_|*FCR!?$~7*m$<5pcuq~Y zvKng_ua@C>{Ctl1kRcA~a|zxTGEm{&MfBHqu^-j|>Z{Z87}U1n;v#s-J;=7H^~lq{ z(ajby9cpg>i$O>yNk<;u~=4bFd&bo-!r?N;4 zr6+HXslxab=IVQUb)w<| z@sV?gGv+Xww_(PQV>1b37O`Ev)Lxu(N^yp1_At+$+Pf*D4XNzc9`QxKJH#sbA?=ly zqR|!Jzj$)n;+Rmb8>gB~1_B3jK5AmSP{ARjLrVEj=abj@SYoE2y<{B%FaQ1Ft$)nWF4RU5og^= z@f>kXt-A3j<+(7fa}fLJJH|+LRxNCOgzq0=k6ZYG{rfN;e$b+S)eK{!!6a5{^Ugs` z9Ol5dW%6*5yqhKdru7HxzAnFeUH61 zFSzHPyD`c<;`io$YYrtb75U6R_YpUGPUai2toSxbj5HRgx%HfUGVG5&W2`RB5R>d+x zXE+;Udx1D&jp1J(Nj@LuK)h$aljP^P`H1+_56<2LrV$^C zm4EYjV!HK$nB6_)e6zg&ulITCM)M1HJBZ&55KF~v@&@61#F{?rMFs3x7EdwAb7{*P%NB*Su*<<{~ z-p!5Xczi_s(#z3&hw<2l?lY=lDp)vZ z3h)VQ72nBbJ(LDxr8ytJM}G8u-}SqSv(&-N&%R919Et`Q+$HRGOOY%6@ z8o~FszvtoS&0%35JQH(m@K@L29FBz=b?LF;L9k!@&>7--AA} zAD_~m{f;mX=deA0KkphsoMIilSmk*VV~Ew_%)lA&Glk}0xQc(`0.9999) - return float4(0,0,0,0); - - //create surface - Surface surface = CreateSurface( normDepth, TORQUE_SAMPLER2D_MAKEARG(colorBufferTex),TORQUE_SAMPLER2D_MAKEARG(matInfoTex), - IN.uv0, eyePosWorld, IN.wsEyeRay, cameraToWorld); - - float4 diffuse = TORQUE_TEX2DLOD( diffuseLightingBuffer, float4(IN.uv0,0,0)); - float4 specular = TORQUE_TEX2DLOD( specularLightingBuffer, float4(IN.uv0,0,0)); - - float3 sceneColor = (surface.albedo * diffuse.rgb) + (surface.F * specular.rgb) * surface.ao; - - return float4(sceneColor.rgb, 1.0); -} diff --git a/Templates/Full/game/shaders/common/lighting/advanced/lightingUtils.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/lightingUtils.hlsl deleted file mode 100644 index 2bff18999..000000000 --- a/Templates/Full/game/shaders/common/lighting/advanced/lightingUtils.hlsl +++ /dev/null @@ -1,51 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - - -float attenuate( float4 lightColor, float2 attParams, float dist ) -{ - // We're summing the results of a scaled constant, - // linear, and quadratic attenuation. - - #ifdef ACCUMULATE_LUV - return lightColor.w * ( 1.0 - dot( attParams, float2( dist, dist * dist ) ) ); - #else - return 1.0 - dot( attParams, float2( dist, dist * dist ) ); - #endif -} - -float3 getDistanceVectorToPlane( float3 origin, float3 direction, float4 plane ) -{ - float denum = dot( plane.xyz, direction.xyz ); - float num = dot( plane, float4( origin, 1.0 ) ); - float t = -num / denum; - - return direction.xyz * t; -} - -float3 getDistanceVectorToPlane( float negFarPlaneDotEye, float3 direction, float4 plane ) -{ - float denum = dot( plane.xyz, direction.xyz ); - float t = negFarPlaneDotEye / denum; - - return direction.xyz * t; -} diff --git a/Templates/Full/game/shaders/common/lighting/advanced/pointLightP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/pointLightP.hlsl index fc650de18..b02229b00 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/pointLightP.hlsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/pointLightP.hlsl @@ -23,7 +23,6 @@ #include "../../shaderModelAutoGen.hlsl" #include "farFrustumQuad.hlsl" -#include "lightingUtils.hlsl" #include "../../lighting.hlsl" #include "../shadowMap/shadowMapIO_HLSL.h" #include "softShadow.hlsl" @@ -88,7 +87,9 @@ TORQUE_UNIFORM_SAMPLERCUBE(cookieMap, 3); // this value was found via experementation // NOTE: this is wrong, it only biases in one direction, not towards the uv // center ( 0.5 0.5 ). - //shadowCoord.xy *= 0.997; + float offsetVal = 0.95; + shadowCoord.xy *= offsetVal; + shadowCoord.xy += (1.0-offsetVal).xx / 2.0; #ifndef SHADOW_PARABOLOID @@ -139,18 +140,14 @@ uniform float3x3 dynamicViewToLightProj; uniform float3 eyePosWorld; uniform float4x4 cameraToWorld; -LightTargetOutput main( ConvexConnectP IN ) +float4 main( ConvexConnectP IN ) : SV_TARGET { - LightTargetOutput Output = (LightTargetOutput)0; - // Compute scene UV float3 ssPos = IN.ssPos.xyz / IN.ssPos.w; float2 uvScene = getUVFromSSPos(ssPos, rtParams0); - //sky and editor background check - float4 normDepth = UnpackDepthNormal(TORQUE_SAMPLER2D_MAKEARG(deferredBuffer), uvScene); - if (normDepth.w>0.9999) - return Output; + //unpack normal and linear depth + float4 normDepth = TORQUE_DEFERRED_UNCONDITION(deferredBuffer, uvScene); //eye ray WS/VS float3 vsEyeRay = getDistanceVectorToPlane( -vsFarPlane.w, IN.vsEyeDir.xyz, vsFarPlane ); @@ -163,15 +160,12 @@ LightTargetOutput main( ConvexConnectP IN ) //early out if emissive if (getFlag(surface.matFlag, 0)) { - Output.diffuse = surface.baseColor; - Output.spec = surface.baseColor; - return Output; + return 0.0.xxxx; } - //create surface to light float3 L = lightPosition - surface.P; float dist = length(L); - LightResult result = (LightResult)0; + float3 result = 0.0.xxx; [branch] if (dist < lightRange) { @@ -215,10 +209,10 @@ LightTargetOutput main( ConvexConnectP IN ) #endif // !NO_SHADOW float3 lightcol = lightColor.rgb; - /*#ifdef USE_COOKIE_TEX + #ifdef USE_COOKIE_TEX // Lookup the cookie sample. - float4 cookie = TORQUE_TEXCUBE(cookieMap, mul(viewToLightProj, -surfaceToLight.L)); + float4 cookie = TORQUE_TEXCUBE(cookieMap, mul(worldToLightProj, -surfaceToLight.L)); // Multiply the light with the cookie tex. lightcol *= cookie.rgb; @@ -228,15 +222,11 @@ LightTargetOutput main( ConvexConnectP IN ) // regions of the cookie texture. atten *= max(cookie.r, max(cookie.g, cookie.b)); - #endif*/ + #endif //get point light contribution result = GetPointLight(surface, surfaceToLight, lightcol, lightBrightness, dist, lightRange, shadowed); } - //output - Output.diffuse = float4(result.diffuse, 0); - Output.spec = float4(result.spec, 0); - - return Output; + return float4(result, 0); } diff --git a/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeP.hlsl index 078fd1b69..485d820bf 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeP.hlsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeP.hlsl @@ -1,7 +1,6 @@ #include "../../shaderModelAutoGen.hlsl" #include "farFrustumQuad.hlsl" -#include "lightingUtils.hlsl" #include "../../lighting.hlsl" #include "../../torque.hlsl" @@ -44,16 +43,16 @@ uniform float useSphereMode; // and https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/ float3 boxProject(float3 wsPosition, float3 reflectDir, float3 boxWSPos, float3 boxMin, float3 boxMax) { - float3 nrdir = reflectDir; + float3 nrdir = reflectDir; float3 offset = wsPosition; - float3 plane1vec = (boxMax - offset) / nrdir; - float3 plane2vec = (boxMin - offset) / nrdir; + float3 plane1vec = (boxMax - offset) / nrdir; + float3 plane2vec = (boxMin - offset) / nrdir; float3 furthestPlane = max(plane1vec, plane2vec); float dist = min(min(furthestPlane.x, furthestPlane.y), furthestPlane.z); - float3 posonbox = offset + nrdir * dist; + float3 posonbox = offset + nrdir * dist; - return posonbox - boxWSPos; + return posonbox - boxWSPos; } float3 iblBoxDiffuse(float3 normal, @@ -64,45 +63,37 @@ float3 iblBoxDiffuse(float3 normal, float3 boxMax) { // Irradiance (Diffuse) - float3 cubeN = normalize(normal); - float3 irradiance = TORQUE_TEXCUBE(irradianceCube, cubeN).xyz; + float3 cubeN = normalize(normal); + float3 irradiance = TORQUE_TEXCUBE(irradianceCube, cubeN).xyz; - return irradiance; + return irradiance; } -float3 iblBoxSpecular(float3 normal, - float3 wsPos, - float roughness, - float3 surfToEye, - TORQUE_SAMPLER2D(brdfTexture), +float3 iblBoxSpecular(float3 normal, float3 wsPos, float roughness, float3 surfToEye, + TORQUE_SAMPLER2D(brdfTexture), TORQUE_SAMPLERCUBE(radianceCube), float3 boxPos, float3 boxMin, float3 boxMax) { - float ndotv = clamp(dot(normal, surfToEye), 0.0, 1.0); + float ndotv = clamp(dot(normal, surfToEye), 0.0, 1.0); // BRDF - float2 brdf = TORQUE_TEX2D(brdfTexture, float2(roughness, ndotv)).xy; + float2 brdf = TORQUE_TEX2D(brdfTexture, float2(roughness, ndotv)).xy; // Radiance (Specular) float maxmip = pow(cubeMips+1,2); - float lod = roughness*maxmip; - float3 r = reflect(surfToEye, normal); - float3 cubeR = normalize(r); - cubeR = boxProject(wsPos, cubeR, boxPos, boxMin, boxMax); + float lod = roughness*maxmip; + float3 r = reflect(surfToEye, normal); + float3 cubeR = normalize(r); + cubeR = boxProject(wsPos, cubeR, boxPos, boxMin, boxMax); - float3 radiance = TORQUE_TEXCUBELOD(radianceCube, float4(cubeR, lod)).xyz * (brdf.x + brdf.y); + float3 radiance = TORQUE_TEXCUBELOD(radianceCube, float4(cubeR, lod)).xyz * (brdf.x + brdf.y); - return radiance; + return radiance; } -struct PS_OUTPUT -{ - float4 diffuse: TORQUE_TARGET1; - float4 spec: TORQUE_TARGET0; -}; - +/* float defineSphereSpaceInfluence(float3 centroidPosVS, float rad, float2 atten, float3 surfPosVS, float3 norm) { // Build light vec, get length, clip pixel if needed @@ -125,6 +116,7 @@ float defineSphereSpaceInfluence(float3 centroidPosVS, float rad, float2 atten, return saturate( nDotL * attn ); } +*/ float defineBoxSpaceInfluence(float3 surfPosWS, float3 probePos, float radius, float atten) { @@ -139,9 +131,7 @@ float defineBoxSpaceInfluence(float3 surfPosWS, float3 probePos, float radius, f float3 localDir = float3(abs(surfPosLS.x), abs(surfPosLS.y), abs(surfPosLS.z)); localDir = (localDir - boxInnerRange) / (boxOuterRange - boxInnerRange); - float influenceVal = max(localDir.x, max(localDir.y, localDir.z)) * -1; - - return influenceVal; + return max(localDir.x, max(localDir.y, localDir.z)) * -1; } float defineDepthInfluence(float3 probePosWS, float3 surfPosWS, TORQUE_SAMPLERCUBE(radianceCube)) @@ -156,55 +146,41 @@ float defineDepthInfluence(float3 probePosWS, float3 surfPosWS, TORQUE_SAMPLERCU return depthRef-dist; } -PS_OUTPUT main( ConvexConnectP IN ) +float4 main( ConvexConnectP IN ) : SV_TARGET { - PS_OUTPUT Output = (PS_OUTPUT)0; + // Compute scene UV + float3 ssPos = IN.ssPos.xyz / IN.ssPos.w; + float2 uvScene = getUVFromSSPos( ssPos, rtParams0 ); - // Compute scene UV - float3 ssPos = IN.ssPos.xyz / IN.ssPos.w; + //eye ray WS/LS + float3 vsEyeRay = getDistanceVectorToPlane( -vsFarPlane.w, IN.vsEyeDir.xyz, vsFarPlane ); + float3 wsEyeRay = mul(cameraToWorld, float4(vsEyeRay, 0)).xyz; + + //unpack normal and linear depth + float4 normDepth = TORQUE_DEFERRED_UNCONDITION(deferredBuffer, uvScene); + + //create surface + Surface surface = CreateSurface( normDepth, TORQUE_SAMPLER2D_MAKEARG(colorBuffer),TORQUE_SAMPLER2D_MAKEARG(matInfoBuffer), + uvScene, eyePosWorld, wsEyeRay, cameraToWorld); - float2 uvScene = getUVFromSSPos( ssPos, rtParams0 ); - // Sample/unpack the normal/z data - float4 deferredSample = TORQUE_DEFERRED_UNCONDITION( deferredBuffer, uvScene ); - float3 normal = deferredSample.rgb; - float depth = deferredSample.a; - if (depth>0.9999) - clip(-1); - - // Matinfo flags - float4 matInfo = TORQUE_TEX2D( matInfoBuffer, uvScene ); - - // Need world-space normal. - float3 wsNormal = mul(cameraToWorld, float4(normal, 0)).xyz; - - float3 vsEyeRay = getDistanceVectorToPlane( -vsFarPlane.w, IN.vsEyeDir.xyz, vsFarPlane ); - float3 vsPos = vsEyeRay * depth; - - float3 wsEyeRay = mul(cameraToWorld, float4(vsEyeRay, 0)).xyz; - // calculate world space position - float3 wsPos = float3(eyePosWorld + wsEyeRay * depth); - - float blendVal = 1.0; - - //clip bounds and (TODO properly: set falloff) - if(useSphereMode) - { - blendVal = defineSphereSpaceInfluence(probeLSPos, radius, attenuation, vsPos, normal); - } - else - { - float tempAttenVal = 3.5; - blendVal = defineBoxSpaceInfluence(wsPos, probeWSPos, radius, tempAttenVal); - } + float tempAttenVal = 3.5; + float blendVal = defineBoxSpaceInfluence(surface.P, probeWSPos, radius, tempAttenVal); clip(blendVal); //flip me on to have probes filter by depth - //clip(defineDepthInfluence(probeWSPos, worldPos, TORQUE_SAMPLERCUBE_MAKEARG(cubeMap))); - + //clip(defineDepthInfluence(probeWSPos, worldPos, TORQUE_SAMPLERCUBE_MAKEARG(cubeMap))); //render into the bound space defined above - float3 surfToEye = normalize(wsPos - eyePosWorld); - Output.diffuse = float4(iblBoxDiffuse(wsNormal, wsPos, TORQUE_SAMPLERCUBE_MAKEARG(irradianceCubemap), probeWSPos, bbMin, bbMax), blendVal); - Output.spec = float4(iblBoxSpecular(wsNormal, wsPos, 1.0 - matInfo.b, surfToEye, TORQUE_SAMPLER2D_MAKEARG(BRDFTexture), TORQUE_SAMPLERCUBE_MAKEARG(cubeMap), probeWSPos, bbMin, bbMax), blendVal); - return Output; + float3 surfToEye = normalize(surface.P - eyePosWorld); + float3 irradiance = iblBoxDiffuse(surface.N, surface.P, TORQUE_SAMPLERCUBE_MAKEARG(irradianceCubemap), probeWSPos, bbMin, bbMax); + float3 specular = iblBoxSpecular(surface.N, surface.P, surface.roughness, surfToEye, TORQUE_SAMPLER2D_MAKEARG(BRDFTexture), TORQUE_SAMPLERCUBE_MAKEARG(cubeMap), probeWSPos, bbMin, bbMax); + + //energy conservation + float3 F = FresnelSchlickRoughness(surface.NdotV, surface.f0, surface.roughness); + float3 kD = 1.0.xxx - F; + kD *= 1.0 - surface.metalness; + //final diffuse color + float3 diffuse = kD * irradiance * surface.baseColor.rgb; + + return float4((diffuse+specular) * surface.ao, blendVal); } diff --git a/Templates/Full/game/shaders/common/lighting/advanced/skylightP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/skylightP.hlsl index bb5bc7337..2bff96e19 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/skylightP.hlsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/skylightP.hlsl @@ -1,7 +1,6 @@ #include "../../shaderModelAutoGen.hlsl" #include "farFrustumQuad.hlsl" -#include "lightingUtils.hlsl" #include "../../lighting.hlsl" #include "../../torque.hlsl" @@ -25,19 +24,16 @@ uniform float4 vsFarPlane; uniform float4x4 cameraToWorld; uniform float3 eyePosWorld; -float3 iblSpecular(float3 v, float3 n, float roughness) +float3 iblSpecular(in Surface surface, float3 F) { - float3 R = reflect(v, n); const float MAX_REFLECTION_LOD = 4.0; - float3 prefilteredColor = TORQUE_TEXCUBELOD(cubeMap, float4(R, roughness * MAX_REFLECTION_LOD)).rgb; - float2 envBRDF = TORQUE_TEX2D(BRDFTexture, float2(max(dot(n, v), 0.0), roughness)).rg; - return prefilteredColor * (envBRDF.x + envBRDF.y); + float3 prefilteredColor = TORQUE_TEXCUBELOD(cubeMap, float4(surface.R, surface.roughness * MAX_REFLECTION_LOD)).rgb; + float2 envBRDF = TORQUE_TEX2D(BRDFTexture, float2(surface.NdotV, surface.roughness)).rg; + return prefilteredColor * (F * envBRDF.x + envBRDF.y); } -LightTargetOutput main( ConvexConnectP IN ) +float4 main( ConvexConnectP IN ) : SV_TARGET { - LightTargetOutput Output = (LightTargetOutput)0; - // Compute scene UV float3 ssPos = IN.ssPos.xyz / IN.ssPos.w; float2 uvScene = getUVFromSSPos( ssPos, rtParams0 ); @@ -46,22 +42,23 @@ LightTargetOutput main( ConvexConnectP IN ) float3 vsEyeRay = getDistanceVectorToPlane( -vsFarPlane.w, IN.vsEyeDir.xyz, vsFarPlane ); float3 wsEyeRay = mul(cameraToWorld, float4(vsEyeRay, 0)).xyz; - //sky and editor background check - float4 normDepth = UnpackDepthNormal(TORQUE_SAMPLER2D_MAKEARG(deferredBuffer), uvScene); - if (normDepth.a>0.9999) - return Output; + //unpack normal and linear depth + float4 normDepth = TORQUE_DEFERRED_UNCONDITION(deferredBuffer, uvScene); //create surface Surface surface = CreateSurface( normDepth, TORQUE_SAMPLER2D_MAKEARG(colorBuffer),TORQUE_SAMPLER2D_MAKEARG(matInfoBuffer), uvScene, eyePosWorld, wsEyeRay, cameraToWorld); - float3 diffuse = TORQUE_TEXCUBELOD(irradianceCubemap, float4(surface.N,0)).rgb; - float3 specular = iblSpecular(wsEyeRay, surface.N, surface.roughness); + float3 F = FresnelSchlickRoughness(surface.NdotV, surface.f0, surface.roughness); + float3 irradiance = TORQUE_TEXCUBELOD(irradianceCubemap, float4(surface.N,0)).rgb; + float3 specular = iblSpecular(surface, F); + //energy conservation + float3 kD = 1.0.xxx - F; + kD *= 1.0 - surface.metalness; + //final diffuse color + float3 diffuse = kD * irradiance * surface.baseColor.rgb; - float blendVal = 0.0001;// ????? - - Output.diffuse = float4(diffuse, blendVal); - Output.spec = float4(specular, blendVal); - return Output; + float blendVal = 0.0001; + return float4(diffuse + specular * surface.ao, blendVal); } diff --git a/Templates/Full/game/shaders/common/lighting/advanced/spotLightP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/spotLightP.hlsl index aee6ac66a..3a669ab8e 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/spotLightP.hlsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/spotLightP.hlsl @@ -24,7 +24,6 @@ #include "../../shaderModelAutoGen.hlsl" #include "farFrustumQuad.hlsl" -#include "lightingUtils.hlsl" #include "../../lighting.hlsl" #include "../shadowMap/shadowMapIO_HLSL.h" #include "softShadow.hlsl" @@ -64,123 +63,57 @@ uniform float3 lightDirection; uniform float4 lightSpotParams; uniform float4 lightMapParams; uniform float4 vsFarPlane; -uniform float4x4 viewToLightProj; +uniform float4x4 worldToLightProj; uniform float4 lightParams; -uniform float4x4 dynamicViewToLightProj; -uniform float2 lightAttenuation; uniform float shadowSoftness; - uniform float3 eyePosWorld; + uniform float4x4 cameraToWorld; -LightTargetOutput main( ConvexConnectP IN ) +float4 main( ConvexConnectP IN ) : SV_TARGET { - LightTargetOutput Output = (LightTargetOutput)0; // Compute scene UV float3 ssPos = IN.ssPos.xyz / IN.ssPos.w; - float2 uvScene = getUVFromSSPos( ssPos, rtParams0 ); - - //sky and editor background check - float4 normDepth = UnpackDepthNormal(TORQUE_SAMPLER2D_MAKEARG(deferredBuffer), uvScene); - if (normDepth.a>0.9999) - return Output; - - // Eye ray - Eye -> Pixel - float3 eyeRay = getDistanceVectorToPlane( -vsFarPlane.w, IN.vsEyeDir.xyz, vsFarPlane ); - float3 viewSpacePos = eyeRay * normDepth.w; - - // Build light vec, get length, clip pixel if needed - float3 lightToPxlVec = viewSpacePos - lightPosition; - float lenLightV = length( lightToPxlVec ); - lightToPxlVec /= lenLightV; + float2 uvScene = getUVFromSSPos(ssPos, rtParams0); - //lightDirection = float3( -lightDirection.xy, lightDirection.z ); //float3( 0, 0, -1 ); - float cosAlpha = dot( lightDirection, lightToPxlVec ); - clip( cosAlpha - lightSpotParams.x ); - clip( lightRange - lenLightV ); + //unpack normal and linear depth + float4 normDepth = TORQUE_DEFERRED_UNCONDITION(deferredBuffer, uvScene); + + //eye ray WS/VS + float3 vsEyeRay = getDistanceVectorToPlane( -vsFarPlane.w, IN.vsEyeDir.xyz, vsFarPlane ); + float3 wsEyeRay = mul(cameraToWorld, float4(vsEyeRay, 0)).xyz; - float atten = attenuate( lightColor, lightAttenuation, lenLightV ); - atten *= ( cosAlpha - lightSpotParams.x ) / lightSpotParams.y; - clip( atten - 1e-6 ); - atten = saturate( atten ); - //create surface Surface surface = CreateSurface( normDepth, TORQUE_SAMPLER2D_MAKEARG(colorBuffer),TORQUE_SAMPLER2D_MAKEARG(matInfoBuffer), - uvScene, eyePosWorld, eyeRay, cameraToWorld); + uvScene, eyePosWorld, wsEyeRay, cameraToWorld); + //early out if emissive if (getFlag(surface.matFlag, 0)) { - Output.diffuse = surface.baseColor; - Output.spec = surface.baseColor; - return Output; + return 0.0.xxxx; } + + float3 L = lightPosition - surface.P; + float dist = length(L); + float3 result = 0.0.xxx; + [branch] + if (dist < lightRange) + { + float distToLight = dist / lightRange; + float spotFactor = dot(L, lightDirection); + float spotCutOff = lightSpotParams.x; + [branch] + //if (spotFactor > spotCutOff) + { + SurfaceToLight surfaceToLight = CreateSurfaceToLight(surface, L); + float shadowed = 1.0; + float3 lightcol = lightColor.rgb; + //get spot light contribution + result = GetSpotLight(surface, surfaceToLight, lightcol, lightBrightness, dist, lightRange, shadowed); + //result = float3(1.0,0,0); + } + } - //create surface to light - float3 wsLightDir = mul(cameraToWorld, float4(lightDirection,0)).xyz; - SurfaceToLight surfaceToLight = CreateSurfaceToLight(surface, -wsLightDir); - - float nDotL = dot( normDepth.xyz, -lightToPxlVec ); - - // Get the shadow texture coordinate - float4 pxlPosLightProj = mul( viewToLightProj, float4( viewSpacePos, 1 ) ); - float2 shadowCoord = ( ( pxlPosLightProj.xy / pxlPosLightProj.w ) * 0.5 ) + float2( 0.5, 0.5 ); - shadowCoord.y = 1.0f - shadowCoord.y; - - // Get the dynamic shadow texture coordinate - float4 dynpxlPosLightProj = mul( dynamicViewToLightProj, float4( viewSpacePos, 1 ) ); - float2 dynshadowCoord = ( ( dynpxlPosLightProj.xy / dynpxlPosLightProj.w ) * 0.5 ) + float2( 0.5, 0.5 ); - dynshadowCoord.y = 1.0f - dynshadowCoord.y; - - #ifdef NO_SHADOW - - float shadowed = 1.0; - - #else - - // Get a linear depth from the light source. - float distToLight = pxlPosLightProj.z / lightRange; - - float static_shadowed = softShadow_filter( TORQUE_SAMPLER2D_MAKEARG(shadowMap), - ssPos.xy, - shadowCoord, - shadowSoftness, - distToLight, - nDotL, - lightParams.y ); - - float dynamic_shadowed = softShadow_filter( TORQUE_SAMPLER2D_MAKEARG(dynamicShadowMap), - ssPos.xy, - dynshadowCoord, - shadowSoftness, - distToLight, - nDotL, - lightParams.y ); - float shadowed = min(static_shadowed, dynamic_shadowed); - #endif // !NO_SHADOW - - float3 lightcol = lightColor.rgb; - #ifdef USE_COOKIE_TEX - - // Lookup the cookie sample. - float4 cookie = TORQUE_TEX2D( cookieMap, shadowCoord ); - - // Multiply the light with the cookie tex. - lightcol *= cookie.rgb; - - // Use a maximum channel luminance to attenuate - // the lighting else we get specular in the dark - // regions of the cookie texture. - atten *= max( cookie.r, max( cookie.g, cookie.b ) ); - - #endif - - //get directional light contribution - LightResult result = GetDirectionalLight(surface, surfaceToLight, lightColor.rgb, lightBrightness, shadowed); - - //output - Output.diffuse = float4(result.diffuse*atten, 0); - Output.spec = float4(result.spec*atten, 0); - - return Output; + return float4(result, 0); } diff --git a/Templates/Full/game/shaders/common/lighting/advanced/vectorLightP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/vectorLightP.hlsl index 065bb2c19..bb7417e46 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/vectorLightP.hlsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/vectorLightP.hlsl @@ -26,7 +26,6 @@ #include "farFrustumQuad.hlsl" #include "../../torque.hlsl" #include "../../lighting.hlsl" -#include "lightingUtils.hlsl" #include "../shadowMap/shadowMapIO_HLSL.h" #include "softShadow.hlsl" @@ -182,15 +181,11 @@ float4 AL_VectorLightShadowCast( TORQUE_SAMPLER2D(sourceShadowMap), }; -LightTargetOutput main(FarFrustumQuadConnectP IN) +float4 main(FarFrustumQuadConnectP IN) : SV_TARGET { - LightTargetOutput Output = (LightTargetOutput)0; - - //sky and editor background check - float4 normDepth = UnpackDepthNormal(TORQUE_SAMPLER2D_MAKEARG(deferredBuffer), IN.uv0); - if (normDepth.w>0.9999) - return Output; - + //unpack normal and linear depth + float4 normDepth = TORQUE_DEFERRED_UNCONDITION(deferredBuffer, IN.uv0); + //create surface Surface surface = CreateSurface( normDepth, TORQUE_SAMPLER2D_MAKEARG(colorBuffer),TORQUE_SAMPLER2D_MAKEARG(matInfoBuffer), IN.uv0, eyePosWorld, IN.wsEyeRay, cameraToWorld); @@ -198,9 +193,7 @@ LightTargetOutput main(FarFrustumQuadConnectP IN) //early out if emissive if (getFlag(surface.matFlag, 0)) { - Output.diffuse = surface.baseColor; - Output.spec = surface.baseColor; - return Output; + return 0.0.xxxx; } //create surface to light @@ -217,7 +210,7 @@ LightTargetOutput main(FarFrustumQuadConnectP IN) float4 zDist = (zNearFarInvNearFar.x + zNearFarInvNearFar.y * surface.depth); float fadeOutAmt = ( zDist.x - fadeStartLength.x ) * fadeStartLength.y; - //there must be a better way of doing this, two shadowcast lookups = very yucky! + //there must be a more effecient way of doing this, two shadowcast lookups = very yucky! float4 static_shadowed_colors = AL_VectorLightShadowCast( TORQUE_SAMPLER2D_MAKEARG(shadowMap), IN.uv0.xy, worldToLightProj, surface.P, scaleX, scaleY, offsetX, offsetY, farPlaneScalePSSM, surfaceToLight.NdotL); @@ -244,10 +237,7 @@ LightTargetOutput main(FarFrustumQuadConnectP IN) #endif //NO_SHADOW //get directional light contribution - LightResult result = GetDirectionalLight(surface, surfaceToLight, lightingColor.rgb, lightBrightness, shadow); - //output - Output.diffuse = float4(result.diffuse, 0); - Output.spec = float4(result.spec, 0); + float3 result = GetDirectionalLight(surface, surfaceToLight, lightingColor.rgb, lightBrightness, shadow); - return Output; + return float4(result, 0); } diff --git a/Templates/Full/game/shaders/common/shaderModelAutoGen.hlsl b/Templates/Full/game/shaders/common/shaderModelAutoGen.hlsl index 4b27b0206..7c789216f 100644 --- a/Templates/Full/game/shaders/common/shaderModelAutoGen.hlsl +++ b/Templates/Full/game/shaders/common/shaderModelAutoGen.hlsl @@ -28,22 +28,6 @@ // Portability helpers for autogenConditioners -//todo deprecate this function #define TORQUE_DEFERRED_UNCONDITION(tex, coords) deferredUncondition(tex, texture_##tex, coords) -inline float4 UnpackDepthNormal(TORQUE_SAMPLER2D(tex), float2 screenUVVar) -{ - // Sampler g-buffer - float4 bufferSample = TORQUE_TEX2DLOD(tex,float4(screenUVVar,0,0)); - // g-buffer unconditioner: float4(normal.X, normal.Y, depth Hi, depth Lo) - float2 _inpXY = bufferSample.xy; - float _xySQ = dot(_inpXY, _inpXY); - float4 _gbUnconditionedInput = float4( sqrt(half(1.0 - (_xySQ / 4.0))) * _inpXY, -1.0 + (_xySQ / 2.0), bufferSample.a).xzyw; - - // Decode depth - _gbUnconditionedInput.w = dot( bufferSample.zw, float2(1.0, 1.0/65535.0)); - - return _gbUnconditionedInput; -} - #endif //_TORQUE_SHADERMODEL_AUTOGEN_