делал нечто подобное, только шейдером, имея карту высот на видюхе и рендеря лайтмап за несколько кадров кусками. шейдер выглдяит вот так:
float2 TexCoords = IN.ScreenTC / MapSize;
float h = tex2D(heighttex,TexCoords).r;
float height = h * heightMult;
float3 pos = float3(TexCoords.x,height,TexCoords.y);
float3 end = saturate(pos - LightDir*(1.0f/MapSize)*128);
float3 step = (end - pos)/128.0f;
float p = 0;
for(int i=0;i<128;i++)
{
pos += step;
p = tex2D(heighttex,pos.xz).r * heightMult;
if (pos.y < p) return float4(0,1-(step.y*i)/heightMult,0,1); //0;// Intersection!//
}
return 1;// (no intersections)
суть в том что от каждого обрабатываемого пикселя ведётся луч в направлении солнца, и если за требуемое кол-во итераций, луч врезается в хейтмап, значит пиксель затенён.