Esempio n. 1
0
        /// <summary>
        ///
        /// </summary>
        internal void UpdateShaders()
        {
            if (mShaderNeedsUpdate)
            {
                mShaderNeedsUpdate = false;
                //Proceed only if there is no custom vertex shader and the user's computer supports vertex shaders
                RenderSystemCapabilities caps = Root.Singleton.RenderSystem.Capabilities;
                if (caps.HasCapability(Capabilities.VertexPrograms))
                {
                    //Generate a string ID that identifies the current set of vertex shader options
                    string tmpName = string.Empty;
                    tmpName += "GrassVS_";
                    if (mAnimate)
                    {
                        tmpName += "anim_";
                    }
                    if (mBlend)
                    {
                        tmpName += "blend_";
                    }
                    tmpName += mRenderTechnique.ToString() + "_";
                    tmpName += mFadeTechnique.ToString() + "_";
                    if (mFadeTechnique == FadeTechnique.Grow || mFadeTechnique == FadeTechnique.AlphaGrow)
                    {
                        tmpName += mMaxHeight + "_";
                    }
                    tmpName += "vp";

                    string vsName = tmpName;
                    //Generate a string ID that identifies the material combined with the vertex shader
                    string matName = mMaterial.Name + "_" + vsName;

                    //Check if the desired material already exists (if not, create it)
                    Material tmpMat = (Material)MaterialManager.Instance.GetByName(matName);
                    if (tmpMat == null)
                    {
                        //Clone the original material
                        tmpMat = mMaterial.Clone(matName);

                        //Disable lighting
                        tmpMat.Lighting = false;
                        //Check if the desired shader already exists (if not, compile it)
                        HighLevelGpuProgram vertexShader = (HighLevelGpuProgram)HighLevelGpuProgramManager.Instance.GetByName(vsName);
                        if (vertexShader == null)
                        {
                            //Generate the grass shader
                            string vertexProgSource = string.Empty;
                            vertexProgSource +=
                                "void main( \n" +
                                "	float4 iPosition : POSITION, \n"+
                                "	float4 iColor : COLOR, \n"+
                                "	float2 iUV       : TEXCOORD0,	\n"+
                                "	out float4 oPosition : POSITION, \n"+
                                "	out float4 oColor : COLOR, \n"+
                                "	out float2 oUV       : TEXCOORD0,	\n";

                            if (mAnimate)
                            {
                                vertexProgSource +=
                                    "	uniform float time,	\n"+
                                    "	uniform float frequency,	\n"+
                                    "	uniform float4 direction,	\n";
                            }
                            if (mFadeTechnique == FadeTechnique.Grow || mFadeTechnique == FadeTechnique.AlphaGrow)
                            {
                                vertexProgSource +=
                                    "	uniform float grassHeight,	\n";
                            }
                            if (mRenderTechnique == GrassTechnique.Sprite)
                            {
                                vertexProgSource +=
                                    "	float4 iNormal : NORMAL, \n";
                            }

                            vertexProgSource +=
                                "	uniform float4x4 worldViewProj,	\n"+
                                "	uniform float3 camPos, \n"+
                                "	uniform float fadeRange ) \n"+
                                "{	\n"+
                                "	oColor.rgb = iColor.rgb;   \n"+
                                "	float4 position = iPosition;	\n"+
                                "	float dist = distance(camPos.xz, position.xz);	\n";

                            if (mFadeTechnique == FadeTechnique.Alpha || mFadeTechnique == FadeTechnique.AlphaGrow)
                            {
                                vertexProgSource +=
                                    //Fade out in the distance
                                    "	oColor.a = 2.0f - (2.0f * dist / fadeRange);   \n";
                            }
                            else
                            {
                                vertexProgSource +=
                                    "	oColor.a = 1.0f;   \n";
                            }

                            vertexProgSource +=
                                "	float oldposx = position.x;	\n";

                            if (mRenderTechnique == GrassTechnique.Sprite)
                            {
                                vertexProgSource +=
                                    //Face the camera
                                    "	float3 dirVec = (float3)position - (float3)camPos;		\n"+
                                    "	float3 p = normalize(cross(float4(0,1,0,0), dirVec));	\n"+
                                    "	position += float4(p.x * iNormal.x, iNormal.y, p.z * iNormal.x, 0);	\n";
                            }

                            if (mAnimate)
                            {
                                vertexProgSource +=
                                    "	if (iUV.y == 0.0f){	\n"+
                                    //Wave grass in breeze
                                    "		float offset = sin(time + oldposx * frequency);	\n"+
                                    "		position += direction * offset;	\n"+
                                    "	}	\n";
                            }
                            if (mBlend && mAnimate)
                            {
                                vertexProgSource +=
                                    "	else {	\n";
                            }
                            else if (mBlend)
                            {
                                vertexProgSource +=
                                    "	if (iUV.y != 0.0f){	\n";
                            }
                            if (mBlend)
                            {
                                vertexProgSource +=
                                    //Blend the base of nearby grass into the terrain
                                    "		if (oColor.a >= 1.0f) \n"+
                                    "			oColor.a = 4.0f * ((dist / fadeRange) - 0.1f);	\n"+
                                    "	}	\n";
                            }
                            if (mFadeTechnique == FadeTechnique.Grow || mFadeTechnique == FadeTechnique.AlphaGrow)
                            {
                                vertexProgSource +=
                                    "	float offset = (2.0f * dist / fadeRange) - 1.0f; \n"+
                                    "	position.y -= grassHeight * clamp(offset, 0, 1); ";
                            }
                            vertexProgSource +=
                                "	oPosition = mul(worldViewProj, position);  \n";

                            vertexProgSource +=
                                "	oUV = iUV;\n"+
                                "}";
                            vertexShader = HighLevelGpuProgramManager.Instance.CreateProgram(
                                vsName,
                                ResourceGroupManager.DefaultResourceGroupName,
                                "cg", GpuProgramType.Vertex);
                            vertexShader.Source = vertexProgSource;
                            vertexShader.SetParam("profiles", "vs_1_1 arbvp1");
                            vertexShader.SetParam("entry_point", "main");
                            vertexShader.Load();
                        }
                        //Now the vertex shader (vertexShader) has either been found or just generated
                        //(depending on whether or not it was already generated).

                        //Apply the shader to the material
                        Pass pass = tmpMat.GetTechnique(0).GetPass(0);
                        pass.VertexProgramName = vsName;
                        GpuProgramParameters gparams = pass.VertexProgramParameters;

                        gparams.SetNamedAutoConstant("worldViewProj", GpuProgramParameters.AutoConstantType.WorldViewProjMatrix, 0);
                        gparams.SetNamedAutoConstant("camPos", GpuProgramParameters.AutoConstantType.CameraPositionObjectSpace, 0);
                        gparams.SetNamedAutoConstant("fadeRange", GpuProgramParameters.AutoConstantType.Custom, 1);

                        if (mAnimate)
                        {
                            gparams.SetNamedAutoConstant("time", GpuProgramParameters.AutoConstantType.Custom, 1);
                            gparams.SetNamedAutoConstant("frequency", GpuProgramParameters.AutoConstantType.Custom, 1);
                            gparams.SetNamedAutoConstant("direction", GpuProgramParameters.AutoConstantType.Custom, 4);
                        }

                        if (mFadeTechnique == FadeTechnique.Grow || mFadeTechnique == FadeTechnique.AlphaGrow)
                        {
                            gparams.SetNamedAutoConstant("grassHeight", GpuProgramParameters.AutoConstantType.Custom, 1);
                            gparams.SetNamedConstant("grassHeight", mMaxHeight * 1.05f);
                        }

                        float farViewDist = mGeom.DetailLevels[0].FarRange;
                        pass.VertexProgramParameters.SetNamedConstant("fadeRange", farViewDist / 1.225f);
                        //Note: 1.225 ~= sqrt(1.5), which is necessary since the far view distance is measured from the centers
                        //of pages, while the vertex shader needs to fade grass completely out (including the closest corner)
                        //before the page center is out of range.
                    }
                    //Now the material (tmpMat) has either been found or just created (depending on whether or not it was already
                    //created). The appropriate vertex shader should be applied and the material is ready for use.

                    //Apply the new material
                    mMaterial = tmpMat;
                }
            }
        }
Esempio n. 2
0
        public IProgram Link(Shader shader, IEnumerable <object> u)
        {
            var units = u.Cast <System.Tuple <ShaderType, SourceDescription> >();

            var          name  = "SLSharp_" + _shaderCounter++;
            const string group = ResourceGroupManager.DefaultResourceGroupName;


            var frags = units.Where(x => x.Item1 == ShaderType.FragmentShader).Select(x => x.Item2);
            var verts = units.Where(x => x.Item1 == ShaderType.VertexShader).Select(x => x.Item2);

            var combinedFrags = frags.Aggregate(SourceDescription.Empty, (x, y) => x.Merge(y));
            var combinedVerts = verts.Aggregate(SourceDescription.Empty, (x, y) => x.Merge(y));

            var samplerRegs = 0;
            var samplers    = new List <VariableDescription>();

            HighLevelGpuProgram ps = null;

            if (combinedFrags.Functions.Count > 0)
            {
                // init default regs
                foreach (var x in combinedFrags.Uniforms)
                {
                    if (!x.IsSampler() || x.DefaultRegister.HasValue)
                    {
                        continue;
                    }
                    x.DefaultRegister = samplerRegs++;
                    samplers.Add(x);
                }

                switch (SLSharp.Language)
                {
                case ShaderLanguage.GLSL:
                    ps        = HighLevelGpuProgramManager.Instance.CreateProgram(name + "_ps", group, "glsl", GpuProgramType.Fragment);
                    ps.Source = combinedFrags.ToGlsl(ShaderType.FragmentShader);
                    break;

                case ShaderLanguage.HLSL:
                    ps = HighLevelGpuProgramManager.Instance.CreateProgram(name + "_ps", group, "hlsl", GpuProgramType.Fragment);
                    ps.SetParam("entry_point", "SLSharp_FragmentMain");
                    ps.SetParam("target", "ps_3_0");
                    ps.Source = combinedFrags.ToHlsl();
                    break;

                case ShaderLanguage.CG:
                    ps = HighLevelGpuProgramManager.Instance.CreateProgram(name + "_ps", group, "cg", GpuProgramType.Fragment);
                    ps.SetParam("entry_point", "SLSharp_FragmentMain");
                    ps.SetParam("target", "ps_3_0");
                    ps.Source = combinedFrags.ToHlsl();
                    break;
                }
            }

            HighLevelGpuProgram vs = null;

            if (combinedVerts.Functions.Count > 0)
            {
                // init default regs
                foreach (var x in combinedVerts.Uniforms)
                {
                    if (!x.IsSampler() || x.DefaultRegister.HasValue)
                    {
                        continue;
                    }
                    x.DefaultRegister = samplerRegs++;
                    samplers.Add(x);
                }

                switch (SLSharp.Language)
                {
                case ShaderLanguage.GLSL:
                    vs = HighLevelGpuProgramManager.Instance.CreateProgram(name + "_vs", group, "glsl", GpuProgramType.Vertex);
                    var vsSource = combinedVerts.ToGlsl(ShaderType.VertexShader);

                    foreach (var vin in combinedVerts.VertexIns)
                    {
                        var sem = SemanticToMogre(vin.Semantic);
                        vsSource = vsSource.Replace(vin.Name, sem);
                    }
                    vs.Source = vsSource;
                    break;

                case ShaderLanguage.HLSL:
                    vs = HighLevelGpuProgramManager.Instance.CreateProgram(name + "_vs", group, "hlsl", GpuProgramType.Vertex);
                    vs.SetParam("entry_point", "SLSharp_VertexMain");
                    vs.SetParam("target", "vs_3_0");
                    vs.Source = combinedVerts.ToHlsl();
                    break;

                case ShaderLanguage.CG:
                    vs = HighLevelGpuProgramManager.Instance.CreateProgram(name + "_vs", group, "cg", GpuProgramType.Vertex);
                    vs.SetParam("entry_point", "SLSharp_VertexMain");
                    vs.SetParam("target", "vs_3_0");
                    vs.Source = combinedVerts.ToHlsl();
                    break;
                }
            }

            var prog = new Program(name, vs, ps, samplers);

            if (SLSharp.Language == ShaderLanguage.GLSL)
            {
                if (vs != null)
                {
                    var pars = prog.Pass.VertexProgramParameters;
                    foreach (var x in combinedVerts.Uniforms)
                    {
                        if (!x.IsSampler())
                        {
                            continue;
                        }
                        pars.SetNamedConstant(x.Name, x.DefaultRegister.GetValueOrDefault());
                    }
                }

                if (ps != null)
                {
                    var pars = prog.Pass.FragmentProgramParameters;
                    foreach (var x in combinedFrags.Uniforms)
                    {
                        if (!x.IsSampler())
                        {
                            continue;
                        }
                        pars.SetNamedConstant(x.Name, x.DefaultRegister.GetValueOrDefault());
                    }
                }
            }

            return(prog);
        }
Esempio n. 3
0
        /// <summary>
        ///
        /// </summary>
        private void UpdateShaders()
        {
            if (!mShadersSupported)
            {
                return;
            }

            int i = 0;

            foreach (BatchedGeometry.SubBatch it in mBatch.SubBatches.Values)
            {
                BatchedGeometry.SubBatch subBatch = it;
                Material mat = mUnfadedMaterials[i++];

                //check ig lighting should be enabled
                bool lightningEnabled = false;
                for (int t = 0; t < mat.TechniqueCount; t++)
                {
                    Technique tech = mat.GetTechnique(t);
                    for (int p = 0; p < tech.PassCount; p++)
                    {
                        Pass pass = tech.GetPass(p);
                        if (pass.LightingEnabled)
                        {
                            lightningEnabled = true;
                            break;
                        }
                        if (lightningEnabled)
                        {
                            break;
                        }
                    }
                }

                //Compile the CG shader script based on various material / fade options
                string tmpName = string.Empty;

                tmpName += "BatchPage_";
                if (mFadeEnabled)
                {
                    tmpName += "fade_";
                }
                if (lightningEnabled)
                {
                    tmpName += "lit_";
                }

                tmpName += "vp";

                string vertexProgName = tmpName;

                //If the shader hasn't been created yet, create it
                if (HighLevelGpuProgramManager.Instance.GetByName(tmpName) == null)
                {
                    string vertexProgSource =
                        "void main( \n" +
                        "	float4 iPosition : POSITION, \n"+
                        "	float3 normal    : NORMAL,	\n"+
                        "	float2 iUV       : TEXCOORD0,	\n"+
                        "	float4 iColor    : COLOR, \n"+

                        "	out float4 oPosition : POSITION, \n"+
                        "	out float2 oUV       : TEXCOORD0,	\n"+
                        "	out float4 oColor : COLOR, \n"+
                        "	out float4 oFog : FOG,	\n";

                    if (lightningEnabled)
                    {
                        vertexProgSource +=
                            "	uniform float4 objSpaceLight,	\n"+
                            "	uniform float4 lightDiffuse,	\n"+
                            "	uniform float4 lightAmbient,	\n";
                    }

                    if (mFadeEnabled)
                    {
                        vertexProgSource +=
                            "	uniform float3 camPos, \n";
                    }

                    vertexProgSource +=
                        "	uniform float4x4 worldViewProj,	\n"+
                        "	uniform float fadeGap, \n"+
                        "   uniform float invisibleDist )\n" +
                        "{	\n";

                    if (lightningEnabled)
                    {
                        vertexProgSource +=
                            //Perform lighting calculations (no specular)
                            "	float3 light = normalize(objSpaceLight.xyz - (iPosition.xyz * objSpaceLight.w)); \n"+
                            "	float diffuseFactor = max(dot(normal, light), 0); \n"+
                            "	oColor = (lightAmbient + diffuseFactor * lightDiffuse) * iColor; \n";
                    }
                    else
                    {
                        vertexProgSource +=
                            "	oColor = iColor; \n";
                    }

                    if (mFadeEnabled)
                    {
                        vertexProgSource +=
                            //Fade out in the distance
                            "	float dist = distance(camPos.xz, iPosition.xz);	\n"+
                            "	oColor.a *= (invisibleDist - dist) / fadeGap;   \n";
                    }

                    vertexProgSource +=
                        "	oUV = iUV;	\n"+
                        "	oPosition = mul(worldViewProj, iPosition);  \n"+
                        "	oFog.x = oPosition.z; \n"+
                        "}";

                    HighLevelGpuProgram vertexShader = HighLevelGpuProgramManager.Instance.CreateProgram(
                        vertexProgName,
                        ResourceGroupManager.DefaultResourceGroupName,
                        "cg", GpuProgramType.Vertex);

                    vertexShader.Source = vertexProgSource;
                    vertexShader.SetParam("profiles", "vs_1_1 arbvp1");
                    vertexShader.SetParam("entry_point", "main");
                    vertexShader.Load();
                }

                //Now that the shader is ready to be applied, apply it
                string materialSignature = string.Empty;
                materialSignature += "BatchMat|";
                materialSignature += mat.Name + "|";
                if (mFadeEnabled)
                {
                    materialSignature += mVisibleDist + "|";
                    materialSignature += mInvisibleDist + "|";
                }
                //Search for the desired material
                Material generatedMaterial = (Material)MaterialManager.Instance.GetByName(materialSignature);
                if (generatedMaterial == null)
                {
                    //Clone the material
                    generatedMaterial = mat.Clone(materialSignature);

                    //And apply the fade shader
                    for (int t = 0; t < generatedMaterial.TechniqueCount; t++)
                    {
                        Technique tech = generatedMaterial.GetTechnique(t);
                        for (int p = 0; p < tech.PassCount; p++)
                        {
                            Pass pass = tech.GetPass(p);
                            //Setup vertex program
                            if (pass.VertexProgramName == "")
                            {
                                pass.VertexProgramName = vertexProgName;
                            }
                            try
                            {
                                GpuProgramParameters gparams = pass.VertexProgramParameters;
                                if (lightningEnabled)
                                {
                                    gparams.SetNamedAutoConstant("objSpaceLight", GpuProgramParameters.AutoConstantType.LightPositionObjectSpace, 0);
                                    gparams.SetNamedAutoConstant("lightDiffuse", GpuProgramParameters.AutoConstantType.LightDiffuseColor, 0);
                                    gparams.SetNamedAutoConstant("lightAmbient", GpuProgramParameters.AutoConstantType.AmbientLightColor, 0);
                                }

                                gparams.SetNamedAutoConstant("worldViewProj", GpuProgramParameters.AutoConstantType.WorldViewProjMatrix, 0);

                                if (mFadeEnabled)
                                {
                                    gparams.SetNamedAutoConstant("camPos", GpuProgramParameters.AutoConstantType.CameraPositionObjectSpace, 0);

                                    //set fade ranges
                                    gparams.SetNamedAutoConstant("invisibleDist", GpuProgramParameters.AutoConstantType.Custom, 0);
                                    gparams.SetNamedConstant("invisibleDist", mInvisibleDist);
                                    gparams.SetNamedAutoConstant("fadeGap", GpuProgramParameters.AutoConstantType.Custom, 0);
                                    gparams.SetNamedConstant("fadeGap", mInvisibleDist - mVisibleDist);

                                    if (pass.AlphaRejectFunction == CompareFunction.AlwaysPass)
                                    {
                                        pass.SetSceneBlending(SceneBlendType.TransparentAlpha);
                                    }
                                }
                            }
                            catch
                            {
                                throw new Exception("Error configuring batched geometry transitions." +
                                                    "If you're using materials with custom vertex shaders, they will need to implement fade transitions to be compatible with BatchPage.");
                            }
                        }
                    }
                }

                //Apply the material
                subBatch.Material = generatedMaterial;
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="mgr"></param>
        /// <param name="rootSceneNode"></param>
        /// <param name="method"></param>
        public StaticBillboardSet(SceneManager mgr, SceneNode rootSceneNode, BillboardMethod method)
        {
            mSceneMgr     = mgr;
            mRenderMethod = method;
            mVisible      = true;
            mFadeEnabled  = false;
            mBBOrigin     = BillboardOrigin.Center;

            //Fall back to Compatible if vertex shaders are not available
            if (mRenderMethod == BillboardMethod.Accelerated)
            {
                RenderSystemCapabilities caps = Root.Singleton.RenderSystem.Capabilities;
                if (!caps.HasCapability(Capabilities.VertexPrograms))
                {
                    mRenderMethod = BillboardMethod.Compatible;
                }
            }

            mNode       = rootSceneNode.CreateChildSceneNode();
            mEntityName = GetUniqueID("SBSEntity");

            if (mRenderMethod == BillboardMethod.Accelerated)
            {
                //Accelerated billboard method
                mEntity  = null;
                mUFactor = 1.0f;
                mVFactor = 1.0f;

                //Load vertex shader to align billboards to face the camera (if not loaded already)
                if (++mSelfInstances == 1)
                {
                    //First shader, simple camera-alignment
                    HighLevelGpuProgram vertexShader =
                        (HighLevelGpuProgram)HighLevelGpuProgramManager.Instance.GetByName("Sprite_vp");
                    if (vertexShader == null)
                    {
                        string vertexProg = string.Empty;

                        vertexProg =
                            "void Sprite_vp(	\n"+
                            "	float4 position : POSITION,	\n"+
                            "	float3 normal   : NORMAL,	\n"+
                            "	float4 color	: COLOR,	\n"+
                            "	float2 uv       : TEXCOORD0,	\n"+
                            "	out float4 oPosition : POSITION,	\n"+
                            "	out float2 oUv       : TEXCOORD0,	\n"+
                            "	out float4 oColor    : COLOR, \n"+
                            "	out float4 oFog      : FOG,	\n"+
                            "	uniform float4x4 worldViewProj,	\n"+
                            "	uniform float    uScroll, \n"+
                            "	uniform float    vScroll, \n"+
                            "	uniform float4   preRotatedQuad[4] )	\n"+
                            "{	\n"+
                            //Face the camera
                            "	float4 vCenter = float4( position.x, position.y, position.z, 1.0f );	\n"+
                            "	float4 vScale = float4( normal.x, normal.y, normal.x, 1.0f );	\n"+
                            "	oPosition = mul( worldViewProj, vCenter + (preRotatedQuad[normal.z] * vScale) );  \n"+

                            //Color
                            "	oColor = color;   \n"+

                            //UV Scroll
                            "	oUv = uv;	\n"+
                            "	oUv.x += uScroll; \n"+
                            "	oUv.y += vScroll; \n"+

                            //Fog
                            "	oFog.x = oPosition.z; \n"+
                            "}";

                        vertexShader = HighLevelGpuProgramManager.Instance.CreateProgram(
                            "Sprite_vp",
                            ResourceGroupManager.DefaultResourceGroupName,
                            "cg", GpuProgramType.Vertex);

                        vertexShader.Source = vertexProg;
                        vertexShader.SetParam("profiles", "vs_1_1 arbvp1");
                        vertexShader.SetParam("entry_point", "Sprite_vp");
                        vertexShader.Load();
                    }

                    //Second shader, camera alignment and distance based fading
                    HighLevelGpuProgram vertexShader2 =
                        (HighLevelGpuProgram)HighLevelGpuProgramManager.Instance.GetByName("SpriteFade_vp");
                    if (vertexShader2 == null)
                    {
                        string vertexProg2 = string.Empty;

                        vertexProg2 =
                            "void SpriteFade_vp(	\n"+
                            "	float4 position : POSITION,	\n"+
                            "	float3 normal   : NORMAL,	\n"+
                            "	float4 color	: COLOR,	\n"+
                            "	float2 uv       : TEXCOORD0,	\n"+
                            "	out float4 oPosition : POSITION,	\n"+
                            "	out float2 oUv       : TEXCOORD0,	\n"+
                            "	out float4 oColor    : COLOR, \n"+
                            "	out float4 oFog      : FOG,	\n"+
                            "	uniform float4x4 worldViewProj,	\n"+

                            "	uniform float3 camPos, \n"+
                            "	uniform float fadeGap, \n"+
                            "   uniform float invisibleDist, \n" +

                            "	uniform float    uScroll, \n"+
                            "	uniform float    vScroll, \n"+
                            "	uniform float4   preRotatedQuad[4] )	\n"+
                            "{	\n"+
                            //Face the camera
                            "	float4 vCenter = float4( position.x, position.y, position.z, 1.0f );	\n"+
                            "	float4 vScale = float4( normal.x, normal.y, normal.x, 1.0f );	\n"+
                            "	oPosition = mul( worldViewProj, vCenter + (preRotatedQuad[normal.z] * vScale) );  \n"+

                            "	oColor.rgb = color.rgb;   \n"+

                            //Fade out in the distance
                            "	float dist = distance(camPos.xz, position.xz);	\n"+
                            "	oColor.a = (invisibleDist - dist) / fadeGap;   \n"+

                            //UV scroll
                            "	oUv = uv;	\n"+
                            "	oUv.x += uScroll; \n"+
                            "	oUv.y += vScroll; \n"+

                            //Fog
                            "	oFog.x = oPosition.z; \n"+
                            "}";

                        vertexShader2 = HighLevelGpuProgramManager.Instance.CreateProgram(
                            "SpriteFade_vp",
                            ResourceGroupManager.DefaultResourceGroupName,
                            "cg", GpuProgramType.Vertex);
                        vertexShader2.Source = vertexProg2;
                        vertexShader2.SetParam("profiles", "vs_1_1 arbvp1");
                        vertexShader2.SetParam("entry_point", "SpriteFade_vp");
                        vertexShader2.Load();
                    }
                }
            }
            else
            {
                //Compatible billboard method
                mFallbackSet = mSceneMgr.CreateBillboardSet(GetUniqueID("SBS"), 100);
                mNode.AttachObject(mFallbackSet);
            }
        }