public STrailsEmitter(STrailsParameters tParams,
                                      PositionFunc posFunc, FwdFunc fwdDirFunc)
                {
                    this.trailParams = tParams;
                    this.posFunc     = posFunc;
                    this.fwdDirFunc  = fwdDirFunc;

                    base.life             = tParams.trailLifetime;
                    base.emissionInterval = tParams.trailsEmissionInterval;
                    base.velocity         = Vector3.Zero;
                    base.color            = new Color4(1f, 1f, 1f, 0.3f);
                }
        public STrailsRenderer(PositionFunc positonFunc, FwdFunc fwdDirFunc, UpFunc upFunc,
                               STrailsParameters trailsParams = null)
            : base(new STrailsData(positonFunc, fwdDirFunc, upFunc,
                                   trailsParams ?? new STrailsParameters()),
                   SSTexturedCube.Instance, _defaultUsageHint)
        {
            trailsParams = trailsData.trailsParams;
            var tex = SSAssetManager.GetInstance <SSTextureWithAlpha>(trailsParams.textureFilename);

            renderState.castsShadow     = false;
            renderState.receivesShadows = false;
            renderState.doBillboarding  = false;
            renderState.alphaBlendingOn = true;
            //renderState.alphaBlendingOn = false;
            renderState.depthTest  = true;
            renderState.depthWrite = false;
            renderState.lighted    = false;

            renderState.blendEquationModeRGB = BlendEquationMode.FuncAdd;
            renderState.blendFactorSrcRGB    = BlendingFactorSrc.SrcAlpha;
            //renderState.blendFactorDestRGB = BlendingFactorDest.DstAlpha;
            renderState.blendFactorDestRGB = BlendingFactorDest.OneMinusSrc1Alpha;

            renderState.blendEquationModeAlpha = BlendEquationMode.FuncAdd;
            renderState.blendFactorSrcAlpha    = BlendingFactorSrc.One;
            renderState.blendFactorDestAlpha   = BlendingFactorDest.One;
            //renderState.blendFactorSrcAlpha = BlendingFactorSrc.SrcAlpha;
            renderState.blendFactorDestAlpha = BlendingFactorDest.OneMinusSrcAlpha;

            simulateOnUpdate = false;
            simulateOnRender = true;

            renderState.frustumCulling = true;

            colorMaterial   = SSColorMaterial.pureAmbient;
            textureMaterial = new SSTextureMaterial(diffuse: tex);
            Name            = "simple trails renderer";

            //this.MainColor = Color4Helper.RandomDebugColor();
            this.renderMode = RenderMode.GpuInstancing;
        }
            //protected readonly STrailUpdater _updater;
            #endregion

            public STrailsData(
                PositionFunc positionFunc, FwdFunc fwdDirFunc, UpFunc upFunc,
                STrailsParameters trailsParams = null)
                : base(trailsParams.capacity)
            {
                this.trailsParams  = trailsParams;
                this._positionFunc = positionFunc;
                this._fwdFunc      = fwdDirFunc;
                this._upFunc       = upFunc;

                _headSegmentIdxs            = new ushort[trailsParams.numJets];
                _tailSegmentIdxs            = new ushort[trailsParams.numJets];
                _prevSplineIntervalEndPos   = new Vector3[trailsParams.numJets];
                _prevSplineIntervalEndSlope = new Vector3[trailsParams.numJets];
                _localJetOrients            = new Matrix4[trailsParams.numJets];

                Vector3 pos          = _positionFunc();
                Vector3 fwd          = _fwdFunc();
                Vector3 up           = _upFunc();
                Vector3 right        = Vector3.Cross(fwd, up);
                Matrix4 globalOrient = new Matrix4(
                    new Vector4(right, 0f),
                    new Vector4(up, 0f),
                    new Vector4(fwd, 0f),
                    new Vector4(0f, 0f, 0f, 1f));

                for (int i = 0; i < trailsParams.numJets; ++i)
                {
                    _headSegmentIdxs[i] = STrailsSegment.NotConnected;
                    _tailSegmentIdxs[i] = STrailsSegment.NotConnected;
                    Vector3 localFwd = trailsParams.localJetDir(i);
                    _localJetOrients[i] = OpenTKHelper.neededRotationMat(-Vector3.UnitZ, localFwd);
                    jetTxfm(i, ref pos, ref globalOrient,
                            out _prevSplineIntervalEndPos[i], out _prevSplineIntervalEndSlope[i]);
                }

                _outerColorEffector = new SSColorKeyframesEffector(trailsParams.outerColorKeyframes)
                {
                    particleLifetime = trailsParams.trailLifetime,
                };
                addEffector(_outerColorEffector);

                _innerColorEffector = new STrailsInnerColorEffector(trailsParams.innerColorKeyframes)
                {
                    particleLifetime = trailsParams.trailLifetime,
                };
                addEffector(_innerColorEffector);


                _innerRatioEffector = new STrailsInnerColorRatioEffector(trailsParams.innerColorRatioKeyframes)
                {
                    particleLifetime = trailsParams.trailLifetime,
                };
                addEffector(_innerRatioEffector);

                _outerRatioEffector = new STrailsOuterColorRatioEffector(trailsParams.outerColorRatioKeyframes)
                {
                    particleLifetime = trailsParams.trailLifetime,
                };
                addEffector(_outerRatioEffector);

                _widthEffector = new STrailsWidthEffector(trailsParams.widthKeyFrames)
                {
                    particleLifetime = trailsParams.trailLifetime,
                };
                addEffector(_widthEffector);


                //_updater = new STrailUpdater(trailsParams);
                //addEffector(_updater);
            }