public void PostProcess(VoxelStorageContext storageContext, RenderDrawContext drawContext, RenderVoxelVolumeData 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"
                };
            }
            var BufferWriter = BufferToTextureColumns;

            for (int i = 0; i < data.Attributes.Count; i++)
            {
                var attr = data.Attributes[i];
                attr.UpdateLayout("AttributesIndirect[" + i + "]");
            }
            foreach (var attr in data.Attributes)
            {
                attr.ApplyWriteParameters(BufferWriter.Parameters);
            }
            if (BufferWriter == BufferToTextureColumns)
            {
                BufferWriter.ThreadGroupCounts = new Int3(32, 1, 32);
                BufferWriter.ThreadNumbers     = new Int3((int)ClipMapResolution.X / BufferWriter.ThreadGroupCounts.X, ClipMapCount / BufferWriter.ThreadGroupCounts.Y, (int)ClipMapResolution.Z / BufferWriter.ThreadGroupCounts.Z);
            }
            else
            {
                BufferWriter.ThreadGroupCounts = new Int3(32, 16, 32);
                BufferWriter.ThreadNumbers     = new Int3((int)ClipMapResolution.X / BufferWriter.ThreadGroupCounts.X, (int)ClipMapResolution.Y * ClipMapCount / 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.AttributesIndirect, data.AttributeIndirect);
            BufferWriter.Parameters.Set(BufferToTextureKeys.Modifiers, data.AttributeModifiers);
            ((RendererBase)BufferWriter).Draw(drawContext);

            drawContext.CommandList.ClearReadWrite(FragmentsBuffer, new Vector4(0));
            ClearBuffer.ThreadGroupCounts = new Int3(4096 * storageUints * 2, 1, 1);
            ClearBuffer.ThreadNumbers     = new Int3(FragmentsBuffer.ElementCount / ClearBuffer.ThreadGroupCounts.X, 1 / ClearBuffer.ThreadGroupCounts.Y, 1 / ClearBuffer.ThreadGroupCounts.Z);
            ClearBuffer.Parameters.Set(ClearBufferKeys.buffer, FragmentsBuffer);
            ((RendererBase)ClearBuffer).Draw(drawContext);
        }
        public virtual void Collect(RenderContext Context, IShadowMapRenderer ShadowMapRenderer)
        {
            renderVoxelVolumes = Context.VisibilityGroup.Tags.Get(CurrentRenderVoxelVolumes);

            if (renderVoxelVolumes == null)
            {
                return;
            }

            Vector3 resolutionMax     = new Vector3(0, 0, 0);
            int     fragmentsMax      = 0;
            int     fragmentsCountMax = 0;

            //Create per-volume textures
            foreach (var pair in renderVoxelVolumes)
            {
                var volume = pair.Value;
                var bounds = volume.ClipMapMatrix.ScaleVector;

                var resolution = bounds / volume.AproxVoxelSize;

                //Calculate closest power of 2 on each axis
                resolution.X = (float)Math.Pow(2, Math.Round(Math.Log(resolution.X, 2)));
                resolution.Y = (float)Math.Pow(2, Math.Round(Math.Log(resolution.Y, 2)));
                resolution.Z = (float)Math.Pow(2, Math.Round(Math.Log(resolution.Z, 2)));

                resolution = new Vector3(resolution.X, resolution.Z, resolution.Y);//Temporary

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

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

                data.ClipMapResolution = resolution;
                if (NeedToRecreateTexture(data.ClipMaps, ClipMapResolution))
                {
                    data.ClipMaps = Xenko.Graphics.Texture.New3D(Context.GraphicsDevice, (int)ClipMapResolution.X, (int)ClipMapResolution.Y, (int)ClipMapResolution.Z, new MipMapCount(false), Xenko.Graphics.PixelFormat.R16G16B16A16_Float, TextureFlags.ShaderResource | TextureFlags.UnorderedAccess);
                }
                if (NeedToRecreateTexture(data.MipMaps, resolution))
                {
                    data.MipMaps = Xenko.Graphics.Texture.New3D(Context.GraphicsDevice, (int)MipMapResolution.X, (int)MipMapResolution.Y, (int)MipMapResolution.Z, new MipMapCount(true), Xenko.Graphics.PixelFormat.R16G16B16A16_Float, TextureFlags.ShaderResource | TextureFlags.UnorderedAccess);
                }


                resolutionMax     = Vector3.Min(new Vector3(256), Vector3.Max(resolutionMax, resolution));
                fragmentsMax      = Math.Max(fragmentsMax, (int)(ClipMapResolution.X * ClipMapResolution.Y * ClipMapResolution.Z));
                fragmentsCountMax = Math.Max(fragmentsCountMax, (int)(ClipMapResolution.X * ClipMapResolution.Y) * volume.ClipMapCount);
            }

            //Create re-usable textures

            float resolutionMaxSide = Math.Max(Math.Max(resolutionMax.X, resolutionMax.Y), resolutionMax.Z);

            if (NeedToRecreateTexture(MSAARenderTarget, new Vector3(resolutionMaxSide, resolutionMaxSide, 1)))
            {
                MSAARenderTarget = Texture.New(Context.GraphicsDevice, TextureDescription.New2D((int)resolutionMaxSide, (int)resolutionMaxSide, new MipMapCount(false), PixelFormat.R8G8B8A8_UNorm, TextureFlags.RenderTarget, 1, GraphicsResourceUsage.Default, MultisampleCount.X8), null);
            }

            if (NeedToRecreateBuffer(Fragments, fragmentsMax))
            {
                Fragments = Xenko.Graphics.Buffer.Structured.New(Context.GraphicsDevice, fragmentsMax, 24, true);
            }
            if (NeedToRecreateBuffer(FragmentsCounter, fragmentsCountMax))
            {
                FragmentsCounter = Xenko.Graphics.Buffer.Typed.New(Context.GraphicsDevice, fragmentsCountMax, PixelFormat.R32_SInt, true);
            }

            Vector3 MipMapResolutionMax = resolutionMax / 2;

            if (TempMipMaps == null || !TextureDimensionsEqual(TempMipMaps[0], MipMapResolutionMax))
            {
                if (TempMipMaps != null)
                {
                    for (int i = 0; i < TempMipMaps.Length; i++)
                    {
                        TempMipMaps[0].Dispose();
                    }
                }

                int mipCount = 1 + (int)Math.Floor(Math.Log(Math.Max(MipMapResolutionMax.X, Math.Max(MipMapResolutionMax.Y, MipMapResolutionMax.Z)), 2));

                TempMipMaps = new Xenko.Graphics.Texture[mipCount];

                for (int i = 0; i < TempMipMaps.Length; i++)
                {
                    TempMipMaps[i] = Xenko.Graphics.Texture.New3D(Context.GraphicsDevice, (int)MipMapResolutionMax.X, (int)MipMapResolutionMax.Y, (int)MipMapResolutionMax.Z, false, Xenko.Graphics.PixelFormat.R16G16B16A16_Float, TextureFlags.ShaderResource | TextureFlags.UnorderedAccess);

                    MipMapResolutionMax /= 2;
                    MipMapResolutionMax  = Vector3.Max(new Vector3(1), MipMapResolutionMax);
                }
            }
            if (Generate3DMipmaps == null)
            {
                Generate3DMipmaps = new Xenko.Rendering.ComputeEffect.ComputeEffectShader(Context)
                {
                    ShaderSourceName = "Generate3DMipmaps"
                };
                ClearBuffer = new Xenko.Rendering.ComputeEffect.ComputeEffectShader(Context)
                {
                    ShaderSourceName = "ClearBuffer"
                };
                ArrangeFragments = new Xenko.Rendering.ComputeEffect.ComputeEffectShader(Context)
                {
                    ShaderSourceName = "ArrangeFragments"
                };
            }

            //Create all the views
            reflectiveVoxelViews.Clear();
            foreach (var pair in renderVoxelVolumes)
            {
                var volume = pair.Value;
                var data   = renderVoxelVolumeData[pair.Key];
                var bounds = volume.ClipMapMatrix.ScaleVector;

                var shadowRenderView = new RenderView();

                float nearClip = 0.1f;
                float farClip  = 999.7f;
                //Currently hard coded and kinda odd
                shadowRenderView.View       = Matrix.Translation(0.0f, 1.0f, 0.0f) * Matrix.RotationX(-3.1415f / 2.0f);
                shadowRenderView.Projection = Matrix.OrthoRH(bounds.X * (float)Math.Pow(2, volume.ClipMapCount), bounds.Z * (float)Math.Pow(2, volume.ClipMapCount), nearClip, farClip);
                Matrix.Multiply(ref shadowRenderView.View, ref shadowRenderView.Projection, out shadowRenderView.ViewProjection);
                shadowRenderView.Frustum     = new BoundingFrustum(ref shadowRenderView.ViewProjection);
                shadowRenderView.CullingMode = CameraCullingMode.Frustum;
                shadowRenderView.ViewSize    = new Vector2(1024, 1024);

                float maxRes = Math.Max(Math.Max(data.ClipMapResolution.X, data.ClipMapResolution.Y), data.ClipMapResolution.Z);

                var rotmat = new Matrix(1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1);//xzy

                var viewToTexTrans = Matrix.Translation(0.5f, 0.5f, 0.5f);
                var viewToTexScale = Matrix.Scaling(0.5f, 0.5f, 0.5f);
                var viewportAspect = Matrix.Scaling(data.ClipMapResolution / maxRes);

                // Matrix BaseVoxelMatrix = transmat * scalemat * rotmat;
                Matrix BaseVoxelMatrix = volume.ClipMapMatrix * Matrix.Identity;
                BaseVoxelMatrix.Invert();
                BaseVoxelMatrix = BaseVoxelMatrix * Matrix.Scaling(2f, 2f, 2f) * rotmat;

                data.Matrix         = BaseVoxelMatrix * viewToTexScale * viewToTexTrans;
                data.ViewportMatrix = BaseVoxelMatrix * viewportAspect;
                data.ClipMapCount   = volume.ClipMapCount;

                shadowRenderView.NearClipPlane = nearClip;
                shadowRenderView.FarClipPlane  = farClip;
                shadowRenderView.RenderStages.Add(VoxelStage);

                reflectiveVoxelViews.Add(shadowRenderView, pair.Key);

                // Add the render view for the current frame
                Context.RenderSystem.Views.Add(shadowRenderView);

                // Collect objects in shadow views
                Context.VisibilityGroup.TryCollect(shadowRenderView);

                ShadowMapRenderer?.RenderViewsWithShadows.Add(shadowRenderView);
            }
        }
        public void PostProcess(RenderDrawContext drawContext, string MipMapShader)
        {
            if (VoxelMipmapSimple == null || curMipMapShader != MipMapShader)
            {
                if (VoxelMipmapSimple != null)
                {
                    VoxelMipmapSimple.Dispose();
                }
                VoxelMipmapSimple = new Xenko.Rendering.ComputeEffect.ComputeEffectShader(drawContext.RenderContext)
                {
                    ShaderSourceName = MipMapShader
                };
            }
            if (VoxelMipmapSimpleGroups == null || VoxelMipmapSimpleGroups.Length != TempMipMaps.Length || curMipMapShader != MipMapShader)
            {
                if (VoxelMipmapSimpleGroups != null)
                {
                    foreach (var shader in VoxelMipmapSimpleGroups)
                    {
                        shader.Dispose();
                    }
                }
                VoxelMipmapSimpleGroups = new Xenko.Rendering.ComputeEffect.ComputeEffectShader[TempMipMaps.Length];
                for (int i = 0; i < VoxelMipmapSimpleGroups.Length; i++)
                {
                    VoxelMipmapSimpleGroups[i] = new Xenko.Rendering.ComputeEffect.ComputeEffectShader(drawContext.RenderContext)
                    {
                        ShaderSourceName = MipMapShader
                    };
                }
            }
            curMipMapShader = MipMapShader;
            //Mipmap detailed clipmaps into less detailed ones
            Vector3 totalResolution   = ClipMapResolution * new Vector3(1, LayoutSize, 1);
            Int3    threadGroupCounts = new Int3(32, 32, 32);

            if (MipmapInner)
            {
                for (int i = 0; i < ClipMapCount - 1; i++)
                {
                    VoxelMipmapSimple.ThreadGroupCounts = threadGroupCounts;
                    VoxelMipmapSimple.ThreadNumbers     = new Int3((int)totalResolution.X / threadGroupCounts.X, (int)totalResolution.Y / threadGroupCounts.Y, (int)totalResolution.Z / threadGroupCounts.Z);

                    VoxelMipmapSimple.Parameters.Set(VoxelMipmapSimpleKeys.ReadTex, ClipMaps);
                    VoxelMipmapSimple.Parameters.Set(VoxelMipmapSimpleKeys.WriteTex, TempMipMaps[0]);
                    VoxelMipmapSimple.Parameters.Set(VoxelMipmapSimpleKeys.ReadOffset, new Vector3(0, (int)totalResolution.Y * i, 0));
                    ((RendererBase)VoxelMipmapSimple).Draw(drawContext);

                    //Copy each axis, ignoring the top and bottom plane
                    for (int axis = 0; axis < LayoutSize; axis++)
                    {
                        int offset = axis * (int)ClipMapResolution.Y;
                        drawContext.CommandList.CopyRegion(TempMipMaps[0], 0,
                                                           new ResourceRegion(
                                                               0, offset / 2 + 1, 0,
                                                               (int)ClipMapResolution.X / 2, offset / 2 + (int)ClipMapResolution.Y / 2 - 1, (int)ClipMapResolution.Z / 2
                                                               ),
                                                           ClipMaps, 0,
                                                           (int)ClipMapResolution.X / 4, (int)totalResolution.Y * (i + 1) + offset + (int)ClipMapResolution.Y / 4 + 1, (int)ClipMapResolution.Z / 4);
                    }
                }
            }

            Vector3 resolution = ClipMapResolution;

            threadGroupCounts = new Int3((int)resolution.X, (int)resolution.Y, (int)resolution.Z) / 4;
            resolution.Y     *= LayoutSize;
            //Mipmaps for the largest clipmap
            for (int i = 0; i < TempMipMaps.Length - 1; i++)
            {
                var mipmapShader = VoxelMipmapSimpleGroups[i];
                resolution /= 2;
                if (resolution.X < 1)
                {
                    resolution.X = 1;
                }
                if (resolution.Y < 1)
                {
                    resolution.Y = 1;
                }
                if (resolution.Z < 1)
                {
                    resolution.Z = 1;
                }
                if (resolution.X < threadGroupCounts.X || resolution.Y < threadGroupCounts.Y || resolution.Z < threadGroupCounts.Z)
                {
                    threadGroupCounts /= 4;
                    if (threadGroupCounts.X < 1)
                    {
                        threadGroupCounts.X = 1;
                    }
                    if (threadGroupCounts.Y < 1)
                    {
                        threadGroupCounts.Y = 1;
                    }
                    if (threadGroupCounts.Z < 1)
                    {
                        threadGroupCounts.Z = 1;
                    }
                }
                mipmapShader.ThreadGroupCounts = threadGroupCounts;
                mipmapShader.ThreadNumbers     = new Int3((int)resolution.X / threadGroupCounts.X, (int)resolution.Y / threadGroupCounts.Y, (int)resolution.Z / threadGroupCounts.Z);

                if (i == 0)
                {
                    mipmapShader.Parameters.Set(VoxelMipmapSimpleKeys.ReadTex, ClipMaps);
                    mipmapShader.Parameters.Set(VoxelMipmapSimpleKeys.ReadOffset, new Vector3(0, (int)ClipMapResolution.Y * LayoutSize * (ClipMapCount - 1), 0));
                }
                else
                {
                    mipmapShader.Parameters.Set(VoxelMipmapSimpleKeys.ReadTex, TempMipMaps[i - 1]);
                    mipmapShader.Parameters.Set(VoxelMipmapSimpleKeys.ReadOffset, new Vector3(0, 0, 0));
                }
                mipmapShader.Parameters.Set(VoxelMipmapSimpleKeys.WriteTex, TempMipMaps[i]);
                ((RendererBase)mipmapShader).Draw(drawContext);
                //Don't seem to be able to read and write to the same texture, even if the views
                //point to different mipmaps.
                drawContext.CommandList.CopyRegion(TempMipMaps[i], 0, null, MipMaps, i);
            }
        }
Esempio n. 4
0
        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);
        }
Esempio n. 5
0
        public void PostProcess(RenderDrawContext drawContext, ShaderSource[] mipmapShaders)
        {
            if (mipmapShaders.Length != LayoutSize)
            {
                return;
            }

            if (VoxelMipmapSimple == null)
            {
                VoxelMipmapSimple = new Xenko.Rendering.ComputeEffect.ComputeEffectShader(drawContext.RenderContext)
                {
                    ShaderSourceName = "Voxel2x2x2MipmapEffect"
                };
            }

            if (VoxelMipmapSimpleGroups == null || VoxelMipmapSimpleGroups.Length != LayoutSize || VoxelMipmapSimpleGroups[0].Length != TempMipMaps.Length)
            {
                if (VoxelMipmapSimpleGroups != null)
                {
                    for (int axis = 0; axis < LayoutSize; axis++)
                    {
                        if (VoxelMipmapSimpleGroups[axis] != null)
                        {
                            foreach (var shader in VoxelMipmapSimpleGroups[axis])
                            {
                                shader.Dispose();
                            }
                        }
                    }
                }
                VoxelMipmapSimpleGroups = new Xenko.Rendering.ComputeEffect.ComputeEffectShader[LayoutSize][];
                for (int axis = 0; axis < LayoutSize; axis++)
                {
                    VoxelMipmapSimpleGroups[axis] = new Xenko.Rendering.ComputeEffect.ComputeEffectShader[TempMipMaps.Length];
                    for (int i = 0; i < VoxelMipmapSimpleGroups[axis].Length; i++)
                    {
                        VoxelMipmapSimpleGroups[axis][i] = new Xenko.Rendering.ComputeEffect.ComputeEffectShader(drawContext.RenderContext)
                        {
                            ShaderSourceName = "Voxel2x2x2MipmapEffect"
                        };
                    }
                }
            }

            int offsetIndex = 0;
            //Mipmap detailed clipmaps into less detailed ones
            Vector3 totalResolution   = ClipMapResolution * new Vector3(1, LayoutSize, 1);
            Int3    threadGroupCounts = new Int3(32, 32, 32);

            if (DownsampleFinerClipMaps)
            {
                for (int i = 0; i < ClipMapCount - 1; i++)
                {
                    Vector3 Offset = MippingOffset[offsetIndex];

                    VoxelMipmapSimple.ThreadNumbers     = new Int3(8);
                    VoxelMipmapSimple.ThreadGroupCounts = (Int3)((ClipMapResolution / 2f) / (Vector3)VoxelMipmapSimple.ThreadNumbers);

                    for (int axis = 0; axis < LayoutSize; axis++)
                    {
                        VoxelMipmapSimple.Parameters.Set(Voxel2x2x2MipmapKeys.ReadTex, ClipMaps);
                        VoxelMipmapSimple.Parameters.Set(Voxel2x2x2MipmapKeys.WriteTex, TempMipMaps[0]);
                        VoxelMipmapSimple.Parameters.Set(Voxel2x2x2MipmapKeys.ReadOffset, -(Vector3.Mod(Offset, new Vector3(2))) + new Vector3(0, (int)totalResolution.Y * i + (int)ClipMapResolution.Y * axis, 0));
                        VoxelMipmapSimple.Parameters.Set(Voxel2x2x2MipmapKeys.WriteOffset, new Vector3(0, ClipMapResolution.Y / 2 * axis, 0));
                        VoxelMipmapSimple.Parameters.Set(Voxel2x2x2MipmapKeys.mipmapper, mipmapShaders[axis]);
                        ((RendererBase)VoxelMipmapSimple).Draw(drawContext);
                    }

                    Offset -= Vector3.Mod(Offset, new Vector3(2));
                    //Copy each axis, ignoring the top and bottom plane
                    for (int axis = 0; axis < LayoutSize; axis++)
                    {
                        int axisOffset = axis * (int)ClipMapResolution.Y;

                        Int3 CopySize = new Int3((int)ClipMapResolution.X / 2 - 2, (int)ClipMapResolution.Y / 2 - 2, (int)ClipMapResolution.Z / 2 - 2);


                        Int3 DstMinBound = new Int3((int)ClipMapResolution.X / 4 + (int)Offset.X / 2 + 1, (int)totalResolution.Y * (i + 1) + axisOffset + (int)ClipMapResolution.Y / 4 + 1 + (int)Offset.Y / 2, (int)ClipMapResolution.Z / 4 + (int)Offset.Z / 2 + 1);
                        Int3 DstMaxBound = DstMinBound + CopySize;

                        DstMaxBound = Int3.Min(DstMaxBound, new Int3((int)totalResolution.X, (int)totalResolution.Y * (i + 2), (int)totalResolution.Z));
                        DstMinBound = Int3.Min(DstMinBound, new Int3((int)totalResolution.X, (int)totalResolution.Y * (i + 2), (int)totalResolution.Z));
                        DstMaxBound = Int3.Max(DstMaxBound, new Int3(0, (int)totalResolution.Y * (i + 1), 0));
                        DstMinBound = Int3.Max(DstMinBound, new Int3(0, (int)totalResolution.Y * (i + 1), 0));

                        Int3 SizeBound = DstMaxBound - DstMinBound;

                        Int3 SrcMinBound = new Int3(1, axisOffset / 2 + 1, 1);
                        Int3 SrcMaxBound = SrcMinBound + SizeBound;

                        if (SizeBound.X > 0 && SizeBound.Y > 0 && SizeBound.Z > 0)
                        {
                            drawContext.CommandList.CopyRegion(TempMipMaps[0], 0,
                                                               new ResourceRegion(
                                                                   SrcMinBound.X, SrcMinBound.Y, SrcMinBound.Z,
                                                                   SrcMaxBound.X, SrcMaxBound.Y, SrcMaxBound.Z
                                                                   ),
                                                               ClipMaps, 0,
                                                               DstMinBound.X, DstMinBound.Y, DstMinBound.Z);
                        }
                    }
                    offsetIndex++;
                }
            }
            Vector3 resolution = ClipMapResolution;

            offsetIndex = ClipMapCount - 1;
            //Mipmaps for the largest clipmap
            for (int i = 0; i < TempMipMaps.Length - 1; i++)
            {
                Vector3 Offset = MippingOffset[offsetIndex];
                resolution /= 2;

                Vector3 threadNums = Vector3.Min(resolution, new Vector3(8));

                for (int axis = 0; axis < LayoutSize; axis++)
                {
                    var mipmapShader = VoxelMipmapSimpleGroups[axis][i];
                    mipmapShader.ThreadNumbers     = (Int3)(threadNums);
                    mipmapShader.ThreadGroupCounts = (Int3)(resolution / threadNums);
                    if (i == 0)
                    {
                        mipmapShader.Parameters.Set(Voxel2x2x2MipmapKeys.ReadTex, ClipMaps);
                        mipmapShader.Parameters.Set(Voxel2x2x2MipmapKeys.ReadOffset, -Offset + new Vector3(0, (int)ClipMapResolution.Y * LayoutSize * (ClipMapCount - 1) + (int)ClipMapResolution.Y * axis, 0));
                        mipmapShader.Parameters.Set(Voxel2x2x2MipmapKeys.WriteOffset, new Vector3(0, resolution.Y * axis, 0));
                    }
                    else
                    {
                        mipmapShader.Parameters.Set(Voxel2x2x2MipmapKeys.ReadTex, TempMipMaps[i - 1]);
                        mipmapShader.Parameters.Set(Voxel2x2x2MipmapKeys.ReadOffset, -Offset + new Vector3(0, resolution.Y * axis * 2, 0));
                        mipmapShader.Parameters.Set(Voxel2x2x2MipmapKeys.WriteOffset, new Vector3(0, resolution.Y * axis, 0));
                    }
                    mipmapShader.Parameters.Set(Voxel2x2x2MipmapKeys.WriteTex, TempMipMaps[i]);
                    mipmapShader.Parameters.Set(Voxel2x2x2MipmapKeys.mipmapper, mipmapShaders[axis]);
                    ((RendererBase)mipmapShader).Draw(drawContext);
                }
                //Don't seem to be able to read and write to the same texture, even if the views
                //point to different mipmaps.
                drawContext.CommandList.CopyRegion(TempMipMaps[i], 0, null, MipMaps, i);
                offsetIndex++;
            }
            Array.Copy(PerMapOffsetScale, PerMapOffsetScaleCurrent, PerMapOffsetScale.Length);
        }