private void _ScriptCodeを解析する(エフェクト effect, テクニック technique = null, パス pass = null) { 実行するファンクションのリスト = new List <関数>(); if (string.IsNullOrWhiteSpace(ScriptCode)) { return; } string[] splittedFunctions = ScriptCode.Split(';'); // ';' で分割し1命令ごとにする foreach (string function in splittedFunctions) { if (string.IsNullOrWhiteSpace(function)) { continue; } int 連番 = 0; // 省略時は 0 string[] segments = function.Split('='); // '=' で分割し、関数名と引数を分ける if (segments.Length > 2) { throw new InvalidMMEEffectShader例外("スクリプト中の'='の数が多すぎます。"); } char 関数名の末尾の文字 = segments[0][segments[0].Length - 1]; if (char.IsNumber(関数名の末尾の文字)) { segments[0] = segments[0].Remove(segments[0].Length - 1); 連番 = int.Parse(関数名の末尾の文字.ToString()); } if (現在対応しているファンクションの一覧.ContainsKey(segments[0])) { 実行するファンクションのリスト.Add( 現在対応しているファンクションの一覧[segments[0]].ファンクションインスタンスを作成する(連番, segments[1], this, effect, technique, pass) ); } } }
/// <summary> /// 自身のインスタンスを作成して返す。 /// </summary> /// <param name="index">連番。ファンクション名の末尾に付与される1桁の数値(0~9)。省略時は 0 。</param> /// <param name="value">値。ファンクション名と '=' を挟んだ右辺に記された文字列。</param> /// <param name="runtime"></param> /// <param name="effect">ファンクションが属しているエフェクト。</param> /// <param name="technique">ファンクションが属しているテクニック。パスに属している場合には null を指定。</param> /// <param name="pass">ファンクションが属しているパス。テクニックに属している場合には null を指定。</param> /// <returns></returns> public override 関数 ファンクションインスタンスを作成する(int index, string value, ScriptRuntime runtime, エフェクト effect, テクニック technique, パス pass) { var func = new LoopGetIndex関数(); func._targetVariable = effect.D3DEffect.GetVariableByName(value); func._runtime = runtime; return(func); }
public override 関数 ファンクションインスタンスを作成する(int index, string value, ScriptRuntime runtime, エフェクト effect, テクニック technique, パス pass) { return(new ScriptExternal関数()); // TODO: 未実装 }
/// <summary> /// 自身のインスタンスを作成して返す。 /// </summary> /// <param name="index">連番。ファンクション名の末尾に付与される1桁の数値(0~9)。省略時は 0 。</param> /// <param name="value">値。ファンクション名と '=' を挟んだ右辺に記された文字列。</param> /// <param name="runtime"></param> /// <param name="effect">ファンクションが属しているエフェクト。</param> /// <param name="technique">ファンクションが属しているテクニック。パスに属している場合には null を指定。</param> /// <param name="pass">ファンクションが属しているパス。テクニックに属している場合には null を指定。</param> /// <returns></returns> public override 関数 ファンクションインスタンスを作成する(int index, string value, ScriptRuntime runtime, エフェクト effect, テクニック technique, パス pass) { var func = new ClearSetColor関数(); func._sourceVariable = effect.D3DEffect.GetVariableByName(value); if (func._sourceVariable == null) { throw new InvalidMMEEffectShader例外($"ClearSetColor={value};が指定されましたが、変数\"{value}\"は見つかりませんでした。"); } if (!func._sourceVariable.TypeInfo.Description.TypeName.ToLower().Equals("float4")) { throw new InvalidMMEEffectShader例外($"ClearSetColor={value};が指定されましたが、変数\"{value}\"はfloat4型ではありません。"); } return(func); }
/// <summary> /// 自身のインスタンスを作成して返す。 /// </summary> /// <param name="index">連番。ファンクション名の末尾に付与される1桁の数値(0~9)。省略時は 0 。</param> /// <param name="value">値。ファンクション名と '=' を挟んだ右辺に記された文字列。</param> /// <param name="runtime"></param> /// <param name="effect">ファンクションが属しているエフェクト。</param> /// <param name="technique">ファンクションが属しているテクニック。パスに属している場合には null を指定。</param> /// <param name="pass">ファンクションが属しているパス。テクニックに属している場合には null を指定。</param> /// <returns></returns> public override 関数 ファンクションインスタンスを作成する(int index, string value, ScriptRuntime runtime, エフェクト effect, テクニック technique, パス pass) { var func = new RenderColorTarget関数(); if (index < 0 || index > 7) { throw new InvalidMMEEffectShader例外("RenderColorTarget[n](0<=n<=7)のnの制約が満たされていません。"); } func._index = index; if (!string.IsNullOrWhiteSpace(value) && !effect.レンダーターゲットビューのマップ.ContainsKey(value)) { throw new InvalidMMEEffectShader例外("指定されたRENDERCOLORTARGETの変数は存在しません。"); } // 右辺が空白だったら、既定のターゲットを設定する。 if (string.IsNullOrWhiteSpace(value)) { func._既定のターゲットを使う = true; } func._renderTargetView = string.IsNullOrWhiteSpace(value) ? index == 0 ? RenderContext.Instance.描画ターゲットコンテキスト.D3Dレンダーターゲットビュー : null : effect.レンダーターゲットビューのマップ[value]; return(func); }
/// <summary> /// 自身のインスタンスを作成して返す。 /// </summary> /// <param name="index">連番。ファンクション名の末尾に付与される1桁の数値(0~9)。省略時は 0 。</param> /// <param name="value">値。ファンクション名と '=' を挟んだ右辺に記された文字列。</param> /// <param name="runtime"></param> /// <param name="effect">ファンクションが属しているエフェクト。</param> /// <param name="technique">ファンクションが属しているテクニック。パスに属している場合には null を指定。</param> /// <param name="pass">ファンクションが属しているパス。テクニックに属している場合には null を指定。</param> /// <returns></returns> public override 関数 ファンクションインスタンスを作成する(int index, string value, ScriptRuntime runtime, エフェクト effect, テクニック technique, パス pass) { var func = new RenderDepthStencilTarget関数(); if (index != 0) { throw new InvalidMMEEffectShader例外("RenderDepthStencilTargetにはインデックス値を指定できません。"); } if (!string.IsNullOrWhiteSpace(value) && !effect.深度ステンシルビューのマップ.ContainsKey(value)) { throw new InvalidMMEEffectShader例外("スクリプトに指定された名前の深度ステンシルバッファは存在しません。"); } // valueが空なら→デフォルトの深度ステンシルバッファ // valueがあるなら→その名前のテクスチャ変数から取得 if (string.IsNullOrWhiteSpace(value)) { func._既定のターゲットを使う = true; func._DepthStencilView = null; } else { func._既定のターゲットを使う = false; func._DepthStencilView = effect.深度ステンシルビューのマップ[value]; // 名前で検索 } return(func); }
public ScriptRuntime(string script, エフェクト effect, テクニック technique = null, パス pass = null) { ScriptCode = script; _ScriptCodeを解析する(effect, technique, pass); }
/// <summary> /// 自身のインスタンスを作成して返す。 /// </summary> /// <param name="index">連番。ファンクション名の末尾に付与される1桁の数値(0~9)。省略時は 0 。</param> /// <param name="value">値。ファンクション名と '=' を挟んだ右辺に記された文字列。</param> /// <param name="runtime"></param> /// <param name="effect">ファンクションが属しているエフェクト。</param> /// <param name="technique">ファンクションが属しているテクニック。パスに属している場合には null を指定。</param> /// <param name="pass">ファンクションが属しているパス。テクニックに属している場合には null を指定。</param> /// <returns></returns> public override 関数 ファンクションインスタンスを作成する(int index, string value, ScriptRuntime runtime, エフェクト effect, テクニック technique, パス pass) { var func = new LoopEnd関数(); return(func); }
/// <summary> /// 自身のインスタンスを作成して返す。 /// </summary> /// <param name="index">連番。ファンクション名の末尾に付与される1桁の数値(0~9)。省略時は 0 。</param> /// <param name="value">値。ファンクション名と '=' を挟んだ右辺に記された文字列。</param> /// <param name="runtime"></param> /// <param name="effect">ファンクションが属しているエフェクト。</param> /// <param name="technique">ファンクションが属しているテクニック。パスに属している場合には null を指定。</param> /// <param name="pass">ファンクションが属しているパス。テクニックに属している場合には null を指定。</param> /// <returns></returns> public override 関数 ファンクションインスタンスを作成する(int index, string value, ScriptRuntime runtime, エフェクト effect, テクニック technique, パス pass) { var func = new Clear関数(); switch (value) { case "Color": func._対象 = 対象.Color; break; case "Depth": func._対象 = 対象.Depth; break; default: throw new InvalidMMEEffectShader例外($"Clear={value}が指定されましたが、\"{value}\"は指定可能ではありません。\"Clear\"もしくは\"Depth\"が指定可能です。"); } func._index = index; return(func); }
public void D3Dスキニングバッファを更新する(スキニング skelton, エフェクト effect) { if (!(D3Dスキニングバッファをリセットする)) { return; } var skinning = (skelton as PMXスケルトン) ?? throw new System.NotSupportedException("PMXバッファ管理クラスでは、スキニングとして PMXスケルトン クラスを指定してください。"); var d3dContext = RenderContext.Instance.DeviceManager.D3DDeviceContext; // エフェクト変数にボーンの情報を設定する。 this._D3DBoneTransデータストリーム.WriteRange(skinning.ボーンのモデルポーズ配列); this._D3DBoneTransデータストリーム.Position = 0; d3dContext.UpdateSubresource(new DataBox(_D3DBoneTransデータストリーム.DataPointer, 0, 0), _D3DBoneTrans定数バッファ, 0); effect.D3DEffect.GetConstantBufferByName("BoneTransBuffer").SetConstantBuffer(this._D3DBoneTrans定数バッファ); this._D3DBoneLocalPositionデータストリーム.WriteRange(skinning.ボーンのローカル位置); this._D3DBoneLocalPositionデータストリーム.Position = 0; d3dContext.UpdateSubresource(new DataBox(_D3DBoneLocalPositionデータストリーム.DataPointer, 0, 0), _D3DBoneLocalPosition定数バッファ, 0); effect.D3DEffect.GetConstantBufferByName("BoneLocalPositionBuffer").SetConstantBuffer(this._D3DBoneLocalPosition定数バッファ); this._D3DBoneQuaternionデータストリーム.WriteRange(skinning.ボーンの回転); this._D3DBoneQuaternionデータストリーム.Position = 0; d3dContext.UpdateSubresource(new DataBox(_D3DBoneQuaternionデータストリーム.DataPointer, 0, 0), _D3DBoneQuaternion定数バッファ, 0); effect.D3DEffect.GetConstantBufferByName("BoneQuaternionBuffer").SetConstantBuffer(this._D3DBoneQuaternion定数バッファ); // 現在の入力頂点リストをスキニングバッファに転送する。 this._頂点データストリーム.WriteRange(入力頂点リスト); this._頂点データストリーム.Position = 0; d3dContext.UpdateSubresource(new DataBox(_頂点データストリーム.DataPointer, 0, 0), D3Dスキニングバッファ, 0); // 使用するtechniqueを検索する。 テクニック technique = (from teq in effect.テクニックリスト where teq.テクニックを適用する描画対象 == MMDPass種別.スキニング select teq).FirstOrDefault(); if (null != technique) { // パスを通じてコンピュートシェーダーステートを設定する。 technique.パスリスト.ElementAt(0).Value.D3DPass.Apply(d3dContext); // コンピュートシェーダーでスキニングを実行し、結果を頂点バッファに格納する。 d3dContext.ComputeShader.SetShaderResource(0, this.D3DスキニングバッファSRView); d3dContext.ComputeShader.SetUnorderedAccessView(0, this.D3D頂点バッファビューUAView); d3dContext.Dispatch((入力頂点リスト.Length / 64) + 1, 1, 1); } // UAVを外す(このあと頂点シェーダーが使えるように) d3dContext.ComputeShader.SetUnorderedAccessView(0, null); #region " (CPUで行ったときのソース)" //---------------- /* * var boneTrans = skinning.ボーンのモデルポーズ配列; * var スキニング後の入力頂点リスト = new VS_INPUT[ 入力頂点リスト.Length ]; * * for( int i = 0; i < 入力頂点リスト.Length; i++ ) * { * switch( 入力頂点リスト[ i ].変形方式 ) * { * case (uint) 変形方式.BDEF1: #region " *** " * //---------------- * { * var 頂点 = 入力頂点リスト[ i ]; * * Matrix bt = * boneTrans[ 頂点.BoneIndex1 ]; * * if( Matrix.Zero == bt ) * bt = Matrix.Identity; * * スキニング後の入力頂点リスト[ i ].Position = Vector4.Transform( 頂点.Position, bt ); * スキニング後の入力頂点リスト[ i ].Normal = Vector3.TransformNormal( 頂点.Normal, bt ); * スキニング後の入力頂点リスト[ i ].Normal.Normalize(); * } * //---------------- #endregion * break; * * case (uint) 変形方式.BDEF2: #region " *** " * //---------------- * { * var 頂点 = 入力頂点リスト[ i ]; * * Matrix bt = * boneTrans[ 頂点.BoneIndex1 ] * 頂点.BoneWeight1 + * boneTrans[ 頂点.BoneIndex2 ] * 頂点.BoneWeight2; * * if( Matrix.Zero == bt ) * bt = Matrix.Identity; * * スキニング後の入力頂点リスト[ i ].Position = Vector4.Transform( 頂点.Position, bt ); * スキニング後の入力頂点リスト[ i ].Normal = Vector3.TransformNormal( 頂点.Normal, bt ); * スキニング後の入力頂点リスト[ i ].Normal.Normalize(); * } * //---------------- #endregion * break; * * case (uint) 変形方式.BDEF4: #region " *** " * //---------------- * { * var 頂点 = 入力頂点リスト[ i ]; * * Matrix bt = * boneTrans[ 頂点.BoneIndex1 ] * 頂点.BoneWeight1 + * boneTrans[ 頂点.BoneIndex2 ] * 頂点.BoneWeight2 + * boneTrans[ 頂点.BoneIndex3 ] * 頂点.BoneWeight3 + * boneTrans[ 頂点.BoneIndex4 ] * 頂点.BoneWeight4; * * if( Matrix.Zero == bt ) * bt = Matrix.Identity; * * スキニング後の入力頂点リスト[ i ].Position = Vector4.Transform( 頂点.Position, bt ); * スキニング後の入力頂点リスト[ i ].Normal = Vector3.TransformNormal( 頂点.Normal, bt ); * スキニング後の入力頂点リスト[ i ].Normal.Normalize(); * } * //---------------- #endregion * break; * * case (uint) 変形方式.SDEF: #region " *** " * //---------------- * { * // 参考: * // 自分用メモ「PMXのスフィリカルデフォームのコードっぽいもの」(sma42氏) * // https://www.pixiv.net/member_illust.php?mode=medium&illust_id=60755964 * * var 頂点 = 入力頂点リスト[ i ]; * #region " 影響度0,1 の算出 " * //---------------- * float 影響度0 = 0f; // 固定値であるSDEFパラメータにのみ依存するので、これらの値も固定値。 * float 影響度1 = 0f; // * { * float L0 = ( 頂点.SdefR0 - (Vector3) skinning.ボーン配列[ 頂点.BoneIndex2 ].ローカル位置 ).Length(); // 子ボーンからR0までの距離 * float L1 = ( 頂点.SdefR1 - (Vector3) skinning.ボーン配列[ 頂点.BoneIndex2 ].ローカル位置 ).Length(); // 子ボーンからR1までの距離 * * 影響度0 = ( System.Math.Abs( L0 - L1 ) < 0.0001f ) ? 0.5f : SharpDX.MathUtil.Clamp( L0 / ( L0 + L1 ), 0.0f, 1.0f ); * 影響度1 = 1.0f - 影響度0; * } * //---------------- #endregion * * Matrix モデルポーズ行列L = boneTrans[ 頂点.BoneIndex1 ] * 頂点.BoneWeight1; * Matrix モデルポーズ行列R = boneTrans[ 頂点.BoneIndex2 ] * 頂点.BoneWeight2; * Matrix モデルポーズ行列C = モデルポーズ行列L + モデルポーズ行列R; * * Vector4 点C = Vector4.Transform( 頂点.Sdef_C, モデルポーズ行列C ); // BDEF2で計算された点Cの位置 * Vector4 点P = Vector4.Transform( 頂点.Position, モデルポーズ行列C ); // BDEF2で計算された頂点の位置 * * Matrix 重み付き回転行列 = Matrix.RotationQuaternion( * Quaternion.Slerp( // 球体線形補間 * skinning.ボーン配列[ 頂点.BoneIndex1 ].回転 * 頂点.BoneWeight1, * skinning.ボーン配列[ 頂点.BoneIndex2 ].回転 * 頂点.BoneWeight2, * 頂点.BoneWeight1 ) ); * * Vector4 点R0 = Vector4.Transform( new Vector4( 頂点.SdefR0, 1f ), ( モデルポーズ行列L + ( モデルポーズ行列C * -頂点.BoneWeight1 ) ) ); * Vector4 点R1 = Vector4.Transform( new Vector4( 頂点.SdefR1, 1f ), ( モデルポーズ行列R + ( モデルポーズ行列C * -頂点.BoneWeight2 ) ) ); * 点C += ( 点R0 * 影響度0 ) + ( 点R1 * 影響度1 ); // 膨らみすぎ防止 * * 点P -= 点C; // 頂点を点Cが中心になるよう移動して * 点P = Vector4.Transform( 点P, 重み付き回転行列 ); // 回転して * 点P += 点C; // 元の位置へ * * スキニング後の入力頂点リスト[ i ].Position = 点P; * スキニング後の入力頂点リスト[ i ].Normal = Vector3.TransformNormal( 頂点.Normal, 重み付き回転行列 ); * スキニング後の入力頂点リスト[ i ].Normal.Normalize(); * } * //---------------- #endregion * break; * * case (uint) 変形方式.QDEF: #region " *** " * //---------------- * { * // ※ QDEFを使ったモデルが見つからないのでテストしてません。あれば教えてください! * * var 頂点 = 入力頂点リスト[ i ]; * * var dualQuaternion = new DualQuaternion[ 4 ]; // 最大4ボーンまで対応 * * var boneIndexes = new[] { 頂点.BoneIndex1, 頂点.BoneIndex2, 頂点.BoneIndex3, 頂点.BoneIndex4 }; * var boneWeights = new[] { 頂点.BoneWeight1, 頂点.BoneWeight2, 頂点.BoneWeight3, 頂点.BoneWeight4 }; * * for( int b = 0; b < 4; b++ ) * { * if( boneWeights[ b ] == 0f ) * { * dualQuaternion[ b ] = DualQuaternion.Zero; // 未使用 * } * else * { * dualQuaternion[ b ] = new DualQuaternion( boneTrans[ boneIndexes[ b ] ] ); * } * } * * Matrix bt = ( * dualQuaternion[ 0 ] * boneWeights[ 0 ] + * dualQuaternion[ 1 ] * boneWeights[ 1 ] + * dualQuaternion[ 2 ] * boneWeights[ 2 ] + * dualQuaternion[ 3 ] * boneWeights[ 3 ] ).ToMatrix(); * * if( Matrix.Zero == bt ) * bt = Matrix.Identity; * * スキニング後の入力頂点リスト[ i ].Position = Vector4.Transform( 頂点.Position, bt ); * スキニング後の入力頂点リスト[ i ].Normal = 頂点.Normal; * } * //---------------- #endregion * break; * } * * スキニング後の入力頂点リスト[ i ].UV = 入力頂点リスト[ i ].UV; * スキニング後の入力頂点リスト[ i ].AddUV1 = 入力頂点リスト[ i ].AddUV1; * スキニング後の入力頂点リスト[ i ].AddUV2 = 入力頂点リスト[ i ].AddUV2; * スキニング後の入力頂点リスト[ i ].AddUV3 = 入力頂点リスト[ i ].AddUV3; * スキニング後の入力頂点リスト[ i ].AddUV4 = 入力頂点リスト[ i ].AddUV4; * スキニング後の入力頂点リスト[ i ].EdgeWeight = 入力頂点リスト[ i ].EdgeWeight; * スキニング後の入力頂点リスト[ i ].Index = 入力頂点リスト[ i ].Index; * } * * // データストリームに、スキニング後の入力頂点リストを書き込む。 * _頂点データストリーム.WriteRange( スキニング後の入力頂点リスト ); * _頂点データストリーム.Position = 0; * * // D3D頂点バッファに、スキニング後の入力頂点リストを(データストリーム経由で)書き込む。 * RenderContext.Instance.DeviceManager.D3DDeviceContext.UpdateSubresource( new DataBox( _頂点データストリーム.DataPointer, 0, 0 ), D3D頂点バッファ, 0 ); */ //---------------- #endregion D3Dスキニングバッファをリセットする = false; }
/// <summary> /// 自身のインスタンスを作成して返す。 /// </summary> /// <param name="index">連番。ファンクション名の末尾に付与される1桁の数値(0~9)。省略時は 0 。</param> /// <param name="value">値。ファンクション名と '=' を挟んだ右辺に記された文字列。</param> /// <param name="runtime"></param> /// <param name="effect">ファンクションが属しているエフェクト。</param> /// <param name="technique">ファンクションが属しているテクニック。パスに属している場合には null を指定。</param> /// <param name="pass">ファンクションが属しているパス。テクニックに属している場合には null を指定。</param> /// <returns></returns> public override 関数 ファンクションインスタンスを作成する(int index, string value, ScriptRuntime runtime, エフェクト effect, テクニック technique, パス pass) { var func = new Draw関数(); func._描画に使用するバス = pass ?? throw new InvalidMMEEffectShader例外("Drawはテクニックのスクリプトに関して適用できません。"); switch (value) { case "Geometry": func._描画するもの = 描画するもの.Geometry; break; case "Buffer": func._描画するもの = 描画するもの.Buffer; break; default: throw new InvalidMMEEffectShader例外($"Draw={value}が指定されましたが、Drawに指定できるのは\"Geometry\"または\"Buffer\"です。"); } if (func._描画するもの == 描画するもの.Geometry && effect.ScriptClass == ScriptClass.Scene) { throw new InvalidMMEEffectShader例外("Draw=Geometryが指定されましたが、STANDARDSGLOBALのScriptClassに\"scene\"を指定している場合、これはできません。"); } if (func._描画するもの == 描画するもの.Buffer && effect.ScriptClass == ScriptClass.Object) { throw new InvalidMMEEffectShader例外("Draw=Bufferが指定されましたが、STANDARDSGLOBALのScriptClassに\"object\"を指定している場合、これはできません。"); } return(func); }
/// <summary> /// 自身のインスタンスを作成して返す。 /// </summary> /// <param name="index">連番。ファンクション名の末尾に付与される1桁の数値(0~9)。省略時は 0 。</param> /// <param name="value">値。ファンクション名と '=' を挟んだ右辺に記された文字列。</param> /// <param name="runtime"></param> /// <param name="effect">ファンクションが属しているエフェクト。</param> /// <param name="technique">ファンクションが属しているテクニック。パスに属している場合には null を指定。</param> /// <param name="pass">ファンクションが属しているパス。テクニックに属している場合には null を指定。</param> /// <returns></returns> public abstract 関数 ファンクションインスタンスを作成する(int index, string value, ScriptRuntime runtime, エフェクト effect, テクニック technique, パス pass);
/// <summary> /// 自身のインスタンスを作成して返す。 /// </summary> /// <param name="index">連番。ファンクション名の末尾に付与される1桁の数値(0~9)。省略時は 0 。</param> /// <param name="value">値。ファンクション名と '=' を挟んだ右辺に記された文字列。</param> /// <param name="runtime"></param> /// <param name="effect">ファンクションが属しているエフェクト。</param> /// <param name="technique">ファンクションが属しているテクニック。パスに属している場合には null を指定。</param> /// <param name="pass">ファンクションが属しているパス。テクニックに属している場合には null を指定。</param> /// <returns></returns> public override 関数 ファンクションインスタンスを作成する(int index, string value, ScriptRuntime runtime, エフェクト effect, テクニック technique, パス pass) { var func = new Pass関数(); if (technique == null) { throw new InvalidMMEEffectShader例外("スクリプト内でPassを利用できるのはテクニックに適用されたスクリプトのみです。パスのスクリプトでは実行できません。"); } // このメソッドの引数のパスは使わない。 if (!technique.パスリスト.ContainsKey(value)) { throw new InvalidMMEEffectShader例外($"スクリプトで指定されたテクニック中では指定されたパス\"{value}\"は見つかりませんでした。(スペルミス?)"); } func._実行対象のパス = technique.パスリスト[value]; return(func); }
/// <summary> /// 自身のインスタンスを作成して返す。 /// </summary> /// <param name="index">連番。ファンクション名の末尾に付与される1桁の数値(0~9)。省略時は 0 。</param> /// <param name="value">値。ファンクション名と '=' を挟んだ右辺に記された文字列。</param> /// <param name="runtime"></param> /// <param name="effect">ファンクションが属しているエフェクト。</param> /// <param name="technique">ファンクションが属しているテクニック。パスに属している場合には null を指定。</param> /// <param name="pass">ファンクションが属しているパス。テクニックに属している場合には null を指定。</param> /// <returns></returns> public override 関数 ファンクションインスタンスを作成する(int index, string value, ScriptRuntime runtime, エフェクト effect, テクニック technique, パス pass) { var func = new LoopByCount関数(); func._runtime = runtime; if (string.IsNullOrWhiteSpace(value)) { throw new InvalidMMEEffectShader例外("LoopByCount=;(空文字列)は指定できません。int,float,boolいずれかの変数名を伴う必要があります。"); } EffectVariable d3dVariable = effect.D3DEffect.GetVariableByName(value); string typeName = d3dVariable.TypeInfo.Description.TypeName.ToLower(); int loopCount = 0; switch (typeName) { case "bool": case "int": loopCount = d3dVariable.AsScalar().GetInt(); break; case "float": loopCount = (int)d3dVariable.AsScalar().GetFloat(); break; default: throw new InvalidMMEEffectShader例外("LoopByCountに指定できる変数の型はfloat,int,boolのいずれかです。"); } func._ループ回数 = loopCount; return(func); }