Пример #1
0
        /// <summary>
        /// Renders a light.
        /// </summary>
        /// <param name="light">The light.</param>
        void IRenderer.Render(Light light)
        {
            if (light == null)
            {
                throw new ArgumentNullException(nameof(light));
            }

            if (this.Phase == Phase.Lights)
            {
                this.lightShader.Use(light);

                if (light.Radius > 0)
                {
                    var radius = light.Radius * 1.1f; // <- Grow the sphere slightly so that it fully encloses the light radius.

                    const int Stacks = 8;
                    const int Slices = 8;

                    this.vertexBuffer.BeginTriangleStrip(Stacks * (Slices + 1) * 2);

                    for (var stack = 0; stack < Stacks; stack++)
                    {
                        for (var slice = 0; slice <= Slices; slice++)
                        {
                            for (var i = 0; i < 2; i++)
                            {
                                var s = slice / (float)Slices;
                                var t = (stack + i) / (float)Stacks;

                                var sa = s * Math.PI * 2;
                                var ta = (t * Math.PI) - (Math.PI / 2);

                                var nx = (float)Math.Cos(sa) * (float)Math.Cos(ta);
                                var ny = (float)Math.Sin(sa) * (float)Math.Cos(ta);
                                var nz = (float)Math.Sin(ta);

                                this.vertexBuffer.Vertex(
                                    light.Position.X + nx * radius,
                                    light.Position.Y + ny * radius,
                                    light.Position.Z + nz * radius);
                            }
                        }
                    }

                    this.vertexBuffer.End().Draw();
                }
                else
                {
                    this.vertexBuffer.FullSceneQuad().Draw();
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Renders the scene.
        /// </summary>
        /// <param name="scene">The scene object.</param>
        /// <param name="primaryLight">The primary light. Only the primary light casts shadows.</param>
        public void Render(IScene scene, Light primaryLight)
        {
            if (scene == null)
            {
                throw new ArgumentNullException(nameof(scene));
            }

            // Phase 1: Geometry
            {
                this.Phase = Phase.Geometry;

                GPU.Draw(ColorTarget, NormalTarget, PositionTarget, CompositionTarget);
                GPU.Use(Cull.Back, Depth.Test | Depth.Write, Stencil.None, Blend.None);
                GPU.Clear(null);

                scene.Render(this);
            }

            // Phase 2: Shadows
            if (primaryLight != null && primaryLight.Intensity > 0)
            {
                this.Phase = Phase.Shadows;
                this.shadowShader.Use(primaryLight);

                GPU.Draw(TargetBuffer.None);
                GPU.Use(Cull.None, Depth.Test | Depth.Clamp | Depth.Offset, Stencil.Shadows, Blend.None);

                scene.Render(this);
            }

            // Phase 3: Lights
            {
                this.Phase = Phase.Lights;
                this.lightShader.Use()
                    .SetUniform("ColorBuffer", this.ColorBuffer)
                    .SetUniform("NormalBuffer", this.NormalBuffer)
                    .SetUniform("PositionBuffer", this.PositionBuffer)
                    .SetUniform("BufferSize", this.Width, this.Height);

                GPU.Draw(CompositionTarget);

                if (primaryLight != null && primaryLight.Intensity > 0)
                {
                    GPU.Use(Cull.Back, Depth.TestReversed, Stencil.Light, Blend.Additive);
                    GPU.Transform(Matrix4x4.Identity);

                    (this as IRenderer).Render(primaryLight);
                }

                GPU.Use(Cull.Back, Depth.TestReversed, Stencil.None, Blend.Additive);

                scene.Render(this);
            }

            // Phase 4: Effects
            {
                this.Phase = Phase.Effects;

                GPU.Use(Cull.None, Depth.Test, Stencil.None, Blend.Additive);

                scene.Render(this);
            }

            this.Phase = 0;
        }