diff --git a/build/engine/shaders/gi/gi_cubes.gs b/build/engine/shaders/gi/gi_cubes.gs
index 3645f109176fb54723d26f35e5ff49a701391471..fa638bafb634e621723294fa19152ebc5ed844fb 100644
--- a/build/engine/shaders/gi/gi_cubes.gs
+++ b/build/engine/shaders/gi/gi_cubes.gs
@@ -16,6 +16,11 @@ cbuffer perFrame: register(b1)
 	float3 g_vParamProj;
 };
 
+/* cbuffer b10: register(b10)
+{
+	float4 g_vCurrentCascade;
+}; */
+
 //##########################################################################
 
 [maxvertexcount(14)]
@@ -23,7 +28,7 @@ void main(point VSO_GICubes input[1], inout TriangleStream<GSO_GICubes> OutputSt
 // void main(point VSO_GICubes input[1], inout LineStream<VSO_GICubes> OutputStream)
 // void main(point VSO_GICubes input[1], inout PointStream<VSO_GICubes> OutputStream)
 {
-	const float fSize = 0.03;
+	const float fSize = 0.03/*  * g_vCurrentCascade.y */;
 	const float fNormal = 0.57735027;
 	
 	float3 vCenter = input[0].vPosition.xyz;
diff --git a/build/engine/shaders/gi/gi_cubes.ps b/build/engine/shaders/gi/gi_cubes.ps
index ed5cd567a485c6a75ead68c49682bbe239d1510b..899e1145d40742ec19bfd234d5cedf5fbc053a55 100644
--- a/build/engine/shaders/gi/gi_cubes.ps
+++ b/build/engine/shaders/gi/gi_cubes.ps
@@ -25,9 +25,10 @@ cbuffer b8: register(b8)
 
 float4 main(GSO_GICubes IN):COLOR0
 {
+	uint uCurrentCascade = g_vCurrentCascade.x;
 	// return(float4(1,1,1,1));
 	
-	float3 vTexCoord = GetGridTexCoord(IN.vCenterPos.xyz, 0);
+	float3 vTexCoord = GetGridTexCoord(IN.vCenterPos.xyz, uCurrentCascade);
 	
 	float4 vColorR = g_txIllumRed.Sample(g_sSampler, vTexCoord);
 	float4 vColorG = g_txIllumGreen.Sample(g_sSampler, vTexCoord);
diff --git a/build/engine/shaders/gi/gi_cubes.vs b/build/engine/shaders/gi/gi_cubes.vs
index 51ef4da0bc8fff26a50ca9c409a3b5592cf51306..3ff5aeb01bb2fba61c553d5217f0a29f35c94e18 100644
--- a/build/engine/shaders/gi/gi_cubes.vs
+++ b/build/engine/shaders/gi/gi_cubes.vs
@@ -21,8 +21,10 @@ cbuffer perFrame: register(b1)
 
 VSO_GICubes main(VSI_GICubes IN)
 {
+	uint uCurrentCascade = g_vCurrentCascade.x;
+	
 	VSO_GICubes OUT = (VSO_GICubes)0;
-	OUT.vPosition = float4(IN.vPosition.xyz * GetGridWorldSize(0) + GetGridCenter(0), 1.0);
+	OUT.vPosition = float4(IN.vPosition.xyz * GetGridWorldSize(uCurrentCascade) + GetGridCenter(uCurrentCascade), 1.0);
 	// OUT.vPosition = mul(half4(IN.vPosition.xyz,1), g_mVP);
 	return(OUT);
 }
diff --git a/build/engine/shaders/gi/gi_inject.vs b/build/engine/shaders/gi/gi_inject.vs
index 3b1f65ef72f4622a289da323b088b871486c4b24..5b91ecaa783b9835a24c869ca10002f20957c736 100644
--- a/build/engine/shaders/gi/gi_inject.vs
+++ b/build/engine/shaders/gi/gi_inject.vs
@@ -3,11 +3,11 @@
 
 cbuffer perLight: register(b7)
 {
-	half4 g_vLightColorPower;
-	half4 g_vLightPosShadow;
+	float4 g_vLightColorPower;
+	float4 g_vLightPosShadow;
 // #ifdef IS_SPOT
-	half4 g_vLightSpotDirection;
-	half2 g_vLightSpotInnerOuterAngles;
+	float4 g_vLightSpotDirection;
+	float2 g_vLightSpotInnerOuterAngles;
 // #endif
 };
 
@@ -72,11 +72,11 @@ RsmTexel GetRsmTexel(int2 coords, uint2 vTexSize)
 	tx.positionWS = vWS.xyz / vWS.w;
 	
 #ifndef IS_SUN
-	half3 vLigth = normalize(g_vLightPosShadow.xyz - tx.positionWS);
-	half fNdotD = dot(-vLigth, g_vLightSpotDirection.xyz);
+	float3 vLigth = normalize(g_vLightPosShadow.xyz - tx.positionWS);
+	float 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);
+	float fDistance = distance(tx.positionWS, g_vLightPosShadow.xyz);
+	float fInvDistance = 1.f - (fDistance/g_vLightColorPower.w);
 	tx.flux *= fInvDistance * fInvDistance;
 #endif
 	
@@ -89,12 +89,14 @@ RsmTexel GetRsmTexel(int2 coords, uint2 vTexSize)
 
 GS_IN main(VS_IN input)
 {	
+	uint uCurrentCascade = g_vCurrentCascade.x;
+	
 	const uint2 RSMsize = uint2(LPV_MAP_SIZE, LPV_MAP_SIZE);
 	const uint2 RSMsizeNew = RSMsize / KERNEL_SIZE;
 	int3 rsmCoords = int3(input.posIndex % RSMsizeNew.x, input.posIndex / RSMsizeNew.x, 0) * KERNEL_SIZE;
 		
 #ifdef _DEBUG
-	RsmTexel rsmTexel = GetRsmTexel(rsmCoords, RSMsize);
+	RsmTexel rsmTexel = GetRsmTexel(rsmCoords.xy, RSMsize);
 	GS_IN output1 = (GS_IN)0;
 	// rsmTexel.positionWS = float4(((float2)rsmCoords + 0.5f) / (float2)RSMsize * 2.0 - 1.0, 0.0f, 1.0);
 	// rsmTexel.positionWS = float4(float3((float)(input.posIndex % 512), 0.0f, (float)(input.posIndex / 512)) / 512, 1.0);
@@ -123,7 +125,7 @@ GS_IN main(VS_IN input)
 				float texLum = Luminance(rsmTexel);
 				if(texLum > maxLuminance)
 				{
-					brightestCellIndex = getGridPos(rsmTexel.positionWS, 0);
+					brightestCellIndex = getGridPos(rsmTexel.positionWS, uCurrentCascade);
 					maxLuminance = texLum;
 				}
 			}
@@ -139,7 +141,7 @@ GS_IN main(VS_IN input)
 			int2 texIdx = rsmCoords.xy + int2(x, y);
 			RsmTexel rsmTexel = GetRsmTexel(texIdx, RSMsize);
 			
-			int3 texelIndex = getGridPos(rsmTexel.positionWS, 0);
+			int3 texelIndex = getGridPos(rsmTexel.positionWS, uCurrentCascade);
 			float3 deltaGrid = texelIndex - brightestCellIndex;
 			if(dot(deltaGrid, deltaGrid) < 10) // If cell proximity is good enough
 			{
@@ -162,7 +164,7 @@ GS_IN main(VS_IN input)
 	//RsmTexel result = GetRsmTexel(rsmCoords.xy);
 
 	GS_IN output;
-	output.cellIndex = float4(getGridPos(result.positionWS, 0), 1.0);
+	output.cellIndex = float4(getGridPos(result.positionWS, uCurrentCascade), 1.0);
 	// output.cellIndex = float4(0.0f, 0.0f, 0.0f, 1.0);
 	// output.cellIndex = float4(result.positionWS, 1.0);
 	output.normal = result.normalWS;
diff --git a/build/engine/shaders/gi/gi_inject_cube.vs b/build/engine/shaders/gi/gi_inject_cube.vs
index 0569951673baf65b5f640413a9422029074b813f..22a26f48e7abf15b04ddd9e1acea1150bf66e7f2 100644
--- a/build/engine/shaders/gi/gi_inject_cube.vs
+++ b/build/engine/shaders/gi/gi_inject_cube.vs
@@ -3,11 +3,11 @@
 
 cbuffer perLight: register(b7)
 {
-	half4 g_vLightColorPower;
-	half4 g_vLightPosShadow;
+	float4 g_vLightColorPower;
+	float4 g_vLightPosShadow;
 #ifdef IS_SPOT
-	half4 g_vLightSpotDirection;
-	half2 g_vLightSpotInnerOuterAngles;
+	float4 g_vLightSpotDirection;
+	float2 g_vLightSpotInnerOuterAngles;
 #endif
 };
 
@@ -91,7 +91,7 @@ RsmTexel GetRsmTexel(int3 coords, uint2 vTexSize)
 	// vDir *= sqrt(0.01);
 	vDir *= sqrt(fVectorLength);
 	// vDir /= 1270.0;
-	tx.positionWS = float4(g_vLightPosShadow.xyz + vDir, 0.0);
+	tx.positionWS = g_vLightPosShadow.xyz + vDir;
 	
 	tx.flux = rsmFluxMap.SampleLevel(g_sPoint, vDir, 0) * float4(g_vLightColorPower.xyz, 1.0);
 	tx.normalWS = rsmWsNorMap.SampleLevel(g_sPoint, vDir, 0).xyz * 2.0 - 1.0;
@@ -104,8 +104,8 @@ RsmTexel GetRsmTexel(int3 coords, uint2 vTexSize)
 	// 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);
+	float fDistance = distance(tx.positionWS, g_vLightPosShadow.xyz);
+	float fInvDistance = 1.f - (fDistance/g_vLightColorPower.w);
 	tx.flux *= fInvDistance * fInvDistance;
 
 #ifndef _DEBUG
@@ -118,6 +118,7 @@ RsmTexel GetRsmTexel(int3 coords, uint2 vTexSize)
 GS_IN main(VS_IN input)
 {	
 	// input.posIndex = 128 + 128 * 256 + 1;
+	uint uCurrentCascade = g_vCurrentCascade.x;
 
 	const uint2 RSMsize = uint2(LPV_MAP_SIZE, LPV_MAP_SIZE);
 	const uint2 RSMsizeNew = RSMsize / KERNEL_SIZE;
@@ -156,7 +157,7 @@ GS_IN main(VS_IN input)
 				float texLum = Luminance(rsmTexel);
 				if (texLum > maxLuminance)
 				{
-					brightestCellIndex = getGridPos(rsmTexel.positionWS, 0);
+					brightestCellIndex = getGridPos(rsmTexel.positionWS, uCurrentCascade);
 					maxLuminance = texLum;
 				}
 			}
@@ -172,7 +173,7 @@ GS_IN main(VS_IN input)
 			int3 texIdx = rsmCoords.xyz + int3(x, y, 0);
 			RsmTexel rsmTexel = GetRsmTexel(texIdx, RSMsize);
 			
-			int3 texelIndex = getGridPos(rsmTexel.positionWS, 0);
+			int3 texelIndex = getGridPos(rsmTexel.positionWS, uCurrentCascade);
 			float3 deltaGrid = texelIndex - brightestCellIndex;
 			if(dot(deltaGrid, deltaGrid) < 10) // If cell proximity is good enough
 			{
@@ -195,7 +196,7 @@ GS_IN main(VS_IN input)
 	//RsmTexel result = GetRsmTexel(rsmCoords.xy);
 
 	GS_IN output;
-	output.cellIndex = float4(getGridPos(result.positionWS, 0), 1.0);
+	output.cellIndex = float4(getGridPos(result.positionWS, uCurrentCascade), 1.0);
 	// output.cellIndex = float4(result.positionWS, 1.0);
 	output.normal = result.normalWS;
 	output.flux = result.flux.rgb;
diff --git a/build/engine/shaders/lighting/lighting_gi.ps b/build/engine/shaders/lighting/lighting_gi.ps
index c2ea1e1ade3aa9a0d76b020d1224604cef4f7252..f3a31a5a46566a631afdf6a6510fc6382b8518ea 100644
--- a/build/engine/shaders/lighting/lighting_gi.ps
+++ b/build/engine/shaders/lighting/lighting_gi.ps
@@ -22,9 +22,9 @@ SamplerState g_sLinearClamp: register(s1);
 
 Texture2D g_txDepth:register(t0);
 Texture2D g_txNormals:register(t1);
-Texture3D g_txLightVolumeRed:register(t2);
-Texture3D g_txLightVolumeGreen:register(t3);
-Texture3D g_txLightVolumeBlue:register(t4);
+Texture3D g_txLightVolumeRed[3]:register(t2);
+Texture3D g_txLightVolumeGreen[3]:register(t5);
+Texture3D g_txLightVolumeBlue[3]:register(t8);
 
 //#############################################################################
 
@@ -40,18 +40,27 @@ PSO_Lbuffer main(VSO_ResPos IN)
 	
 	float3 vNormalPixel = normalize(NormalDecode(vNormals.xyz).xyz);
 	
-	float3 vTexCoord = GetGridTexCoord(vPosition.xyz, 0);
-	
-	float4 vColorR = g_txLightVolumeRed.Sample(g_sLinearClamp, vTexCoord);
-	float4 vColorG = g_txLightVolumeGreen.Sample(g_sLinearClamp, vTexCoord);
-	float4 vColorB = g_txLightVolumeBlue.Sample(g_sLinearClamp, vTexCoord);
 	
 	// float3 vNormalPixel = normalize(IN.vNormal);
 	float4 SHintensity = dirToSH(-vNormalPixel);
 	
-	float r = saturate(dot(SHintensity, vColorR));
-	float g = saturate(dot(SHintensity, vColorG));
-	float b = saturate(dot(SHintensity, vColorB));
+	float r = 0.0f;
+	float g = 0.0f;
+	float b = 0.0f;
+
+	for(uint i = 0; i < 3; ++i)
+	{
+		float3 vTexCoord = GetGridTexCoord(vPosition.xyz, i);
+		float4 vColorR = g_txLightVolumeRed[i].Sample(g_sLinearClamp, vTexCoord);
+		float4 vColorG = g_txLightVolumeGreen[i].Sample(g_sLinearClamp, vTexCoord);
+		float4 vColorB = g_txLightVolumeBlue[i].Sample(g_sLinearClamp, vTexCoord);
+		
+		r += saturate(dot(SHintensity, vColorR));
+		g += saturate(dot(SHintensity, vColorG));
+		b += saturate(dot(SHintensity, vColorB));
+	}
+	
+	
 	
 	OUT.vAmdient.xyz = float3(r, g, b) / PI/*  * 6.0f */;
 	OUT.vAmdient.w = 1;
diff --git a/build/engine/shaders/lpv.h b/build/engine/shaders/lpv.h
index 07f0a897a001af22918d17833e194313d81bef51..77b0fc0b9559c5088b97bfa88b0407f52431f542 100644
--- a/build/engine/shaders/lpv.h
+++ b/build/engine/shaders/lpv.h
@@ -7,7 +7,7 @@
 // #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))
+#define LPV_POINT_WEIGHT (256.0f * 256.0f * 64.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
@@ -20,6 +20,11 @@ cbuffer b9: register(b9)
 	float4 g_vCenterSize[3];
 };
 
+cbuffer b10: register(b10)
+{
+	float4 g_vCurrentCascade;
+};
+
 // https://github.com/mafian89/Light-Propagation-Volumes/blob/master/shaders/lightInject.frag and
 // https://github.com/djbozkosz/Light-Propagation-Volumes/blob/master/data/shaders/lpvInjection.cs seem
 // to use the same coefficients, which differ from the RSM paper. Due to completeness of their code, I will stick to their solutions.
@@ -65,5 +70,5 @@ int3 getGridPos(float3 worldPos, uint uCascade)
 
 float3 GetGridTexCoord(float3 worldPos, uint uCascade)
 {
-	return((worldPos - GetGridCenter(0)) / (GetGridWorldSize(uCascade) * LPV_DIM) + 0.5f + 1.0f / (LPV_DIM * 2.0f));
+	return((worldPos - GetGridCenter(uCascade)) / (GetGridWorldSize(uCascade) * LPV_DIM) + 0.5f + 1.0f / (LPV_DIM * 2.0f));
 }
diff --git a/source/game/GameData.cpp b/source/game/GameData.cpp
index 3eab59e0935a1132bb19fa381f305c7085595edc..21759e2f2f9472f518053290f52f81fdf085c6e1 100644
--- a/source/game/GameData.cpp
+++ b/source/game/GameData.cpp
@@ -445,7 +445,7 @@ GameData::GameData(HWND hWnd, bool isGame):
 	{
 		//	252, 212, 64
 		IXLightSun *pSun = m_pLightSystem->createSun();
-		pSun->setColor(float3(2.52f, 2.12f, 0.64f) * 0.5f);
+		pSun->setColor(float3(2.52f, 2.12f, 0.64f) * 1.0f);
 		pSun->setDirection(SMQuaternion(LIGHTS_DIR_BASE, float3(1.0f, -1.0f, 1.0f)));
 	}
 
diff --git a/source/render/RenderPipeline.cpp b/source/render/RenderPipeline.cpp
index 194d54902efde03644f7cf489986a2fdc2238652..5710b833c8d1c1dcd3aee1b76867141289a289aa 100644
--- a/source/render/RenderPipeline.cpp
+++ b/source/render/RenderPipeline.cpp
@@ -419,6 +419,7 @@ CRenderPipeline::CRenderPipeline(IGXDevice *pDevice):
 	m_pCameraShaderDataVS = m_pDevice->createConstantBuffer(sizeof(m_cameraShaderData.vs));
 
 	m_pLPVcentersShaderData = m_pDevice->createConstantBuffer(sizeof(m_lpvCentersShaderData.vs));
+	m_pLPVcurrentCascadeShaderData = m_pDevice->createConstantBuffer(sizeof(float4_t));
 
 	m_pLightingShaderDataVS = m_pDevice->createConstantBuffer(sizeof(m_lightingShaderData.vs));
 	m_pLightingShaderDataPS = m_pDevice->createConstantBuffer(sizeof(m_lightingShaderData.ps));
@@ -459,13 +460,17 @@ CRenderPipeline::CRenderPipeline(IGXDevice *pDevice):
 	}
 
 //#define TIDX(x, y, z) (x + y * 32 + z * 32 * 32)
-	m_pGIAccumRed = m_pDevice->createTexture3D(32, 32, 32, 1, GX_TEXFLAG_RENDERTARGET | GX_TEXFLAG_UNORDERED_ACCESS, GXFMT_A32B32G32R32F);
-	m_pGIAccumGreen = m_pDevice->createTexture3D(32, 32, 32, 1, GX_TEXFLAG_RENDERTARGET | GX_TEXFLAG_UNORDERED_ACCESS, GXFMT_A32B32G32R32F);
-	m_pGIAccumBlue = m_pDevice->createTexture3D(32, 32, 32, 1, GX_TEXFLAG_RENDERTARGET | GX_TEXFLAG_UNORDERED_ACCESS, GXFMT_A32B32G32R32F);
+	for(UINT i = 0; i < 3; ++i)
+	{
+		m_aLPVs[i].pGIAccumRed = m_pDevice->createTexture3D(32, 32, 32, 1, GX_TEXFLAG_RENDERTARGET | GX_TEXFLAG_UNORDERED_ACCESS, GXFMT_A32B32G32R32F);
+		m_aLPVs[i].pGIAccumGreen = m_pDevice->createTexture3D(32, 32, 32, 1, GX_TEXFLAG_RENDERTARGET | GX_TEXFLAG_UNORDERED_ACCESS, GXFMT_A32B32G32R32F);
+		m_aLPVs[i].pGIAccumBlue = m_pDevice->createTexture3D(32, 32, 32, 1, GX_TEXFLAG_RENDERTARGET | GX_TEXFLAG_UNORDERED_ACCESS, GXFMT_A32B32G32R32F);
+		
+		m_aLPVs[i].pGIAccumRed2 = m_pDevice->createTexture3D(32, 32, 32, 1, GX_TEXFLAG_RENDERTARGET | GX_TEXFLAG_UNORDERED_ACCESS, GXFMT_A32B32G32R32F);
+		m_aLPVs[i].pGIAccumGreen2 = m_pDevice->createTexture3D(32, 32, 32, 1, GX_TEXFLAG_RENDERTARGET | GX_TEXFLAG_UNORDERED_ACCESS, GXFMT_A32B32G32R32F);
+		m_aLPVs[i].pGIAccumBlue2 = m_pDevice->createTexture3D(32, 32, 32, 1, GX_TEXFLAG_RENDERTARGET | GX_TEXFLAG_UNORDERED_ACCESS, GXFMT_A32B32G32R32F);
 
-	m_pGIAccumRed2 = m_pDevice->createTexture3D(32, 32, 32, 1, GX_TEXFLAG_RENDERTARGET | GX_TEXFLAG_UNORDERED_ACCESS, GXFMT_A32B32G32R32F);
-	m_pGIAccumGreen2 = m_pDevice->createTexture3D(32, 32, 32, 1, GX_TEXFLAG_RENDERTARGET | GX_TEXFLAG_UNORDERED_ACCESS, GXFMT_A32B32G32R32F);
-	m_pGIAccumBlue2 = m_pDevice->createTexture3D(32, 32, 32, 1, GX_TEXFLAG_RENDERTARGET | GX_TEXFLAG_UNORDERED_ACCESS, GXFMT_A32B32G32R32F);
+	}
 //#undef TIDX
 
 	m_idLightBoundShader = SGCore_ShaderCreateKit(SGCore_ShaderLoad(SHADER_TYPE_VERTEX, "lighting_bound.vs"), -1);
@@ -513,6 +518,7 @@ CRenderPipeline::~CRenderPipeline()
 	mem_release(m_pCameraShaderDataVS);
 
 	mem_release(m_pLPVcentersShaderData);
+	mem_release(m_pLPVcurrentCascadeShaderData);
 
 	mem_release(m_pLightingShaderDataVS);
 	mem_release(m_pLightingShaderDataPS);
@@ -534,9 +540,16 @@ CRenderPipeline::~CRenderPipeline()
 
 	mem_release(m_pGICubesRB);
 
-	mem_release(m_pGIAccumRed);
-	mem_release(m_pGIAccumGreen);
-	mem_release(m_pGIAccumBlue);
+	for(UINT i = 0; i < 3; ++i)
+	{
+		mem_release(m_aLPVs[i].pGIAccumRed);
+		mem_release(m_aLPVs[i].pGIAccumGreen);
+		mem_release(m_aLPVs[i].pGIAccumBlue);
+
+		mem_release(m_aLPVs[i].pGIAccumRed2);
+		mem_release(m_aLPVs[i].pGIAccumGreen2);
+		mem_release(m_aLPVs[i].pGIAccumBlue2);
+	}
 
 	mem_delete(m_pShadowCache);
 	mem_release(m_pShadowShaderDataVS);
@@ -721,12 +734,24 @@ void CRenderPipeline::showGICubes()
 	SGCore_ShaderBind(m_idGICubesShader);
 	pCtx->setGSConstant(m_pLightingShaderDataVS, 1);
 	pCtx->setDepthStencilState(m_pDepthStencilStateDefault);
-	pCtx->setPSTexture(m_pGIAccumRed2, 0);
-	pCtx->setPSTexture(m_pGIAccumGreen2, 1);
-	pCtx->setPSTexture(m_pGIAccumBlue2, 2);
 	pCtx->setSamplerState(gdata::rstates::pSamplerPointClamp, 0);
+
+	pCtx->setVSConstant(m_pLPVcurrentCascadeShaderData, 10);
+	pCtx->setGSConstant(m_pLPVcurrentCascadeShaderData, 10);
+	pCtx->setPSConstant(m_pLPVcurrentCascadeShaderData, 10);
+
+	for(UINT i = 2; i < 3; ++i)
+	{
+		float4_t vTmp((float)i + 0.5f);  // just to be sure
+		m_pLPVcurrentCascadeShaderData->update(&vTmp);
+
+		pCtx->setPSTexture(m_aLPVs[i].pGIAccumRed2, 0);
+		pCtx->setPSTexture(m_aLPVs[i].pGIAccumGreen2, 1);
+		pCtx->setPSTexture(m_aLPVs[i].pGIAccumBlue2, 2);
+
+		pCtx->drawPrimitive(0, m_uGICubesCount);
+	}
 	
-	pCtx->drawPrimitive(0, m_uGICubesCount);
 
 	pCtx->setPrimitiveTopology(GXPT_TRIANGLELIST);
 
@@ -857,9 +882,12 @@ void CRenderPipeline::renderGI()
 
 	const float c_aLPVsizes[] = {
 		//0.5f,
+		//1.0f,
+		//2.0f
+
 		1.0f,
-		1.0f,
-		2.0f
+		2.0f,
+		4.0f
 	};
 
 	m_lpvCentersShaderData.vs.vCenterSize[0] = float4(gdata::vConstCurrCamPos + vCamDir * (LPV_GRID_SIZE / 2 - LPV_STEP_COUNT) * c_aLPVsizes[0], c_aLPVsizes[0]);
@@ -1041,49 +1069,58 @@ void CRenderPipeline::renderGI()
 	pCtx->setVSConstant(m_pLPVcentersShaderData, 9);
 	pCtx->setPSConstant(m_pLPVcentersShaderData, 9);
 
-	bool isFirstRun = true;
+	bool isFirstRun[3] = {true, true, true};
 	while((uShadowCount = m_pShadowCache->processNextRSMBunch()))
 	{
+		pCtx->setVSConstant(m_pLPVcurrentCascadeShaderData, 10);
+		pCtx->setPSConstant(m_pLPVcurrentCascadeShaderData, 10);
+
 		pCtx->setDepthStencilSurface(pOldDSSurface);
 		pCtx->setBlendState(gdata::rstates::pBlendAlphaOneOne);
 
 		pCtx->setVSConstant(m_pLightingShaderDataVS, 1);
 		pCtx->setPSConstant(m_pLightingShaderDataPS, 1);
 
+		IGXDepthStencilSurface *pOldSurface = pCtx->getDepthStencilSurface();
+		pCtx->unsetDepthStencilSurface();
 
-		IGXSurface *pLPVRed = m_pGIAccumRed->asRenderTarget();
-		IGXSurface *pLPVGreen = m_pGIAccumGreen->asRenderTarget();
-		IGXSurface *pLPVBlue = m_pGIAccumBlue->asRenderTarget();
+		IBaseReflectiveShadowMap *pShadow = NULL;
 
-		//m_pDevice->setColorTarget(pAmbientSurf);
-		pCtx->setColorTarget(pLPVRed);
-		pCtx->setColorTarget(pLPVGreen, 1);
-		pCtx->setColorTarget(pLPVBlue, 2);
+		for(UINT i = 0; i < 3; ++i)
+		{
+			float4_t vTmp((float)i + 0.5f); // just to be sure
+			m_pLPVcurrentCascadeShaderData->update(&vTmp);
 
-		mem_release(pLPVRed);
-		mem_release(pLPVGreen);
-		mem_release(pLPVBlue);
+			IGXSurface *pLPVRed = m_aLPVs[i].pGIAccumRed->asRenderTarget();
+			IGXSurface *pLPVGreen = m_aLPVs[i].pGIAccumGreen->asRenderTarget();
+			IGXSurface *pLPVBlue = m_aLPVs[i].pGIAccumBlue->asRenderTarget();
 
-		IGXDepthStencilSurface *pOldSurface = pCtx->getDepthStencilSurface();
-		pCtx->unsetDepthStencilSurface();
+			//m_pDevice->setColorTarget(pAmbientSurf);
+			pCtx->setColorTarget(pLPVRed);
+			pCtx->setColorTarget(pLPVGreen, 1);
+			pCtx->setColorTarget(pLPVBlue, 2);
 
-		if(isFirstRun)
-		{
-			pCtx->clear(GX_CLEAR_COLOR);
-			isFirstRun = false;
-		}
+			mem_release(pLPVRed);
+			mem_release(pLPVGreen);
+			mem_release(pLPVBlue);
 
-		IBaseReflectiveShadowMap *pShadow = NULL;
-		//inject VPLs into LPV grid
-		for(UINT i = 0; i < uShadowCount; ++i)
-		{
-			pShadow = m_pShadowCache->getRSMShadow(i);
-			pShadow->genLPV();
-		}
+			if(isFirstRun[i])
+			{
+				pCtx->clear(GX_CLEAR_COLOR);
+				isFirstRun[i] = false;
+			}
 
-		pCtx->setColorTarget(NULL);
-		pCtx->setColorTarget(NULL, 1);
-		pCtx->setColorTarget(NULL, 2);
+			//inject VPLs into LPV grid
+			for(UINT j = 0; j < uShadowCount; ++j)
+			{
+				pShadow = m_pShadowCache->getRSMShadow(j);
+				pShadow->genLPV();
+			}
+
+			pCtx->setColorTarget(NULL);
+			pCtx->setColorTarget(NULL, 1);
+			pCtx->setColorTarget(NULL, 2);
+		}
 
 		const bool *dev_lpv_points = GET_PCVAR_BOOL("dev_lpv_points");
 		if(*dev_lpv_points)
@@ -1104,26 +1141,29 @@ void CRenderPipeline::renderGI()
 
 		//break;
 	}
-	if(isFirstRun)
+	for(UINT i = 0; i < 3; ++i)
 	{
-		IGXSurface *pLPVRed = m_pGIAccumRed->asRenderTarget();
-		IGXSurface *pLPVGreen = m_pGIAccumGreen->asRenderTarget();
-		IGXSurface *pLPVBlue = m_pGIAccumBlue->asRenderTarget();
+		if(isFirstRun[i])
+		{
+			IGXSurface *pLPVRed =   m_aLPVs[i].pGIAccumRed->asRenderTarget();
+			IGXSurface *pLPVGreen = m_aLPVs[i].pGIAccumGreen->asRenderTarget();
+			IGXSurface *pLPVBlue =  m_aLPVs[i].pGIAccumBlue->asRenderTarget();
 
-		pCtx->setColorTarget(pLPVRed);
-		pCtx->setColorTarget(pLPVGreen, 1);
-		pCtx->setColorTarget(pLPVBlue, 2);
+			pCtx->setColorTarget(pLPVRed);
+			pCtx->setColorTarget(pLPVGreen, 1);
+			pCtx->setColorTarget(pLPVBlue, 2);
 
-		mem_release(pLPVRed);
-		mem_release(pLPVGreen);
-		mem_release(pLPVBlue);
+			mem_release(pLPVRed);
+			mem_release(pLPVGreen);
+			mem_release(pLPVBlue);
 
-		pCtx->clear(GX_CLEAR_COLOR);
-		isFirstRun = false;
+			pCtx->clear(GX_CLEAR_COLOR);
+			isFirstRun[i] = false;
 
-		pCtx->setColorTarget(NULL);
-		pCtx->setColorTarget(NULL, 1);
-		pCtx->setColorTarget(NULL, 2);
+			pCtx->setColorTarget(NULL);
+			pCtx->setColorTarget(NULL, 1);
+			pCtx->setColorTarget(NULL, 2);
+		}
 	}
 
 	SGCore_ShaderUnBind();
@@ -1135,45 +1175,48 @@ void CRenderPipeline::renderGI()
 
 	{
 		SGCore_ShaderBind(m_idLPVPropagateShader);
-
-		for(UINT i = 0; i < 6/*6*/; ++i)
+		UINT uStepCount[] = {4, 6, 8};
+		for(UINT j = 0; j < 3; ++j)
 		{
-			pCtx->setCSTexture(m_pGIAccumRed, 0);
-			pCtx->setCSTexture(m_pGIAccumGreen, 1);
-			pCtx->setCSTexture(m_pGIAccumBlue, 2);
+			for(UINT i = 0; i < uStepCount[j]; ++i)
+			{
+				pCtx->setCSTexture(m_aLPVs[j].pGIAccumRed, 0);
+				pCtx->setCSTexture(m_aLPVs[j].pGIAccumGreen, 1);
+				pCtx->setCSTexture(m_aLPVs[j].pGIAccumBlue, 2);
 
-			pCtx->setCSUnorderedAccessView(m_pGIAccumRed2, 0);
-			pCtx->setCSUnorderedAccessView(m_pGIAccumGreen2, 1);
-			pCtx->setCSUnorderedAccessView(m_pGIAccumBlue2, 2);
+				pCtx->setCSUnorderedAccessView(m_aLPVs[j].pGIAccumRed2, 0);
+				pCtx->setCSUnorderedAccessView(m_aLPVs[j].pGIAccumGreen2, 1);
+				pCtx->setCSUnorderedAccessView(m_aLPVs[j].pGIAccumBlue2, 2);
 
-			pCtx->computeDispatch(2, 16, 32);
+				pCtx->computeDispatch(2, 16, 32);
 
-			pCtx->setCSUnorderedAccessView(NULL, 0);
-			pCtx->setCSUnorderedAccessView(NULL, 1);
-			pCtx->setCSUnorderedAccessView(NULL, 2);
+				pCtx->setCSUnorderedAccessView(NULL, 0);
+				pCtx->setCSUnorderedAccessView(NULL, 1);
+				pCtx->setCSUnorderedAccessView(NULL, 2);
 
-			pCtx->setCSTexture(NULL, 0);
-			pCtx->setCSTexture(NULL, 1);
-			pCtx->setCSTexture(NULL, 2);
+				pCtx->setCSTexture(NULL, 0);
+				pCtx->setCSTexture(NULL, 1);
+				pCtx->setCSTexture(NULL, 2);
 
 
-			pCtx->setCSTexture(m_pGIAccumRed2, 0);
-			pCtx->setCSTexture(m_pGIAccumGreen2, 1);
-			pCtx->setCSTexture(m_pGIAccumBlue2, 2);
-			
-			pCtx->setCSUnorderedAccessView(m_pGIAccumRed, 0);
-			pCtx->setCSUnorderedAccessView(m_pGIAccumGreen, 1);
-			pCtx->setCSUnorderedAccessView(m_pGIAccumBlue, 2);
+				pCtx->setCSTexture(m_aLPVs[j].pGIAccumRed2, 0);
+				pCtx->setCSTexture(m_aLPVs[j].pGIAccumGreen2, 1);
+				pCtx->setCSTexture(m_aLPVs[j].pGIAccumBlue2, 2);
 
-			pCtx->computeDispatch(2, 16, 32);
+				pCtx->setCSUnorderedAccessView(m_aLPVs[j].pGIAccumRed, 0);
+				pCtx->setCSUnorderedAccessView(m_aLPVs[j].pGIAccumGreen, 1);
+				pCtx->setCSUnorderedAccessView(m_aLPVs[j].pGIAccumBlue, 2);
 
-			pCtx->setCSUnorderedAccessView(NULL, 0);
-			pCtx->setCSUnorderedAccessView(NULL, 1);
-			pCtx->setCSUnorderedAccessView(NULL, 2);
-			
-			pCtx->setCSTexture(NULL, 0);
-			pCtx->setCSTexture(NULL, 1);
-			pCtx->setCSTexture(NULL, 2);
+				pCtx->computeDispatch(2, 16, 32);
+
+				pCtx->setCSUnorderedAccessView(NULL, 0);
+				pCtx->setCSUnorderedAccessView(NULL, 1);
+				pCtx->setCSUnorderedAccessView(NULL, 2);
+
+				pCtx->setCSTexture(NULL, 0);
+				pCtx->setCSTexture(NULL, 1);
+				pCtx->setCSTexture(NULL, 2);
+			}
 		}
 
 		SGCore_ShaderUnBind();
@@ -1203,9 +1246,21 @@ void CRenderPipeline::renderGI()
 
 		pCtx->setPSTexture(m_pGBufferDepth);
 		pCtx->setPSTexture(m_pGBufferNormals, 1);
-		pCtx->setPSTexture(m_pGIAccumRed, 2);
-		pCtx->setPSTexture(m_pGIAccumGreen, 3);
-		pCtx->setPSTexture(m_pGIAccumBlue, 4);
+		for(UINT i = 0; i < 3; ++i)
+		{
+			pCtx->setPSTexture(m_aLPVs[i].pGIAccumRed,   2 + i);
+			pCtx->setPSTexture(m_aLPVs[i].pGIAccumGreen, 5 + i);
+			pCtx->setPSTexture(m_aLPVs[i].pGIAccumBlue,  8 + i);
+		}
+		//r2  |0
+		//r3  |1
+		//r4  |2
+		//g5  |3
+		//g6  |4
+		//g7  |5
+		//b8  |6
+		//b9  |7
+		//b10 |8
 
 		SGCore_ScreenQuadDraw();
 
diff --git a/source/render/RenderPipeline.h b/source/render/RenderPipeline.h
index 96c995b935f0bf79e05f87cfa5367e918c84d79f..b89e14ada815116faed687843a72d9287fd78f00 100644
--- a/source/render/RenderPipeline.h
+++ b/source/render/RenderPipeline.h
@@ -142,6 +142,7 @@ protected:
 		//float4 vNearFarLayers;
 	} m_lpvCentersShaderData;
 	IGXConstantBuffer *m_pLPVcentersShaderData = NULL;
+	IGXConstantBuffer *m_pLPVcurrentCascadeShaderData = NULL;
 
 	struct
 	{
@@ -238,14 +239,17 @@ protected:
 	IGXTexture2D *m_pSceneTexture = NULL;
 
 	//###################################
-
-	IGXTexture3D *m_pGIAccumRed = NULL;
-	IGXTexture3D *m_pGIAccumGreen = NULL;
-	IGXTexture3D *m_pGIAccumBlue = NULL;
-
-	IGXTexture3D *m_pGIAccumRed2 = NULL;
-	IGXTexture3D *m_pGIAccumGreen2 = NULL;
-	IGXTexture3D *m_pGIAccumBlue2 = NULL;
+	
+	struct LPVcascade
+	{
+		IGXTexture3D *pGIAccumRed = NULL;
+		IGXTexture3D *pGIAccumGreen = NULL;
+		IGXTexture3D *pGIAccumBlue = NULL;
+
+		IGXTexture3D *pGIAccumRed2 = NULL;
+		IGXTexture3D *pGIAccumGreen2 = NULL;
+		IGXTexture3D *pGIAccumBlue2 = NULL;
+	} m_aLPVs[3];
 
 	IGXRenderBuffer *m_pGICubesRB = NULL;
 	UINT m_uGICubesCount = 0;
diff --git a/source/render/shadow.cpp b/source/render/shadow.cpp
index 5a72114229fd2cd2e0b2e8695f71ca8ecf533e90..75955758e9269443634fc935662161fb9c947557 100644
--- a/source/render/shadow.cpp
+++ b/source/render/shadow.cpp
@@ -858,14 +858,14 @@ void CReflectiveShadowSun::init(IGXDevice *pContext, UINT uSize)
 	samplerDesc.filter = GXFILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT;
 	m_pSamplerComparisonLinearClamp = pContext->createSamplerState(&samplerDesc);
 
-	GXMacro definesInject[] = {{"IS_SUN", "1"}, {"LPV_POINT_COUNT", "64"}, {"LPV_MAP_SIZE", MACRO_TEXT(RSM_SUN_SIZE)}, {0, 0}};
+	GXMacro definesInject[] = {{"IS_SUN", "1"}, {"LPV_POINT_COUNT", MACRO_TEXT(RSM_SUN_POINTS)}, {"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[] = {{"IS_SUN", "1"}, {"_DEBUG", "1"}, {"LPV_POINT_COUNT", "64"}, {"LPV_MAP_SIZE", MACRO_TEXT(RSM_SUN_SIZE)}, {0, 0}};
+	GXMacro definesInjectDebug[] = {{"IS_SUN", "1"}, {"_DEBUG", "1"}, {"LPV_POINT_COUNT", MACRO_TEXT(RSM_SUN_POINTS)}, {"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)
@@ -967,7 +967,8 @@ void CReflectiveShadowSun::updateFrustum()
 
 	//! @todo: fix grid center pos!
 	float3 vGridCenter = vStart;
-	float fGridRadius = sqrtf(16.0f * 16.0f * 3.0f);
+	//float fGridRadius = sqrtf(16.0f * 16.0f * 3.0f);
+	float fGridRadius = sqrtf(64.0f * 64.0f * 3.0f);
 
 	SMMATRIX mLight(SMMatrixTranspose(SMMATRIX(
 		float4(SMVector3Cross(vUpDir, vLightDir)),
@@ -1017,7 +1018,7 @@ void CReflectiveShadowSun::genLPV(bool isDebug)
 	mem_release(pLightConstant);
 
 	SGCore_ShaderBind(isDebug ? m_idInjectDebugShader : m_idInjectShader);
-	pCtx->drawPrimitive(0, 64 * 64);
+	pCtx->drawPrimitive(0, RSM_SUN_POINTS * RSM_SUN_POINTS);
 
 	SGCore_ShaderUnBind();
 	pCtx->setPrimitiveTopology(GXPT_TRIANGLELIST);
diff --git a/source/render/shadow.h b/source/render/shadow.h
index 282945fabe59578c28032559838c8dc375877a23..50f1d9b419caa4927c0622e6c4ff7e0e0a33671e 100644
--- a/source/render/shadow.h
+++ b/source/render/shadow.h
@@ -17,7 +17,8 @@ See the license in LICENSE
 
 #define RSM_POINT_SIZE 32
 #define RSM_SPOT_SIZE 32
-#define RSM_SUN_SIZE 64
+#define RSM_SUN_SIZE 128
+#define RSM_SUN_POINTS 128
 
 class IXTexture;
 class IBaseShadowMap