private void AssignRectangle(LightShadowMapTexture lightShadowMapTexture) { lightShadowMapTexture.CascadeCount = lightShadowMapTexture.Shadow.GetCascadeCount(); var size = lightShadowMapTexture.Size; // Try to fit the shadow map into an existing atlas ShadowMapAtlasTexture currentAtlas = null; foreach (var atlas in atlases) { if (atlas.TryInsert(size, size, lightShadowMapTexture.CascadeCount, (int index, ref Rectangle rectangle) => lightShadowMapTexture.SetRectangle(index, rectangle))) { currentAtlas = atlas; break; } } // Allocate a new atlas texture if (currentAtlas == null) { // For now, our policy is to allow only one shadow map, esp. because we can have only one shadow texture per lighting group // TODO: Group by DirectLightGroups, so that we can have different atlas per lighting group // TODO: Allow multiple textures per LightingGroup (using array of Texture?) if (atlases.Count == 0) { // TODO: handle FilterType texture creation here // TODO: This does not work for Omni lights var texture = Texture.New2D(RenderSystem.GraphicsDevice, MaximumTextureSize, MaximumTextureSize, 1, shadowMapRenderStage.Output.DepthStencilFormat, TextureFlags.DepthStencil | TextureFlags.ShaderResource); currentAtlas = new ShadowMapAtlasTexture(texture, atlases.Count) { FilterType = lightShadowMapTexture.FilterType }; atlases.Add(currentAtlas); for (int i = 0; i < lightShadowMapTexture.CascadeCount; i++) { var rect = Rectangle.Empty; currentAtlas.Insert(size, size, ref rect); lightShadowMapTexture.SetRectangle(i, rect); } } } // Make sure the atlas cleared (will be clear just once) lightShadowMapTexture.Atlas = currentAtlas; lightShadowMapTexture.TextureId = (byte)(currentAtlas?.Id ?? 0); }
private void AssignRectangles(LightShadowMapTexture lightShadowMapTexture) { lightShadowMapTexture.CascadeCount = lightShadowMapTexture.Shadow.GetCascadeCount(); var size = lightShadowMapTexture.Size; // Try to fit the shadow map into an existing atlas ShadowMapAtlasTexture currentAtlas = null; foreach (var atlas in atlases) { if (atlas.TryInsert(size, size, lightShadowMapTexture.CascadeCount, (int index, ref Rectangle rectangle) => lightShadowMapTexture.SetRectangle(index, rectangle))) { currentAtlas = atlas; break; } } // Allocate a new atlas texture if (currentAtlas == null) { // TODO: handle FilterType texture creation here // TODO: This does not work for Omni lights var texture = Texture.New2D(Context.GraphicsDevice, MaximumTextureSize, MaximumTextureSize, 1, PixelFormat.D32_Float, TextureFlags.DepthStencil | TextureFlags.ShaderResource); currentAtlas = new ShadowMapAtlasTexture(texture, atlases.Count) { FilterType = lightShadowMapTexture.FilterType }; atlases.Add(currentAtlas); for (int i = 0; i < lightShadowMapTexture.CascadeCount; i++) { var rect = Rectangle.Empty; currentAtlas.Insert(size, size, ref rect); lightShadowMapTexture.SetRectangle(i, rect); } } // Make sure the atlas cleared (will be clear just once) currentAtlas.ClearRenderTarget(Context); lightShadowMapTexture.TextureId = (byte)currentAtlas.Id; lightShadowMapTexture.Atlas = currentAtlas; }