Beispiel #1
0
        public void CalculateInitials(RenderDrawContext context, ComputeEffectShader initialSpectrumShader, ComputeEffectShader conjugatedSpectrumShader, WavesSettings wavesSettings, float lengthScale, float cutoffLow, float cutoffHigh)
        {
            _lambda = wavesSettings.Lambda;

            var commandList = context.CommandList;

            commandList.ResourceBarrierTransition(_buffer, GraphicsResourceState.UnorderedAccess);
            commandList.ResourceBarrierTransition(PrecomputedData, GraphicsResourceState.UnorderedAccess);
            commandList.ResourceBarrierTransition(GaussianNoise, GraphicsResourceState.UnorderedAccess);

            initialSpectrumShader.Parameters.Set(OceanInitialSpectrumCommonKeys.Size, (uint)_size);
            initialSpectrumShader.Parameters.Set(OceanInitialSpectrumCommonKeys.LengthScale, lengthScale);
            initialSpectrumShader.Parameters.Set(OceanInitialSpectrumCommonKeys.CutoffHigh, cutoffHigh);
            initialSpectrumShader.Parameters.Set(OceanInitialSpectrumCommonKeys.CutoffLow, cutoffLow);

            initialSpectrumShader.Parameters.Set(OceanInitialSpectrumCommonKeys.GravityAcceleration, wavesSettings.G);
            initialSpectrumShader.Parameters.Set(OceanInitialSpectrumCommonKeys.Depth, wavesSettings.Depth);
            initialSpectrumShader.Parameters.Set(OceanInitialSpectrumCommonKeys.Spectrums, wavesSettings.Spectrums);

            initialSpectrumShader.Parameters.Set(OceanInitialSpectrumCommonKeys.H0K, _buffer);
            initialSpectrumShader.Parameters.Set(OceanInitialSpectrumCommonKeys.WavesData, PrecomputedData);
            initialSpectrumShader.Parameters.Set(OceanInitialSpectrumCommonKeys.Noise, GaussianNoise);

            initialSpectrumShader.ThreadGroupCounts = new Int3(_size / LOCAL_WORK_GROUPS_X, _size / LOCAL_WORK_GROUPS_Y, 1);
            initialSpectrumShader.ThreadNumbers     = new Int3(LOCAL_WORK_GROUPS_X, LOCAL_WORK_GROUPS_Y, 1);
            initialSpectrumShader.Draw(context);

            conjugatedSpectrumShader.Parameters.Set(OceanInitialSpectrumCommonKeys.H0, InitialSpectrum);
            conjugatedSpectrumShader.Parameters.Set(OceanInitialSpectrumCommonKeys.H0K, _buffer);
            conjugatedSpectrumShader.Parameters.Set(OceanInitialSpectrumCommonKeys.Size, (uint)_size);

            conjugatedSpectrumShader.ThreadGroupCounts = new Int3(_size / LOCAL_WORK_GROUPS_X, _size / LOCAL_WORK_GROUPS_Y, 1);
            conjugatedSpectrumShader.ThreadNumbers     = new Int3(LOCAL_WORK_GROUPS_X, LOCAL_WORK_GROUPS_Y, 1);
            conjugatedSpectrumShader.Draw(context);
        }
        protected override void DrawCore(RenderContext context)
        {
            var output = PrefilteredRadiance;

            if (output == null || (output.Dimension != TextureDimension.Texture2D && output.Dimension != TextureDimension.TextureCube) || output.ArraySize != 6)
            {
                throw new NotSupportedException("Only array of 2D textures are currently supported as output");
            }

            var input = RadianceMap;

            if (input == null || input.Dimension != TextureDimension.TextureCube)
            {
                throw new NotSupportedException("Only cubemaps are currently supported as input");
            }

            var roughness = 0f;
            var faceCount = output.ArraySize;
            var levelSize = new Int2(output.Width, output.Height);
            var mipCount  = MipmapGenerationCount == 0 ? output.MipLevels : MipmapGenerationCount;

            for (int l = 0; l < mipCount; l++)
            {
                if (l == 0 && DoNotFilterHighestLevel && input.Width >= output.Width)
                {
                    var inputLevel = MathUtil.Log2(input.Width / output.Width);
                    for (int f = 0; f < 6; f++)
                    {
                        var inputSubresource  = inputLevel + f * input.MipLevels;
                        var outputSubresource = 0 + f * output.MipLevels;
                        GraphicsDevice.CopyRegion(input, inputSubresource, null, output, outputSubresource);
                    }
                }
                else
                {
                    var outputView = output.ToTextureView(ViewType.MipBand, 0, l);

                    computeShader.ThreadGroupCounts = new Int3(levelSize.X, levelSize.Y, faceCount);
                    computeShader.ThreadNumbers     = new Int3(SamplingsCount, 1, 1);
                    computeShader.Parameters.Set(RadiancePrefilteringGGXShaderKeys.Roughness, roughness);
                    computeShader.Parameters.Set(RadiancePrefilteringGGXShaderKeys.MipmapCount, input.MipLevels - 1);
                    computeShader.Parameters.Set(RadiancePrefilteringGGXShaderKeys.RadianceMap, input);
                    computeShader.Parameters.Set(RadiancePrefilteringGGXShaderKeys.RadianceMapSize, input.Width);
                    computeShader.Parameters.Set(RadiancePrefilteringGGXShaderKeys.FilteredRadiance, outputView);
                    computeShader.Parameters.Set(RadiancePrefilteringGGXParams.NbOfSamplings, SamplingsCount);
                    computeShader.Draw(context);

                    outputView.Dispose();
                }

                if (mipCount > 1)
                {
                    roughness += 1f / (mipCount - 1);
                    levelSize /= 2;
                }
            }
        }
Beispiel #3
0
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(output, Color4.White);
            renderHammersley.ThreadGroupCounts = new Int3(samplesCount, 1, 1);
            renderHammersley.ThreadNumbers     = new Int3(1);
            renderHammersley.Parameters.Set(HammersleyTestKeys.OutputTexture, output);
            renderHammersley.Parameters.Set(HammersleyTestKeys.SamplesCount, samplesCount);
            renderHammersley.Draw();

            GraphicsDevice.DrawTexture(output);

            base.Draw(gameTime);
        }
Beispiel #4
0
        protected override void Draw(GameTime gameTime)
        {
            var renderDrawContext = new RenderDrawContext(Services, RenderContext.GetShared(Services), GraphicsContext);

            GraphicsContext.CommandList.Clear(output, Color4.White);
            renderHammersley.ThreadGroupCounts = new Int3(samplesCount, 1, 1);
            renderHammersley.ThreadNumbers     = new Int3(1);
            renderHammersley.Parameters.Set(HammersleyTestKeys.OutputTexture, output);
            renderHammersley.Parameters.Set(HammersleyTestKeys.SamplesCount, samplesCount);
            renderHammersley.Draw(renderDrawContext);

            GraphicsContext.DrawTexture(output);

            base.Draw(gameTime);
        }
Beispiel #5
0
        protected override void Draw(GameTime gameTime)
        {
            var renderDrawContext = new RenderDrawContext(Services, RenderContext.GetShared(Services), GraphicsContext);

            computeShaderEffect.Parameters.Set(ComputeShaderTestParams.NbOfIterations, ReductionRatio);
            computeShaderEffect.Parameters.Set(ComputeShaderTestKeys.input, inputTexture);
            computeShaderEffect.Parameters.Set(ComputeShaderTestKeys.output, outputTexture);
            computeShaderEffect.Draw(renderDrawContext);

            if (displayedTexture == null || spriteBatch == null)
            {
                return;
            }

            GraphicsContext.DrawTexture(displayedTexture);

            base.Draw(gameTime);
        }
Beispiel #6
0
        protected override void Draw(GameTime gameTime)
        {
            var renderDrawContext = new RenderDrawContext(Services, RenderContext.GetShared(Services), GraphicsContext);

            base.Draw(gameTime);

            pass2.ThreadNumbers     = new Int3(NbOfSums, 1, 1);
            pass2.ThreadGroupCounts = new Int3(nbOfGroups.X, nbOfGroups.Y, NbOfCoeffs);
            pass2.Parameters.Set(LambertianPrefilteringSHParameters.BlockSize, NbOfSums);
            pass2.Parameters.Set(SphericalHarmonicsParameters.HarmonicsOrder, Order);
            pass2.Parameters.Set(LambertianPrefilteringSHPass2Keys.InputBuffer, inputBuffer);
            pass2.Parameters.Set(LambertianPrefilteringSHPass2Keys.OutputBuffer, outputBuffer);
            pass2.Draw(renderDrawContext);

            // Get the data out of the final buffer
            var finalsValues = outputBuffer.GetData <Vector4>(GraphicsContext.CommandList);

            // performs last possible additions, normalize the result and store it in the SH
            var result = new Vector4[NbOfCoeffs];

            for (var c = 0; c < NbOfCoeffs; c++)
            {
                var coeff = Vector4.Zero;
                for (var f = 0; f < nbOfGroups.X * nbOfGroups.Y; ++f)
                {
                    coeff += finalsValues[NbOfCoeffs * f + c];
                }
                result[c] = coeff;
            }

            var nbOfTerms = NbOfSums * nbOfGroups.X * nbOfGroups.Y;
            var valueSum  = (nbOfTerms - 1) * nbOfTerms / 2;

            if (assertResults)
            {
                Assert.Equal(new Vector4(valueSum, 0, 0, 0), result[0]);
                Assert.Equal(new Vector4(0, 2 * valueSum, 0, 0), result[1]);
                Assert.Equal(new Vector4(0, 0, 3 * valueSum, 0), result[2]);
                Assert.Equal(new Vector4(0, 0, 0, 4 * valueSum), result[3]);
            }
        }
        protected override void DrawCore(RenderContext context)
        {
            var inputTexture = RadianceMap;

            if (inputTexture == null)
            {
                return;
            }

            // Gets and checks the input texture
            if (inputTexture.Dimension != TextureDimension.TextureCube)
            {
                throw new NotSupportedException("Only texture cube are currently supported as input of 'LambertianPrefilteringSH' effect.");
            }

            const int FirstPassBlockSize = 4;
            const int FirstPassSumsCount = FirstPassBlockSize * FirstPassBlockSize;

            var faceCount         = inputTexture.Dimension == TextureDimension.TextureCube ? 6 : 1;
            var inputSize         = new Int2(inputTexture.Width, inputTexture.Height); // (Note: for cube maps width = height)
            var coefficientsCount = harmonicalOrder * harmonicalOrder;

            var sumsToPerfomRemaining = inputSize.X * inputSize.Y * faceCount / FirstPassSumsCount;
            var partialSumBuffer      = NewScopedTypedBuffer(coefficientsCount * sumsToPerfomRemaining, PixelFormat.R32G32B32A32_Float, true);


            // Project the radiance on the SH basis and sum up the results along the 4x4 blocks
            firstPassEffect.ThreadNumbers     = new Int3(FirstPassBlockSize, FirstPassBlockSize, 1);
            firstPassEffect.ThreadGroupCounts = new Int3(inputSize.X / FirstPassBlockSize, inputSize.Y / FirstPassBlockSize, faceCount);
            firstPassEffect.Parameters.Set(LambertianPrefilteringSHParameters.BlockSize, FirstPassBlockSize);
            firstPassEffect.Parameters.Set(SphericalHarmonicsParameters.HarmonicsOrder, harmonicalOrder);
            firstPassEffect.Parameters.Set(LambertianPrefilteringSHPass1Keys.RadianceMap, inputTexture);
            firstPassEffect.Parameters.Set(LambertianPrefilteringSHPass1Keys.OutputBuffer, partialSumBuffer);
            firstPassEffect.Draw(context);

            // Recursively applies the pass2 (sums the coefficients together) as long as needed. Swap input/output buffer at each iteration.
            var    secondPassInputBuffer  = partialSumBuffer;
            Buffer secondPassOutputBuffer = null;

            while (sumsToPerfomRemaining % 2 == 0)
            {
                // we are limited in the number of summing threads by the group-shared memory size.
                // determine the number of threads to use and update the number of sums remaining afterward.
                var sumsCount = 1;
                while (sumsCount < (1 << 10) && sumsToPerfomRemaining % 2 == 0) // shader can perform only an 2^x number of sums.
                {
                    sumsCount             <<= 1;
                    sumsToPerfomRemaining >>= 1;
                }

                // determine the numbers of groups (limited to 65535 groups by dimensions)
                var groupCountX = 1;
                var groupCountY = sumsToPerfomRemaining;
                while (groupCountX >= short.MaxValue)
                {
                    groupCountX <<= 1;
                    groupCountY >>= 1;
                }

                // create the output buffer if not existing yet
                if (secondPassOutputBuffer == null)
                {
                    secondPassOutputBuffer = NewScopedTypedBuffer(coefficientsCount * sumsToPerfomRemaining, PixelFormat.R32G32B32A32_Float, true);
                }

                // draw pass 2
                secondPassEffect.ThreadNumbers     = new Int3(sumsCount, 1, 1);
                secondPassEffect.ThreadGroupCounts = new Int3(groupCountX, groupCountY, coefficientsCount);
                secondPassEffect.Parameters.Set(LambertianPrefilteringSHParameters.BlockSize, sumsCount);
                secondPassEffect.Parameters.Set(SphericalHarmonicsParameters.HarmonicsOrder, harmonicalOrder);
                secondPassEffect.Parameters.Set(LambertianPrefilteringSHPass2Keys.InputBuffer, secondPassInputBuffer);
                secondPassEffect.Parameters.Set(LambertianPrefilteringSHPass2Keys.OutputBuffer, secondPassOutputBuffer);
                secondPassEffect.Draw(context);

                // swap second pass input/output buffers.
                var swapTemp = secondPassOutputBuffer;
                secondPassOutputBuffer = secondPassInputBuffer;
                secondPassInputBuffer  = swapTemp;
            }

            // create and initialize result SH
            prefilteredLambertianSH = new SphericalHarmonics(HarmonicOrder);

            // Get the data out of the final buffer
            var sizeResult   = coefficientsCount * sumsToPerfomRemaining * PixelFormat.R32G32B32A32_Float.SizeInBytes();
            var stagedBuffer = NewScopedBuffer(new BufferDescription(sizeResult, BufferFlags.None, GraphicsResourceUsage.Staging));

            GraphicsDevice.CopyRegion(secondPassInputBuffer, 0, new ResourceRegion(0, 0, 0, sizeResult, 1, 1), stagedBuffer, 0);
            var finalsValues = stagedBuffer.GetData <Vector4>();

            // performs last possible additions, normalize the result and store it in the SH
            for (var c = 0; c < coefficientsCount; c++)
            {
                var coeff = Vector4.Zero;
                for (var f = 0; f < sumsToPerfomRemaining; ++f)
                {
                    coeff += finalsValues[coefficientsCount * f + c];
                }
                prefilteredLambertianSH.Coefficients[c] = 4 * MathUtil.Pi / coeff.W * new Color3(coeff.X, coeff.Y, coeff.Z);
            }
        }
Beispiel #8
0
        public void CalculateWavesAtTime(RenderDrawContext context, ComputeEffectShader timeDependantSpectrumShader, ComputeEffectShader fillResultTexturesShader, ComputeEffectShader generateMipsShader, float time, float deltaTime)
        {
            var commandList = context.CommandList;

            commandList.ResourceBarrierTransition(_dxDz, GraphicsResourceState.UnorderedAccess);
            commandList.ResourceBarrierTransition(_dyDxz, GraphicsResourceState.UnorderedAccess);
            commandList.ResourceBarrierTransition(_dyxDyz, GraphicsResourceState.UnorderedAccess);
            commandList.ResourceBarrierTransition(_dxxDzz, GraphicsResourceState.UnorderedAccess);
            commandList.ResourceBarrierTransition(Displacement, GraphicsResourceState.UnorderedAccess);
            commandList.ResourceBarrierTransition(Derivatives, GraphicsResourceState.UnorderedAccess);
            commandList.ResourceBarrierTransition(Turbulence, GraphicsResourceState.UnorderedAccess);

            // Calculating complex amplitudes
            timeDependantSpectrumShader.Parameters.Set(OceanTimeDependentSpectrumKeys.Dx_Dz, _dxDz);
            timeDependantSpectrumShader.Parameters.Set(OceanTimeDependentSpectrumKeys.Dy_Dxz, _dyDxz);
            timeDependantSpectrumShader.Parameters.Set(OceanTimeDependentSpectrumKeys.Dyx_Dyz, _dyxDyz);
            timeDependantSpectrumShader.Parameters.Set(OceanTimeDependentSpectrumKeys.Dxx_Dzz, _dxxDzz);
            timeDependantSpectrumShader.Parameters.Set(OceanTimeDependentSpectrumKeys.H0, InitialSpectrum);
            timeDependantSpectrumShader.Parameters.Set(OceanTimeDependentSpectrumKeys.WavesData, PrecomputedData);

            timeDependantSpectrumShader.Parameters.Set(OceanTimeDependentSpectrumKeys.Time, time);

            timeDependantSpectrumShader.ThreadGroupCounts = new Int3(_size / LOCAL_WORK_GROUPS_X, _size / LOCAL_WORK_GROUPS_Y, 1);
            timeDependantSpectrumShader.ThreadNumbers     = new Int3(LOCAL_WORK_GROUPS_X, LOCAL_WORK_GROUPS_Y, 1);
            timeDependantSpectrumShader.Draw(context);

            // Calculating IFFTs of complex amplitudes
            _fft.IFFT2D(context, _dxDz, _buffer, true, false, true);
            _fft.IFFT2D(context, _dyDxz, _buffer, true, false, true);
            _fft.IFFT2D(context, _dyxDyz, _buffer, true, false, true);
            _fft.IFFT2D(context, _dxxDzz, _buffer, true, false, true);

            // Filling displacement and normals textures
            fillResultTexturesShader.Parameters.Set(OceanFillResultTexturesKeys.DeltaTime, deltaTime);
            fillResultTexturesShader.Parameters.Set(OceanFillResultTexturesKeys.Lambda, _lambda);

            fillResultTexturesShader.Parameters.Set(OceanFillResultTexturesKeys.Dx_Dz, _dxDz);
            fillResultTexturesShader.Parameters.Set(OceanFillResultTexturesKeys.Dy_Dxz, _dyDxz);
            fillResultTexturesShader.Parameters.Set(OceanFillResultTexturesKeys.Dyx_Dyz, _dyxDyz);
            fillResultTexturesShader.Parameters.Set(OceanFillResultTexturesKeys.Dxx_Dzz, _dxxDzz);
            fillResultTexturesShader.Parameters.Set(OceanFillResultTexturesKeys.Displacement, Displacement);
            fillResultTexturesShader.Parameters.Set(OceanFillResultTexturesKeys.Derivatives, Derivatives);
            fillResultTexturesShader.Parameters.Set(OceanFillResultTexturesKeys.Turbulence, Turbulence);

            fillResultTexturesShader.ThreadGroupCounts = new Int3(_size / LOCAL_WORK_GROUPS_X, _size / LOCAL_WORK_GROUPS_Y, 1);
            fillResultTexturesShader.ThreadNumbers     = new Int3(LOCAL_WORK_GROUPS_X, LOCAL_WORK_GROUPS_Y, 1);
            fillResultTexturesShader.Draw(context);

            // TODO: Mipsmaps dont look great, could potentially be used by using better filtering
            // Not using them for now, uncomment to enable and switch Sample methods in OceanEmissive.sdsl
            //ResetState();

            //// Generate mip maps
            //GenerateMipsMaps(Derivatives);
            //GenerateMipsMaps(Turbulence);

            //ResetState();

            commandList.ResourceBarrierTransition(Displacement, GraphicsResourceState.PixelShaderResource);
            commandList.ResourceBarrierTransition(Derivatives, GraphicsResourceState.PixelShaderResource);
            commandList.ResourceBarrierTransition(Turbulence, GraphicsResourceState.PixelShaderResource);

            void GenerateMipsMaps(Texture texture)
            {
                for (var i = 0; i < texture.MipLevels - 1; i++)
                {
                    // Copy source mip to staging texture
                    commandList.CopyRegion(texture, i, null, _mipStagingTexture, i);

                    using var targetMip = texture.ToTextureView(ViewType.MipBand, 0, i + 1);

                    generateMipsShader.Parameters.Set(OceanGenerateMipsKeys.SrcMip, _mipStagingTexture);
                    generateMipsShader.Parameters.Set(OceanGenerateMipsKeys.OutMip, targetMip);

                    generateMipsShader.Parameters.Set(OceanGenerateMipsKeys.InvOutTexelSize, new Vector2(1.0f / targetMip.Width, 1.0f / targetMip.Height));
                    generateMipsShader.Parameters.Set(OceanGenerateMipsKeys.SrcMipIndex, (uint)i);

                    generateMipsShader.ThreadGroupCounts = new Int3(targetMip.Width / LOCAL_WORK_GROUPS_X, targetMip.Height / LOCAL_WORK_GROUPS_Y, 1);
                    generateMipsShader.ThreadNumbers     = new Int3(LOCAL_WORK_GROUPS_X, LOCAL_WORK_GROUPS_Y, 1);
                    generateMipsShader.Draw(context);
                }
            }

            void ResetState()
            {
                // This is to solve an issue where child resources (texture views) bound as UAV wont be properly
                // reset when binding the parent texture as an SRV and thus resulting in the SRV potentionally failing to bind
                using (context.PushRenderTargetsAndRestore())
                    commandList.ClearState();
            }
        }