public ParticleSystem(GraphicsDevice device, ContentManager content)
        {
            this.device = device;

            // Create vertex buffer used to spawn new particles
            this.particleStart = Buffer.Vertex.New<ParticleVertex>(device, MAX_NEW);

            // Create vertex buffers to use for updating and drawing the particles alternatively
            var vbFlags = BufferFlags.VertexBuffer | BufferFlags.StreamOutput;
            this.particleDrawFrom = Buffer.New<ParticleVertex>(device, MAX_PARTICLES, vbFlags);
            this.particleStreamTo = Buffer.New<ParticleVertex>(device, MAX_PARTICLES, vbFlags);

            this.layout = VertexInputLayout.FromBuffer(0, this.particleStreamTo);
            this.effect = content.Load<Effect>("ParticleEffect");
            this.texture = content.Load<Texture2D>("Dot");

            this.viewParameter = effect.Parameters["_view"];
            this.projParameter = effect.Parameters["_proj"];
            this.lookAtMatrixParameter = effect.Parameters["_lookAtMatrix"];
            this.elapsedSecondsParameter = effect.Parameters["_elapsedSeconds"];
            this.camDirParameter = effect.Parameters["_camDir"];
            this.gravityParameter = effect.Parameters["_gravity"];
            this.textureParameter = effect.Parameters["_texture"];
            this.samplerParameter = effect.Parameters["_sampler"];
            this.updatePass = effect.Techniques["UpdateTeq"].Passes[0];
            this.renderPass = effect.Techniques["RenderTeq"].Passes[0];
        }
Esempio n. 2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="PrimitiveQuad" /> class.
        /// </summary>
        /// <param name="graphicsDevice">The graphics device.</param>
        public PrimitiveQuad(GraphicsDevice graphicsDevice)
        {
            GraphicsDevice = graphicsDevice;
            quadEffect = ToDispose(new Effect(GraphicsDevice, effectBytecode));
            quadPass = quadEffect.CurrentTechnique.Passes[0];
            matrixParameter = quadEffect.Parameters["MatrixTransform"];

            textureCopyPass = quadEffect.CurrentTechnique.Passes[1];
            textureParameter = quadEffect.Parameters["Texture"];
            colorParameter = quadEffect.Parameters["Color"];
            textureSamplerParameter = quadEffect.Parameters["TextureSampler"];

            // Default LinearClamp
            textureSamplerParameter.SetResource(GraphicsDevice.SamplerStates.LinearClamp);

            Transform = Matrix.Identity;
            Color = new Color4(1.0f);

            sharedData = GraphicsDevice.GetOrCreateSharedData(SharedDataType.PerDevice, "Toolkit::PrimitiveQuad::VertexBuffer", () => new SharedData(GraphicsDevice));
        }
Esempio n. 3
0
        /// <summary>
        /// Lazily computes derived parameter values immediately before applying the effect.
        /// </summary>
        protected internal override EffectPass OnApply(EffectPass pass)
        {
            // Make sure that domain, hull and geometry shaders are disable.
            GraphicsDevice.DomainShaderStage.Set(null);
            GraphicsDevice.HullShaderStage.Set(null);
            GraphicsDevice.GeometryShaderStage.Set(null);

            // Recompute the world+view+projection matrix or fog vector?
            dirtyFlags = EffectHelpers.SetWorldViewProjAndFog(dirtyFlags, ref world, ref view, ref projection, ref worldView, fogEnabled, fogStart, fogEnd, worldViewProjParam, fogVectorParam);
            
            // Recompute the diffuse/emissive/alpha material color parameters?
            if ((dirtyFlags & EffectDirtyFlags.MaterialColor) != 0)
            {
                EffectHelpers.SetMaterialColor(lightingEnabled, alpha, ref diffuseColor, ref emissiveColor, ref ambientLightColor, diffuseColorParam, emissiveColorParam);

                dirtyFlags &= ~EffectDirtyFlags.MaterialColor;
            }

            if (lightingEnabled)
            {
                // Recompute the world inverse transpose and eye position?
                dirtyFlags = EffectHelpers.SetLightingMatrices(dirtyFlags, ref world, ref view, worldParam, worldInverseTransposeParam, eyePositionParam);
                
                // Check if we can use the only-bother-with-the-first-light shader optimization.
                bool newOneLight = !light1.Enabled && !light2.Enabled;
                
                if (oneLight != newOneLight)
                {
                    oneLight = newOneLight;
                    dirtyFlags |= EffectDirtyFlags.ShaderIndex;
                }
            }

            // Recompute the shader index?
            if ((dirtyFlags & EffectDirtyFlags.ShaderIndex) != 0)
            {
                int shaderIndex = 0;
                
                if (!fogEnabled)
                    shaderIndex += 1;
                
                if (vertexColorEnabled)
                    shaderIndex += 2;
                
                if (textureEnabled)
                    shaderIndex += 4;

                if (lightingEnabled)
                {
                    if (preferPerPixelLighting)
                        shaderIndex += 24;
                    else if (oneLight)
                        shaderIndex += 16;
                    else
                        shaderIndex += 8;
                }

                shaderPass = pass.SubPasses[shaderIndex];

                dirtyFlags &= ~EffectDirtyFlags.ShaderIndex;
            }

            // Call the base class to process callbacks
            pass = base.OnApply(shaderPass);

            return pass;
        }
Esempio n. 4
0
        /// <summary>
        /// Lazily computes derived parameter values immediately before applying the effect.
        /// </summary>
        protected internal override EffectPass OnApply(EffectPass pass)
        {
            // Recompute the world+view+projection matrix or fog vector?
            dirtyFlags = EffectHelpers.SetWorldViewProjAndFog(dirtyFlags, ref world, ref view, ref projection, ref worldView, fogEnabled, fogStart, fogEnd, worldViewProjParam, fogVectorParam);

            // Recompute the world inverse transpose and eye position?
            dirtyFlags = EffectHelpers.SetLightingMatrices(dirtyFlags, ref world, ref view, worldParam, worldInverseTransposeParam, eyePositionParam);
            
            // Recompute the diffuse/emissive/alpha material color parameters?
            if ((dirtyFlags & EffectDirtyFlags.MaterialColor) != 0)
            {
                EffectHelpers.SetMaterialColor(true, alpha, ref diffuseColor, ref emissiveColor, ref ambientLightColor, diffuseColorParam, emissiveColorParam);

                dirtyFlags &= ~EffectDirtyFlags.MaterialColor;
            }

            // Check if we can use the only-bother-with-the-first-light shader optimization.
            bool newOneLight = !light1.Enabled && !light2.Enabled;
            
            if (oneLight != newOneLight)
            {
                oneLight = newOneLight;
                dirtyFlags |= EffectDirtyFlags.ShaderIndex;
            }

            // Recompute the shader index?
            if ((dirtyFlags & EffectDirtyFlags.ShaderIndex) != 0)
            {
                int shaderIndex = 0;
                
                if (!fogEnabled)
                    shaderIndex += 1;
                
                if (weightsPerVertex == 2)
                    shaderIndex += 2;
                else if (weightsPerVertex == 4)
                    shaderIndex += 4;
                
                if (preferPerPixelLighting)
                    shaderIndex += 12;
                else if (oneLight)
                    shaderIndex += 6;

                shaderPass = pass.SubPasses[shaderIndex];

                dirtyFlags &= ~EffectDirtyFlags.ShaderIndex;
            }

            return base.OnApply(shaderPass);
        }
Esempio n. 5
0
        protected internal virtual EffectPass OnApply(EffectPass pass)
        {
            var handler = OnApplyCallback;
            if (handler != null) pass = handler(pass);

            return pass;
        }
Esempio n. 6
0
        /// <summary>
        /// Binds the specified effect data to this instance.
        /// </summary>
        /// <param name="effectDataArg">The effect data arg.</param>
        /// <param name="cloneFromEffect">The clone from effect.</param>
        /// <exception cref="System.InvalidOperationException">If no techniques found in this effect.</exception>
        /// <exception cref="System.ArgumentException">If unable to find effect [effectName] from the EffectPool.</exception>
        internal void InitializeFrom(EffectData.Effect effectDataArg, Effect cloneFromEffect)
        {
            RawEffectData = effectDataArg;

            // Clean any previously allocated resources
            if (DisposeCollector != null)
            {
                DisposeCollector.DisposeAndClear();
            }
            ConstantBuffers.Clear();
            Parameters.Clear();
            Techniques.Clear();
            ResourceLinker = ToDispose(new EffectResourceLinker());
            if (effectConstantBuffersCache != null)
            {
                effectConstantBuffersCache.Clear();
            }

            // Copy data
            IsSupportingDynamicCompilation = RawEffectData.Arguments != null;
            ShareConstantBuffers = RawEffectData.ShareConstantBuffers;

            // Create the local effect constant buffers cache
            if (!ShareConstantBuffers)
                effectConstantBuffersCache = new Dictionary<EffectConstantBufferKey, EffectConstantBuffer>();

            var logger = new Logger();
            int techniqueIndex = 0;
            int totalPassCount = 0;
            EffectPass parentPass = null;
            foreach (var techniqueRaw in RawEffectData.Techniques)
            {
                var name = techniqueRaw.Name;
                if (string.IsNullOrEmpty(name))
                    name = string.Format("${0}", techniqueIndex++);

                var technique = new EffectTechnique(this, name);
                Techniques.Add(technique);

                int passIndex = 0;
                foreach (var passRaw in techniqueRaw.Passes)
                {
                    name = passRaw.Name;
                    if (string.IsNullOrEmpty(name))
                        name = string.Format("${0}", passIndex++);

                    var pass = new EffectPass(logger, this, technique, passRaw, name);

                    pass.Initialize(logger);

                    // If this is a subpass, add it to the parent pass
                    if (passRaw.IsSubPass)
                    {
                        if (parentPass == null)
                        {
                            logger.Error("Pass [{0}] is declared as a subpass but has no parent.");
                        }
                        else
                        {
                            parentPass.SubPasses.Add(pass);
                        }
                    }
                    else
                    {
                        technique.Passes.Add(pass);
                        parentPass = pass;
                    }
                }

                // Count the number of passes
                totalPassCount += technique.Passes.Count;
            }

            if (totalPassCount == 0)
                throw new InvalidOperationException("No passes found in this effect.");

            // Log all the exception in a single throw
            if (logger.HasErrors)
                throw new InvalidOperationException(Utilities.Join("\n", logger.Messages));

            // Initialize the resource linker when we are done with all pass/parameters
            ResourceLinker.Initialize();

            //// Sort all parameters by their resource types
            //// in order to achieve better local cache coherency in resource linker
            Parameters.Items.Sort((left, right) =>
                {
                    // First, order first all value types, then resource type
                    var comparison = left.IsValueType != right.IsValueType ? left.IsValueType ? -1 : 1 : 0;

                    // If same type
                    if (comparison == 0)
                    {
                        // Order by resource type
                        comparison = ((int)left.ResourceType).CompareTo((int)right.ResourceType);

                        // If same, order by resource index
                        if (comparison == 0)
                        {
                            comparison = left.Offset.CompareTo(right.Offset);
                        }
                    }
                    return comparison;
                });

            // Prelink constant buffers
            int resourceIndex = 0;
            foreach (var parameter in Parameters)
            {
                // Recalculate parameter resource index
                if (!parameter.IsValueType)
                {
                    parameter.Offset = resourceIndex++;
                }

                // Set the default values 
                parameter.SetDefaultValue();

                if (parameter.ResourceType == EffectResourceType.ConstantBuffer)
                    parameter.SetResource(ConstantBuffers[parameter.Name]);
            }

            // Compute slot links
            foreach (var technique in Techniques)
            {
                foreach (var pass in technique.Passes)
                {
                    foreach (var subPass in pass.SubPasses)
                    {
                        subPass.ComputeSlotLinks();
                    }
                    pass.ComputeSlotLinks();
                }
            }

            // Setup the first Current Technique.
            CurrentTechnique = this.Techniques[0];

            // Initialize predefined parameters used by Model.Draw (to speedup things internally)
            DefaultParameters = new EffectDefaultParameters(this);

            // If this is a clone, we need to 
            if (cloneFromEffect != null)
            {
                // Copy the content of the constant buffers to the new instance.
                for (int i = 0; i < ConstantBuffers.Count; i++)
                {
                    cloneFromEffect.ConstantBuffers[i].CopyTo(ConstantBuffers[i]);
                }

                // Copy back all bound resources except constant buffers
                // that are already initialized with InitializeFrom method.
                for (int i = 0; i < cloneFromEffect.ResourceLinker.Count; i++)
                {
                    if (cloneFromEffect.ResourceLinker.BoundResources[i] is EffectConstantBuffer)
                        continue;

                    ResourceLinker.BoundResources[i] = cloneFromEffect.ResourceLinker.BoundResources[i];
                    unsafe
                    {
                        ResourceLinker.Pointers[i] = cloneFromEffect.ResourceLinker.Pointers[i];
                    }
                }

                // If everything was fine, then we can register it into the pool
                Pool.AddEffect(this);
            }

            // Allow subclasses to complete initialization.
            Initialize();
        }
Esempio n. 7
0
        /// <summary>
        /// Initializes the specified effect bytecode.
        /// </summary>
        /// <param name="effectDataArg">The effect bytecode.</param>
        /// <exception cref="System.InvalidOperationException"></exception>
        private void Initialize(EffectData.Effect effectDataArg)
        {
            if (effectDataArg == null)
                throw new ArgumentException(string.Format("Unable to find effect [{0}] from the EffectPool", Name), "effectName");

            rawEffect = effectDataArg;

            ShareConstantBuffers = effectDataArg.ShareConstantBuffers;

            // Create the local effect constant buffers cache
            if (!ShareConstantBuffers)
                effectConstantBuffersCache = new Dictionary<EffectConstantBufferKey, EffectConstantBuffer>();

            if (effectDataArg.Techniques.Count == 0)
                throw new InvalidOperationException("No techniques found in this effect");

            var logger = new Logger();
            int techniqueIndex = 0;
            int totalPassCount = 0;
            EffectPass parentPass = null;
            foreach (var techniqueRaw in effectDataArg.Techniques)
            {
                var name = techniqueRaw.Name;
                if (string.IsNullOrEmpty(name))
                    name = string.Format("${0}", techniqueIndex++);

                var technique = new EffectTechnique(this, name);
                Techniques.Add(technique);

                int passIndex = 0;
                foreach (var passRaw in techniqueRaw.Passes)
                {
                    name = passRaw.Name;
                    if (string.IsNullOrEmpty(name))
                        name = string.Format("${0}", passIndex++);

                    var pass = new EffectPass(logger, this, technique, passRaw, name);

                    pass.Initialize(logger);

                    // If this is a subpass, add it to the parent pass
                    if (passRaw.IsSubPass)
                    {
                        if (parentPass == null)
                        {
                            logger.Error("Pass [{0}] is declared as a subpass but has no parent");
                        }
                        else
                        {
                            parentPass.SubPasses.Add(pass);
                        }
                    }
                    else
                    {
                        technique.Passes.Add(pass);
                        parentPass = pass;
                    }
                }

                // Count the number of passes
                totalPassCount += technique.Passes.Count;
            }

            if (totalPassCount == 0)
                throw new InvalidOperationException("No passes found in this effect");

            // Log all the exception in a single throw
            if (logger.HasErrors)
                throw new InvalidOperationException(Utilities.Join("\n", logger.Messages));

            // Initialize the resource linker when we are done with all pass/parameters
            ResourceLinker.Initialize();

            //// Sort all parameters by their resource types
            //// in order to achieve better local cache coherency in resource linker
            Parameters.Items.Sort((left, right) =>
                {
                    // First, order first all value types, then resource type
                    var comparison = left.IsValueType != right.IsValueType ? left.IsValueType ? -1 : 1 : 0;

                    // If same type
                    if (comparison == 0)
                    {
                        // Order by resource type
                        comparison = ((int)left.ResourceType).CompareTo((int)right.ResourceType);

                        // If same, order by resource index
                        if (comparison == 0)
                        {
                            comparison = left.Offset.CompareTo(right.Offset);
                        }
                    }
                    return comparison;
                });

            // Prelink constant buffers
            int resourceIndex = 0;
            foreach (var parameter in Parameters)
            {
                // Recalculate parameter resource index
                if (!parameter.IsValueType)
                {
                    parameter.Offset = resourceIndex++;
                }

                // Set the default values 
                parameter.SetDefaultValue();

                if (parameter.ResourceType == EffectResourceType.ConstantBuffer)
                    parameter.SetResource(0, ConstantBuffers[parameter.Name]);
            }

            // Compute slot links
            foreach (var technique in Techniques)
            {
                foreach (var pass in technique.Passes)
                {
                    foreach (var subPass in pass.SubPasses)
                    {
                        subPass.ComputeSlotLinks();
                    }
                    pass.ComputeSlotLinks();
                }
            }

            // Setup the first Current Technique.
            CurrentTechnique = this.Techniques[0];
        }
Esempio n. 8
0
        /// <summary>
        /// Draws the specified effect pass onto the quad. The effect pass must have a pixel shader with the signature float2:TEXCOORD.
        /// </summary>
        /// <param name="effectPass">The effect pass.</param>
        /// <param name="fullScreenTriangle">if set to <c>true</c> to draw an optimized full screen triangle as a full screen quad.</param>
        public void Draw(EffectPass effectPass, bool fullScreenTriangle = false)
        {
            ResetShaderStages();

            // Apply the Effect pass
            effectPass.Apply();
            Draw(fullScreenTriangle);

            // Unapply this effect
            effectPass.UnApply();
        }
        protected override EffectPass OnApply(EffectPass pass)
        {
            _pixelShaderConstantBuffer.Update();

            return base.OnApply(pass);
        }
Esempio n. 10
0
        ///// <summary>
        ///// Creates a new DualTextureEffect by cloning parameter settings from an existing instance.
        ///// </summary>
        //protected DualTextureEffect(DualTextureEffect cloneSource)
        //    : base(cloneSource)
        //{
        //    CacheEffectParameters();

        //    fogEnabled = cloneSource.fogEnabled;
        //    vertexColorEnabled = cloneSource.vertexColorEnabled;

        //    world = cloneSource.world;
        //    view = cloneSource.view;
        //    projection = cloneSource.projection;

        //    diffuseColor = cloneSource.diffuseColor;

        //    alpha = cloneSource.alpha;

        //    fogStart = cloneSource.fogStart;
        //    fogEnd = cloneSource.fogEnd;
        //}


        ///// <summary>
        ///// Creates a clone of the current DualTextureEffect instance.
        ///// </summary>
        //public override Effect Clone()
        //{
        //    return new DualTextureEffect(this);
        //}

        /// <summary>
        /// Lazily computes derived parameter values immediately before applying the effect.
        /// </summary>
        protected internal override EffectPass OnApply(EffectPass pass)
        {
            // Recompute the world+view+projection matrix or fog vector?
            dirtyFlags = EffectHelpers.SetWorldViewProjAndFog(dirtyFlags, ref world, ref view, ref projection, ref worldView, fogEnabled, fogStart, fogEnd, worldViewProjParam, fogVectorParam);

            // Recompute the diffuse/alpha material color parameter?
            if ((dirtyFlags & EffectDirtyFlags.MaterialColor) != 0)
            {
                diffuseColorParam.SetValue(new Vector4(diffuseColor * alpha, alpha));

                dirtyFlags &= ~EffectDirtyFlags.MaterialColor;
            }

            // Recompute the shader index?
            if ((dirtyFlags & EffectDirtyFlags.ShaderIndex) != 0)
            {
                int shaderIndex = 0;
                
                if (!fogEnabled)
                    shaderIndex += 1;
                
                if (vertexColorEnabled)
                    shaderIndex += 2;

                shaderPass = pass.SubPasses[shaderIndex];

                dirtyFlags &= ~EffectDirtyFlags.ShaderIndex;
            }

            return base.OnApply(shaderPass);
        }
Esempio n. 11
0
        protected override EffectPass OnApply(EffectPass pass)
        {
            var device = this.GraphicsDevice;

            device.SetVertexInputLayout(m_vertexInputLayout);

            return base.OnApply(pass);
        }
Esempio n. 12
0
        ///// <summary>
        ///// Creates a new AlphaTestEffect by cloning parameter settings from an existing instance.
        ///// </summary>
        //protected AlphaTestEffect(AlphaTestEffect cloneSource)
        //    : base(cloneSource)
        //{
        //    fogEnabled = cloneSource.fogEnabled;
        //    vertexColorEnabled = cloneSource.vertexColorEnabled;

        //    world = cloneSource.world;
        //    view = cloneSource.view;
        //    projection = cloneSource.projection;

        //    diffuseColor = cloneSource.diffuseColor;

        //    alpha = cloneSource.alpha;

        //    fogStart = cloneSource.fogStart;
        //    fogEnd = cloneSource.fogEnd;
            
        //    alphaFunction = cloneSource.alphaFunction;
        //    referenceAlpha = cloneSource.referenceAlpha;
        //}


        ///// <summary>
        ///// Creates a clone of the current AlphaTestEffect instance.
        ///// </summary>
        //public override Effect Clone()
        //{
        //    return new AlphaTestEffect(this);
        //}

        /// <summary>
        /// Lazily computes derived parameter values immediately before applying the effect.
        /// </summary>
        protected internal override EffectPass OnApply(EffectPass pass)
        {
            // Recompute the world+view+projection matrix or fog vector?
            dirtyFlags = EffectHelpers.SetWorldViewProjAndFog(dirtyFlags, ref world, ref view, ref projection, ref worldView, fogEnabled, fogStart, fogEnd, worldViewProjParam, fogVectorParam);

            // Recompute the diffuse/alpha material color parameter?
            if ((dirtyFlags & EffectDirtyFlags.MaterialColor) != 0)
            {
                diffuseColorParam.SetValue(new Vector4(diffuseColor * alpha, alpha));

                dirtyFlags &= ~EffectDirtyFlags.MaterialColor;
            }

            // Recompute the alpha test settings?
            if ((dirtyFlags & EffectDirtyFlags.AlphaTest) != 0)
            {
                var alphaTest = new Vector4();
                bool eqNe = false;
                
                // Convert reference alpha from 8 bit integer to 0-1 float format.
                float reference = (float)referenceAlpha / 255f;
                
                // Comparison tolerance of half the 8 bit integer precision.
                const float threshold = 0.5f / 255f;
                
                switch (alphaFunction)
                {
                    case Direct3D11.Comparison.Less:
                        // Shader will evaluate: clip((a < x) ? z : w)
                        alphaTest.X = reference - threshold;
                        alphaTest.Z = 1;
                        alphaTest.W = -1;
                        break;

                    case Direct3D11.Comparison.LessEqual:
                        // Shader will evaluate: clip((a < x) ? z : w)
                        alphaTest.X = reference + threshold;
                        alphaTest.Z = 1;
                        alphaTest.W = -1;
                        break;

                    case Direct3D11.Comparison.GreaterEqual:
                        // Shader will evaluate: clip((a < x) ? z : w)
                        alphaTest.X = reference - threshold;
                        alphaTest.Z = -1;
                        alphaTest.W = 1;
                        break;

                    case Direct3D11.Comparison.Greater:
                        // Shader will evaluate: clip((a < x) ? z : w)
                        alphaTest.X = reference + threshold;
                        alphaTest.Z = -1;
                        alphaTest.W = 1;
                        break;

                    case Direct3D11.Comparison.Equal:
                        // Shader will evaluate: clip((abs(a - x) < Y) ? z : w)
                        alphaTest.X = reference;
                        alphaTest.Y = threshold;
                        alphaTest.Z = 1;
                        alphaTest.W = -1;
                        eqNe = true;
                        break;

                    case Direct3D11.Comparison.NotEqual:
                        // Shader will evaluate: clip((abs(a - x) < Y) ? z : w)
                        alphaTest.X = reference;
                        alphaTest.Y = threshold;
                        alphaTest.Z = -1;
                        alphaTest.W = 1;
                        eqNe = true;
                        break;

                    case Direct3D11.Comparison.Never:
                        // Shader will evaluate: clip((a < x) ? z : w)
                        alphaTest.Z = -1;
                        alphaTest.W = -1;
                        break;

                    case Direct3D11.Comparison.Always:
                    default:
                        // Shader will evaluate: clip((a < x) ? z : w)
                        alphaTest.Z = 1;
                        alphaTest.W = 1;
                        break;
                }
                
                alphaTestParam.SetValue(alphaTest);

                dirtyFlags &= ~EffectDirtyFlags.AlphaTest;
                
                // If we changed between less/greater vs. equal/notequal
                // compare modes, we must also update the shader index.
                if (isEqNe != eqNe)
                {
                    isEqNe = eqNe;
                    dirtyFlags |= EffectDirtyFlags.ShaderIndex;
                }
            }

            // Recompute the shader index?
            if ((dirtyFlags & EffectDirtyFlags.ShaderIndex) != 0)
            {
                int shaderIndex = 0;
                
                if (!fogEnabled)
                    shaderIndex += 1;
                
                if (vertexColorEnabled)
                    shaderIndex += 2;
                
                if (isEqNe)
                    shaderIndex += 4;

                shaderPass = pass.SubPasses[shaderIndex];

                dirtyFlags &= ~EffectDirtyFlags.ShaderIndex;
            }

            return base.OnApply(shaderPass);
        }