private void RenderOverlays() { PIXHelper.BeginEvent("Render overlays"); foreach (Renderable renderable in overlays) { Debug.Assert(renderable.RenderMode == RenderMode.RenderOverlays); renderable.Draw(this); } PIXHelper.EndEvent(); }
private void RenderParticles() { //transparentRenderables.Sort(TransparentRenderableComparison); PIXHelper.BeginEvent("Render particles"); foreach (Renderable renderable in transparentRenderables) { Debug.Assert(renderable.RenderMode == RenderMode.RenderToSceneAlpha); renderable.Draw(this); } PIXHelper.BeginEvent("Render lava fires"); if (explosionSystem != null) { explosionSystem.Render(lastFrameTime, currentFrameTime); } PIXHelper.EndEvent(); PIXHelper.BeginEvent("Render Snow"); if (snowSystem != null) { snowSystem.Render(lastFrameTime, currentFrameTime); } PIXHelper.EndEvent(); PIXHelper.BeginEvent("Render ice explosion"); if (iceExplosionSystem != null) { iceExplosionSystem.Render(Time.PausableLast / 1000d, Time.PausableAt / 1000d); } PIXHelper.EndEvent(); PIXHelper.BeginEvent("Render robot explosion"); if (fireExplosionSystem != null) { fireExplosionSystem.Render(Time.PausableLast / 1000d, Time.PausableAt / 1000d); } PIXHelper.EndEvent(); PIXHelper.BeginEvent("Render flamethrower"); if (flamethrowerSystem != null) { flamethrowerSystem.Render(Time.PausableLast / 1000d, Time.PausableAt / 1000d); } PIXHelper.EndEvent(); PIXHelper.BeginEvent("Render ice spike"); if (iceSpikeSystem != null) { iceSpikeSystem.Render(Time.PausableLast / 1000d, Time.PausableAt / 1000d); } PIXHelper.EndEvent(); PIXHelper.EndEvent(); }
/// <summary> /// If regular foward rendering is being used for transparents, this method is called /// and renders the transparents /// </summary> private void DrawTransparents() { PIXHelper.BeginEvent("Draw Transparents Pass"); List <Vector3> lightPositions = new List <Vector3>(); List <float> lightRanges = new List <float>(); List <Vector3> lightColors = new List <Vector3>(); foreach (Light light in lights) { if (light is PointLight) { PointLight pointLight = (PointLight)light; lightPositions.Add(Vector3.Transform(pointLight.Position, camera.ViewMatrix)); lightRanges.Add(pointLight.Range); lightColors.Add(pointLight.Color); } else if (light is DirectionalLight) { DirectionalLight directionalLight = (DirectionalLight)light; Vector3 lightDirVS = Vector3.TransformNormal(directionalLight.Direction, camera.ViewMatrix); transparentEffect.Parameters["LightDirVS"].SetValue(Vector3.Normalize(lightDirVS)); transparentEffect.Parameters["LightColor"].SetValue(light.Color); } } transparentEffect.Parameters["LightPositionsVS"].SetValue(lightPositions.ToArray()); transparentEffect.Parameters["LightRanges"].SetValue(lightRanges.ToArray()); transparentEffect.Parameters["LightColors"].SetValue(lightColors.ToArray()); transparentEffect.Parameters["AmbientColor"].SetValue(AmbientLight); transparentEffect.Parameters["EnablePointLights"].SetValue(enablePointLights); transparentEffect.Parameters["ViewToLight"].SetValue(camera.WorldMatrix * lightCam.ViewProjectionMatrix); transparentEffect.Parameters["ShadowMapTexture"].SetValue(shadowMap.GetTexture()); transparentEffect.Parameters["ShadowMapDimensions"].SetValue(new Vector2((int)shadowMapSize)); if (enableNormalMaps) { transparentEffect.CurrentTechnique = transparentEffect.Techniques["TransparentNM"]; } else { transparentEffect.CurrentTechnique = transparentEffect.Techniques["Transparent"]; } foreach (ModelInstance instance in sortedTransparents) { instance.Draw(GraphicsDevice, transparentEffect, camera); } PIXHelper.EndEvent(); }
/// <summary> /// Draws all opaque instances to the shadow map /// </summary> private void DrawShadowMap() { PIXHelper.BeginEvent("Draw ShadowMap"); GraphicsDevice.SetRenderTarget(0, shadowMap); GraphicsDevice.DepthStencilBuffer = shadowMapDS; GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer | ClearOptions.Stencil, Vector4.One, 1.0f, 0); foreach (ModelInstance instance in opaques) { instance.Draw(GraphicsDevice, shadowMapEffect, lightCam); } PIXHelper.EndEvent(); }
private void RenderScene() { PIXHelper.BeginEvent("Render Scene"); if (EnablePostProcessing) { Device.SetRenderTargets(targetOpaqueColorBuffer, targetOpaqueRenderChannels, targetOpaqueDepth); } // clear the render targets Device.Clear(Color.White); // make sure to disable blending. XNA does not like alpha blending on floating point surfaces. And // it looks like it does not set them correctly when specified in .fx files. just disable it to make sure // that everything works as it should! Device.BlendState = BlendState.Opaque; foreach (Renderable renderable in opaqueRenderables) { Debug.Assert(renderable.RenderMode == RenderMode.RenderToScene); renderable.Draw(this); } if (EnablePostProcessing) { Device.SetRenderTargets(null); } //Texture2D texture = TargetDepth.GetTexture(); //float[] pixelData = new float[texture.Width * texture.Height]; //texture.GetData(pixelData, 0, texture.Width * texture.Height); //Console.WriteLine("start"); //for (int i = 0; i < texture.Width * texture.Height; i++) // if (pixelData[i] != 0.0f) // { // float g = pixelData[i]; // Console.WriteLine(g); // } //Console.WriteLine("end"); //int a = 0; PIXHelper.EndEvent(); }
public void Render( Texture2D hdrColorBuffer, Texture2D renderChannelBuffer, RenderTarget2D targetIntermediateBlurredHDRColorBuffer, RenderTarget2D targetIntermediateBlurredRenderChannelBuffer, RenderTarget2D targetBlurredHDRColorBuffer, RenderTarget2D targetBlurredRenderChannelBuffer ) { // pass 1 horizontal blur PIXHelper.BeginEvent("Horizontal Blur"); SetBlurEffectParameters( 1.0f / hdrColorBuffer.Width, 0, hdrColorBuffer, renderChannelBuffer ); DrawFullscreenQuad( hdrColorBuffer, targetIntermediateBlurredHDRColorBuffer, targetIntermediateBlurredRenderChannelBuffer, gaussianBlurEffect ); PIXHelper.EndEvent(); // result Texture2D intermediateBlurredHDRColorBuffer = targetIntermediateBlurredHDRColorBuffer; Texture2D intermediateBlurredRenderChannelBuffer = targetIntermediateBlurredRenderChannelBuffer; // pass 2 vertical blurr PIXHelper.BeginEvent("Vertical Blur"); SetBlurEffectParameters( 0, 1.0f / hdrColorBuffer.Height, intermediateBlurredHDRColorBuffer, intermediateBlurredRenderChannelBuffer ); DrawFullscreenQuad( intermediateBlurredHDRColorBuffer, targetBlurredHDRColorBuffer, targetBlurredRenderChannelBuffer, gaussianBlurEffect ); PIXHelper.EndEvent(); }
private void UpdateParticles( double currentFrameTime, int nextTexture ) { PIXHelper.BeginEvent("Update particles"); particleUpdateEffect.Parameters["View"].SetValue(renderer.Camera.View); particleUpdateEffect.Parameters["Projection"].SetValue(renderer.Camera.Projection); particleUpdateEffect.Parameters["StartSize"].SetValue(new Vector2(5.0f, 10.0f)); particleUpdateEffect.Parameters["EndSize"].SetValue(new Vector2(50.0f, 200.0f)); particleUpdateEffect.Parameters["MinColor"].SetValue(Vector4.One); particleUpdateEffect.Parameters["MaxColor"].SetValue(Vector4.One); particleUpdateEffect.Parameters["ViewportHeight"].SetValue(device.Viewport.Height); particleUpdateEffect.Parameters["ViewportWidth"].SetValue(device.Viewport.Width); particleUpdateEffect.Parameters["Time"].SetValue((float)currentFrameTime); particleUpdateEffect.Parameters["Dt"].SetValue((float)SimulationStep); particleUpdateEffect.Parameters["PositionTexture"].SetValue(positionTextures[activeTexture]); particleUpdateEffect.Parameters["VelocityTexture"].SetValue(velocityTextures[activeTexture]); particleUpdateEffect.Parameters["RandomTexture"].SetValue(renderer.VectorCloudTexture); particleUpdateEffect.Parameters["SpriteTexture"].SetValue(spriteTexture); if (particleUpdateEffect.Parameters["ViewportSize"] != null) { particleUpdateEffect.Parameters["ViewportSize"].SetValue(new Vector2(positionTextures[nextTexture].Width, positionTextures[nextTexture].Height)); } SetUpdateParameters(particleUpdateEffect.Parameters); Texture2D positionTexture = positionTextures[activeTexture]; // TODO: fix rendering code! spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.Opaque, SamplerState.PointClamp, null, null, particleUpdateEffect); spriteBatch.Draw(positionTexture, new Rectangle(0, 0, positionTexture.Width, positionTexture.Height), Color.White); spriteBatch.End(); PIXHelper.EndEvent(); }
public void Render() { PIXHelper.BeginEvent("Render Frame"); renderTime.Update(); //Console.WriteLine("rendering {0}", renderTime.PausableAt); Game.Instance.Profiler.BeginSection("beginning_stuff"); Update(); LightManager.Update(this); device.Clear(Color.White); // 1) Set the light's render target device.SetRenderTargets(lightRenderTarget); Game.Instance.Profiler.EndSection("beginning_stuff"); Game.Instance.Profiler.BeginSection("rendering"); // 2) Render the scene from the perspective of the light Game.Instance.Profiler.BeginSection("renderer_shadow"); RenderShadow(); Game.Instance.Profiler.EndSection("renderer_shadow"); // 3) Set our render target back to the screen, and get the //depth texture created by step 2 Game.Instance.Profiler.BeginSection("change_render_target"); device.SetRenderTargets(null); lightResolve = lightRenderTarget; Game.Instance.Profiler.EndSection("change_render_target"); // 4) Render the scene from the view of the camera, //and do depth comparisons in the shader to determine shadowing Game.Instance.Profiler.BeginSection("renderer_scene"); RenderScene(); Game.Instance.Profiler.EndSection("renderer_scene"); // TODO: alpha blended objects... bool hasAlphaObjects = false;// transparentRenderablesTEST.Count > 0; Game.Instance.Profiler.BeginSection("render_scene_alpha"); if (hasAlphaObjects) { RenderSceneAlpha(); } Game.Instance.Profiler.EndSection("render_scene_alpha"); if (EnablePostProcessing) { Game.Instance.Profiler.BeginSection("postprocessing"); PIXHelper.BeginEvent("PostProcessing"); // downscaling is done as part of the blur during the glow-pass if (hasAlphaObjects) { Game.Instance.Profiler.BeginSection("combine"); combinePass.Render(targetOpaqueColorBuffer, targetAlphaColorBuffer, targetHDRColorBuffer); combinePass.Render(targetOpaqueRenderChannels, targetAlphaRenderChannels, targetRenderChannels); combineDepthPass.Render(targetOpaqueDepth, targetAlphaDepth, targetDepth); Game.Instance.Profiler.EndSection("combine"); Game.Instance.Profiler.BeginSection("renderer_post_glow"); glowPass.Render( targetHDRColorBuffer, targetRenderChannels, targetHorizontalBlurredHDRColorBuffer, targetHorizontalBlurredRenderChannels, targetBlurredHDRColorBuffer, targetBlurredRenderChannels ); Game.Instance.Profiler.EndSection("renderer_post_glow"); // FIXME: do we really need to downscale and blur the renderchannels? we don't use // the blurred version. Game.Instance.Profiler.BeginSection("renderer_post_hdr"); hdrCombinePass.Render( targetHDRColorBuffer, targetBlurredHDRColorBuffer, targetRenderChannels, targetDepth ); Game.Instance.Profiler.EndSection("renderer_post_hdr"); } else { Game.Instance.Profiler.BeginSection("renderer_post_glow"); PIXHelper.BeginEvent("Glow Pass"); glowPass.Render( targetOpaqueColorBuffer, targetOpaqueRenderChannels, targetHorizontalBlurredHDRColorBuffer, targetHorizontalBlurredRenderChannels, targetBlurredHDRColorBuffer, targetBlurredRenderChannels ); PIXHelper.EndEvent(); Game.Instance.Profiler.EndSection("renderer_post_glow"); // FIXME: do we really need to downscale and blur the renderchannels? we don't use // the blurred version. Game.Instance.Profiler.BeginSection("renderer_post_hdr"); PIXHelper.BeginEvent("HDR Combine Pass"); hdrCombinePass.Render( targetOpaqueColorBuffer, targetBlurredHDRColorBuffer, targetOpaqueRenderChannels, targetOpaqueDepth ); PIXHelper.EndEvent(); Game.Instance.Profiler.EndSection("renderer_post_hdr"); } PIXHelper.EndEvent(); Game.Instance.Profiler.EndSection("postprocessing"); } RenderParticles(); RenderSceneAfterPost(); Game.Instance.Profiler.EndSection("rendering"); // 6) Render overlays Game.Instance.Profiler.BeginSection("overlay"); RenderOverlays(); Game.Instance.Profiler.EndSection("overlay"); PIXHelper.EndEvent(); }
private void Update() { if (Camera != null) { // should only be called if a level has already been loaded Camera.Update(this); Camera.RecomputeFrame(ref opaqueRenderables); } RendererUpdateQueue q = GetNextUpdateQueue(); while (q != null) { for (int i = 0; i < q.Count; ++i) { q[i].Apply(q.Timestamp); } q = GetNextUpdateQueue(); } foreach (Renderable renderable in updateRenderables) { renderable.Update(this); } Game.Instance.Profiler.BeginSection("particle_systems"); PIXHelper.BeginEvent("Update Particles"); PIXHelper.BeginEvent("Update lava flames"); Game.Instance.Profiler.BeginSection("explosion_system"); if (explosionSystem != null) { explosionSystem.Update(Time.Last / 1000d, Time.At / 1000d); } Game.Instance.Profiler.EndSection("explosion_system"); PIXHelper.EndEvent(); PIXHelper.BeginEvent("Update snow"); Game.Instance.Profiler.BeginSection("snow_system"); if (snowSystem != null) { snowSystem.Update(Time.Last / 1000d, Time.At / 1000d); } Game.Instance.Profiler.EndSection("snow_system"); PIXHelper.EndEvent(); PIXHelper.BeginEvent("Update ice explosions"); Game.Instance.Profiler.BeginSection("ice_explosion_system"); if (iceExplosionSystem != null) { iceExplosionSystem.Update(Time.PausableLast / 1000d, Time.PausableAt / 1000d); } Game.Instance.Profiler.EndSection("ice_explosion_system"); PIXHelper.EndEvent(); PIXHelper.BeginEvent("Update fire explosions"); Game.Instance.Profiler.BeginSection("fire_explosion_system"); if (fireExplosionSystem != null) { fireExplosionSystem.Update(Time.PausableLast / 1000d, Time.PausableAt / 1000d); } Game.Instance.Profiler.EndSection("fire_explosion_system"); PIXHelper.EndEvent(); PIXHelper.BeginEvent("Update flamethrowers"); Game.Instance.Profiler.BeginSection("flamethrower_system"); if (flamethrowerSystem != null) { flamethrowerSystem.Update(Time.PausableLast / 1000d, Time.PausableAt / 1000d); } Game.Instance.Profiler.EndSection("flamethrower_system"); PIXHelper.EndEvent(); PIXHelper.BeginEvent("Update ice spikes"); Game.Instance.Profiler.BeginSection("ice_spike_system"); if (iceSpikeSystem != null) { iceSpikeSystem.Update(Time.PausableLast / 1000d, Time.PausableAt / 1000d); } Game.Instance.Profiler.EndSection("ice_spike_system"); PIXHelper.EndEvent(); PIXHelper.EndEvent(); Game.Instance.Profiler.EndSection("particle_systems"); }
/// <summary> /// Renders the composite pass, where instances a re-rendered and sample the /// L-Buffer to determine the lighting value that should be applied. /// </summary> private void DrawCompositePass() { PIXHelper.BeginEvent("Draw Composite Pass"); GraphicsDevice.SetRenderTarget(0, colorBuffer); GraphicsDevice.DepthStencilBuffer = msaaDS; GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer | ClearOptions.Stencil, Color.Black, 1.0f, 0); compositeEffect.Parameters["GBufferDimensions"].SetValue(gBufferDimensions); compositeEffect.Parameters["RTDimensions"].SetValue(new Vector2(ScreenWidth, ScreenHeight)); compositeEffect.Parameters["AmbientColor"].SetValue(AmbientLight); compositeEffect.Parameters["LightTexture"].SetValue(lightBuffer.GetTexture()); compositeEffect.Parameters["DepthIDTexture"].SetValue(depthIDBuffer.GetTexture()); compositeEffect.Parameters["Alpha"].SetValue(1.0f); PIXHelper.BeginEvent("Opaques"); // Draw the opaques if (gBufferSize == GBufferSize.FullSize && transparencyMode == TransparencyMode.ForwardRendered) { compositeEffect.CurrentTechnique = compositeEffect.Techniques["CompositeOpaque"]; } else { compositeEffect.CurrentTechnique = compositeEffect.Techniques["CompositeOpaqueFiltered"]; } int instanceID = 1; foreach (ModelInstance instance in opaques) { compositeEffect.Parameters["InstanceID"].SetValue(instanceID); instance.Draw(GraphicsDevice, compositeEffect, camera); ++instanceID; } PIXHelper.EndEvent(); if (transparencyMode == TransparencyMode.ForwardRendered) { PIXHelper.EndEvent(); return; } PIXHelper.BeginEvent("Transparents"); compositeEffect.CurrentTechnique = compositeEffect.Techniques["CompositeTransparent"]; compositeEffect.Parameters["Alpha"].SetValue(0.5f); foreach (ModelInstance instance in sortedTransparents) { compositeEffect.Parameters["InstanceID"].SetValue(instanceID); compositeEffect.Parameters["XFilterOffsets"].SetValue(XFilterOffsets[instanceID % NumMasks]); compositeEffect.Parameters["YFilterOffsets"].SetValue(YFilterOffsets[instanceID % NumMasks]); instance.Draw(GraphicsDevice, compositeEffect, camera); ++instanceID; } PIXHelper.EndEvent(); PIXHelper.EndEvent(); }
/// <summary> /// Renders the lighting pass by rendering all lights to the L-Buffer /// </summary> private void DrawLights() { PIXHelper.BeginEvent("Draw Lights"); GraphicsDevice.SetRenderTarget(0, lightBuffer); GraphicsDevice.SetRenderTarget(1, null); GraphicsDevice.Clear(ClearOptions.Target, Vector4.Zero, 1.0f, 0); lightEffect.Parameters["FarClip"].SetValue(camera.FarClip); lightEffect.Parameters["GBufferDimensions"].SetValue(gBufferDimensions); lightEffect.Parameters["DepthIDTexture"].SetValue(depthIDBuffer.GetTexture()); lightEffect.Parameters["NormalSpecTexture"].SetValue(normalSpecularBuffer.GetTexture()); foreach (Light light in lights) { lightEffect.Parameters["LightColor"].SetValue(light.Color); if (light is PointLight && enablePointLights) { PointLight pointLight = (PointLight)light; Matrix worldMatrix = Matrix.CreateScale(pointLight.Range) * Matrix.CreateTranslation(pointLight.Position); lightEffect.Parameters["WorldView"].SetValue(worldMatrix * camera.ViewMatrix); lightEffect.Parameters["WorldViewProjection"].SetValue(worldMatrix * camera.ViewProjectionMatrix); lightEffect.Parameters["LightRange"].SetValue(pointLight.Range); lightEffect.Parameters["LightPosVS"].SetValue(Vector3.Transform(pointLight.Position, camera.ViewMatrix)); // For our light volume we'll want to render front faces if the volume intersects // our far clipping plane, or back faces otherwise. float lightDepth = -Vector3.Transform(pointLight.Position, camera.ViewMatrix).Z; if (lightDepth > camera.FarClip - pointLight.Range) { lightEffect.CurrentTechnique = lightEffect.Techniques["PointLightFront"]; } else { lightEffect.CurrentTechnique = lightEffect.Techniques["PointLightBack"]; } lightEffect.Begin(SaveStateMode.None); lightEffect.CurrentTechnique.Passes[0].Begin(); ModelMesh mesh = lightSphere.Meshes[0]; ModelMeshPart meshPart = mesh.MeshParts[0]; GraphicsDevice.Indices = mesh.IndexBuffer; GraphicsDevice.VertexDeclaration = meshPart.VertexDeclaration; GraphicsDevice.Vertices[0].SetSource(mesh.VertexBuffer, meshPart.StreamOffset, meshPart.VertexStride); GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, meshPart.BaseVertex, 0, meshPart.NumVertices, meshPart.StartIndex, meshPart.PrimitiveCount); lightEffect.CurrentTechnique.Passes[0].End(); lightEffect.End(); } else if (light is DirectionalLight) { DirectionalLight directionalLight = (DirectionalLight)light; // Do shadow mapping first DrawShadowMap(); // Now draw the directional light GraphicsDevice.SetRenderTarget(0, lightBuffer); GraphicsDevice.DepthStencilBuffer = nonMSAADS; lightEffect.Parameters["ShadowMapTexture"].SetValue(shadowMap.GetTexture()); lightEffect.Parameters["ViewToLight"].SetValue(camera.WorldMatrix * lightCam.ViewProjectionMatrix); lightEffect.Parameters["ShadowMapDimensions"].SetValue(new Vector2((int)shadowMapSize)); Vector3 lightDirVS = Vector3.TransformNormal(directionalLight.Direction, camera.ViewMatrix); lightEffect.Parameters["LightDirVS"].SetValue(Vector3.Normalize(lightDirVS)); // Get the frustum corners for position reconstruction Vector3[] cornersWS = camera.BoundingFrustum.GetCorners(); Vector3[] cornersVS = new Vector3[4]; for (int i = 0; i < 4; ++i) { cornersVS[i] = Vector3.Transform(cornersWS[i + 4], camera.ViewMatrix); } lightEffect.Parameters["FrustumCornersVS"].SetValue(cornersVS); lightEffect.CurrentTechnique = lightEffect.Techniques["DirectionalLight"]; lightEffect.Begin(SaveStateMode.None); lightEffect.CurrentTechnique.Passes[0].Begin(); quad.Draw(GraphicsDevice); lightEffect.CurrentTechnique.Passes[0].End(); lightEffect.End(); } } PIXHelper.EndEvent(); }
/// <summary> /// Draws all opaque instances to the G-Buffer, as well as transparents (if deferred mode /// is being used to render the transparents) /// </summary> private void DrawGBuffer() { PIXHelper.BeginEvent("Draw G-Buffer"); GraphicsDevice.SetRenderTarget(0, depthIDBuffer); GraphicsDevice.SetRenderTarget(1, normalSpecularBuffer); GraphicsDevice.DepthStencilBuffer = nonMSAADS; GraphicsDevice.Clear(ClearOptions.DepthBuffer | ClearOptions.Stencil | ClearOptions.Target, Vector4.Zero, 1.0f, 0); PIXHelper.BeginEvent("Opaques"); if (enableNormalMaps) { gBufferEffect.CurrentTechnique = gBufferEffect.Techniques["GBufferNM"]; } else { gBufferEffect.CurrentTechnique = gBufferEffect.Techniques["GBuffer"]; } // We'll make sure each instance has a unique ID by incrementing a variable // every time we render one. 0 is reserved for no instances, so we start // at one. int instanceID = 1; foreach (ModelInstance instance in opaques) { gBufferEffect.Parameters["InstanceID"].SetValue(instanceID); instance.Draw(GraphicsDevice, gBufferEffect, camera); ++instanceID; } PIXHelper.EndEvent(); if (transparencyMode == TransparencyMode.ForwardRendered) { PIXHelper.EndEvent(); return; } PIXHelper.BeginEvent("Transparents"); if (enableNormalMaps) { gBufferEffect.CurrentTechnique = gBufferEffect.Techniques["GBufferMaskNM"]; } else { gBufferEffect.CurrentTechnique = gBufferEffect.Techniques["GBufferMask"]; } foreach (ModelInstance instance in sortedTransparents) { // For each instance, rotate through our 3 output masks gBufferEffect.Parameters["OutputMask"].SetValue(OutputMasks[instanceID % NumMasks]); gBufferEffect.Parameters["InstanceID"].SetValue(instanceID); instance.Draw(GraphicsDevice, gBufferEffect, camera); ++instanceID; } PIXHelper.EndEvent(); PIXHelper.EndEvent(); }
private void CreateParticles( double lastFrameTime, double currentFrameTime, double dt ) { Game.Instance.Profiler.BeginSection("create_particles"); PIXHelper.BeginEvent("Create particles"); Game.Instance.Profiler.BeginSection("count"); Vector2 positionHalfPixel = new Vector2(1.0f / (2.0f * positionTextures[0].Width), 1.0f / (2.0f * positionTextures[0].Height)); Vector2 positionPixel = new Vector2(1.0f / (positionTextures[0].Width), 1.0f / (positionTextures[0].Height)); int[] particleCount = new int[emitters.Count]; int sumParticleCount = 0; for (int emitterIndex = 0; emitterIndex < emitters.Count; ++emitterIndex) { ParticleEmitter emitter = emitters[emitterIndex]; particleCount[emitterIndex] = emitter.CalculateParticleCount(lastFrameTime, currentFrameTime); sumParticleCount += particleCount[emitterIndex]; } Game.Instance.Profiler.EndSection("count"); // nothing to do if there are no new particles! if (sumParticleCount == 0) { PIXHelper.EndEvent(); Game.Instance.Profiler.EndSection("create_particles"); return; } Game.Instance.Profiler.BeginSection("allocate"); CreateVertexArray vertices = renderer.StatefulParticleResourceManager.AllocateCreateVertexArray(sumParticleCount * 3); Game.Instance.Profiler.EndSection("allocate"); Game.Instance.Profiler.BeginSection("create"); int maxindex = positionTextures[0].Width * positionTextures[0].Height; for (int i = 0; i < sumParticleCount; ++i) { if (nextParticleIndex >= maxindex) { nextParticleIndex = 0; } int textureSize = textureSizes[(int)GetSystemSize()]; int x = nextParticleIndex % textureSize; int y = nextParticleIndex / textureSize; Debug.Assert(textureSize == positionTextures[0].Width); Debug.Assert(textureSize == positionTextures[0].Height); Vector2[] offsets = { new Vector2(-1, -1), new Vector2(1, -1), new Vector2(0, 1) }; for (int j = 0; j < 3; ++j) { vertices.Array[i * 3 + j] = new CreateVertex( Vector3.Zero, Vector3.Zero, new Vector2( -1.0f + positionPixel.X + 2.0f * x * positionPixel.X + 2 * offsets[j].X * positionPixel.X, -1.0f + positionPixel.Y + 2.0f * y * positionPixel.Y + 2 * offsets[j].Y * positionPixel.Y ), new Short2( x, y ), 0 // emitterIndex ); } ++nextParticleIndex; } Game.Instance.Profiler.EndSection("create"); Game.Instance.Profiler.BeginSection("emit"); int vertexIndex = 0; for (int emitterIndex = 0; emitterIndex < emitters.Count; ++emitterIndex) { ParticleEmitter emitter = emitters[emitterIndex]; emitter.CreateParticles(lastFrameTime, currentFrameTime, vertices.Array, vertexIndex, particleCount[emitterIndex]); vertexIndex += particleCount[emitterIndex]; } Game.Instance.Profiler.EndSection("emit"); Game.Instance.Profiler.BeginSection("render"); int localCreateVerticesIndex = 0; int verticesCopied = 0; while (verticesCopied < vertices.OccupiedSize) { int passVerticesCount = vertices.OccupiedSize - verticesCopied; int passVerticesAvailable = createVertexBufferSize - localCreateVerticesIndex; if (passVerticesCount > passVerticesAvailable) { passVerticesCount = passVerticesAvailable; } for (int j = 0; j < passVerticesCount; ++j) { localCreateVertices[localCreateVerticesIndex + j] = vertices.Array[verticesCopied + j]; } verticesCopied += passVerticesCount; localCreateVerticesIndex += passVerticesCount; if (localCreateVerticesIndex >= createVertexBufferSize - createVertexBufferIndex) { FlushCreateParticles(verticesCopied, currentFrameTime, dt); localCreateVerticesIndex = 0; createVertexBufferIndex = 0; } } renderer.StatefulParticleResourceManager.FreeCreateVertexArray(vertices); if (localCreateVerticesIndex > 0) { FlushCreateParticles(localCreateVerticesIndex, currentFrameTime, dt); } Game.Instance.Profiler.EndSection("render"); PIXHelper.EndEvent(); Game.Instance.Profiler.EndSection("create_particles"); }