/// <summary> /// Attach another GLSL Shader to this one. /// </summary> /// <param name="name"></param> public void AttachChildShader(string name) { // is the name valid and already loaded? // check with the high level program manager to see if it was loaded HighLevelGpuProgram hlProgram = HighLevelGpuProgramManager.Instance.GetByName(name); if (hlProgram != null) { if (hlProgram.SyntaxCode == "glsl") { // make sure attached program source gets loaded and compiled // don't need a low level implementation for attached shader objects // loadHighLevelImpl will only load the source and compile once // so don't worry about calling it several times GLSLProgram childShader = (GLSLProgram)hlProgram; // load the source and attach the child shader only if supported if (IsSupported) { childShader.LoadHighLevelImpl(); // add to the constainer attachedGLSLPrograms.Add(childShader); attachedShaderNames += name + " "; } } } }
public override void destroy(HighLevelGpuProgram prog) { OgrePINVOKE.UnifiedHighLevelGpuProgramFactory_destroy(swigCPtr, HighLevelGpuProgram.getCPtr(prog)); if (OgrePINVOKE.SWIGPendingException.Pending) { throw OgrePINVOKE.SWIGPendingException.Retrieve(); } }
public override HighLevelGpuProgram create(ResourceManager creator, string name, ulong handle, string group, bool isManual, ManualResourceLoader loader) { global::System.IntPtr cPtr = OgrePINVOKE.UnifiedHighLevelGpuProgramFactory_create(swigCPtr, ResourceManager.getCPtr(creator), name, handle, group, isManual, ManualResourceLoader.getCPtr(loader)); HighLevelGpuProgram ret = (cPtr == global::System.IntPtr.Zero) ? null : new HighLevelGpuProgram(cPtr, false); if (OgrePINVOKE.SWIGPendingException.Pending) { throw OgrePINVOKE.SWIGPendingException.Retrieve(); } return(ret); }
public HighLevelGpuProgram __deref__() { global::System.IntPtr cPtr = OgrePINVOKE.HighLevelGpuProgramPtr___deref__(swigCPtr); HighLevelGpuProgram ret = (cPtr == global::System.IntPtr.Zero) ? null : new HighLevelGpuProgram(cPtr, false); if (OgrePINVOKE.SWIGPendingException.Pending) { throw OgrePINVOKE.SWIGPendingException.Retrieve(); } return(ret); }
public Program(string name, HighLevelGpuProgram vs, HighLevelGpuProgram ps, IEnumerable <VariableDescription> samplers) { VertexShader = vs; PixelShader = ps; LogManager.Instance.Write("VS:"); LogManager.Instance.Write("================================================================================"); LogManager.Instance.Write(vs.Source); LogManager.Instance.Write("PS:"); LogManager.Instance.Write("================================================================================"); LogManager.Instance.Write(ps.Source); var mm = MaterialManager.Instance; Material = (Material)mm.Create(name, "SLSharp"); var mat = Material; mat.RemoveAllTechniques(); _tech = mat.CreateTechnique(); _tech.SchemeName = "SLSharp"; _tech.RemoveAllPasses(); Pass = _tech.CreatePass(); if (vs != null) { Pass.SetVertexProgram(vs.Name); } if (ps != null) { Pass.SetFragmentProgram(ps.Name); } foreach (var s in samplers) { var tu = Pass.CreateTextureUnitState(); tu.Name = s.Name; _textureUnits.Add(s.Name, tu); } Pass.LightingEnabled = false; mat.Load(); MatToProg.Add(mat, this); }
internal static global::System.Runtime.InteropServices.HandleRef getCPtr(HighLevelGpuProgram obj) { return((obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr); }
public override void DestroyInstance(ref HighLevelGpuProgram obj) { base.DestroyInstance(ref obj); }
/// <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; } } }
private void BindSubShaders(Program program, GpuProgram gpuProgram) { if (program.DependencyCount > 0) { // Get all attached shaders so we do not attach shaders twice. // maybe GLSLProgram should take care of that ( prevent add duplicate shaders ) string attachedShaders = string.Empty; //TODO: gpuProgram.GetParameter("attach"); string subSharedDef = string.Empty; for (int i = 0; i < program.DependencyCount; i++) { // Here we append _VS and _FS to the library shaders (so max each lib shader // is compiled twice once as vertex and once as fragment shader) string subShaderName = program.GetDependency(i); if (program.Type == GpuProgramType.Vertex) { subShaderName += "_VS"; } else { subShaderName += "_FS"; } //Check if the library shader already compiled if (!HighLevelGpuProgramManager.Instance.ResourceExists(subShaderName)) { //Create the library shader HighLevelGpuProgram subGpuProgram = HighLevelGpuProgramManager.Instance.CreateProgram(subShaderName, ResourceGroupManager. DefaultResourceGroupName, TargetLanguage, program.Type); //Set the source name string sourceName = program.GetDependency(i) + "." + TargetLanguage; subGpuProgram.SourceFile = sourceName; //If we have compiler errors than stop processing if (subGpuProgram.HasCompileError) { throw new AxiomException("Could not compile shader library from the source file: " + sourceName); } this.libraryPrograms.Add(subShaderName); } //Check if the lib shader already attached to this shader if (attachedShaders.Contains(subShaderName)) { subSharedDef += subShaderName + " "; } } //Check if we have something to attach if (subSharedDef.Length > 0) { var nvpl = new Axiom.Collections.NameValuePairList(); nvpl.Add("attach", subSharedDef); gpuProgram.SetParameters(nvpl); } } }
protected void _translateUnifiedGpuProgram(ScriptCompiler compiler, ObjectAbstractNode obj) { var customParameters = new NameValuePairList(); AbstractNode parameters = null; foreach (var i in obj.Children) { if (i is PropertyAbstractNode) { var prop = (PropertyAbstractNode)i; if (prop.Name == "delegate") { var value = string.Empty; if (prop.Values.Count != 0 && prop.Values[0] is AtomAbstractNode) { value = ((AtomAbstractNode)prop.Values[0]).Value; } ScriptCompilerEvent evt = new ProcessResourceNameScriptCompilerEvent(ProcessResourceNameScriptCompilerEvent.ResourceType.GpuProgram, value); compiler._fireEvent(ref evt); customParameters["delegate"] = ((ProcessResourceNameScriptCompilerEvent)evt).Name; } else { var name = prop.Name; var value = string.Empty; var first = true; foreach (var it in prop.Values) { if (it is AtomAbstractNode) { if (!first) { value += " "; } else { first = false; } value += ((AtomAbstractNode)it).Value; } } customParameters.Add(name, value); } } else if (i is ObjectAbstractNode) { if (((ObjectAbstractNode)i).Id == (uint)Keywords.ID_DEFAULT_PARAMS) { parameters = i; } else { processNode(compiler, i); } } } // Allocate the program Object progObj; HighLevelGpuProgram prog = null; ScriptCompilerEvent evnt = new CreateHighLevelGpuProgramScriptCompilerEvent(obj.File, obj.Name, compiler.ResourceGroup, string.Empty, "unified", _translateIDToGpuProgramType(obj.Id)); var processed = compiler._fireEvent(ref evnt, out progObj); if (!processed) { prog = (HighLevelGpuProgram) (HighLevelGpuProgramManager.Instance.CreateProgram(obj.Name, compiler.ResourceGroup, "unified", _translateIDToGpuProgramType(obj.Id))); } else { prog = (HighLevelGpuProgram)progObj; } // Check that allocation worked if (prog == null) { compiler.AddError(CompileErrorCode.ObjectAllocationError, obj.File, obj.Line, "gpu program \"" + obj.Name + "\" could not be created"); return; } obj.Context = prog; prog.IsMorphAnimationIncluded = false; prog.PoseAnimationCount = 0; prog.IsSkeletalAnimationIncluded = false; prog.IsVertexTextureFetchRequired = false; prog.Origin = obj.File; // Set the custom parameters prog.SetParameters(customParameters); // Set up default parameters if (prog.IsSupported && parameters != null) { var ptr = prog.DefaultParameters; GpuProgramTranslator.TranslateProgramParameters(compiler, ptr, (ObjectAbstractNode)parameters); } }
/// <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; } }
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); }
/// <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); } }