public void AddAttributes(ShaderSourceCollection modifiers) { if (!Enabled) { return; } modifiers.Add(source); }
public void PostProcess(VoxelStorageContext storageContext, RenderDrawContext drawContext, ProcessedVoxelVolume data) { if (Math.Max(Math.Max(ClipMapResolution.X, ClipMapResolution.Y), ClipMapResolution.Z) < 32) { return; } if (FragmentsBuffer == null) { return; } var context = drawContext.RenderContext; if (ClearBuffer == null) { ClearBuffer = new Xenko.Rendering.ComputeEffect.ComputeEffectShader(context) { ShaderSourceName = "ClearBuffer" }; BufferToTexture = new Xenko.Rendering.ComputeEffect.ComputeEffectShader(context) { ShaderSourceName = "BufferToTextureEffect" }; BufferToTextureColumns = new Xenko.Rendering.ComputeEffect.ComputeEffectShader(context) { ShaderSourceName = "BufferToTextureColumnsEffect" }; } bool VoxelsAreIndependent = true; List <VoxelAttribute> IndirectVoxels = new List <VoxelAttribute>(); List <VoxelAttribute> TempVoxels = new List <VoxelAttribute>(); ShaderSourceCollection Indirect = new ShaderSourceCollection(); ShaderSourceCollection Temp = new ShaderSourceCollection(); //Assign sample indices and check whether voxels can be calculated independently int sampleIndex = 0; foreach (var attr in data.Attributes) { attr.Attribute.LocalSamplerID = sampleIndex; VoxelsAreIndependent &= !attr.Attribute.RequiresColumns(); sampleIndex++; } //Populate ShaderSourceCollections and temp lists foreach (var attr in data.Attributes) { if (attr.Stage != VoxelizationStage.Post) { continue; } if (attr.Output) { Indirect.Add(attr.Attribute.GetVoxelizationShader()); IndirectVoxels.Add(attr.Attribute); } else { Temp.Add(attr.Attribute.GetVoxelizationShader()); TempVoxels.Add(attr.Attribute); } } var BufferWriter = VoxelsAreIndependent ? BufferToTexture : BufferToTextureColumns; for (int i = 0; i < IndirectVoxels.Count; i++) { var attr = IndirectVoxels[i]; attr.UpdateVoxelizationLayout($"AttributesIndirect[{i}]"); } for (int i = 0; i < TempVoxels.Count; i++) { var attr = TempVoxels[i]; attr.UpdateVoxelizationLayout($"AttributesTemp[{i}]"); } foreach (var attr in data.Attributes) { attr.Attribute.ApplyVoxelizationParameters(BufferWriter.Parameters); } int processYSize = VoxelsAreIndependent ? (int)ClipMapResolution.Y : 1; processYSize *= (UpdatesPerFrame == UpdateMethods.SingleClipmap) ? 1 : ClipMapCount; BufferWriter.ThreadGroupCounts = VoxelsAreIndependent ? new Int3(32, 32, 32) : new Int3(32, 1, 32); BufferWriter.ThreadNumbers = new Int3((int)ClipMapResolution.X / BufferWriter.ThreadGroupCounts.X, processYSize / BufferWriter.ThreadGroupCounts.Y, (int)ClipMapResolution.Z / BufferWriter.ThreadGroupCounts.Z); BufferWriter.Parameters.Set(BufferToTextureKeys.VoxelFragments, FragmentsBuffer); BufferWriter.Parameters.Set(BufferToTextureKeys.clipMapResolution, ClipMapResolution); BufferWriter.Parameters.Set(BufferToTextureKeys.storageUints, storageUints); BufferWriter.Parameters.Set(BufferToTextureKeys.clipOffset, (uint)(UpdatesPerFrame == UpdateMethods.SingleClipmap ? ClipMapCurrent : 0)); //Modifiers are stored within attributes, yet need to be able to query their results. //Ideally a stage stream could resolve this, however due to the lack of pointers, there would be a cyclic dependency of AttributesList->Attribute->Modifier->AttributesList->... //So instead the results will be stored within a second array that only contains float4s. Unfortunately the only way to iterate through the AttributesList is by foreach, which //makes it difficult to access the results array (AttributeLocalSamples) by index. So instead it's just all done through this macro... string IndirectReadAndStoreMacro = ""; string IndirectStoreMacro = ""; for (int i = 0; i < Temp.Count; i++) { string iStr = i.ToString(); string sampleIndexStr = TempVoxels[i].LocalSamplerID.ToString(); IndirectReadAndStoreMacro += $"AttributesTemp[{iStr}].InitializeFromBuffer(VoxelFragments, VoxelFragmentsIndex + {TempVoxels[i].BufferOffset}, uint2({TempVoxels[i].BufferOffset} + initialVoxelFragmentsIndex, yStride));\n" + $"streams.LocalSample[{sampleIndexStr}] = AttributesTemp[{iStr}].SampleLocal();\n\n"; IndirectStoreMacro += $"streams.LocalSample[{sampleIndexStr}] = AttributesTemp[{iStr}].SampleLocal();\n"; } for (int i = 0; i < Indirect.Count; i++) { string iStr = i.ToString(); string sampleIndexStr = IndirectVoxels[i].LocalSamplerID.ToString(); IndirectReadAndStoreMacro += $"AttributesIndirect[{iStr}].InitializeFromBuffer(VoxelFragments, VoxelFragmentsIndex + {IndirectVoxels[i].BufferOffset}, uint2({IndirectVoxels[i].BufferOffset} + initialVoxelFragmentsIndex, yStride));\n" + $"streams.LocalSample[{sampleIndexStr}] = AttributesIndirect[{iStr}].SampleLocal();\n\n"; IndirectStoreMacro += $"streams.LocalSample[{sampleIndexStr}] = AttributesIndirect[{iStr}].SampleLocal();\n"; } BufferWriter.Parameters.Set(BufferToTextureKeys.AttributesIndirect, Indirect); BufferWriter.Parameters.Set(BufferToTextureKeys.AttributesTemp, Temp); BufferWriter.Parameters.Set(BufferToTextureKeys.IndirectReadAndStoreMacro, IndirectReadAndStoreMacro); BufferWriter.Parameters.Set(BufferToTextureKeys.IndirectStoreMacro, IndirectStoreMacro); ((RendererBase)BufferWriter).Draw(drawContext); ClearBuffer.Parameters.Set(ClearBufferKeys.buffer, FragmentsBuffer); if (UpdatesPerFrame != UpdateMethods.SingleClipmap) { //Clear all ClearBuffer.ThreadNumbers = new Int3(1024, 1, 1); ClearBuffer.ThreadGroupCounts = new Int3(FragmentsBuffer.ElementCount / 1024, 1, 1); ClearBuffer.Parameters.Set(ClearBufferKeys.offset, 0); } else { //Clear next clipmap buffer ClearBuffer.ThreadNumbers = new Int3(1024, 1, 1); ClearBuffer.ThreadGroupCounts = new Int3((int)(ClipMapResolution.X * ClipMapResolution.Y * ClipMapResolution.Z * storageUints) / 1024, 1, 1); ClearBuffer.Parameters.Set(ClearBufferKeys.offset, (int)(((ClipMapCurrent + 1) % ClipMapCount) * ClipMapResolution.X * ClipMapResolution.Y * ClipMapResolution.Z * storageUints)); } ((RendererBase)ClearBuffer).Draw(drawContext); }
public virtual void Collect(RenderContext Context, Shadows.IShadowMapRenderer ShadowMapRenderer) { renderVoxelVolumes = Context.VisibilityGroup.Tags.Get(CurrentRenderVoxelVolumes); if (renderVoxelVolumes == null || renderVoxelVolumes.Count == 0) { return; } List <VoxelVolumeComponent> toRemove = new List <VoxelVolumeComponent>(); foreach (var pair in renderVoxelVolumeData) { bool used = false; foreach (var pair2 in renderVoxelVolumes) { if (pair2.Key == pair.Key) { used = true; } } if (!used) { toRemove.Add(pair.Key); } } foreach (var comp in toRemove) { renderVoxelVolumeDataList.Remove(renderVoxelVolumeData[comp]); renderVoxelVolumeData.Remove(comp); renderVoxelVolumes.Remove(comp); } //Create per-volume textures foreach (var pair in renderVoxelVolumes) { var volume = pair.Value; var bounds = volume.VoxelMatrix.ScaleVector; RenderVoxelVolumeData data; if (!renderVoxelVolumeData.TryGetValue(pair.Key, out data)) { data = new RenderVoxelVolumeData(); renderVoxelVolumeDataList.Add(data); renderVoxelVolumeData.Add(pair.Key, data); } VoxelStorageContext storageContext = new VoxelStorageContext { device = Context.GraphicsDevice, Extents = bounds, VoxelSize = volume.AproxVoxelSize, Matrix = volume.VoxelMatrix }; volume.Storage.UpdateFromContext(storageContext, data); foreach (var attr in volume.Attributes) { attr.PrepareLocalStorage(storageContext, volume.Storage); } volume.Storage.UpdateTempStorage(storageContext); ShaderSourceCollection AttributeIndirect = new ShaderSourceCollection(); ShaderSourceCollection AttributeModifiers = new ShaderSourceCollection(); foreach (var attr in volume.Attributes) { AttributeIndirect.Add(attr.GetShader()); attr.AddAttributes(AttributeModifiers); } if (AttributeModifiers != data.AttributeModifiers) { data.AttributeModifiers = AttributeModifiers; } if (AttributeIndirect != data.AttributeIndirect) { data.AttributeIndirect = AttributeIndirect; } data.VisualizeVoxels = volume.VisualizeVoxels; data.Attributes = volume.Attributes; data.Storage = volume.Storage; data.StorageContext = storageContext; data.VoxelizationMethod = volume.VoxelizationMethod; data.VoxelVisualization = volume.VoxelVisualization; data.Voxelize = volume.Voxelize; data.ReprView = volume.VoxelizationMethod.CollectViews(VoxelStage, volume, storageContext, Context); ShadowMapRenderer?.RenderViewsWithShadows.Add(data.ReprView); } }