Ejemplo n.º 1
0
        public void Render()
        {
            // Update hulls internal data structures.
            Hulls.Update();

            // We want to use clamping sampler state throughout the lightmap rendering process.
            // This is required when drawing lights. Since light rendering and alpha clearing is done
            // in a single step, light is rendered with slightly larger quad where tex coords run out of the [0..1] range.
            Device.SamplerStates[0] = SamplerState.LinearClamp;

            // Switch render target to lightmap.
            Device.SetRenderTargets(Textures.LightmapBindings);

            // Clear lightmap color, depth and stencil data.
            Device.Clear(ClearOptions.DepthBuffer | ClearOptions.Stencil | ClearOptions.Target, _ambientColor, 1f, 0);

            // Set per frame shader data.
            ShadowRenderer.PreRender();

            // Generate lightmap. For each light, mask the shadowed areas determined by hulls and render light.
            int lightCount = Lights.Count;

            for (int i = 0; i < lightCount; i++)
            {
                Light light = Lights[i];

                // Continue only if light is enabled and not inside any hull.
                if (!light.Enabled || Hulls.Contains(light))
                {
                    continue;
                }

                // Update light's internal data structures.
                light.Update();

                // Continue only if light is within camera view.
                if (!light.Intersects(Camera))
                {
                    continue;
                }

                // Set scissor rectangle to clip any shadows outside of light's range.
                BoundingRectangle scissor;
                Camera.GetScissorRectangle(light, out scissor);
                Device.SetScissorRectangle(ref scissor);

                // Mask shadowed areas by reducing alpha.
                ShadowRenderer.Render(light);

                // Draw light and clear alpha (reset it to 1 [fully lit] for next light).
                LightRenderer.Render(light);

                // Clear light's dirty flag.
                light.Dirty = false;
            }

            // Switch render target back to default.
            Device.SetRenderTargets(Textures.GetOriginalRenderTargetBindings());

            // Blend original scene and lightmap and present to backbuffer.
            LightMapRenderer.Present();

            // Clear hulls dirty flag.
            Hulls.Dirty = false;
        }
Ejemplo n.º 2
0
        //--------------------------------------------------------------
        #region Methods
        //--------------------------------------------------------------

        public void Render(IList <SceneNode> lights, RenderContext context)
        {
            var graphicsService  = context.GraphicsService;
            var graphicsDevice   = graphicsService.GraphicsDevice;
            var renderTargetPool = graphicsService.RenderTargetPool;

            var target   = context.RenderTarget;
            var viewport = context.Viewport;
            var width    = viewport.Width;
            var height   = viewport.Height;

            RenderTarget2D aoRenderTarget = null;

            if (_ssaoFilter != null)
            {
                // Render ambient occlusion info into a render target.
                aoRenderTarget = renderTargetPool.Obtain2D(new RenderTargetFormat(
                                                               width / _ssaoDownsampleFactor,
                                                               height / _ssaoDownsampleFactor,
                                                               false,
                                                               SurfaceFormat.Color,
                                                               DepthFormat.None));

                // PostProcessors require that context.SourceTexture is set. But since
                // _ssaoFilter.CombineWithSource is set to false, the SourceTexture is not
                // used and we can set it to anything except null.
                context.SourceTexture = aoRenderTarget;
                context.RenderTarget  = aoRenderTarget;
                context.Viewport      = new Viewport(0, 0, aoRenderTarget.Width, aoRenderTarget.Height);
                _ssaoFilter.Process(context);
                context.SourceTexture = null;
            }

            // The light buffer consists of two full-screen render targets into which we
            // render the accumulated diffuse and specular light intensities.
            var lightBufferFormat = new RenderTargetFormat(width, height, false, SurfaceFormat.HdrBlendable, DepthFormat.Depth24Stencil8);

            context.LightBuffer0 = renderTargetPool.Obtain2D(lightBufferFormat);
            context.LightBuffer1 = renderTargetPool.Obtain2D(lightBufferFormat);

            // Set the device render target to the light buffer.
            _renderTargetBindings[0] = new RenderTargetBinding(context.LightBuffer0); // Diffuse light accumulation
            _renderTargetBindings[1] = new RenderTargetBinding(context.LightBuffer1); // Specular light accumulation
            graphicsDevice.SetRenderTargets(_renderTargetBindings);
            context.RenderTarget = context.LightBuffer0;
            context.Viewport     = graphicsDevice.Viewport;

            // Clear the light buffer. (The alpha channel is not used. We can set it to anything.)
            graphicsDevice.Clear(new Color(0, 0, 0, 255));

            // Restore the depth buffer (which XNA destroys in SetRenderTarget).
            // (This is only needed if lights can use a clip geometry (LightNode.Clip).)
            var rebuildZBufferRenderer = (RebuildZBufferRenderer)context.Data[RenderContextKeys.RebuildZBufferRenderer];

            rebuildZBufferRenderer.Render(context, true);

            // Render all lights into the light buffers.
            LightRenderer.Render(lights, context);

            if (aoRenderTarget != null)
            {
                // Render the ambient occlusion texture using multiplicative blending.
                // This will darken the light buffers depending on the ambient occlusion term.
                // Note: Theoretically, this should be done after the ambient light renderer
                // and before the directional light renderer because AO should not affect
                // directional lights. But doing this here has more impact.
                context.SourceTexture     = aoRenderTarget;
                graphicsDevice.BlendState = GraphicsHelper.BlendStateMultiply;
                _copyFilter.Process(context);
            }

            // Clean up.
            graphicsService.RenderTargetPool.Recycle(aoRenderTarget);
            context.SourceTexture = null;
            context.RenderTarget  = target;
            context.Viewport      = viewport;

            _renderTargetBindings[0] = new RenderTargetBinding();
            _renderTargetBindings[1] = new RenderTargetBinding();
        }