Ejemplo n.º 1
0
        private void RenderShadows(RenderTarget renderTarget, Light light, Stage stage, Camera camera, int cascadeIndex, out Matrix4 viewProjection, out Vector2 clipPlane)
        {
            Backend.BeginPass(renderTarget, new Vector4(0, 0, 0, 1), true);

            var modelViewProjection = Matrix4.Identity;

            var orientation = Vector3.GetRotationTo(Vector3.UnitY, light.Direction);

            clipPlane = new Vector2(light.ShadowNearClipDistance, light.Range * 2.0f);

            Matrix4 view, projection;
            if (light.Type == LighType.Directional)
            {
                var cameraFrustum = camera.GetFrustum();
                var lightDir = -light.Direction;
                lightDir.Normalize();

                Matrix4 lightRotation = Matrix4.LookAt(Vector3.Zero, lightDir, Vector3.UnitY);
                Vector3[] corners = cameraFrustum.GetCorners();

                for (var i = 0; i < corners.Length; i++)
                {
                    corners[i] = Vector3.Transform(corners[i], lightRotation);
                }

                var lightBox = BoundingBox.CreateFromPoints(corners);
                var boxSize = lightBox.Max - lightBox.Min;
                Vector3 halfBoxSize;
                Vector3.Multiply(ref boxSize, 0.5f, out halfBoxSize);

                var lightPosition = lightBox.Min + halfBoxSize;
                lightPosition.Z = lightBox.Min.Z;

                lightPosition = Vector3.Transform(lightPosition, Matrix4.Invert(lightRotation));

                view = Matrix4.LookAt(lightPosition, lightPosition - lightDir, Vector3.UnitY);
                projection = Matrix4.CreateOrthographic(boxSize.X, boxSize.Y, -boxSize.Z, boxSize.Z);
                clipPlane.X = -boxSize.Z;
                clipPlane.Y = boxSize.Z;
            }
            else
            {
                view = Matrix4.LookAt(light.Position, light.Position + light.Direction, Vector3.UnitY);
                projection = Matrix4.CreatePerspectiveFieldOfView(light.OuterAngle, renderTarget.Width / (float)renderTarget.Height, clipPlane.X, clipPlane.Y);
            }

            viewProjection = view * projection;

            ShadowRenderOperations.Reset();
            stage.PrepareRenderOperations(view, ShadowRenderOperations, true, false);

            RenderOperation[] operations;
            int count;
            ShadowRenderOperations.GetOperations(out operations, out count);

            for (var i = 0; i < count; i++)
            {
                var world = operations[i].WorldMatrix;

                modelViewProjection = world * view * projection;

                Resources.ShaderProgram program;
                RenderShadowsParams shadowParams;

                if (operations[i].Skeleton != null)
                {
                    program = RenderShadowsSkinnedShader;
                    shadowParams = RenderShadowsSkinnedParams;
                }
                else
                {
                    program = RenderShadowsShader;
                    shadowParams = RenderShadowsParams;
                }

                Backend.BeginInstance(program.Handle, null, null, ShadowsRenderState);
                Backend.BindShaderVariable(shadowParams.ModelViewProjection, ref modelViewProjection);
                Backend.BindShaderVariable(shadowParams.ClipPlane, ref clipPlane);

                if (light.Type == LighType.Directional)
                {
                    float shadowBias = 0.05f * (cascadeIndex + 1);
                    Backend.BindShaderVariable(shadowParams.ShadowBias, shadowBias);
                }

                if (operations[i].Skeleton != null)
                {
                    Backend.BindShaderVariable(shadowParams.Bones, ref operations[i].Skeleton.FinalBoneTransforms);
                }

                Backend.DrawMesh(operations[i].MeshHandle);

                Backend.EndInstance();
            }

            Backend.EndPass();
        }
Ejemplo n.º 2
0
        private void RenderShadowsCube(RenderTarget renderTarget, Light light, Stage stage, Camera camera, out Matrix4 viewProjection, out Vector2 clipPlane)
        {
            Backend.BeginPass(renderTarget, new Vector4(0, 0, 0, 1), true);

            var modelViewProjection = Matrix4.Identity;

            var orientation = Vector3.GetRotationTo(Vector3.UnitY, light.Direction);

            clipPlane = new Vector2(light.ShadowNearClipDistance, light.Range * 2.0f);

            var projection = Matrix4.CreatePerspectiveFieldOfView(OpenTK.MathHelper.DegreesToRadians(90), renderTarget.Width / (float)renderTarget.Height, clipPlane.X, clipPlane.Y);

            var viewProjectionMatrices = new Matrix4[]
            {
                (Matrix4.CreateTranslation(-light.Position) * new Matrix4(0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 1)) * projection,
                (Matrix4.CreateTranslation(-light.Position) * new Matrix4(0, 0, 1, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1)) * projection,

                (Matrix4.CreateTranslation(-light.Position) * new Matrix4(1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1)) * projection,
                (Matrix4.CreateTranslation(-light.Position) * new Matrix4(1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1)) * projection,

                (Matrix4.CreateTranslation(-light.Position) * new Matrix4(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1)) * projection,
                (Matrix4.CreateTranslation(-light.Position) * new Matrix4(-1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)) * projection
            };

            viewProjection = projection;

            ShadowRenderOperations.Reset();
            stage.PrepareRenderOperations(light.Position, light.Range * 2, ShadowRenderOperations, true);

            RenderOperation[] operations;
            int count;
            ShadowRenderOperations.GetOperations(out operations, out count);

            for (var i = 0; i < count; i++)
            {
                var world = operations[i].WorldMatrix;

                Resources.ShaderProgram program;
                RenderShadowsParams shadowParams;

                if (operations[i].Skeleton != null)
                {
                    program = RenderShadowsSkinnedCubeShader;
                    shadowParams = RenderShadowsSkinnedCubeParams;
                }
                else
                {
                    program = RenderShadowsCubeShader;
                    shadowParams = RenderShadowsCubeParams;
                }

                Backend.BeginInstance(program.Handle, null, null, ShadowsRenderState);
                Backend.BindShaderVariable(shadowParams.Model, ref world);
                Backend.BindShaderVariable(shadowParams.ClipPlane, ref clipPlane);
                Backend.BindShaderVariable(shadowParams.ViewProjectionMatrices, ref viewProjectionMatrices);
                Backend.BindShaderVariable(shadowParams.LightPosition, ref light.Position);

                if (operations[i].Skeleton != null)
                {
                    Backend.BindShaderVariable(shadowParams.Bones, ref operations[i].Skeleton.FinalBoneTransforms);
                }

                Backend.DrawMesh(operations[i].MeshHandle);

                Backend.EndInstance();
            }
            Backend.EndPass();
        }
Ejemplo n.º 3
0
        private void RenderScene(Stage stage, Camera camera, ref Matrix4 view, ref Matrix4 projection)
        {
            var viewProjection = view * projection;

            RenderOperations.Reset();
            stage.PrepareRenderOperations(viewProjection, RenderOperations);

            RenderOperation[] operations;
            int count;
            RenderOperations.GetOperations(out operations, out count);

            Resources.Material activeMaterial = null;
            Matrix4 worldView, world, itWorld, worldViewProjection;

            for (var i = 0; i < count; i++)
            {
                world = operations[i].WorldMatrix;

                Matrix4.Mult(ref world, ref viewProjection, out worldViewProjection);
                Matrix4.Mult(ref world, ref view, out worldView);

                itWorld = Matrix4.Transpose(Matrix4.Invert(world));

                if (activeMaterial == null || activeMaterial.Id != operations[i].Material.Id)
                {
                    operations[i].Material.BeginInstance(Backend, camera, 0);
                }

                operations[i].Material.BindPerObject(Backend, ref world, ref worldView, ref itWorld, ref worldViewProjection, operations[i].Skeleton);
                Backend.DrawMesh(operations[i].MeshHandle);
            }
        }