/// <summary> /// Performs good-old StretchRect to destination buffer with blending. /// </summary> /// <param name="dst"></param> /// <param name="src"></param> /// <param name="filter"></param> /// <param name="rect"></param> public void RenderSsao ( RenderTargetSurface ssaoDst, StereoEye stereoEye, Camera camera, DepthStencil2D depthSource, RenderTarget2D normalsSource ) { SetDefaultRenderStates(); using( new PixEvent("SSAO") ) { var ssaoParams = new SsaoParams(); ssaoParams.View = camera.GetViewMatrix( stereoEye ); ssaoParams.Projection = camera.GetProjectionMatrix( stereoEye ); ssaoParams.InverseProjection = Matrix.Invert( ssaoParams.Projection ); paramsCB.SetData( ssaoParams ); SetViewport( ssaoDst ); device.SetTargets( null, ssaoDst ); device.PipelineState = factory[ (int)(ShaderFlags.SSAO) ]; device.VertexShaderResources[0] = depthSource; device.PixelShaderResources[0] = depthSource; device.PixelShaderSamplers[0] = SamplerState.PointClamp; device.PixelShaderConstants[0] = paramsCB; device.PixelShaderConstants[1] = randomDirsCB; device.Draw( 3, 0 ); } device.ResetStates(); }
/// <summary> /// /// </summary> /// <param name="camera"></param> /// <param name="depthBuffer"></param> /// <param name="hdrTarget"></param> /// <param name="diffuse"></param> /// <param name="specular"></param> /// <param name="normals"></param> internal void RenderGBuffer ( StereoEye stereoEye, Camera camera, HdrFrame frame, RenderWorld viewLayer ) { using ( new PixEvent("RenderGBuffer") ) { if (surfaceShader==null) { return; } if (rs.SkipSceneRendering) { return; } var device = Game.GraphicsDevice; var view = camera.GetViewMatrix( stereoEye ); var projection = camera.GetProjectionMatrix( stereoEye ); var viewPosition = camera.GetCameraPosition4( stereoEye ); var cbData = new CBMeshInstanceData(); var hdr = frame.HdrBuffer.Surface; var depth = frame.DepthBuffer.Surface; var diffuse = frame.DiffuseBuffer.Surface; var specular = frame.SpecularBuffer.Surface; var normals = frame.NormalMapBuffer.Surface; var scattering = frame.ScatteringBuffer.Surface; device.ResetStates(); device.SetTargets( depth, hdr, diffuse, specular, normals, scattering ); device.PixelShaderSamplers[0] = SamplerState.AnisotropicWrap ; var instances = viewLayer.Instances; //#warning INSTANSING! foreach ( var instance in instances ) { if (!instance.Visible) { continue; } cbData.View = view; cbData.Projection = projection; cbData.World = instance.World; cbData.ViewPos = viewPosition; constBuffer.SetData( cbData ); device.PixelShaderConstants[0] = constBuffer ; device.VertexShaderConstants[0] = constBuffer ; device.SetupVertexInput( instance.vb, instance.ib ); if (instance.IsSkinned) { constBufferBones.SetData( instance.BoneTransforms ); device.VertexShaderConstants[3] = constBufferBones ; } try { foreach ( var sg in instance.ShadingGroups ) { device.PipelineState = instance.IsSkinned ? sg.Material.GBufferSkinned : sg.Material.GBufferRigid; device.PixelShaderConstants[1] = sg.Material.ConstantBufferParameters; device.PixelShaderConstants[2] = sg.Material.ConstantBufferUVModifiers; device.VertexShaderConstants[1] = sg.Material.ConstantBufferParameters; device.VertexShaderConstants[2] = sg.Material.ConstantBufferUVModifiers; sg.Material.SetTextures( device ); device.DrawIndexed( sg.IndicesCount, sg.StartIndex, 0 ); rs.Counters.SceneDIPs++; } } catch ( UbershaderException e ) { Log.Warning( e.Message ); ExceptionDialog.Show( e ); } } } }
/// <summary> /// Performs luminance measurement, tonemapping, applies bloom. /// </summary> /// <param name="target">LDR target.</param> /// <param name="hdrImage">HDR source image.</param> public void Render ( StereoEye stereoEye, Camera camera, ShaderResource depthBuffer, ShaderResource wsNormals ) { var view = camera.GetViewMatrix( stereoEye ); var projection = camera.GetProjectionMatrix( stereoEye ); var device = Game.GraphicsDevice; var filter = Game.RenderSystem.Filter; if (!Enabled) { device.Clear( occlusionMap0.Surface, Color4.White ); return; } using (new PixEvent("SSAO Render")) { filter.StretchRect( downsampledDepth.Surface, depthBuffer ); filter.StretchRect( downsampledNormals.Surface, wsNormals ); using (new PixEvent("SSAO Pass")) { // // Setup parameters : // var paramsData = new Params(); paramsData.ProjMatrix = projection; paramsData.View = view; paramsData.ViewProj = view * projection; paramsData.InvViewProj = Matrix.Invert( view * projection ); paramsData.InvProj = Matrix.Invert(projection); //paramsData.TraceStep = Config.TraceStep; //paramsData.DecayRate = Config.DecayRate; paramsData.MaxSampleRadius = MaxSamplingRadius; paramsData.MaxDepthJump = MaxDepthJump; paramsCB.SetData( paramsData ); sampleDirectionsCB.SetData(sampleDirectionData); device.PixelShaderConstants[0] = paramsCB; device.PixelShaderConstants[1] = sampleDirectionsCB; // // Measure and adapt : // device.SetTargets( null, occlusionMap0 ); device.PixelShaderResources[0] = downsampledDepth; device.PixelShaderResources[1] = downsampledNormals; device.PixelShaderResources[2] = randomDir; device.PixelShaderSamplers[0] = SamplerState.LinearClamp; Flags sampleNumFlag = getSampleNumFlag(); device.PipelineState = factory[getFlags()]; device.Draw( 3, 0 ); device.ResetStates(); } using (new PixEvent("Bilateral Filter")) { if (BlurSigma!=0) { filter.GaussBlurBilateral( occlusionMap0, occlusionMap1, downsampledDepth, downsampledNormals, BlurSigma, Sharpness, 0 ); } } } }
/// <summary> /// /// </summary> void RenderGeneric ( string passName, GameTime gameTime, Camera camera, Viewport viewport, Matrix view, Matrix projection, RenderTargetSurface colorTarget, DepthStencilSurface depthTarget, ShaderResource depthValues, Flags flags ) { var device = Game.GraphicsDevice; if (rs.SkipParticles) { return; } using ( new PixEvent(passName) ) { device.ResetStates(); // // Setup images : // if (Images!=null && !Images.IsDisposed) { imagesCB.SetData( Images.GetNormalizedRectangles( MaxImages ) ); } SetupGPUParameters( 0, renderWorld, view, projection, flags ); device.ComputeShaderConstants[0] = paramsCB ; // // Render // using (new PixEvent("Drawing")) { device.ResetStates(); // target and viewport : device.SetTargets( depthTarget, colorTarget ); device.SetViewport( viewport ); // params CB : device.ComputeShaderConstants[0] = paramsCB ; device.VertexShaderConstants[0] = paramsCB ; device.GeometryShaderConstants[0] = paramsCB ; device.PixelShaderConstants[0] = paramsCB ; // atlas CB : device.VertexShaderConstants[1] = imagesCB ; device.GeometryShaderConstants[1] = imagesCB ; device.PixelShaderConstants[1] = imagesCB ; // sampler & textures : device.PixelShaderSamplers[0] = SamplerState.LinearClamp4Mips ; device.PixelShaderResources[0] = Images==null? rs.WhiteTexture.Srv : Images.Texture.Srv; device.PixelShaderResources[5] = depthValues; device.GeometryShaderResources[1] = simulationBuffer ; device.GeometryShaderResources[2] = simulationBuffer ; device.GeometryShaderResources[3] = sortParticlesBuffer; device.GeometryShaderResources[4] = particleLighting; // setup PS : device.PipelineState = factory[ (int)flags ]; // GPU time : 0.81 ms -> 0.91 ms device.Draw( MaxSimulatedParticles, 0 ); } } }
/// <summary> /// /// </summary> /// <param name="gameTime"></param> internal void Render ( GameTime gameTime, Camera camera, StereoEye stereoEye, HdrFrame viewFrame ) { var view = camera.GetViewMatrix( stereoEye ); var projection = camera.GetProjectionMatrix( stereoEye ); var colorTarget = viewFrame.HdrBuffer.Surface; var depthTarget = viewFrame.DepthBuffer.Surface; var viewport = new Viewport( 0, 0, colorTarget.Width, colorTarget.Height ); RenderGeneric( "Particles", gameTime, camera, viewport, view, projection, colorTarget, null, viewFrame.DepthBuffer, Flags.DRAW ); }
/// <summary> /// Creates ViewLayer instance /// </summary> /// <param name="Game">Game engine</param> public RenderLayer ( Game game ) { Game = game; this.rs = Game.RenderSystem; Visible = true; Order = 0; Camera = new Camera(); SpriteLayers = new SpriteLayerCollection(); GisLayers = new List<Gis.GisLayer>(); GlobeCamera = new GlobeCamera(Game); }
/// <summary> /// Updates particle properties. /// </summary> /// <param name="gameTime"></param> internal void Simulate ( GameTime gameTime, Camera camera ) { var device = Game.GraphicsDevice; var view = camera.GetViewMatrix( StereoEye.Mono ); var projection = camera.GetProjectionMatrix( StereoEye.Mono ); timeAccumulator += gameTime.ElapsedSec; using ( new PixEvent("Particle Simulation") ) { device.ResetStates(); // // Inject : // using (new PixEvent("Injection")) { injectionBuffer.SetData( injectionBufferCPU ); device.ComputeShaderResources[1] = injectionBuffer ; device.SetCSRWBuffer( 0, simulationBuffer, 0 ); device.SetCSRWBuffer( 1, deadParticlesIndices, -1 ); SetupGPUParameters( 0, renderWorld, view, projection, Flags.INJECTION ); device.ComputeShaderConstants[0] = paramsCB ; device.PipelineState = factory[ (int)Flags.INJECTION ]; // GPU time ???? -> 0.0046 device.Dispatch( MathUtil.IntDivUp( MaxInjectingParticles, BlockSize ) ); ClearParticleBuffer(); } // // Simulate : // using (new PixEvent("Simulation")) { if (!renderWorld.IsPaused && !rs.SkipParticlesSimulation) { device.SetCSRWBuffer( 0, simulationBuffer, 0 ); device.SetCSRWBuffer( 1, deadParticlesIndices, -1 ); device.SetCSRWBuffer( 2, sortParticlesBuffer, 0 ); float stepTime = SimulationStepTime; while ( timeAccumulator > stepTime ) { SetupGPUParameters( stepTime, renderWorld, view, projection, Flags.SIMULATION); device.ComputeShaderConstants[0] = paramsCB ; device.PipelineState = factory[ (int)Flags.SIMULATION ]; /// GPU time : 1.665 ms --> 0.38 ms device.Dispatch( MathUtil.IntDivUp( MaxSimulatedParticles, BlockSize ) );//*/ timeAccumulator -= stepTime; } } } // // Sort : // using (new PixEvent("Sort")) { rs.BitonicSort.Sort( sortParticlesBuffer ); } if (rs.ShowParticles) { rs.Counters.DeadParticles = deadParticlesIndices.GetStructureCount(); } } }
/// <summary> /// Renders sky with specified technique /// </summary> /// <param name="rendCtxt"></param> /// <param name="techName"></param> internal void Render( Camera camera, StereoEye stereoEye, HdrFrame frame, SkySettings settings ) { var scale = Matrix.Scaling( settings.SkySphereSize ); var rotation = Matrix.Identity; var sunPos = settings.SunPosition; var sunColor = settings.SunGlowColor; rs.ResetStates(); //rs.DepthStencilState = depthBuffer==null? DepthStencilState.None : DepthStencilState.Default ; rs.SetTargets( frame.DepthBuffer.Surface, frame.HdrBuffer.Surface ); var viewMatrix = camera.GetViewMatrix( stereoEye ); var projMatrix = camera.GetProjectionMatrix( stereoEye ); skyConstsData.MatrixWVP = scale * rotation * MathUtil.Transformation( viewMatrix.Right, viewMatrix.Up, viewMatrix.Backward ) * projMatrix; skyConstsData.SunPosition = sunPos; skyConstsData.SunColor = sunColor; skyConstsData.Turbidity = settings.SkyTurbidity; skyConstsData.Temperature = Temperature.Get( settings.SunTemperature ); skyConstsData.SkyIntensity = settings.SkyIntensity; skyConstsCB.SetData( skyConstsData ); rs.VertexShaderConstants[0] = skyConstsCB; rs.PixelShaderConstants[0] = skyConstsCB; // // Sky : // SkyFlags flags = SkyFlags.SKY; ApplyColorSpace( ref flags, settings ); rs.PipelineState = factory[(int)flags]; rs.SetupVertexInput( skyVB, null ); rs.Draw( skyVB.Capacity, 0 ); rs.ResetStates(); }
/// <summary> /// /// </summary> /// <param name="gameTime"></param> internal void Render ( GameTime gameTime, Camera camera, StereoEye stereoEye, HdrFrame viewFrame ) { var device = Game.GraphicsDevice; device.ResetStates(); device.SetTargets( viewFrame.DepthBuffer, viewFrame.HdrBuffer ); device.SetViewport( 0,0,viewFrame.HdrBuffer.Width, viewFrame.HdrBuffer.Height ); int w = device.DisplayBounds.Width; int h = device.DisplayBounds.Height; //var map = "SV_POSITION.xyzw;COLOR0.xyzw;COLOR1.xyzw;TEXCOORD0.xyzw;TEXCOORD1.xyzw;TEXCOORD2.xyzw"; Params param = new Params(); //param.View = Matrix.Identity; //param.Projection = Matrix.OrthoOffCenterRH(0, w, h, 0, -9999, 9999); param.View = camera.GetViewMatrix( stereoEye ); param.Projection = camera.GetProjectionMatrix( stereoEye ); param.MaxParticles = 100; param.DeltaTime = gameTime.ElapsedSec; paramsCB.SetData( param ); device.VertexShaderConstants[0] = paramsCB ; device.GeometryShaderConstants[0] = paramsCB ; device.PixelShaderConstants[0] = paramsCB ; device.PixelShaderSamplers[0] = SamplerState.LinearWrap ; // // Simulate : // device.PipelineState = factory[ (int)Flags.SIMULATION ]; device.SetupVertexInput( simulationSrcVB, null ); device.SetupVertexOutput( simulationDstVB, 0 ); device.DrawAuto(); // // Inject : // injectionVB.SetData( injectionBufferCPU ); device.PipelineState = factory[ (int)Flags.INJECTION ]; device.SetupVertexInput( injectionVB, null ); device.SetupVertexOutput( simulationDstVB, -1 ); device.Draw(injectionCount, 0 ); SwapParticleBuffers(); // // Render // paramsCB.SetData( param ); device.VertexShaderConstants[0] = paramsCB ; device.GeometryShaderConstants[0] = paramsCB ; device.PixelShaderConstants[0] = paramsCB ; device.PipelineState = factory[ (int)Flags.RENDER ]; device.PixelShaderResources[0] = null; device.SetupVertexOutput( null, 0 ); device.SetupVertexInput( simulationSrcVB, null ); //device.Draw( Primitive.PointList, injectionCount, 0 ); device.DrawAuto(); //device.Draw( Primitive.PointList, MaxSimulatedParticles, 0 ); ClearParticleBuffer(); }
/// <summary> /// /// </summary> public void Render ( RenderTargetSurface colorBuffer, Camera camera ) { DrawTracers(); if (!vertexDataAccum.Any()) { return; } var dev = Game.GraphicsDevice; dev.ResetStates(); dev.SetTargets( null, colorBuffer ); constData.Transform = camera.GetViewMatrix(StereoEye.Mono) * camera.GetProjectionMatrix(StereoEye.Mono); constBuffer.SetData(constData); dev.SetupVertexInput( vertexBuffer, null ); dev.VertexShaderConstants[0] = constBuffer ; dev.PipelineState = factory[0]; int numDPs = MathUtil.IntDivUp(vertexDataAccum.Count, vertexBufferSize); for (int i = 0; i < numDPs; i++) { int numVerts = i < numDPs - 1 ? vertexBufferSize : vertexDataAccum.Count % vertexBufferSize; if (numVerts == 0) { break; } vertexDataAccum.CopyTo(i * vertexBufferSize, vertexArray, 0, numVerts); vertexBuffer.SetData(vertexArray, 0, numVerts); dev.Draw( numVerts, 0); } vertexDataAccum.Clear(); }
/// <summary> /// /// </summary> /// <param name="view"></param> /// <param name="projection"></param> internal void RenderLighting ( StereoEye stereoEye, Camera camera, HdrFrame hdrFrame, RenderWorld viewLayer, RenderTargetCube envLight ) { using ( new PixEvent("TiledLighting") ) { var view = camera.GetViewMatrix( stereoEye ); var projection = camera.GetProjectionMatrix( stereoEye ); var device = Game.GraphicsDevice; device.ResetStates(); var width = hdrFrame.HdrBuffer.Width; var height = hdrFrame.HdrBuffer.Height; ICSMController csmCtrl = viewLayer.LightSet.DirectLight.CSMController ?? csmController; int activeCascadeCount = Math.Min( cascadedShadowMap.CascadeCount, csmCtrl.GetActiveCascadeCount() ); // // Setup compute shader parameters and states : // try { var cbData = new LightingParams(); var invView = Matrix.Invert( view ); var invVP = Matrix.Invert( view * projection ); var viewPos = invView.TranslationVector; cbData.DirectLightDirection = new Vector4( viewLayer.LightSet.DirectLight.Direction, 0 ); cbData.DirectLightIntensity = viewLayer.LightSet.DirectLight.Intensity.ToVector4(); cbData.Projection = projection; cbData.CSMViewProjection0 = csmCtrl.GetShadowViewMatrix(0) * csmCtrl.GetShadowProjectionMatrix(0); cbData.CSMViewProjection1 = csmCtrl.GetShadowViewMatrix(1) * csmCtrl.GetShadowProjectionMatrix(1); cbData.CSMViewProjection2 = csmCtrl.GetShadowViewMatrix(2) * csmCtrl.GetShadowProjectionMatrix(2); cbData.CSMViewProjection3 = csmCtrl.GetShadowViewMatrix(3) * csmCtrl.GetShadowProjectionMatrix(3); cbData.View = view; cbData.ViewPosition = new Vector4(viewPos,1); cbData.InverseViewProjection = invVP; cbData.CSMFilterRadius = new Vector4( CSMFilterSize ); cbData.AmbientColor = viewLayer.LightSet.AmbientLevel; cbData.Viewport = new Vector4( 0, 0, width, height ); cbData.ShowCSLoadOmni = ShowOmniLightTileLoad ? 1 : 0; cbData.ShowCSLoadEnv = ShowEnvLightTileLoad ? 1 : 0; cbData.ShowCSLoadSpot = ShowSpotLightTileLoad ? 1 : 0; cbData.CascadeCount = activeCascadeCount; cbData.CascadeScale = 1.0f / (float)cascadedShadowMap.CascadeCount; ComputeOmniLightsTiles( view, projection, viewLayer.LightSet ); ComputeSpotLightsTiles( view, projection, viewLayer.LightSet ); ComputeEnvLightsTiles( view, projection, viewLayer.LightSet ); // // set states : // device.SetTargets( null, hdrFrame.HdrBuffer.Surface ); lightingCB.SetData( cbData ); device.ComputeShaderSamplers[0] = SamplerState.PointClamp; device.ComputeShaderSamplers[1] = SamplerState.LinearClamp; device.ComputeShaderSamplers[2] = SamplerState.ShadowSampler; device.ComputeShaderSamplers[3] = SamplerState.LinearPointWrap; device.ComputeShaderResources[0] = hdrFrame.DiffuseBuffer; device.ComputeShaderResources[1] = hdrFrame.SpecularBuffer; device.ComputeShaderResources[2] = hdrFrame.NormalMapBuffer; device.ComputeShaderResources[3] = hdrFrame.ScatteringBuffer; device.ComputeShaderResources[4] = hdrFrame.DepthBuffer; device.ComputeShaderResources[5] = cascadedShadowMap.ColorBuffer; device.ComputeShaderResources[6] = spotColor; device.ComputeShaderResources[7] = viewLayer.LightSet.SpotAtlas==null ? rs.WhiteTexture.Srv : viewLayer.LightSet.SpotAtlas.Texture.Srv; device.ComputeShaderResources[8] = omniLightBuffer; device.ComputeShaderResources[9] = spotLightBuffer; device.ComputeShaderResources[10] = envLightBuffer; device.ComputeShaderResources[11] = rs.SsaoFilter.OcclusionMap; device.ComputeShaderResources[12] = viewLayer.RadianceCache; device.ComputeShaderResources[13] = viewLayer.ParticleSystem.SimulatedParticles; device.ComputeShaderResources[14] = cascadedShadowMap.ParticleShadow; device.ComputeShaderConstants[0] = lightingCB; device.SetCSRWTexture( 0, hdrFrame.LightAccumulator.Surface ); device.SetCSRWTexture( 1, hdrFrame.SSSAccumulator.Surface ); device.SetCSRWBuffer( 2, viewLayer.ParticleSystem.ParticleLighting ); // // Dispatch solids : // using (new PixEvent("Solid Lighting")) { device.PipelineState = factory[ (int)LightingFlags.SOLIDLIGHTING ]; device.Dispatch( MathUtil.IntDivUp( width, BlockSizeX ), MathUtil.IntDivUp( height, BlockSizeY ), 1 ); } // // Dispatch particles : // using (new PixEvent("Particle Lighting")) { if (stereoEye!=StereoEye.Right) { int threadGroupCount = MathUtil.IntDivUp( ParticleSystem.MaxSimulatedParticles, ParticleSystem.BlockSize ); device.PipelineState = factory[ (int)LightingFlags.PARTICLES ]; device.Dispatch( threadGroupCount, 1, 1 ); } } } catch ( UbershaderException e ) { Log.Warning("{0}", e.Message ); } // // Add accumulated light : // rs.Filter.OverlayAdditive( hdrFrame.HdrBuffer.Surface, hdrFrame.LightAccumulator ); // Uncomment to enable SSS : #if false rs.Filter.GaussBlur( hdrFrame.SSSAccumulator, hdrFrame.LightAccumulator, 5, 0 ); rs.Filter.OverlayAdditive( hdrFrame.HdrBuffer.Surface, hdrFrame.SSSAccumulator ); #endif device.ResetStates(); if (rs.ShowLightCounters) { var ls = viewLayer.LightSet; Log.Message("lights: {0,5} omni {1,5} spot {2,5} env", ls.OmniLights.Count, ls.SpotLights.Count, ls.EnvLights.Count ); } } }
/// <summary> /// /// </summary> /// <param name="gameTime"></param> public void RenderRadiance () { var sw = new Stopwatch(); Log.Message("Radiance capture..."); sw.Start(); using (new PixEvent("Capture Radiance")) { var sun = SkySettings.SunGlowIntensity; SkySettings.SunGlowIntensity = 0; int index = 0; foreach ( var envLight in LightSet.EnvLights ) { for (int i=0; i<6; i++) { ClearBuffers( radianceFrame ); var camera = new Camera(); camera.SetupCameraCubeFace( envLight.Position, (CubeFace)i, 0.125f, 5000 ); // render g-buffer : rs.SceneRenderer.RenderGBuffer( StereoEye.Mono, camera, radianceFrame, this ); // render sky : rs.Sky.Render( camera, StereoEye.Mono, radianceFrame, SkySettings ); // render lights : rs.LightRenderer.RenderLighting( StereoEye.Mono, camera, radianceFrame, this, rs.Sky.SkyCube ); // downsample captured frame to cube face. rs.Filter.StretchRect4x4( Radiance.GetSurface( 0, (CubeFace)i ), radianceFrame.HdrBuffer, SamplerState.LinearClamp, true ); // prefilter cubemap : rs.Filter.PrefilterEnvMap( Radiance ); } RadianceCache.CopyFromRenderTargetCube( index, Radiance ); index ++; } sw.Stop(); SkySettings.SunGlowIntensity = sun; } Log.Message("{0} light probes - {1} ms", LightSet.EnvLights.Count, sw.ElapsedMilliseconds); }