diff --git a/build/engine/shaders/gi/gi_inject.vs b/build/engine/shaders/gi/gi_inject.vs
index 0c890065d6c3a24b839e99e91687ac9da3e4be17..3b1f65ef72f4622a289da323b088b871486c4b24 100644
--- a/build/engine/shaders/gi/gi_inject.vs
+++ b/build/engine/shaders/gi/gi_inject.vs
@@ -48,7 +48,13 @@ struct RsmTexel
 
 float Luminance(RsmTexel rsmTexel)
 {
-	return((rsmTexel.flux.r * 0.299f + rsmTexel.flux.g * 0.587f + rsmTexel.flux.b * 0.114f) + max(0.0f, dot(rsmTexel.normalWS, -g_vLightSpotDirection.xyz)));
+	return((rsmTexel.flux.r * 0.299f + rsmTexel.flux.g * 0.587f + rsmTexel.flux.b * 0.114f) + max(0.0f, 
+#ifdef IS_SUN
+	dot(rsmTexel.normalWS, -g_vLightSpotDirection.xyz)
+#else
+	dot(rsmTexel.normalWS, -g_vLightPosShadow.xyz)
+#endif
+	));
 }
 
 RsmTexel GetRsmTexel(int2 coords, uint2 vTexSize)
@@ -65,13 +71,14 @@ RsmTexel GetRsmTexel(int2 coords, uint2 vTexSize)
 	float4 vWS = mul(vScreenSpace, g_mInvVP);
 	tx.positionWS = vWS.xyz / vWS.w;
 	
-	half3 vLigth  = normalize(g_vLightPosShadow.xyz - tx.positionWS);
+#ifndef IS_SUN
+	half3 vLigth = normalize(g_vLightPosShadow.xyz - tx.positionWS);
 	half fNdotD = dot(-vLigth, g_vLightSpotDirection.xyz);
 	tx.flux *= saturate(fNdotD - g_vLightSpotInnerOuterAngles.y) / (g_vLightSpotInnerOuterAngles.x - g_vLightSpotInnerOuterAngles.y);
-	
 	half fDistance = distance(tx.positionWS, g_vLightPosShadow.xyz);
 	half fInvDistance = 1.f - (fDistance/g_vLightColorPower.w);
 	tx.flux *= fInvDistance * fInvDistance;
+#endif
 	
 	tx.positionWS += (tx.normalWS * POSWS_BIAS_NORMAL);
 	return(tx);
@@ -156,9 +163,12 @@ GS_IN main(VS_IN input)
 
 	GS_IN output;
 	output.cellIndex = float4(getGridPos(result.positionWS, 0), 1.0);
+	// output.cellIndex = float4(0.0f, 0.0f, 0.0f, 1.0);
 	// output.cellIndex = float4(result.positionWS, 1.0);
 	output.normal = result.normalWS;
+	// output.normal = float3(0.0f, 1.0f, 0.0f);
 	output.flux = result.flux.rgb;
+	// output.flux = float3(1.0f, 0.0f, 0.0f);
 
 	return(output);
 }
diff --git a/build/engine/shaders/lpv.h b/build/engine/shaders/lpv.h
index fd68c5ad539ac6fc95093891fe302826e09ca2ef..07f0a897a001af22918d17833e194313d81bef51 100644
--- a/build/engine/shaders/lpv.h
+++ b/build/engine/shaders/lpv.h
@@ -6,7 +6,11 @@
 // #define LPV_MAP_SIZE 1024
 // #define LPV_MAP_SIZE 32
 #define KERNEL_SIZE (LPV_MAP_SIZE / LPV_POINT_COUNT)
+#ifdef IS_SUN
+#define LPV_POINT_WEIGHT (256.0f * 256.0f * 10.0f / (float)(LPV_POINT_COUNT * LPV_POINT_COUNT))
+#else
 #define LPV_POINT_WEIGHT (256.0f * 256.0f / (float)(LPV_POINT_COUNT * LPV_POINT_COUNT))
+#endif
 #define STEP_SIZE 1
 
 
diff --git a/build/engine/shaders/material/gbuffer.ps b/build/engine/shaders/material/gbuffer.ps
index 842e43539aa63da917d488632afdbb8efb549a8b..e6800563a711100cecdd737bbf564a6d3a113c62 100644
--- a/build/engine/shaders/material/gbuffer.ps
+++ b/build/engine/shaders/material/gbuffer.ps
@@ -4,10 +4,10 @@ gbuffer.ps
 
 */
 
-#include "../struct.h"
-#include "../mtrl.h"
-#include "../const.h"
-#include "../xmat.h"
+#include <struct.h>
+#include <mtrl.h>
+#include <const.h>
+#include <xmat.h>
 
 //##########################################################################
 
diff --git a/build/engine/shaders/material/illum.ps b/build/engine/shaders/material/illum.ps
index 9554228b6db5107abf4e09309699a19d742cb021..fe987520fb7462e934f6a8ae712b00ff98326ecc 100644
--- a/build/engine/shaders/material/illum.ps
+++ b/build/engine/shaders/material/illum.ps
@@ -4,10 +4,10 @@ gbuffer.ps
 
 */
 
-#include "../struct.h"
-#include "../mtrl.h"
-#include "../const.h"
-#include "../xmat.h"
+#include <struct.h>
+#include <mtrl.h>
+#include <const.h>
+#include <xmat.h>
 
 //##########################################################################
 
diff --git a/build/engine/shaders/material/shadow.ps b/build/engine/shaders/material/shadow.ps
index f81d632fadd2b5627c2c31babaf9738be78ddfe2..63221c2ea0ac1c690442883b0e033c6a62e8533b 100644
--- a/build/engine/shaders/material/shadow.ps
+++ b/build/engine/shaders/material/shadow.ps
@@ -4,11 +4,11 @@ gbuffer.ps
 
 */
 
-#include "../struct.h"
-#include "../mtrl.h"
-#include "../shadow.h"
-#include "../const.h"
-#include "../xmat.h"
+#include <struct.h>
+#include <mtrl.h>
+#include <shadow.h>
+#include <const.h>
+#include <xmat.h>
 
 
 //##########################################################################
diff --git a/build/engine/shaders/material/transparent.ps b/build/engine/shaders/material/transparent.ps
index 367ac7a3beaba62f842447c9db41a583b604984e..8e12119cfa0d4242284b4e27eea8c10d78ea0a2f 100644
--- a/build/engine/shaders/material/transparent.ps
+++ b/build/engine/shaders/material/transparent.ps
@@ -4,10 +4,10 @@ gbuffer.ps
 
 */
 
-#include "../struct.h"
-#include "../mtrl.h"
-#include "../const.h"
-#include "../xmat.h"
+#include <struct.h>
+#include <mtrl.h>
+#include <const.h>
+#include <xmat.h>
 
 //##########################################################################
 
diff --git a/build/engine/shaders/ppgensm/ppgensm_pssm.ps b/build/engine/shaders/ppgensm/ppgensm_pssm.ps
index 692ed9b4986cf5a540de8e576356b64c36e4b9e1..1bea42987e3f28e1b5f2155f9a9608e39d15e059 100644
--- a/build/engine/shaders/ppgensm/ppgensm_pssm.ps
+++ b/build/engine/shaders/ppgensm/ppgensm_pssm.ps
@@ -147,5 +147,6 @@ float4 main(VSO_ResPos IN): COLOR0
 			}
 		// }
 	}
-	return(fShadow * 0.95 + 0.05);
+	// return(fShadow * 0.95 + 0.05);
+	return(fShadow * g_vLightPosShadow.w + (1.0f - g_vLightPosShadow.w));
 }
diff --git a/source/game/GameData.cpp b/source/game/GameData.cpp
index 4206db5e7bfa462f89b60552b1f0b178000f6bac..b5375ad2f27e8a401600c804856356b067c338ac 100644
--- a/source/game/GameData.cpp
+++ b/source/game/GameData.cpp
@@ -441,11 +441,11 @@ GameData::GameData(HWND hWnd, bool isGame):
 
 	m_pLightSystem = (IXLightSystem*)Core_GetIXCore()->getPluginManager()->getInterface(IXLIGHTSYSTEM_GUID);
 
-	if(m_pLightSystem && false)
+	if(m_pLightSystem)
 	{
 		//	252, 212, 64
 		IXLightSun *pSun = m_pLightSystem->createSun();
-		pSun->setColor(float3(2.52f, 2.12f, 0.64f));
+		pSun->setColor(float3(2.52f, 2.12f, 0.64f) * 0.5f);
 		pSun->setDirection(SMQuaternion(LIGHTS_DIR_BASE, float3(1.0f, -1.0f, 1.0f)));
 	}
 
diff --git a/source/light/light.cpp b/source/light/light.cpp
index 44dd97b3d327b8c4bc3f9d8ef8aec454e341ead1..16ce57ec7ddd9d48ed4c390169db07dbf1d58fe5 100644
--- a/source/light/light.cpp
+++ b/source/light/light.cpp
@@ -302,7 +302,7 @@ void CXLightSun::updatePSConstants(IGXDevice *pDevice)
 		m_pPSData = pDevice->createConstantBuffer(sizeof(m_dataPS));
 	}
 	m_dataPS.vLightColor = float4(m_vColor, SMVector3Length2(m_vColor));
-	m_dataPS.vLightPos = -float4(m_qDirection * LIGHTS_DIR_BASE, m_fShadowIntensity);
+	m_dataPS.vLightPos = float4(m_qDirection * -LIGHTS_DIR_BASE, m_fShadowIntensity);
 	m_pPSData->update(&m_dataPS);
 }
 
@@ -313,7 +313,7 @@ float CXLightSun::getMaxDistance()
 
 void CXLightSun::updateVisibility(ICamera *pMainCamera, const float3 &vLPVmin, const float3 &vLPVmax)
 {
-	m_renderType = LRT_LIGHT;
+	m_renderType = LRT_LIGHT | LRT_LPV;
 #if 0
 	m_renderType = LRT_NONE;
 
diff --git a/source/render/RenderPipeline.cpp b/source/render/RenderPipeline.cpp
index 26d0648b6bca5a638803d088d1f4a48c7e611f3d..194d54902efde03644f7cf489986a2fdc2238652 100644
--- a/source/render/RenderPipeline.cpp
+++ b/source/render/RenderPipeline.cpp
@@ -418,6 +418,8 @@ CRenderPipeline::CRenderPipeline(IGXDevice *pDevice):
 
 	m_pCameraShaderDataVS = m_pDevice->createConstantBuffer(sizeof(m_cameraShaderData.vs));
 
+	m_pLPVcentersShaderData = m_pDevice->createConstantBuffer(sizeof(m_lpvCentersShaderData.vs));
+
 	m_pLightingShaderDataVS = m_pDevice->createConstantBuffer(sizeof(m_lightingShaderData.vs));
 	m_pLightingShaderDataPS = m_pDevice->createConstantBuffer(sizeof(m_lightingShaderData.ps));
 
@@ -510,6 +512,8 @@ CRenderPipeline::~CRenderPipeline()
 
 	mem_release(m_pCameraShaderDataVS);
 
+	mem_release(m_pLPVcentersShaderData);
+
 	mem_release(m_pLightingShaderDataVS);
 	mem_release(m_pLightingShaderDataPS);
 
@@ -669,6 +673,7 @@ void CRenderPipeline::updateVisibility()
 	{
 		float3 vCamPos;
 		gdata::pCamera->getPosition(&vCamPos);
+		//! @todo: fix grid center pos!
 		m_pLightSystem->updateVisibility(gdata::pCamera, float3(-16.0f, -16.0f, -16.0f) + vCamPos, float3(16.0f, 16.0f, 16.0f) + vCamPos);
 	}
 }
@@ -796,7 +801,10 @@ void CRenderPipeline::renderGBuffer()
 }
 void CRenderPipeline::renderShadows()
 {
+	IGXContext *pCtx = m_pDevice->getThreadContext();
 
+	rfunc::SetRenderSceneFilter();
+	pCtx->setSamplerState(gdata::rstates::pSamplerPointClamp, 1);
 }
 void CRenderPipeline::renderGI()
 {
@@ -844,6 +852,20 @@ void CRenderPipeline::renderGI()
 	m_lightingShaderData.ps.vViewPos = gdata::vConstCurrCamPos;
 	m_pLightingShaderDataPS->update(&m_lightingShaderData.ps.vViewPos);
 
+	float3 vCamDir;
+	gdata::pCamera->getLook(&vCamDir);
+
+	const float c_aLPVsizes[] = {
+		//0.5f,
+		1.0f,
+		1.0f,
+		2.0f
+	};
+
+	m_lpvCentersShaderData.vs.vCenterSize[0] = float4(gdata::vConstCurrCamPos + vCamDir * (LPV_GRID_SIZE / 2 - LPV_STEP_COUNT) * c_aLPVsizes[0], c_aLPVsizes[0]);
+	m_lpvCentersShaderData.vs.vCenterSize[1] = float4(gdata::vConstCurrCamPos + vCamDir * (LPV_GRID_SIZE / 2 - LPV_STEP_COUNT) * c_aLPVsizes[1], c_aLPVsizes[1]);
+	m_lpvCentersShaderData.vs.vCenterSize[2] = float4(gdata::vConstCurrCamPos + vCamDir * (LPV_GRID_SIZE / 2 - LPV_STEP_COUNT) * c_aLPVsizes[2], c_aLPVsizes[2]);
+	m_pLPVcentersShaderData->update(&m_lpvCentersShaderData.vs);
 
 	/*
 	vs:
@@ -913,6 +935,7 @@ void CRenderPipeline::renderGI()
 
 	pCtx->setVSConstant(m_pCameraShaderDataVS, 8);
 	pCtx->setPSConstant(m_pCameraShaderDataVS, 8);
+	
 	UINT uShadowCount = 0;
 	while((uShadowCount = m_pShadowCache->processNextBunch()))
 	{
@@ -1009,8 +1032,15 @@ void CRenderPipeline::renderGI()
 
 			SGCore_ScreenQuadDraw();
 		}
+
+
+		//pCtx->setSamplerState(gdata::rstates::pSamplerLinearWrap, 0);
+		//pCtx->setSamplerState(gdata::rstates::pSamplerLinearWrap, 1);
 	}
 
+	pCtx->setVSConstant(m_pLPVcentersShaderData, 9);
+	pCtx->setPSConstant(m_pLPVcentersShaderData, 9);
+
 	bool isFirstRun = true;
 	while((uShadowCount = m_pShadowCache->processNextRSMBunch()))
 	{
@@ -1232,6 +1262,8 @@ void CRenderPipeline::renderGI()
 }
 void CRenderPipeline::renderPostprocessMain()
 {
+	rfunc::SetRenderSceneFilter();
+
 	m_pMaterialSystem->bindRenderPass(m_pRenderPassPostprocess);
 
 	renderStage(XRS_POSTPROCESS_MAIN);
@@ -1838,6 +1870,8 @@ void CRenderPipeline::buildTransparencyBSP(XTransparentPSP *pPSPs, UINT uPSPcoun
 
 void CRenderPipeline::renderPostprocessFinal()
 {
+	rfunc::SetRenderSceneFilter();
+
 	m_pMaterialSystem->bindRenderPass(m_pRenderPassPostprocess);
 
 	Core_PStartSection(PERF_SECTION_RENDER_INFO);
diff --git a/source/render/RenderPipeline.h b/source/render/RenderPipeline.h
index bc586cc1c1b48ade55a565b56b7f1acc615f8b06..96c995b935f0bf79e05f87cfa5367e918c84d79f 100644
--- a/source/render/RenderPipeline.h
+++ b/source/render/RenderPipeline.h
@@ -10,6 +10,9 @@
 #include "OcclusionCuller.h"
 
 #define MAX_TRANSPARENCY_CLIP_PANES 4
+#define LPV_CASCADES_COUNT 3
+#define LPV_GRID_SIZE 32
+#define LPV_STEP_COUNT 6
 
 class CRenderPipeline: public IXRenderPipeline
 {
@@ -130,6 +133,16 @@ protected:
 	IGXConstantBuffer *m_pCameraShaderDataVS = NULL;
 	//IGXConstantBuffer *m_pCameraShaderDataPS = NULL;
 
+	struct
+	{
+		struct
+		{
+			float4 vCenterSize[LPV_CASCADES_COUNT]; // xyz: center / size; w: world size of cell in meters
+		} vs;
+		//float4 vNearFarLayers;
+	} m_lpvCentersShaderData;
+	IGXConstantBuffer *m_pLPVcentersShaderData = NULL;
+
 	struct
 	{
 		struct
diff --git a/source/render/shadow.cpp b/source/render/shadow.cpp
index e2adbab0e10dcf4be742434b455fd6e42fbf07fb..2bbb79d961c470211ec1f8a0d883b1c3b483f9f8 100644
--- a/source/render/shadow.cpp
+++ b/source/render/shadow.cpp
@@ -158,6 +158,7 @@ void CShadowMap::process(IXRenderPipeline *pRenderPipeline)
 	
 	//m_pLight->setPSConstants(m_pDevice, 5);
 
+	pRenderPipeline->renderShadows();
 	pRenderPipeline->renderStage(XRS_SHADOWS, m_pLight->getVisibility());
 
 	pCtx->setColorTarget(NULL);
@@ -191,7 +192,7 @@ void CShadowMap::genShadow(IGXTexture2D *pShadowMap, IGXTexture2D *pGBufferDepth
 //	pCtx->clear(GX_CLEAR_COLOR);
 
 	pCtx->setSamplerState(ms_pSamplerPointClamp, 0);
-	//m_pDevice->setSamplerState(ms_pSamplerLinearClamp, 1);
+	//pCtx->setSamplerState(ms_pSamplerLinearClamp, 1);
 	pCtx->setSamplerState(ms_pSamplerComparisonLinearClamp, 1);
 	pCtx->setSamplerState(ms_pSamplerPointWrap, 2);
 	
@@ -425,6 +426,7 @@ void CReflectiveShadowMap::process(IXRenderPipeline *pRenderPipeline)
 
 	//m_pLight->setPSConstants(m_pDevice, 5);
 
+	pRenderPipeline->renderShadows();
 	pRenderPipeline->renderStage(XRS_SHADOWS, m_pLight->getVisibility());
 
 	pCtx->setColorTarget(NULL);
@@ -599,6 +601,7 @@ void CShadowPSSM::process(IXRenderPipeline *pRenderPipeline)
 	pCtx->setGSConstant(pLightConstants, SCR_OBJECT);
 	mem_release(pLightConstants);
 
+	pRenderPipeline->renderShadows();
 	pRenderPipeline->renderStage(XRS_SHADOWS, NULL); // m_pLight->getVisibility());
 
 	pCtx->setColorTarget(NULL);
@@ -790,12 +793,9 @@ CReflectiveShadowSun::~CReflectiveShadowSun()
 	mem_release(m_pShaderDataInjectVS);
 	mem_release(m_pShaderDataPS);
 
-	for(UINT i = 0; i < PSSM_MAX_SPLITS; ++i)
-	{
-		mem_release(m_splits[i].pDepthMap);
-		mem_release(m_splits[i].pNormalMap);
-		mem_release(m_splits[i].pFluxMap);
-	}
+	mem_release(m_pDepthMap);
+	mem_release(m_pNormalMap);
+	mem_release(m_pFluxMap);
 }
 
 UINT CReflectiveShadowSun::GetMapMemory(UINT uSize)
@@ -804,7 +804,7 @@ UINT CReflectiveShadowSun::GetMapMemory(UINT uSize)
 	//GXFMT_A8R8G8B8 - xyz:color; w:???
 	//GXFMT_A8R8G8B8 - xyz:normals; w:???
 
-	return(uSize * uSize * 12 * PSSM_MAX_SPLITS);
+	return(RSM_SUN_SIZE * RSM_SUN_SIZE * 12 * PSSM_MAX_SPLITS);
 }
 
 void CReflectiveShadowSun::setObserverCamera(ICamera *pCamera)
@@ -816,17 +816,14 @@ void CReflectiveShadowSun::init(IGXDevice *pContext, UINT uSize)
 {
 	m_pDevice = pContext;
 
-	for(UINT i = 0; i < PSSM_MAX_SPLITS; ++i)
-	{
-		//GXFMT_A8R8G8B8
-		m_splits[i].pNormalMap = m_pDevice->createTexture2D(uSize, uSize, 1, GX_TEXFLAG_RENDERTARGET, GXFMT_A8R8G8B8);
-		//GXFMT_A8R8G8B8
-		m_splits[i].pFluxMap = m_pDevice->createTexture2D(uSize, uSize, 1, GX_TEXFLAG_RENDERTARGET, GXFMT_A8R8G8B8);
-		//GXFMT_R32F
-		m_splits[i].pDepthMap = m_pDevice->createTexture2D(uSize, uSize, 1, GX_TEXFLAG_RENDERTARGET, GXFMT_R32F);
-	}
+	//GXFMT_A8R8G8B8
+	m_pNormalMap = m_pDevice->createTexture2D(RSM_SUN_SIZE, RSM_SUN_SIZE, 1, GX_TEXFLAG_RENDERTARGET, GXFMT_A8R8G8B8);
+	//GXFMT_A8R8G8B8
+	m_pFluxMap = m_pDevice->createTexture2D(RSM_SUN_SIZE, RSM_SUN_SIZE, 1, GX_TEXFLAG_RENDERTARGET, GXFMT_A8R8G8B8);
+	//GXFMT_R32F
+	m_pDepthMap = m_pDevice->createTexture2D(RSM_SUN_SIZE, RSM_SUN_SIZE, 1, GX_TEXFLAG_RENDERTARGET, GXFMT_R32F);
 
-	float fOffset = 0.5f + (0.5f / (float)uSize);
+	float fOffset = 0.5f + (0.5f / (float)RSM_SUN_SIZE);
 	float fRange = 1.0f;
 	float fBias = 0.0f;
 	m_mScaleBiasMat = float4x4(0.5f, 0.0f, 0.0f, 0.0f,
@@ -834,9 +831,9 @@ void CReflectiveShadowSun::init(IGXDevice *pContext, UINT uSize)
 		0.0f, 0.0f, fRange, 0.0f,
 		fOffset, fOffset, fBias, 1.0f);
 
-	m_fSize = (float)uSize;
+	m_fSize = (float)RSM_SUN_SIZE;
 
-	m_pDepthStencilSurface = pContext->createDepthStencilSurface(uSize, uSize, GXFMT_D24S8, GXMULTISAMPLE_NONE, false);
+	m_pDepthStencilSurface = pContext->createDepthStencilSurface(RSM_SUN_SIZE, RSM_SUN_SIZE, GXFMT_D24S8, GXMULTISAMPLE_NONE, false);
 
 	GXSamplerDesc samplerDesc;
 	samplerDesc.filter = GXFILTER_MIN_MAG_MIP_POINT;
@@ -855,23 +852,14 @@ void CReflectiveShadowSun::init(IGXDevice *pContext, UINT uSize)
 	samplerDesc.filter = GXFILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT;
 	m_pSamplerComparisonLinearClamp = pContext->createSamplerState(&samplerDesc);
 
-
-	ID idResPosDepth = SGCore_ShaderLoad(SHADER_TYPE_VERTEX, "pp_res_pos.vs");
-	GXMacro Defines_GSD_9[] = {{"GSD_9", ""}, {0, 0}};
-	ID idGenShadowDirect9 = SGCore_ShaderLoad(SHADER_TYPE_PIXEL, "ppgensm_direct.ps", "ppgensm_direct_9.ps", Defines_GSD_9);
-	m_idShader = SGCore_ShaderCreateKit(idResPosDepth, idGenShadowDirect9);
-
-	static char tmp[32];
-	sprintf(tmp, "%u", uSize);
-
-	GXMacro definesInject[] = {{"LPV_POINT_COUNT", "256"}, {"LPV_MAP_SIZE", tmp}, {0, 0}};
+	GXMacro definesInject[] = {{"IS_SUN", "1"}, {"LPV_POINT_COUNT", "64"}, {"LPV_MAP_SIZE", MACRO_TEXT(RSM_SUN_SIZE)}, {0, 0}};
 	m_idInjectShader = SGCore_ShaderCreateKit(
 		SGCore_ShaderLoad(SHADER_TYPE_VERTEX, "gi_inject.vs", 0, definesInject),
 		SGCore_ShaderLoad(SHADER_TYPE_PIXEL, "gi_inject.ps", 0, definesInject),
 		SGCore_ShaderLoad(SHADER_TYPE_GEOMETRY, "gi_inject.gs", 0, definesInject)
 		);
 
-	GXMacro definesInjectDebug[] = {{"_DEBUG", "1"}, {"LPV_POINT_COUNT", "256"}, {"LPV_MAP_SIZE", tmp}, {0, 0}};
+	GXMacro definesInjectDebug[] = {{"IS_SUN", "1"}, {"_DEBUG", "1"}, {"LPV_POINT_COUNT", "64"}, {"LPV_MAP_SIZE", MACRO_TEXT(RSM_SUN_SIZE)}, {0, 0}};
 	m_idInjectDebugShader = SGCore_ShaderCreateKit(
 		SGCore_ShaderLoad(SHADER_TYPE_VERTEX, "gi_inject.vs", 0, definesInjectDebug),
 		SGCore_ShaderLoad(SHADER_TYPE_PIXEL, "gi_inject.ps", 0, definesInjectDebug)
@@ -894,17 +882,19 @@ void CReflectiveShadowSun::process(IXRenderPipeline *pRenderPipeline)
 	{
 		return;
 	}
-#if 0
+
+	IGXContext *pCtx = m_pDevice->getThreadContext();
 
 	IXLightSun *pSunLight = m_pLight->asSun();
 
+
 	//! @todo remove double with Light::updateFrustum()
-	float3 vPos = pSpotLight->getPosition();
-	float3 vDir = pSpotLight->getDirection() * LIGHTS_DIR_BASE;
-	float3 vUp = pSpotLight->getDirection() * float3(0.0f, 0.0f, 1.0f);
+	float3 vPos = pSunLight->getPosition();
+	float3 vDir = pSunLight->getDirection() * LIGHTS_DIR_BASE;
+	float3 vUp = pSunLight->getDirection() * float3(0.0f, 0.0f, 1.0f);
 
-	m_mView = SMMatrixLookAtLH(vPos, vPos + vDir, vUp);
-	m_mProj = SMMatrixPerspectiveFovLH(pSpotLight->getOuterAngle(), 1.0f, 0.025f, pSpotLight->getMaxDistance());
+
+	updateFrustum();
 
 	Core_RMatrixSet(G_RI_MATRIX_VIEW, &m_mView);
 	Core_RMatrixSet(G_RI_MATRIX_PROJECTION, &m_mProj);
@@ -912,56 +902,123 @@ void CReflectiveShadowSun::process(IXRenderPipeline *pRenderPipeline)
 	m_cameraShaderData.vs.mVP = SMMatrixTranspose(m_mView * m_mProj);
 	m_cameraShaderData.vs.vPosCam = vPos;
 	m_pCameraShaderDataVS->update(&m_cameraShaderData.vs);
-	m_pDevice->setVertexShaderConstant(m_pCameraShaderDataVS, SCR_CAMERA);
-
-	m_pDevice->setDepthStencilSurface(m_pDepthStencilSurface);
+	pCtx->setVSConstant(m_pCameraShaderDataVS, SCR_CAMERA);
 
-	m_pDevice->setBlendState(NULL);
+	pCtx->setDepthStencilSurface(m_pDepthStencilSurface);
 
-	IGXSurface *pDepthSurface = NULL;
-	IGXSurface *pNormalSurface = NULL;
-	IGXSurface *pFluxSurface = NULL;
+	pCtx->setBlendState(NULL);
 
-	pDepthSurface = m_pDepthMap->asRenderTarget();
-	pNormalSurface = m_pNormalMap->asRenderTarget();
-	pFluxSurface = m_pFluxMap->asRenderTarget();
+	IGXSurface *pDepthSurface = m_pDepthMap->asRenderTarget();
+	IGXSurface *pNormalSurface = m_pNormalMap->asRenderTarget();
+	IGXSurface *pFluxSurface = m_pFluxMap->asRenderTarget();
 
-	m_pDevice->setColorTarget(pDepthSurface);
-	m_pDevice->setColorTarget(NULL, 1);
-	m_pDevice->setColorTarget(NULL, 2);
-	m_pDevice->clear(GX_CLEAR_COLOR | GX_CLEAR_DEPTH | GX_CLEAR_STENCIL, GX_COLOR_ARGB(255, 255, 255, 255));
+	pCtx->setColorTarget(pDepthSurface);
+	pCtx->setColorTarget(NULL, 1);
+	pCtx->setColorTarget(NULL, 2);
+	pCtx->clear(GX_CLEAR_COLOR | GX_CLEAR_DEPTH | GX_CLEAR_STENCIL, GX_COLOR_ARGB(255, 255, 255, 255));
 
-	m_pDevice->setColorTarget(pFluxSurface, 0);
-	m_pDevice->setColorTarget(pNormalSurface, 1);
-	m_pDevice->clear(GX_CLEAR_COLOR);
+	pCtx->setColorTarget(pFluxSurface, 0);
+	pCtx->setColorTarget(pNormalSurface, 1);
+	pCtx->clear(GX_CLEAR_COLOR);
 
-	m_pDevice->setColorTarget(pDepthSurface);
-	m_pDevice->setColorTarget(pNormalSurface, 1);
-	m_pDevice->setColorTarget(pFluxSurface, 2);
+	pCtx->setColorTarget(pDepthSurface);
+	pCtx->setColorTarget(pNormalSurface, 1);
+	pCtx->setColorTarget(pFluxSurface, 2);
 
 	mem_release(pDepthSurface);
 	mem_release(pNormalSurface);
 	mem_release(pFluxSurface);
 
 	//m_pLight->setPSConstants(m_pDevice, 5);
+	pRenderPipeline->renderShadows();
+	pRenderPipeline->renderStage(XRS_SHADOWS, NULL); // m_pLight->getVisibility());
 
-	pRenderPipeline->renderStage(XRS_SHADOWS, m_pLight->getVisibility());
-
-	m_pDevice->setColorTarget(NULL);
-	m_pDevice->setColorTarget(NULL, 1);
-	m_pDevice->setColorTarget(NULL, 2);
+	pCtx->setColorTarget(NULL);
+	pCtx->setColorTarget(NULL, 1);
+	pCtx->setColorTarget(NULL, 2);
 
 	/*if(GetAsyncKeyState('U') < 0)
 	{
-	m_pDevice->saveTextureToFile("sm_depth.dds", m_pDepthMap);
-	m_pDevice->saveTextureToFile("sm_normal.dds", m_pNormalMap);
-	m_pDevice->saveTextureToFile("sm_flux.dds", m_pFluxMap);
+		m_pDevice->saveTextureToFile("sm_depth.dds", m_pDepthMap);
+		m_pDevice->saveTextureToFile("sm_normal.dds", m_pNormalMap);
+		m_pDevice->saveTextureToFile("sm_flux.dds", m_pFluxMap);
 	}*/
-#endif
 }
 
+void CReflectiveShadowSun::updateFrustum()
+{
+	assert(m_pCamera);
+
+	IXLightSun *pSunLight = m_pLight->asSun();
+	float3 vLightDir = pSunLight->getDirection() * LIGHTS_DIR_BASE;
+	float3 vUpDir = pSunLight->getDirection() * float3(1.0f, 0.0f, 0.0f);
+
+	float3 vStart;
+	m_pCamera->getPosition(&vStart);
+	float3 vDir;
+	m_pCamera->getLook(&vDir);
+	vDir = SMVector3Normalize(vDir);
+
+	//! @todo: fix grid center pos!
+	float3 vGridCenter = vStart;
+	float fGridRadius = sqrtf(16.0f * 16.0f * 3.0f);
+
+	SMMATRIX mLight(SMMatrixTranspose(SMMATRIX(
+		float4(SMVector3Cross(vUpDir, vLightDir)),
+		float4(vUpDir),
+		float4(vLightDir),
+		float4(0.0f, 0.0f, 0.0f, 1.0f)
+		)));
+	SMMATRIX mLightInv = SMMatrixInverse(NULL, mLight);
+
+	vGridCenter = SMVector3Transform(vGridCenter, mLight);
+	float fStep = (fGridRadius * 2.0f / m_fSize);
+	vGridCenter.x -= fmodf(vGridCenter.x, fStep);
+	vGridCenter.y -= fmodf(vGridCenter.y, fStep);
+
+	vGridCenter = SMVector3Transform(vGridCenter, mLightInv);
+
+	float fMaxDistance = PSSM_LIGHT_FAR;
+
+	m_mProj = SMMatrixOrthographicLH(fGridRadius * 2.0f, fGridRadius * 2.0f, PSSM_LIGHT_NEAR, fMaxDistance);
+	m_mView = SMMatrixLookToLH(vGridCenter - vLightDir * (fMaxDistance /*- fRadius * 2*/ * 0.5f), vLightDir, vUpDir);
+}
+
+
 void CReflectiveShadowSun::genLPV(bool isDebug)
 {
+	if(!m_pDevice || !(m_pLight->getRenderType() & LRT_LPV))
+	{
+		return;
+	}
+
+	IGXContext *pCtx = m_pDevice->getThreadContext();
+
+	pCtx->setRenderBuffer(NULL);
+	pCtx->setIndexBuffer(NULL);
+	pCtx->setPrimitiveTopology(GXPT_POINTLIST);
+	//SGCore_ShaderBind(isDebug ? ms_idInjectDebugShader : ms_idInjectShader);
+
+	pCtx->setVSTexture(m_pDepthMap);
+	pCtx->setVSTexture(m_pNormalMap, 1);
+	pCtx->setVSTexture(m_pFluxMap, 2);
+
+	m_pShaderDataInjectVS->update(&SMMatrixTranspose(SMMatrixInverse(NULL, m_mView * m_mProj)));
+	pCtx->setVSConstant(m_pShaderDataInjectVS, 6);
+
+	IGXConstantBuffer *pLightConstant = m_pLight->getConstants(m_pDevice);
+	pCtx->setVSConstant(pLightConstant, 7);
+	mem_release(pLightConstant);
+
+	SGCore_ShaderBind(isDebug ? m_idInjectDebugShader : m_idInjectShader);
+	pCtx->drawPrimitive(0, 64 * 64);
+
+	SGCore_ShaderUnBind();
+	pCtx->setPrimitiveTopology(GXPT_TRIANGLELIST);
+
+	pCtx->setVSTexture(NULL);
+	pCtx->setVSTexture(NULL, 1);
+	pCtx->setVSTexture(NULL, 2);
 }
 
 //##########################################################################
@@ -1121,6 +1178,7 @@ void CShadowCubeMap::process(IXRenderPipeline *pRenderPipeline)
 	pCtx->setGSConstant(pLightConstants, SCR_OBJECT);
 	mem_release(pLightConstants);
 
+	pRenderPipeline->renderShadows();
 	pRenderPipeline->renderStage(XRS_SHADOWS, m_pLight->getVisibility());
 
 	pCtx->setColorTarget(NULL);
@@ -1367,6 +1425,7 @@ void CReflectiveShadowCubeMap::process(IXRenderPipeline *pRenderPipeline)
 	pCtx->setGSConstant(pLightConstants, SCR_OBJECT);
 	mem_release(pLightConstants);
 
+	pRenderPipeline->renderShadows();
 	pRenderPipeline->renderStage(XRS_SHADOWS, m_pLight->getVisibility());
 
 	pCtx->setColorTarget(NULL);
diff --git a/source/render/shadow.h b/source/render/shadow.h
index 4d56c2612e861398153f382e43b222d0f4ff701a..282945fabe59578c28032559838c8dc375877a23 100644
--- a/source/render/shadow.h
+++ b/source/render/shadow.h
@@ -17,7 +17,7 @@ See the license in LICENSE
 
 #define RSM_POINT_SIZE 32
 #define RSM_SPOT_SIZE 32
-#define RSM_SUN_SIZE 32
+#define RSM_SUN_SIZE 64
 
 class IXTexture;
 class IBaseShadowMap
@@ -278,35 +278,29 @@ public:
 	void setLight(IXLight *pLight);
 	void process(IXRenderPipeline *pRenderPipeline);
 	void genLPV(bool isDebug = false) override;
-
+protected:
+	void updateFrustum();
 private:
 	IGXDevice *m_pDevice = NULL;
 	ICamera *m_pCamera = NULL;
 
 	IGXDepthStencilSurface *m_pDepthStencilSurface = NULL;
 
+	IGXTexture2D *m_pDepthMap = NULL;
+	IGXTexture2D *m_pNormalMap = NULL;
+	IGXTexture2D *m_pFluxMap = NULL;
+
+	float4x4 m_mView;
+	float4x4 m_mProj;
+
 	IGXSamplerState *m_pSamplerPointWrap = NULL;
 	IGXSamplerState *m_pSamplerPointClamp = NULL;
 	IGXSamplerState *m_pSamplerLinearClamp = NULL;
 	IGXSamplerState *m_pSamplerComparisonLinearClamp = NULL;
 
-	ID m_idShader = -1;
 	ID m_idInjectShader = -1;
 	ID m_idInjectDebugShader = -1;
 
-	struct Split
-	{
-		SX_ALIGNED_OP_MEM2();
-
-		IGXTexture2D *pDepthMap = NULL;
-		IGXTexture2D *pNormalMap = NULL;
-		IGXTexture2D *pFluxMap = NULL;
-
-		float4x4 mView;
-		float4x4 mProj;
-	};
-	Split m_splits[PSSM_MAX_SPLITS];
-
 	float4x4 m_mScaleBiasMat;
 	float m_fBias = 0.0001f;
 	float m_fBlurPixel = 0.5f;
@@ -319,7 +313,7 @@ private:
 	{
 		struct
 		{
-			SMMATRIX mMatrixTexture[PSSM_MAX_SPLITS];
+			SMMATRIX mMatrixTexture;
 			float3 vPixelMapSizeBias;
 		} ps;
 	} m_shaderData;