示例#1
0
        public void UpdateTexture(VoxelStorageContext context, ref IVoxelStorageTexture texture, Stride.Graphics.PixelFormat pixelFormat, int LayoutSize)
        {
            VoxelStorageTextureClipmap clipmap = texture as VoxelStorageTextureClipmap;

            if (clipmap == null)
            {
                clipmap = new VoxelStorageTextureClipmap();
            }

            Vector3 ClipMapTextureResolution = new Vector3(ClipMapResolution.X, ClipMapResolution.Y * ClipMapCount * LayoutSize, ClipMapResolution.Z);
            Vector3 MipMapResolution         = new Vector3(ClipMapResolution.X / 2, ClipMapResolution.Y / 2 * LayoutSize, ClipMapResolution.Z / 2);

            if (VoxelUtils.DisposeTextureBySpecs(clipmap.ClipMaps, ClipMapTextureResolution, pixelFormat))
            {
                clipmap.ClipMaps = Stride.Graphics.Texture.New3D(context.device, (int)ClipMapTextureResolution.X, (int)ClipMapTextureResolution.Y, (int)ClipMapTextureResolution.Z, new MipMapCount(false), pixelFormat, TextureFlags.ShaderResource | TextureFlags.UnorderedAccess);
            }
            if (VoxelUtils.DisposeTextureBySpecs(clipmap.MipMaps, MipMapResolution, pixelFormat))
            {
                if (clipmap.TempMipMaps != null)
                {
                    for (int i = 0; i < clipmap.TempMipMaps.Length; i++)
                    {
                        clipmap.TempMipMaps[i].Dispose();
                    }
                }

                Vector3 MipMapResolutionMax = MipMapResolution;

                clipmap.MipMaps = Stride.Graphics.Texture.New3D(context.device, (int)MipMapResolution.X, (int)MipMapResolution.Y, (int)MipMapResolution.Z, new MipMapCount(true), pixelFormat, TextureFlags.ShaderResource | TextureFlags.UnorderedAccess);

                clipmap.TempMipMaps = new Stride.Graphics.Texture[MipMapCount];

                for (int i = 0; i < clipmap.TempMipMaps.Length; i++)
                {
                    clipmap.TempMipMaps[i] = Stride.Graphics.Texture.New3D(context.device, (int)MipMapResolutionMax.X, (int)MipMapResolutionMax.Y, (int)MipMapResolutionMax.Z, false, pixelFormat, TextureFlags.ShaderResource | TextureFlags.UnorderedAccess);

                    MipMapResolutionMax /= 2;
                }
            }
            clipmap.DownsampleFinerClipMaps = DownsampleFinerClipMaps;
            clipmap.ClipMapResolution       = ClipMapResolution;
            clipmap.ClipMapCount            = ClipMapCount;
            clipmap.LayoutSize        = LayoutSize;
            clipmap.VoxelSize         = context.RealVoxelSize();
            clipmap.VolumeTranslation = new Int3((int)context.VoxelSpaceTranslation.X, (int)context.VoxelSpaceTranslation.Y, (int)context.VoxelSpaceTranslation.Z);

            Array.Copy(MippingOffset, clipmap.MippingOffset, MippingOffset.Length);
            Array.Copy(PerMapOffsetScale, clipmap.PerMapOffsetScale, PerMapOffsetScale.Length);



            texture = clipmap;
        }
示例#2
0
        public virtual void Collect(RenderContext Context, Shadows.IShadowMapRenderer ShadowMapRenderer)
        {
            renderVoxelVolumes    = Context.VisibilityGroup.Tags.Get(CurrentRenderVoxelVolumes);
            renderVoxelVolumeData = Context.VisibilityGroup.Tags.Get(CurrentProcessedVoxelVolumes);

            if (renderVoxelVolumes == null || renderVoxelVolumes.Count == 0)
            {
                return;
            }

            if (Context.RenderSystem.GraphicsDevice.Features.CurrentProfile < GraphicsProfile.Level_11_0)
            {
                throw new ArgumentOutOfRangeException("Graphics Profile Level 11 or higher required for Voxelization.");
            }

            //Setup per volume passes and texture allocations
            foreach (var pair in renderVoxelVolumes)
            {
                var dataVolume = pair.Value;
                var bounds     = dataVolume.VolumeSize;

                ProcessedVoxelVolume processedVolume;
                if (!renderVoxelVolumeData.TryGetValue(pair.Key, out processedVolume))
                {
                    processedVolume = new ProcessedVoxelVolume();
                    renderVoxelVolumeData.Add(pair.Key, processedVolume);
                }


                //Setup matrix
                Vector3 matScale = dataVolume.VolumeSize;
                Vector3 matTrans = dataVolume.VolumeTranslation;

                Matrix corMatrix = Matrix.Scaling(matScale) * Matrix.Translation(matTrans);
                VoxelStorageContext storageContext = new VoxelStorageContext
                {
                    device    = Context.GraphicsDevice,
                    Extents   = bounds,
                    VoxelSize = dataVolume.AproxVoxelSize,
                    Matrix    = corMatrix
                };

                if (dataVolume.VoxelGridSnapping)
                {
                    matTrans  /= storageContext.RealVoxelSize();
                    matTrans.X = MathF.Floor(matTrans.X);
                    matTrans.Y = MathF.Floor(matTrans.Y);
                    matTrans.Z = MathF.Floor(matTrans.Z);
                    matTrans  *= storageContext.RealVoxelSize();

                    corMatrix             = Matrix.Scaling(matScale) * Matrix.Translation(matTrans);
                    storageContext.Matrix = corMatrix;
                }
                storageContext.Translation           = matTrans;
                storageContext.VoxelSpaceTranslation = matTrans / storageContext.RealVoxelSize();

                //Update storage
                dataVolume.Storage.UpdateFromContext(storageContext);

                //Transfer voxelization info
                processedVolume.VisualizeVoxels        = dataVolume.VisualizeVoxels;
                processedVolume.Storage                = dataVolume.Storage;
                processedVolume.StorageContext         = storageContext;
                processedVolume.VoxelizationMethod     = dataVolume.VoxelizationMethod;
                processedVolume.VoxelVisualization     = dataVolume.VoxelVisualization;
                processedVolume.VisualizationAttribute = dataVolume.VisualizationAttribute;
                processedVolume.Voxelize               = dataVolume.Voxelize;
                processedVolume.OutputAttributes       = dataVolume.Attributes;

                processedVolume.Attributes.Clear();
                processedVolume.passList.Clear();
                processedVolume.groupedPasses.Clear();

                processedVolume.passList.defaultVoxelizationMethod = dataVolume.VoxelizationMethod;


                //Create final list of attributes (including temporary ones)
                foreach (var attr in dataVolume.Attributes)
                {
                    attr.CollectAttributes(processedVolume.Attributes, VoxelizationStage.Initial, true);
                }

                //Allocate textures and space in the temporary buffer
                foreach (var attr in processedVolume.Attributes)
                {
                    attr.Attribute.PrepareLocalStorage(storageContext, dataVolume.Storage);
                    if (attr.Output)
                    {
                        attr.Attribute.PrepareOutputStorage(storageContext, dataVolume.Storage);
                    }
                    else
                    {
                        attr.Attribute.ClearOutputStorage();
                    }
                }
                dataVolume.Storage.UpdateTempStorage(storageContext);

                //Create list of voxelization passes that need to be done
                dataVolume.Storage.CollectVoxelizationPasses(processedVolume, storageContext);

                //Group voxelization passes where the RenderStage can be shared
                //TODO: Group identical attributes
                for (int i = 0; i < processedVolume.passList.passes.Count; i++)
                {
                    bool added = false;
                    var  passA = processedVolume.passList.passes[i];
                    for (int group = 0; group < processedVolume.groupedPasses.Count; group++)
                    {
                        var passB = processedVolume.groupedPasses[group][0];
                        if (
                            passB.storer.CanShareRenderStage(passA.storer) &&
                            passB.method.CanShareRenderStage(passA.method) &&
                            passB.AttributesDirect.SequenceEqual(passA.AttributesDirect) &&
                            passB.AttributesIndirect.SequenceEqual(passA.AttributesIndirect) &&
                            passB.AttributesTemp.SequenceEqual(passA.AttributesTemp)
                            )
                        {
                            processedVolume.groupedPasses[group].Add(passA);
                            added = true;
                            break;
                        }
                    }
                    if (!added)
                    {
                        List <VoxelizationPass> newGroup = new List <VoxelizationPass>
                        {
                            passA
                        };
                        processedVolume.groupedPasses.Add(newGroup);
                    }
                }

                if (VoxelStages.Count < processedVolume.groupedPasses.Count)
                {
                    throw new ArgumentOutOfRangeException(processedVolume.groupedPasses.Count.ToString() + " Render Stages required for voxelization, only " + VoxelStages.Count.ToString() + " provided.");
                }

                //Finish preparing the passes, collecting views and setting up shader sources and shadows
                for (int group = 0; group < processedVolume.groupedPasses.Count; group++)
                {
                    foreach (var pass in processedVolume.groupedPasses[group])
                    {
                        pass.renderStage = VoxelStages[group];
                        pass.source      = pass.storer.GetVoxelizationShader(pass, processedVolume);
                        pass.view.RenderStages.Add(pass.renderStage);

                        Context.RenderSystem.Views.Add(pass.view);
                        Context.VisibilityGroup.TryCollect(pass.view);

                        if (pass.requireShadows)
                        {
                            ShadowMapRenderer?.RenderViewsWithShadows.Add(pass.view);
                        }
                    }
                }
            }
        }
示例#3
0
        public void UpdateFromContext(VoxelStorageContext context)
        {
            var virtualResolution = context.Resolution();
            var largestDimension  = (double)Math.Max(virtualResolution.X, Math.Max(virtualResolution.Y, virtualResolution.Z));

            ClipMapCount = (int)Math.Log(largestDimension / Math.Min(largestDimension, (double)ClipResolution), 2) + 1;

            ClipMapCurrent++;
            if (ClipMapCurrent >= ClipMapCount)
            {
                ClipMapCurrent = 0;
            }

            float FinestClipMapScale = (float)Math.Pow(2, ClipMapCount - 1);

            ClipMapResolution = new Vector3(virtualResolution.X, virtualResolution.Y, virtualResolution.Z) / FinestClipMapScale;
            MipMapCount       = (int)Math.Floor(Math.Log(Math.Min(ClipMapResolution.X, Math.Min(ClipMapResolution.Y, ClipMapResolution.Z)), 2));

            int voxelScale = 1;

            for (int i = 0; i < (ClipMapCount + MipMapCount); i++)
            {
                Vector3 SnappedVolumeTranslation = context.VoxelSpaceTranslation;
                SnappedVolumeTranslation.X = MathF.Floor(SnappedVolumeTranslation.X / voxelScale) * voxelScale;
                SnappedVolumeTranslation.Y = MathF.Floor(SnappedVolumeTranslation.Y / voxelScale) * voxelScale;
                SnappedVolumeTranslation.Z = MathF.Floor(SnappedVolumeTranslation.Z / voxelScale) * voxelScale;

                if (ShouldUpdateClipIndex(i))
                {
                    PerMapSnappingOffset[i] = -SnappedVolumeTranslation *context.RealVoxelSize();

                    MippingOffsetTranslation[i] = new Int3((int)SnappedVolumeTranslation.X, (int)SnappedVolumeTranslation.Y, (int)SnappedVolumeTranslation.Z);
                }

                voxelScale *= 2;
            }

            float extentScale = (float)Math.Pow(2f, ClipMapCount - 1);

            voxelScale = 1;

            for (int i = 0; i < (ClipMapCount + MipMapCount); i++)
            {
                if (ShouldUpdateClipIndex(i))
                {
                    Vector3 offset = (PerMapSnappingOffset[i]) * extentScale / context.Extents + 0.5f;
                    PerMapOffsetScale[i] = new Vector4(offset, (1.0f / context.Extents.X) * extentScale);
                }

                if (i + 1 == ClipMapCurrent || ShouldUpdateClipIndex(i))
                {
                    MippingOffset[i] = (Vector3)((MippingOffsetTranslation[i] - MippingOffsetTranslation[i + 1]) / voxelScale);
                }

                if (i < ClipMapCount - 1)
                {
                    extentScale /= 2;
                }
                voxelScale *= 2;
            }
        }