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; } } }
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); }
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); }
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); }
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); } }
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(); } }