/// <summary>
        /// Returns the in parameters for a ShaderEffect, depending on the given ShaderEffectProps.
        /// </summary>
        /// <param name="effectProps">The ShaderEffectProps.</param>
        /// <returns></returns>
        public static string InParams(ShaderEffectProps effectProps)
        {
            var pxIn = new List <string>
            {
                GLSL.CreateIn(GLSL.Type.Vec3, VaryingNameDeclarations.ViewDirection),
                GLSL.CreateIn(GLSL.Type.Vec4, VaryingNameDeclarations.Position),
                GLSL.CreateIn(GLSL.Type.Vec3, VaryingNameDeclarations.CameraPosition)
            };

            if (effectProps.MeshProbs.HasColors)
            {
                pxIn.Add(GLSL.CreateIn(GLSL.Type.Vec3, VaryingNameDeclarations.Color));
            }

            if (effectProps.MeshProbs.HasNormals)
            {
                pxIn.Add(GLSL.CreateIn(GLSL.Type.Vec3, VaryingNameDeclarations.Normal));
            }

            if (effectProps.MeshProbs.HasTangents && effectProps.MeshProbs.HasBiTangents)
            {
                pxIn.Add(GLSL.CreateIn(GLSL.Type.Vec4, VaryingNameDeclarations.Tangent));
                pxIn.Add(GLSL.CreateIn(GLSL.Type.Vec3, VaryingNameDeclarations.Bitangent));
            }

            if (effectProps.MeshProbs.HasUVs)
            {
                pxIn.Add(GLSL.CreateIn(GLSL.Type.Vec2, VaryingNameDeclarations.TextureCoordinates));
            }

            return(string.Join("\n", pxIn));
        }
        /// <summary>
        /// Creates the in (with prefix "fu") and out parameters of the vertex shader, depending on the given ShaderEffectProps.
        /// </summary>
        /// <param name="effectProps">>The ShaderEffectProps.</param>
        /// <returns></returns>
        public static string InAndOutParams(ShaderEffectProps effectProps)
        {
            var vertProps = new List <string>
            {
                GLSL.CreateOut(GLSL.Type.Vec3, VaryingNameDeclarations.CameraPosition),
                GLSL.CreateOut(GLSL.Type.Vec4, VaryingNameDeclarations.Position)
            };

            vertProps.Add(GLSL.CreateIn(GLSL.Type.Vec3, UniformNameDeclarations.Vertex));

            if (effectProps.MeshProbs.HasTangents && effectProps.MeshProbs.HasBiTangents)
            {
                vertProps.Add(GLSL.CreateIn(GLSL.Type.Vec4, UniformNameDeclarations.TangentAttribName));
                vertProps.Add(GLSL.CreateIn(GLSL.Type.Vec3, UniformNameDeclarations.BitangentAttribName));

                vertProps.Add(GLSL.CreateOut(GLSL.Type.Vec4, VaryingNameDeclarations.Tangent));
                vertProps.Add(GLSL.CreateOut(GLSL.Type.Vec3, VaryingNameDeclarations.Bitangent));
            }

            if (effectProps.MatProbs.HasSpecular)
            {
                vertProps.Add(GLSL.CreateOut(GLSL.Type.Vec3, VaryingNameDeclarations.ViewDirection));
            }

            if (effectProps.MeshProbs.HasWeightMap)
            {
                vertProps.Add(GLSL.CreateIn(GLSL.Type.Vec4, UniformNameDeclarations.BoneIndex));
                vertProps.Add(GLSL.CreateIn(GLSL.Type.Vec4, UniformNameDeclarations.BoneWeight));
            }

            if (effectProps.MeshProbs.HasNormals)
            {
                vertProps.Add(GLSL.CreateIn(GLSL.Type.Vec3, UniformNameDeclarations.Normal));
                vertProps.Add(GLSL.CreateOut(GLSL.Type.Vec3, VaryingNameDeclarations.Normal));
            }

            if (effectProps.MeshProbs.HasUVs)
            {
                vertProps.Add(GLSL.CreateIn(GLSL.Type.Vec2, UniformNameDeclarations.TextureCoordinates));
                vertProps.Add(GLSL.CreateOut(GLSL.Type.Vec2, VaryingNameDeclarations.TextureCoordinates));
            }

            if (effectProps.MeshProbs.HasColors)
            {
                vertProps.Add(GLSL.CreateIn(GLSL.Type.Vec4, UniformNameDeclarations.Color));
                vertProps.Add(GLSL.CreateOut(GLSL.Type.Vec4, VaryingNameDeclarations.Color));
            }

            return(string.Join("\n", vertProps));
        }
        private static string CreateDeferredLightingPixelShader(Light lc, bool isCascaded = false, int numberOfCascades = 0, bool debugCascades = false)
        {
            var frag = new StringBuilder();

            frag.Append(HeaderShard.Version300Es);
            frag.Append("#extension GL_ARB_explicit_uniform_location : enable\n");
            frag.Append("#extension GL_ARB_gpu_shader5 : enable\n");
            frag.Append(HeaderShard.EsPrecisionHighpFloat);

            frag.Append(FragPropertiesShard.DeferredTextureUniforms());
            frag.Append(FragPropertiesShard.FuseeMatrixUniforms());

            frag.Append(LightingShard.LightStructDeclaration);
            frag.Append(FragPropertiesShard.DeferredLightAndShadowUniforms(lc, isCascaded, numberOfCascades));

            frag.Append(GLSL.CreateIn(GLSL.Type.Vec2, VaryingNameDeclarations.TextureCoordinates));

            frag.Append(FragPropertiesShard.ColorOut());

            //Shadow calculation methods
            //--------------------------------------
            if (lc.Type != LightType.Point)
            {
                frag.Append(LightingShard.ShadowCalculation());
            }
            else
            {
                frag.Append(LightingShard.ShadowCalculationCubeMap());
            }

            //Lighting methods
            //------------------------------------------
            frag.Append(LightingShard.AmbientComponent());
            frag.Append(LightingShard.SpecularComponent());
            frag.Append(LightingShard.DiffuseComponent());
            frag.Append(LightingShard.AttenuationPointComponent());
            frag.Append(LightingShard.AttenuationConeComponent());

            frag.Append(LightingShard.ApplyLightDeferred(lc, isCascaded, numberOfCascades, debugCascades));

            return(frag.ToString());
        }