{
  "Name": "SimpleGPUParticles",
  "_id": "f9e42933-d2a5-499b-99bb-687aac83edc2",
  "Namespace": "lib.3d.generate",
  "Description": "A quick and dirty hard coded particle effect for the scrape game.",
  "Inputs": [
    {
      "Name": "InitCode",
      "MetaInstanceID": "ed13125b-9957-42b8-9b80-90348511db15",
      "DefaultValue": {
        "Type": "Text",
        "Value": [
          "//>>> InitParticle\r",
          "struct Particle\r",
          "{\r",
          "    float3 Position;\r",
          "    float3 Velocity;\r",
          "    float Size;\r",
          "    float BirthTime;\r",
          "    float TextureRow;\r",
          "};\r",
          "\r",
          "RWStructuredBuffer<Particle> ParticleStates : register (u0);\r",
          "\r",
          "cbuffer ParticleParams\r",
          "{\r",
          "    int4 StartIndex;\r",
          "    int4 EndIndex;\r",
          "    float4 Time;\r",
          "    float4 EmitPosition;\r",
          "    float4 PreviousEmitPosition;\r",
          "    float4 EmitDirection;\r",
          "    float4 PreviousEmitDirection;\r",
          "    float4 ScatterSpeed;\r",
          "    float4 ScatterAngle;\r",
          "    float4 TextureCells;\r",
          "    float4 EmitSizeRange;\r",
          "    int4 MaxNumParticles;\r",
          "    int4 Reset;\r",
          "};\r",
          "\r",
          "float3 rotate(float3 v, float3 axis, float angle)\r",
          "{\r",
          "    float ux = axis.x*v.x;\r",
          "    float uy = axis.x*v.y;\r",
          "    float uz = axis.x*v.z;\r",
          "    float vx = axis.y*v.x;\r",
          "    float vy = axis.y*v.y;\r",
          "    float vz = axis.y*v.z;\r",
          "    float wx = axis.z*v.x;\r",
          "    float wy = axis.z*v.y;\r",
          "    float wz = axis.z*v.z;\r",
          "    float sa = sin(angle);\r",
          "    float ca = cos(angle);\r",
          "    return float3(axis.x*(ux+vy+wz)+(v.x*(axis.y*axis.y+axis.z*axis.z)-axis.x*(vy+wz))*ca+(-wy+vz)*sa,\r",
          "                  axis.y*(ux+vy+wz)+(v.y*(axis.x*axis.x+axis.z*axis.z)-axis.y*(ux+wz))*ca+(wx-uz)*sa,\r",
          "                  axis.z*(ux+vy+wz)+(v.z*(axis.x*axis.x+axis.y*axis.y)-axis.z*(ux+vy))*ca+(-vx+uy)*sa);\r",
          "}\r",
          "\r",
          "#define M_PI 3.14159265358979323846\r",
          "float Noise(int x, int seed)\r",
          "{\r",
          "    int n = x + seed*137;\r",
          "    n = (n<<13) ^ n;\r",
          "    return (float)( 1.0 - ( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0);\r",
          "}\r",
          "\r",
          "float3 random(int x)\r",
          "{\r",
          "    return float3(Noise(x, x), Noise(x*1.5, x*1.5), Noise(x*3.75, x*3.75));\r",
          "}\r",
          "\r",
          "[numthreads(512, 1, 1)]\r",
          "void CSInitParticles(uint3 threadID : SV_DispatchThreadID)\r",
          "{\r",
          "    int id = threadID.x;\r",
          "    if (Reset.x > 0)\r",
          "    {\r",
          "        Particle p = ParticleStates[id]; \r",
          "        p.Position = float3(0.0f, 0.0f, 0.0f);\r",
          "        p.Velocity = float3(0.0f, 0.0f, 0.0f);\r",
          "        p.Size = 0.0f;\r",
          "        p.BirthTime = -1.0f;\r",
          "        p.TextureRow = 0;\r",
          "        ParticleStates[id] = p;\r",
          "        return;\r",
          "    }\r",
          "    \r",
          "    if (StartIndex.x == EndIndex.x)\r",
          "        return;\r",
          "\r",
          "    int numParticlesToAdd = 0;\r",
          "    int currentParticleNumber = 0;\r",
          "    bool useAsNewParticle = false;\r",
          "    if (StartIndex.x < EndIndex.x)\r",
          "    {\r",
          "        useAsNewParticle = StartIndex.x <= id && id < EndIndex.x;\r",
          "        numParticlesToAdd = EndIndex.x - StartIndex.x;\r",
          "        currentParticleNumber = id - StartIndex.x;\r",
          "    }\r",
          "    else\r",
          "    {\r",
          "        useAsNewParticle = id >= StartIndex.x || id < EndIndex.x;\r",
          "        numParticlesToAdd = MaxNumParticles.x - StartIndex.x + EndIndex.x;\r",
          "        currentParticleNumber = id + MaxNumParticles.x - StartIndex.x;\r",
          "    }\r",
          "\r",
          "    if (!useAsNewParticle)\r",
          "        return;\r",
          "\r",
          "    float3 randValue = random(id);\r",
          "    float3 randDir = randValue - float3(0.5, 0.5, 0.5);\r",
          "    float3 interpolatedEmitDirection = PreviousEmitDirection.xyz + (EmitDirection.xyz - PreviousEmitDirection.xyz)*(float)currentParticleNumber/numParticlesToAdd;\r",
          "\r",
          "    float3 axis1 = normalize(cross(interpolatedEmitDirection, randDir));\r",
          "    float angle1 = (randValue.x - 0.5)*radians(ScatterAngle.x);\r",
          "    float3 currentEmitDir = rotate(interpolatedEmitDirection, axis1, angle1);\r",
          "\r",
          "    float3 axis2 = normalize(cross(interpolatedEmitDirection, axis1));\r",
          "    float angle2 = (randValue.y - 0.5)*radians(ScatterAngle.x);\r",
          "    currentEmitDir = rotate(currentEmitDir, axis2, angle2);\r",
          "\r",
          "    Particle p = ParticleStates[id]; \r",
          "    p.Position = PreviousEmitPosition.xyz + (EmitPosition.xyz - PreviousEmitPosition.xyz)*(float)currentParticleNumber/numParticlesToAdd;\r",
          "    p.Velocity = currentEmitDir*(1 - randValue.x*ScatterSpeed.x);\r",
          "    p.Size = randValue.x*(EmitSizeRange.y - EmitSizeRange.x) + EmitSizeRange.x;\r",
          "    p.BirthTime = Time.x;\r",
          "    p.TextureRow = (int)(randValue.x*TextureCells.y);\r",
          "    ParticleStates[id] = p;\r",
          "}\r",
          "//<<< InitParticle\r",
          ""
        ]
      },
      "MetaID": "c522a66e-3260-4692-b3e3-79fd0361fa3d",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-100000",
      "Max": "100000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "UpdateCode",
      "MetaInstanceID": "6f2ff940-1864-4107-b5b7-e2e801c5e4f7",
      "DefaultValue": {
        "Type": "Text",
        "Value": [
          "//>>> UpdateParticle\r",
          "struct Particle\r",
          "{\r",
          "    float3 Position;\r",
          "    float3 Velocity;\r",
          "    float Size;\r",
          "    float BirthTime;\r",
          "    float TextureRow;\r",
          "};\r",
          "\r",
          "RWStructuredBuffer<Particle> ParticleStates : register (u0);\r",
          "\r",
          "cbuffer ParticleParams\r",
          "{\r",
          "    float4 DeltaTime;\r",
          "    float4 Friction;\r",
          "    float4 Wind;\r",
          "    float4 AttractorPosition;\r",
          "    float4 AttractorStrength;\r",
          "    float4 AttractorRadius;\r",
          "    float4 AttractorDecay;\r",
          "    \r",
          "    float4 NoiseTime;\r",
          "    float4 NoiseAmount;\r",
          "    float4 NoiseScale;    \r",
          "    float4 NoiseSeed;\r",
          "    float4 NoiseRadius;\r",
          "    \r",
          "};\r",
          "\r",
          "\r",
          "[numthreads(512, 1, 1)]\r",
          " float Noise(int x, int seed)\r",
          "{\r",
          "    int n = x + seed*137;\r",
          "    n = (n<<13) ^ n;\r",
          "    return (float)( 1.0 - ( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0);\r",
          "}\r",
          "\r",
          "[numthreads(512, 1, 1)]\r",
          "float Lerp(float a, float b, float t)\r",
          "{\r",
          "    return a + t * (b - a);\r",
          "}\r",
          "\r",
          "[numthreads(512, 1, 1)]\r",
          "float Fade(float t)\r",
          "{\r",
          "    return t * t * t * (t * (t * 6 - 15) + 10);\r",
          "}\r",
          "\r",
          "[numthreads(512, 1, 1)]\r",
          "float getNoise(float value, float zoom, float noiseTime, int seed, float period)\r",
          "{\r",
          "    value /= zoom;\r",
          "    value += noiseTime;\r",
          "        \r",
          "    float noiseSum = 0;\r",
          "    for(int a=0; a<4; a++) {\r",
          "        float f = (float)pow(2,a); \r",
          "        float amplitude = (float)pow(period ,a);\r",
          "\r",
          "        float v = value*f / zoom;\r",
          "       \r",
          "        noiseSum += Lerp( Noise( (int)v  , (int)seed ),\r",
          "                          Noise( (int)v+1, (int)seed ),\r",
          "                          Fade( v - (float)floor(v) )\r",
          "                    )* amplitude;\r",
          "    }   \r",
          "    return noiseSum;    \r",
          "}\r",
          "\r",
          "[numthreads(512, 1, 1)]\r",
          "void CSUpdateParticles(uint3 threadID : SV_DispatchThreadID)\r",
          "{\r",
          "\r",
          "    Particle p = ParticleStates[threadID.x];\r",
          "    p.Position += p.Velocity*DeltaTime.x;\r",
          "\r",
          "    float attractorDistance = length(AttractorPosition.xyz - p.Position);\r",
          "    float3 attractorForceDir = (AttractorPosition.xyz - p.Position)/attractorDistance;\r",
          "    float attractorForce = AttractorStrength.x;\r",
          "    if (attractorDistance > AttractorRadius.x)\r",
          "        attractorForce = pow(attractorDistance - AttractorRadius.x, -AttractorDecay.x)*AttractorStrength.x;\r",
          "        \r",
          "\r",
          "\r",
          "    if(abs(NoiseAmount.x) > 0.01f) {\r",
          "        float3 noiseOffset = float3(getNoise(p.Position.y - 16.3f,NoiseScale.x, NoiseTime.x, NoiseSeed.x , NoiseRadius.x  ),\r",
          "                                    getNoise(p.Position.z + 9.3f, NoiseScale.x, NoiseTime.x, NoiseSeed.x , NoiseRadius.x  ),\r",
          "                                    getNoise(p.Position.x - 0.3f, NoiseScale.x, NoiseTime.x, NoiseSeed.x , NoiseRadius.x ));\r",
          "    \r",
          "        p.Velocity += noiseOffset * NoiseAmount.x*DeltaTime.x;\r",
          "    }\r",
          "    p.Velocity = (1.0 - Friction.x*DeltaTime.x)*p.Velocity + (Wind.xyz + attractorForceDir*attractorForce)*DeltaTime.x;\r",
          "    ParticleStates[threadID.x] = p;\r",
          "}\r",
          "\r",
          "\r",
          "\r",
          "",
          "//<<< UpdateParticle\r",
          ""
        ]
      },
      "MetaID": "c522a66e-3260-4692-b3e3-79fd0361fa3d",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-100000",
      "Max": "100000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "RenderCode",
      "MetaInstanceID": "29b8873c-8852-41fe-afdc-e10db60d7984",
      "DefaultValue": {
        "Type": "Text",
        "Value": [
          "//>>> RenderParticle\r",
          "//>>> _common parameters\r",
          "float4x4 objectToWorldMatrix;",
          "float4x4 worldToCameraMatrix;",
          "float4x4 projMatrix;",
          "Texture2D txDiffuse;",
          "float2 RenderTargetSize;",
          "//<<< _common parameters\r",
          "\r",
          "//>>> _parameters\r",
          "float Time;",
          "Texture2D Image;",
          "float Count;",
          "float LifeTime;",
          "float EmitRate;",
          "float3 EmitPosition;",
          "float3 EmitDirection;",
          "float ScatterSpeed;",
          "float ScatterAngle;",
          "float3 Wind;",
          "float Friction;",
          "float4 Color;",
          "float4 ColorRandom;",
          "float2 TextureCells;",
          "float2 EmitSizeRange;",
          "float AspectRatio;",
          "float Scale;",
          "float MotionStretch;",
          "float2 SizeOverLife;",
          "float2 OpacityOverLife;",
          "float ResetTrigger;",
          "float3 AttractorPosition;",
          "float AttractorStrength;",
          "float AttractorRadius;",
          "float AttractorDecay;",
          "float NoiseTime;",
          "float NoiseAmount;",
          "float NoiseScale;",
          "float NoiseSeed;",
          "float NoiseRadius;",
          "//<<< _parameters\r",
          "\r",
          "static const float scale = 0.5f;\r",
          "\r",
          "static const float2 g_texcoords[4] = \r",
          "{ \r",
          "    float2( -1, 1 ), \r",
          "    float2( 1, 1 ),\r",
          "    float2( -1, -1 ),\r",
          "    float2( 1, -1 ),\r",
          "};\r",
          "\r",
          "\r",
          "struct Particle\r",
          "{\r",
          "    float3 Position;\r",
          "    float3 Velocity;\r",
          "    float Size;\r",
          "    float BirthTime;\r",
          "    float TextureRow;\r",
          "};\r",
          "\r",
          "StructuredBuffer<Particle> ParticleStates;\r",
          "\r",
          "//>>> _setup\r",
          "SamplerState samLinear",
          "{",
          "    Filter = MIN_MAG_MIP_LINEAR;",
          "    AddressU = Clamp;",
          "    AddressV = Clamp;",
          "};",
          "//<<< _setup\r",
          "\r",
          "//>>> __declarations\r",
          "struct GS_INPUT",
          "{",
          "    float3 position : Position;",
          "    float3 velocity : Vel;",
          "    float birthTime : Value0;",
          "    float size : Value1;",
          "    int textureRow : Value2;",
          "};",
          "",
          "struct PS_INPUT",
          "{",
          "    float4 pos : SV_POSITION;",
          "    float2 texCoord: TEXCOORD0;",
          "    float opacity: Value;",
          "};",
          "//<<< __declarations\r",
          "\r",
          "//>>> __VS \r",
          "GS_INPUT VS( in uint vertexid : SV_VertexID )\r",
          "{\r",
          "\tGS_INPUT output = (GS_INPUT)0;\r",
          "\t\r",
          "\toutput.position = ParticleStates[vertexid].Position;\r",
          "\toutput.velocity = ParticleStates[vertexid].Velocity;\r",
          "\toutput.birthTime = ParticleStates[vertexid].BirthTime;\r",
          "\toutput.size = ParticleStates[vertexid].Size;\r",
          "\toutput.textureRow = ParticleStates[vertexid].TextureRow;\r",
          "\r",
          "\treturn output;\r",
          "}\r",
          "//<<< __VS\r",
          "\r",
          "//>>> __GS\r",
          "float Noise(int x, int seed)\r",
          "{\r",
          "    int n = x + seed*137;\r",
          "    n = (n<<13) ^ n;\r",
          "    return (float)( 1.0 - ( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0);\r",
          "}\r",
          "\r",
          "float Lerp(float a, float b, float t)\r",
          "{\r",
          "    return a + t * (b - a);\r",
          "}\r",
          "\r",
          "float Fade(float t)\r",
          "{\r",
          "    return t * t * t * (t * (t * 6 - 15) + 10);\r",
          "}\r",
          "\r",
          "float getNoise(float value, float frequency, float noiseTime, int seed)\r",
          "{\r",
          "    value *= frequency;\r",
          "    value += noiseTime;\r",
          "    return Lerp(Noise((int)value, seed),\r",
          "                Noise((int)value + 1, seed),\r",
          "                Fade(value - floor(value)));\r",
          "}\r",
          "\r",
          "[maxvertexcount(4)]\r",
          "void GS( point GS_INPUT input[1], inout TriangleStream<PS_INPUT> SpriteStream )\r",
          "{\r",
          "    if (Time - input[0].birthTime < 0 ||\r",
          "        Time - input[0].birthTime > LifeTime)\r",
          "        return;\r",
          "\r",
          "\tPS_INPUT output = (PS_INPUT)0;\r",
          "\r",
          "    float age = (Time - input[0].birthTime)/LifeTime;\r",
          "\r",
          "    output.opacity = smoothstep(0, OpacityOverLife.x, age)*smoothstep(0, 1 - OpacityOverLife.y, 1 - age);\r",
          "\r",
          "    float4 viewposition = mul(float4(input[0].position, 1.0f), objectToWorldMatrix);\r",
          "    float4 cameraTVelocity = mul(float4(input[0].velocity, 0.0f), objectToWorldMatrix);\r",
          "\r",
          "/*\r",
          "    if (NoiseAmount != 0.0f)\r",
          "    {\r",
          "        float3 noiseOffset = float3(getNoise(viewposition.x/NoiseRadius - 6.3f, NoiseScale, NoiseTime, NoiseSeed),\r",
          "                                    getNoise(viewposition.y/NoiseRadius + 9.3f, NoiseScale, NoiseTime, NoiseSeed),\r",
          "                                    getNoise(viewposition.z/NoiseRadius - 0.3f, NoiseScale, NoiseTime, NoiseSeed));\r",
          "        viewposition.xyz += noiseOffset*NoiseAmount;\r",
          "        cameraTVelocity.xyz = normalize(noiseOffset)*length(cameraTVelocity);\r",
          "    }\r",
          "*/\r",
          "    viewposition = mul(viewposition, worldToCameraMatrix);\r",
          "    cameraTVelocity = mul(cameraTVelocity, worldToCameraMatrix);\r",
          "    float velocity = length(cameraTVelocity.xy);\r",
          "    float2 direction = cameraTVelocity.xy/velocity;\r",
          "\r",
          "    float2 up = direction*input[0].size.x;\r",
          "    float2 right = float2(direction.y, -direction.x)*input[0].size.x;\r",
          "    float scaleOverLife = smoothstep(0, SizeOverLife.x, age)*smoothstep(0, 1 - SizeOverLife.y, 1 - age);\r",
          "    up *= Scale*scaleOverLife + velocity*MotionStretch;\r",
          "    right *= Scale*scaleOverLife*AspectRatio;\r",
          "\r",
          "    float4 positions[4] =\r",
          "    {\r",
          "        float4(-scale*right +  scale*up, 0, 0),\r",
          "        float4( scale*right +  scale*up, 0, 0),\r",
          "        float4(-scale*right + -scale*up, 0, 0),\r",
          "        float4( scale*right + -scale*up, 0, 0),\r",
          "    };\r",
          "\r",
          "    float columnWidth = 1.0/TextureCells.x;\r",
          "    float columnWidthHalf = columnWidth*0.5;\r",
          "    float column = (int)(age*TextureCells.x) *columnWidth + columnWidthHalf;\r",
          "    float rowHeight = 1.0/TextureCells.y;\r",
          "    float rowHeightHalf = rowHeight*0.5;\r",
          "    float row = input[0].textureRow*rowHeight + rowHeightHalf;\r",
          "\r",
          "    for (int i = 0; i < 4; ++i)\r",
          "    {\r",
          "\t\toutput.pos = mul(viewposition + positions[i], projMatrix);\r",
          "        float u = column + columnWidthHalf*g_texcoords[i].x;\r",
          "        float v = row + rowHeightHalf*g_texcoords[i].y;\r",
          "        output.texCoord = float2(u, v);\r",
          "        SpriteStream.Append(output);\r",
          "    }\r",
          "\r",
          "\tSpriteStream.RestartStrip();\r",
          "}\r",
          "//<<< __GS\r",
          "\r",
          "//>>> __PS\r",
          "float4 PS( in PS_INPUT input ) : SV_TARGET\r",
          "{\r",
          "    float4 c = Image.Sample(samLinear, input.texCoord)*Color;\r",
          "    c.a *= input.opacity;\r",
          "    return c;\r",
          "}\r",
          "//<<< __PS\r",
          "\r",
          "//>>> __technique\r",
          "technique10 Render",
          "{",
          "    pass P0",
          "    {",
          "        SetVertexShader( CompileShader( vs_5_0, VS() ) );",
          "        SetGeometryShader( CompileShader( gs_5_0, GS() ) );",
          "        SetPixelShader( CompileShader( ps_5_0, PS() ) );",
          "    }",
          "}",
          "//<<< __technique\r",
          "",
          "//<<< RenderParticle\r",
          ""
        ]
      },
      "MetaID": "c522a66e-3260-4692-b3e3-79fd0361fa3d",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-100000",
      "Max": "100000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "Time",
      "MetaInstanceID": "0744dbaf-7436-4bb2-916d-0df57bd29b94",
      "DefaultValue": {
        "Type": "Float",
        "Value": "0"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-100000",
      "Max": "100000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "Image",
      "MetaInstanceID": "0ca8099e-56fa-4c7f-87b9-3773b2496a46",
      "DefaultValue": {
        "Type": "Image",
        "Value": "Framefield.Core.Image"
      },
      "MetaID": "9848060d-fd84-45b0-b658-d0d531c61dab",
      "IsMultiInput": "False",
      "Relevance": "Required",
      "Description": "",
      "Min": "-100000",
      "Max": "100000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "Count",
      "MetaInstanceID": "9701a750-c1c9-4696-ac89-73755df2892b",
      "DefaultValue": {
        "Type": "Float",
        "Value": "10000"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "512",
      "Max": "1E+08",
      "Scale": "1",
      "ScaleType": "Quadratic",
      "EnumValues": []
    },
    {
      "Name": "LifeTime",
      "MetaInstanceID": "ca002ebd-4803-48f1-b88c-2286dddb2599",
      "DefaultValue": {
        "Type": "Float",
        "Value": "20"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-100000",
      "Max": "100000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "EmitRate",
      "MetaInstanceID": "f9b022c7-86e5-48ee-b102-d22eb34825ab",
      "DefaultValue": {
        "Type": "Float",
        "Value": "7"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "0",
      "Max": "100000",
      "Scale": "1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "EmitPosition.X",
      "MetaInstanceID": "1c446a47-7f43-4f9a-96a0-20fd99ab3a15",
      "DefaultValue": {
        "Type": "Float",
        "Value": "0"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Relevant",
      "Description": "",
      "Min": "-10000",
      "Max": "10000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "EmitPosition.Y",
      "MetaInstanceID": "7215f477-d5db-4de9-b387-92d6b875dd96",
      "DefaultValue": {
        "Type": "Float",
        "Value": "0"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Relevant",
      "Description": "",
      "Min": "-10000",
      "Max": "10000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "EmitPosition.Z",
      "MetaInstanceID": "0147d885-baf5-46fb-940f-99183cf20c75",
      "DefaultValue": {
        "Type": "Float",
        "Value": "0"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Relevant",
      "Description": "",
      "Min": "-10000",
      "Max": "10000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "EmitDirection.X",
      "MetaInstanceID": "c98f96b6-d073-428a-86e4-7735d7a5ce40",
      "DefaultValue": {
        "Type": "Float",
        "Value": "0"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-10000",
      "Max": "10000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "EmitDirection.Y",
      "MetaInstanceID": "534133af-ccf5-426b-872b-1b2e6f2adf3e",
      "DefaultValue": {
        "Type": "Float",
        "Value": "1"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-10000",
      "Max": "10000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "EmitDirection.Z",
      "MetaInstanceID": "fc4950c2-90a5-49db-8580-66abf6db2d25",
      "DefaultValue": {
        "Type": "Float",
        "Value": "0"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-10000",
      "Max": "10000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "ScatterSpeed",
      "MetaInstanceID": "bfe5ce5f-4558-4100-b59d-db0c946af495",
      "DefaultValue": {
        "Type": "Float",
        "Value": "0.09999999"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-100000",
      "Max": "100000",
      "Scale": "1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "ScatterAngle",
      "MetaInstanceID": "18c1ec41-33c0-47fb-bf4a-fe42e60c8974",
      "DefaultValue": {
        "Type": "Float",
        "Value": "30"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-100000",
      "Max": "100000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "Wind.X",
      "MetaInstanceID": "ff0e674c-90c9-4a14-a457-b8c7a751052e",
      "DefaultValue": {
        "Type": "Float",
        "Value": "0"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-10000",
      "Max": "10000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "Wind.Y",
      "MetaInstanceID": "aeadba0c-f5fa-4a8a-ad7f-0e9b3984a668",
      "DefaultValue": {
        "Type": "Float",
        "Value": "-0.1"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-10000",
      "Max": "10000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "Wind.Z",
      "MetaInstanceID": "b0d3b4d5-2097-4aa1-9eb3-551ecb6584a4",
      "DefaultValue": {
        "Type": "Float",
        "Value": "0"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-10000",
      "Max": "10000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "Friction",
      "MetaInstanceID": "52e665a5-3a8c-49d2-b248-6ae089d7b1a5",
      "DefaultValue": {
        "Type": "Float",
        "Value": "0.04"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-100000",
      "Max": "100000",
      "Scale": "0.01",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "Color.R",
      "MetaInstanceID": "cdacdc39-3804-442e-b57d-02c5c22637f1",
      "DefaultValue": {
        "Type": "Float",
        "Value": "1"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "0",
      "Max": "1",
      "Scale": "0.01",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "Color.G",
      "MetaInstanceID": "8cc147fd-d9ca-4ecb-8251-a57facdfcdcc",
      "DefaultValue": {
        "Type": "Float",
        "Value": "1"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "0",
      "Max": "1",
      "Scale": "0.01",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "Color.B",
      "MetaInstanceID": "bda3fe4e-a1a4-4bb6-81c1-403a47ffeb3c",
      "DefaultValue": {
        "Type": "Float",
        "Value": "1"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "0",
      "Max": "1",
      "Scale": "0.01",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "Color.A",
      "MetaInstanceID": "70f0e1a7-63fe-45c8-ba42-1fed2abacb17",
      "DefaultValue": {
        "Type": "Float",
        "Value": "1"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "0",
      "Max": "1",
      "Scale": "0.01",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "ColorRandom.R",
      "MetaInstanceID": "5982d1c5-9d98-4528-a431-ca5d8f0b7145",
      "DefaultValue": {
        "Type": "Float",
        "Value": "1"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "0",
      "Max": "1",
      "Scale": "0.01",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "ColorRandom.G",
      "MetaInstanceID": "9ed350cb-0fcf-43c7-b92a-1d18cfa9eb5b",
      "DefaultValue": {
        "Type": "Float",
        "Value": "1"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "0",
      "Max": "1",
      "Scale": "0.01",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "ColorRandom.B",
      "MetaInstanceID": "1afbc129-b231-462e-8d67-f9daa9dcdd47",
      "DefaultValue": {
        "Type": "Float",
        "Value": "1"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "0",
      "Max": "1",
      "Scale": "0.01",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "ColorRandom.A",
      "MetaInstanceID": "dacf87dc-289b-43bf-95a9-b67f20ccd02c",
      "DefaultValue": {
        "Type": "Float",
        "Value": "1"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "0",
      "Max": "1",
      "Scale": "0.01",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "TextureCells.X",
      "MetaInstanceID": "c0c3c6b1-065c-4b33-904d-98c728ec6287",
      "DefaultValue": {
        "Type": "Float",
        "Value": "16"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-10000",
      "Max": "10000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "TextureCells.Y",
      "MetaInstanceID": "9591b9a4-092b-4e67-a4ae-4739d8b5be7d",
      "DefaultValue": {
        "Type": "Float",
        "Value": "8"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-10000",
      "Max": "10000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "EmitSizeRange.Min",
      "MetaInstanceID": "c5ff3ea9-a587-45c9-9f9e-f8b2c99a33ee",
      "DefaultValue": {
        "Type": "Float",
        "Value": "0.09999999"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-9999",
      "Max": "10000",
      "Scale": "0.01",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "EmitSizeRange.Max",
      "MetaInstanceID": "0ee60abf-1d0a-4a4c-944f-3440c69d8737",
      "DefaultValue": {
        "Type": "Float",
        "Value": "0.09999999"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-9999",
      "Max": "10000",
      "Scale": "0.01",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "AspectRatio",
      "MetaInstanceID": "017e5475-91c9-4844-81d0-a35109d7e560",
      "DefaultValue": {
        "Type": "Float",
        "Value": "1"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-9999",
      "Max": "10000",
      "Scale": "0.01",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "Scale",
      "MetaInstanceID": "f4a2705c-1e99-41e8-bc27-d258b17ae330",
      "DefaultValue": {
        "Type": "Float",
        "Value": "1"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "0",
      "Max": "100000",
      "Scale": "0.01",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "MotionStretch",
      "MetaInstanceID": "99479879-b69a-472b-a15b-4f358bfe23d3",
      "DefaultValue": {
        "Type": "Float",
        "Value": "0"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-100000",
      "Max": "100000",
      "Scale": "0.01",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "SizeOverLife.X",
      "MetaInstanceID": "9e569fd4-f209-47ac-9a64-59dc25cac23f",
      "DefaultValue": {
        "Type": "Float",
        "Value": "0.02"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "0",
      "Max": "1",
      "Scale": "0.01",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "SizeOverLife.Y",
      "MetaInstanceID": "57c466d9-1c0b-4173-8194-5060c2f44e0a",
      "DefaultValue": {
        "Type": "Float",
        "Value": "1"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "0",
      "Max": "1",
      "Scale": "0.01",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "OpacityOverLife.X",
      "MetaInstanceID": "60243669-dd17-4e4c-af54-6e49e7518a73",
      "DefaultValue": {
        "Type": "Float",
        "Value": "0"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "0",
      "Max": "1",
      "Scale": "0.01",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "OpacityOverLife.Y",
      "MetaInstanceID": "ef63190a-6b7b-4c3c-9313-6c250ff34182",
      "DefaultValue": {
        "Type": "Float",
        "Value": "0.5"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "0",
      "Max": "1",
      "Scale": "0.01",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "ResetTrigger",
      "MetaInstanceID": "804b952f-f6e2-4835-8b15-6fd4f7a7fd24",
      "DefaultValue": {
        "Type": "Float",
        "Value": "0"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "0",
      "Max": "1",
      "Scale": "1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "AttractorPosition.X",
      "MetaInstanceID": "df75ce7a-d94c-445e-9fb9-5d195fc3e2fe",
      "DefaultValue": {
        "Type": "Float",
        "Value": "0"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-10000",
      "Max": "10000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "AttractorPosition.Y",
      "MetaInstanceID": "ecb22b1a-cdeb-4a6d-9b5b-4c4a8ebd6a0a",
      "DefaultValue": {
        "Type": "Float",
        "Value": "0"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-10000",
      "Max": "10000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "AttractorPosition.Z",
      "MetaInstanceID": "9b7124d2-9f0e-40fd-8cb7-ca2c39355a58",
      "DefaultValue": {
        "Type": "Float",
        "Value": "0"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-10000",
      "Max": "10000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "AttractorStrength",
      "MetaInstanceID": "8b2b2bab-d58d-4879-bdcd-728bcb6f6550",
      "DefaultValue": {
        "Type": "Float",
        "Value": "1"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-100000",
      "Max": "100000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "AttractorRadius",
      "MetaInstanceID": "76cefae6-6414-4c3c-9228-f9afd770eba6",
      "DefaultValue": {
        "Type": "Float",
        "Value": "1"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-100000",
      "Max": "100000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "AttractorDecay",
      "MetaInstanceID": "bdafa0c9-ca26-4d23-8d48-965751514938",
      "DefaultValue": {
        "Type": "Float",
        "Value": "0.5"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-100000",
      "Max": "100000",
      "Scale": "0.01",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "NoiseTime",
      "MetaInstanceID": "00e2efa1-df51-4054-a798-78b08f738117",
      "DefaultValue": {
        "Type": "Float",
        "Value": "0"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-100000",
      "Max": "100000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "NoiseAmount",
      "MetaInstanceID": "5fcd9042-5820-40ec-81ad-70665bee09ce",
      "DefaultValue": {
        "Type": "Float",
        "Value": "0"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-100000",
      "Max": "100000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "NoiseScale",
      "MetaInstanceID": "7fde69c7-1e1e-4590-b648-751bc041c8cd",
      "DefaultValue": {
        "Type": "Float",
        "Value": "1"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-100000",
      "Max": "100000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "NoiseSeed",
      "MetaInstanceID": "200bb68a-ac79-4a32-a619-57155bac8810",
      "DefaultValue": {
        "Type": "Float",
        "Value": "0"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-100000",
      "Max": "100000",
      "Scale": "1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "NoiseRadius",
      "MetaInstanceID": "d36076eb-a1a1-4a08-892f-d2266c46ee9e",
      "DefaultValue": {
        "Type": "Float",
        "Value": "1"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-100000",
      "Max": "100000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    }
  ],
  "Outputs": [
    {
      "Name": "Scene",
      "MetaInstanceID": "02946c7c-8ea9-4fb2-ac11-40058664a3c0",
      "MetaID": "79122951-7bc4-4c68-b085-866eab828248"
    }
  ],
  "OperatorParts": [
    {
      "MetaInstanceID": "48803f16-f69d-4c57-91f8-b56dc0920d09",
      "MetaID": "25f3b72e-c299-489d-8ce8-6f7a7195260d",
      "Name": "SimpleGPUParticlesFunc",
      "Version": "0accd5dd-6025-45be-adca-7d9b2bc203b4",
      "Type": "Float",
      "IsMultiInput": "True",
      "Script": [
        "//>>> _using",
        "using System;",
        "using System.Collections.Generic;",
        "using System.Linq;",
        "using System.Text;",
        "using SharpDX;",
        "using SharpDX.Direct3D11;",
        "using SharpDX.Windows;",
        "//<<< _using",
        "",
        "using System.Runtime.InteropServices;",
        "using Framefield.Core;",
        "using Framefield.Core.Rendering;",
        "using SharpDX.DXGI;",
        "using SharpDX.Direct3D;",
        "using SharpDX.D3DCompiler;",
        "using System.CodeDom.Compiler;",
        "using Buffer = SharpDX.Direct3D11.Buffer;",
        "",
        "namespace Framefield.Core.ID25f3b72e_c299_489d_8ce8_6f7a7195260d",
        "{",
        "    public class Class_SimpleGPUParticles : FXSourceCodeFunction, IFXSceneSourceCode",
        "    {",
        "        //structured buffer element type. size must be multiple of 4",
        "        [StructLayout(LayoutKind.Explicit, Size = 36)]",
        "        public struct ParticleStateLayout",
        "        {",
        "            public ParticleStateLayout(Vector3 position, Vector3 velocity, float size, float birthTime, float textureRow)",
        "            {",
        "                Position = position;",
        "                Velocity = velocity;",
        "                Size = size;",
        "                BirthTime = birthTime;",
        "                TextureRow = textureRow;",
        "            }",
        "            [FieldOffset(0)]",
        "            Vector3 Position;",
        "            [FieldOffset(12)]",
        "            Vector3 Velocity;",
        "            [FieldOffset(24)]",
        "            float Size;",
        "            [FieldOffset(28)]",
        "            float BirthTime;",
        "            [FieldOffset(32)]",
        "            float TextureRow;",
        "        }",
        "",
        "        //constant buffer element type. size must be multiple of 16",
        "        [StructLayout(LayoutKind.Explicit, Size = 208)]",
        "        public struct ParticleInitParametersBufferLayout",
        "        {",
        "            public ParticleInitParametersBufferLayout(int particlesStartIndex, int particlesEndIndex, float time, ",
        "                                                      Vector3 emitPosition, Vector3 previousEmitPosition, Vector3 emitDirection, Vector3 previousEmitDirection,",
        "                                                      float scatterSpeed, float scatterAngle, Vector2 textureCells, Vector2 emitSizeRange, ",
        "                                                      int maxNumParticles, int reset)",
        "            {",
        "                StartIndex = particlesStartIndex;",
        "                EndIndex = particlesEndIndex;",
        "                Time = time;",
        "                EmitPosition = emitPosition;",
        "                PreviousEmitPosition = previousEmitPosition;",
        "                EmitDirection = emitDirection;",
        "                PreviousEmitDirection = previousEmitDirection;",
        "                ScatterSpeed = scatterSpeed;",
        "                ScatterAngle = scatterAngle;",
        "                TextureCells = textureCells;",
        "                EmitSizeRange = emitSizeRange;",
        "                MaxNumParticles = maxNumParticles;",
        "                Reset = reset;",
        "            }",
        "            [FieldOffset(0)]",
        "            int StartIndex;",
        "            [FieldOffset(16)]",
        "            int EndIndex;",
        "            [FieldOffset(32)]",
        "            float Time;",
        "            [FieldOffset(48)]",
        "            Vector3 EmitPosition;",
        "            [FieldOffset(64)]",
        "            Vector3 PreviousEmitPosition;",
        "            [FieldOffset(80)]",
        "            Vector3 EmitDirection;",
        "            [FieldOffset(96)]",
        "            Vector3 PreviousEmitDirection;",
        "            [FieldOffset(112)]",
        "            float ScatterSpeed;",
        "            [FieldOffset(128)]",
        "            float ScatterAngle;",
        "            [FieldOffset(144)]",
        "            Vector2 TextureCells;",
        "            [FieldOffset(160)]",
        "            Vector2 EmitSizeRange;",
        "            [FieldOffset(176)]",
        "            int MaxNumParticles;",
        "            [FieldOffset(192)]",
        "            int Reset;",
        "        }",
        "        private Buffer _particleInitParametersBuffer;",
        "",
        "        //constant buffer element type. size must be multiple of 16",
        "        [StructLayout(LayoutKind.Explicit, Size = 208)]",
        "        public struct ParticleUpdateParametersBufferLayout",
        "        {",
        "            public ParticleUpdateParametersBufferLayout(float deltaTime, float friction, Vector3 wind, Vector3 attractorPosition,",
        "                                                        float attractorStrength, float attractorRadius, float attractorDecay, ",
        "                                                        float noiseTime, float noiseAmount, float noiseScale, float noiseSeed, float noiseRadius)",
        "            {",
        "                DeltaTime = deltaTime;",
        "                Friction = friction;",
        "                Wind = wind;",
        "                AttractorPosition = attractorPosition;",
        "                AttractorStrength = attractorStrength;",
        "                AttractorRadius = attractorRadius;",
        "                AttractorDecay = attractorDecay;",
        "                NoiseTime = noiseTime;",
        "                NoiseAmount = noiseAmount;",
        "                NoiseScale = noiseScale;",
        "                NoiseSeed = noiseSeed;",
        "                NoiseRadius = noiseRadius;",
        "                ",
        "            }",
        "            [FieldOffset(0)]",
        "            float DeltaTime;",
        "            [FieldOffset(16)]",
        "            float Friction;",
        "            [FieldOffset(32)]",
        "            Vector3 Wind;",
        "            [FieldOffset(48)]",
        "            Vector3 AttractorPosition;",
        "            [FieldOffset(64)]",
        "            float AttractorStrength;",
        "            [FieldOffset(80)]",
        "            float AttractorRadius;",
        "            [FieldOffset(96)]",
        "            float AttractorDecay;            ",
        "            [FieldOffset(112)]",
        "            float NoiseTime;",
        "            [FieldOffset(128)]",
        "            float NoiseAmount;",
        "            [FieldOffset(144)]",
        "            float NoiseScale;",
        "            [FieldOffset(160)]",
        "            float NoiseSeed;",
        "            [FieldOffset(176)]",
        "            float NoiseRadius;",
        "        }",
        "        private Buffer _particleUpdateParametersBuffer;",
        "",
        "        //>>> _inputids",
        "        private enum InputId",
        "        {",
        "            InitCode = 0,",
        "            UpdateCode = 1,",
        "            RenderCode = 2,",
        "            Time = 3,",
        "            Image = 4,",
        "            Count = 5,",
        "            LifeTime = 6,",
        "            EmitRate = 7,",
        "            EmitPositionX = 8,",
        "            EmitPositionY = 9,",
        "            EmitPositionZ = 10,",
        "            EmitDirectionX = 11,",
        "            EmitDirectionY = 12,",
        "            EmitDirectionZ = 13,",
        "            ScatterSpeed = 14,",
        "            ScatterAngle = 15,",
        "            WindX = 16,",
        "            WindY = 17,",
        "            WindZ = 18,",
        "            Friction = 19,",
        "            ColorR = 20,",
        "            ColorG = 21,",
        "            ColorB = 22,",
        "            ColorA = 23,",
        "            ColorRandomR = 24,",
        "            ColorRandomG = 25,",
        "            ColorRandomB = 26,",
        "            ColorRandomA = 27,",
        "            TextureCellsX = 28,",
        "            TextureCellsY = 29,",
        "            EmitSizeRangeMin = 30,",
        "            EmitSizeRangeMax = 31,",
        "            AspectRatio = 32,",
        "            Scale = 33,",
        "            MotionStretch = 34,",
        "            SizeOverLifeX = 35,",
        "            SizeOverLifeY = 36,",
        "            OpacityOverLifeX = 37,",
        "            OpacityOverLifeY = 38,",
        "            ResetTrigger = 39,",
        "            AttractorPositionX = 40,",
        "            AttractorPositionY = 41,",
        "            AttractorPositionZ = 42,",
        "            AttractorStrength = 43,",
        "            AttractorRadius = 44,",
        "            AttractorDecay = 45,",
        "            NoiseTime = 46,",
        "            NoiseAmount = 47,",
        "            NoiseScale = 48,",
        "            NoiseSeed = 49,",
        "            NoiseRadius = 50",
        "        }",
        "        //<<< _inputids",
        "",
        "        public override void Dispose()",
        "        {",
        "            Utilities.DisposeObj(ref _csInitParticles);",
        "            Utilities.DisposeObj(ref _csUpdateParticles);",
        "            Utilities.DisposeObj(ref _fxRenderParticles);",
        "            Utilities.DisposeObj(ref _particleStateBuffer);",
        "            base.Dispose();",
        "        }",
        "",
        "        bool _firstEval = true;",
        "        public override OperatorPartContext Eval(OperatorPartContext context, List<OperatorPart> inputs, int outputIdx)",
        "        {",
        "            if (_firstEval)",
        "            {",
        "                for (int i = 0; i < NumCodes(); ++i)",
        "                    Compile(i);",
        "                _firstEval = false;",
        "                Changed = true;",
        "            }",
        "",
        "            //>>> _params",
        "            var InitCode = inputs[(int)InputId.InitCode].Eval(context).Text;",
        "            var UpdateCode = inputs[(int)InputId.UpdateCode].Eval(context).Text;",
        "            var RenderCode = inputs[(int)InputId.RenderCode].Eval(context).Text;",
        "            var Time = inputs[(int)InputId.Time].Eval(context).Value;",
        "            var Image = inputs[(int)InputId.Image].Eval(context).Image; // Needs to be checked for null!",
        "            var Count = inputs[(int)InputId.Count].Eval(context).Value;",
        "            var LifeTime = inputs[(int)InputId.LifeTime].Eval(context).Value;",
        "            var EmitRate = inputs[(int)InputId.EmitRate].Eval(context).Value;",
        "            var EmitPositionX = inputs[(int)InputId.EmitPositionX].Eval(context).Value;",
        "            var EmitPositionY = inputs[(int)InputId.EmitPositionY].Eval(context).Value;",
        "            var EmitPositionZ = inputs[(int)InputId.EmitPositionZ].Eval(context).Value;",
        "            var EmitPosition = new Vector3(EmitPositionX, EmitPositionY, EmitPositionZ);",
        "            var EmitDirectionX = inputs[(int)InputId.EmitDirectionX].Eval(context).Value;",
        "            var EmitDirectionY = inputs[(int)InputId.EmitDirectionY].Eval(context).Value;",
        "            var EmitDirectionZ = inputs[(int)InputId.EmitDirectionZ].Eval(context).Value;",
        "            var EmitDirection = new Vector3(EmitDirectionX, EmitDirectionY, EmitDirectionZ);",
        "            var ScatterSpeed = inputs[(int)InputId.ScatterSpeed].Eval(context).Value;",
        "            var ScatterAngle = inputs[(int)InputId.ScatterAngle].Eval(context).Value;",
        "            var WindX = inputs[(int)InputId.WindX].Eval(context).Value;",
        "            var WindY = inputs[(int)InputId.WindY].Eval(context).Value;",
        "            var WindZ = inputs[(int)InputId.WindZ].Eval(context).Value;",
        "            var Wind = new Vector3(WindX, WindY, WindZ);",
        "            var Friction = inputs[(int)InputId.Friction].Eval(context).Value;",
        "            var ColorR = inputs[(int)InputId.ColorR].Eval(context).Value;",
        "            var ColorG = inputs[(int)InputId.ColorG].Eval(context).Value;",
        "            var ColorB = inputs[(int)InputId.ColorB].Eval(context).Value;",
        "            var ColorA = inputs[(int)InputId.ColorA].Eval(context).Value;",
        "            var Color = new Color4(ColorR, ColorG, ColorB, ColorA);",
        "            var ColorRandomR = inputs[(int)InputId.ColorRandomR].Eval(context).Value;",
        "            var ColorRandomG = inputs[(int)InputId.ColorRandomG].Eval(context).Value;",
        "            var ColorRandomB = inputs[(int)InputId.ColorRandomB].Eval(context).Value;",
        "            var ColorRandomA = inputs[(int)InputId.ColorRandomA].Eval(context).Value;",
        "            var ColorRandom = new Color4(ColorRandomR, ColorRandomG, ColorRandomB, ColorRandomA);",
        "            var TextureCellsX = inputs[(int)InputId.TextureCellsX].Eval(context).Value;",
        "            var TextureCellsY = inputs[(int)InputId.TextureCellsY].Eval(context).Value;",
        "            var TextureCells = new Vector2(TextureCellsX, TextureCellsY);",
        "            var EmitSizeRangeMin = inputs[(int)InputId.EmitSizeRangeMin].Eval(context).Value;",
        "            var EmitSizeRangeMax = inputs[(int)InputId.EmitSizeRangeMax].Eval(context).Value;",
        "            var EmitSizeRange = new Vector2(EmitSizeRangeMin, EmitSizeRangeMax);",
        "            var AspectRatio = inputs[(int)InputId.AspectRatio].Eval(context).Value;",
        "            var Scale = inputs[(int)InputId.Scale].Eval(context).Value;",
        "            var MotionStretch = inputs[(int)InputId.MotionStretch].Eval(context).Value;",
        "            var SizeOverLifeX = inputs[(int)InputId.SizeOverLifeX].Eval(context).Value;",
        "            var SizeOverLifeY = inputs[(int)InputId.SizeOverLifeY].Eval(context).Value;",
        "            var SizeOverLife = new Vector2(SizeOverLifeX, SizeOverLifeY);",
        "            var OpacityOverLifeX = inputs[(int)InputId.OpacityOverLifeX].Eval(context).Value;",
        "            var OpacityOverLifeY = inputs[(int)InputId.OpacityOverLifeY].Eval(context).Value;",
        "            var OpacityOverLife = new Vector2(OpacityOverLifeX, OpacityOverLifeY);",
        "            var ResetTrigger = inputs[(int)InputId.ResetTrigger].Eval(context).Value;",
        "            var AttractorPositionX = inputs[(int)InputId.AttractorPositionX].Eval(context).Value;",
        "            var AttractorPositionY = inputs[(int)InputId.AttractorPositionY].Eval(context).Value;",
        "            var AttractorPositionZ = inputs[(int)InputId.AttractorPositionZ].Eval(context).Value;",
        "            var AttractorPosition = new Vector3(AttractorPositionX, AttractorPositionY, AttractorPositionZ);",
        "            var AttractorStrength = inputs[(int)InputId.AttractorStrength].Eval(context).Value;",
        "            var AttractorRadius = inputs[(int)InputId.AttractorRadius].Eval(context).Value;",
        "            var AttractorDecay = inputs[(int)InputId.AttractorDecay].Eval(context).Value;",
        "            var NoiseTime = inputs[(int)InputId.NoiseTime].Eval(context).Value;",
        "            var NoiseAmount = inputs[(int)InputId.NoiseAmount].Eval(context).Value;",
        "            var NoiseScale = inputs[(int)InputId.NoiseScale].Eval(context).Value;",
        "            var NoiseSeed = inputs[(int)InputId.NoiseSeed].Eval(context).Value;",
        "            var NoiseRadius = inputs[(int)InputId.NoiseRadius].Eval(context).Value;",
        "            //<<< _params",
        "",
        "            float deltaTime = Time - _time;",
        "            _time = Time;",
        "",
        "            InitializeBuffer(context, (int)Count);",
        "",
        "            var uavDesc = new UnorderedAccessViewDescription",
        "                              {",
        "                                  Format = Format.Unknown, ",
        "                                  Dimension = UnorderedAccessViewDimension.Buffer,",
        "                                  Buffer = new UnorderedAccessViewDescription.BufferResource",
        "                                               {",
        "                                                   FirstElement = 0,",
        "                                                   ElementCount = _maxNumParticles,",
        "                                                   Flags = UnorderedAccessViewBufferFlags.None",
        "                                               }",
        "                              };",
        "",
        "            var deviceContext = context.D3DDevice.ImmediateContext;",
        "",
        "            //particle initializing",
        "            int particleEmitCountForFrame = Math.Max(0, (int)(deltaTime*EmitRate*60));",
        "            int particleEndIndex = (_currentParticleIndex + particleEmitCountForFrame) % _maxNumParticles;",
        "",
        "            SetupParticleInitParametersBuffer(context, _currentParticleIndex, particleEndIndex, (float)_time,",
        "                                              EmitPosition, _previousEmitPosition, EmitDirection, _previousEmitDirection,",
        "                                              ScatterSpeed, ScatterAngle, TextureCells, EmitSizeRange, _maxNumParticles,",
        "                                              (int)ResetTrigger);",
        "            ",
        "            _currentParticleIndex = particleEndIndex;",
        "",
        "            using (var particleStateUAV = new UnorderedAccessView(context.D3DDevice, _particleStateBuffer, uavDesc))",
        "            {",
        "                deviceContext.ComputeShader.Set(_csInitParticles);",
        "                deviceContext.ComputeShader.SetUnorderedAccessView(0, particleStateUAV);",
        "                deviceContext.ComputeShader.SetConstantBuffer(0, _particleInitParametersBuffer);",
        "",
        "                deviceContext.Dispatch(_maxNumParticles/512, 1, 1);",
        "",
        "                deviceContext.ComputeShader.SetUnorderedAccessView(0, null);",
        "                deviceContext.ComputeShader.SetConstantBuffer(0, null);",
        "            }",
        "            _previousEmitPosition = EmitPosition;",
        "            _previousEmitDirection = EmitDirection;",
        "",
        "            //particle updating",
        "            SetupParticleUpdateParametersBuffer(context, deltaTime, Friction, Wind, AttractorPosition, AttractorStrength, ",
        "                                                AttractorRadius, AttractorDecay, ",
        "                                                NoiseTime, NoiseAmount, NoiseScale, NoiseSeed, NoiseRadius);",
        "",
        "            using (var particleStateUAV = new UnorderedAccessView(context.D3DDevice, _particleStateBuffer, uavDesc))",
        "            {",
        "                deviceContext.ComputeShader.Set(_csUpdateParticles);",
        "                deviceContext.ComputeShader.SetUnorderedAccessView(0, particleStateUAV);",
        "                deviceContext.ComputeShader.SetConstantBuffer(0, _particleUpdateParametersBuffer);",
        "",
        "                deviceContext.Dispatch(_maxNumParticles/512, 1, 1);",
        "",
        "                deviceContext.ComputeShader.SetUnorderedAccessView(0, null);",
        "                deviceContext.ComputeShader.SetConstantBuffer(0, null);",
        "            }",
        "",
        "            //particle rendering",
        "            using (var particleStateSRV = new ShaderResourceView(context.D3DDevice, _particleStateBuffer))",
        "            using (var imageSRV = new ShaderResourceView(context.D3DDevice, Image))",
        "            {",
        "                try",
        "                {",
        "                    deviceContext.ClearState();",
        "",
        "                    _fxRenderParticles.GetVariableByName(\"ParticleStates\").AsShaderResource().SetResource(particleStateSRV);",
        "                    _fxRenderParticles.GetVariableByName(\"Image\").AsShaderResource().SetResource(imageSRV);",
        "                    _fxRenderParticles.GetVariableByName(\"Time\").AsScalar().Set((float)_time);",
        "                    _fxRenderParticles.GetVariableByName(\"LifeTime\").AsScalar().Set((float)LifeTime);",
        "                    _fxRenderParticles.GetVariableByName(\"TextureCells\").AsVector().Set(TextureCells);",
        "                    _fxRenderParticles.GetVariableByName(\"Color\").AsVector().Set(Color);",
        "                    _fxRenderParticles.GetVariableByName(\"Scale\").AsScalar().Set(Scale);",
        "                    _fxRenderParticles.GetVariableByName(\"AspectRatio\").AsScalar().Set(AspectRatio);",
        "                    _fxRenderParticles.GetVariableByName(\"MotionStretch\").AsScalar().Set(MotionStretch);",
        "                    _fxRenderParticles.GetVariableByName(\"SizeOverLife\").AsVector().Set(SizeOverLife);",
        "                    _fxRenderParticles.GetVariableByName(\"OpacityOverLife\").AsVector().Set(OpacityOverLife);",
        "                    _fxRenderParticles.GetVariableByName(\"NoiseTime\").AsScalar().Set(NoiseTime);",
        "                    //_fxRenderParticles.GetVariableByName(\"NoiseAmount\").AsScalar().Set(NoiseAmount);",
        "                    //_fxRenderParticles.GetVariableByName(\"NoiseScale\").AsScalar().Set(NoiseScale);",
        "                    //_fxRenderParticles.GetVariableByName(\"NoiseSeed\").AsScalar().Set(NoiseSeed);",
        "                    //_fxRenderParticles.GetVariableByName(\"NoiseRadius\").AsScalar().Set(NoiseRadius);",
        "",
        "                    var previousEffect = context.Effect;",
        "                    context.Effect = _fxRenderParticles;",
        "                    context.Renderer.SetupEffect(context);",
        "",
        "                    if (context.DepthStencilView != null)",
        "                        deviceContext.OutputMerger.SetTargets(context.DepthStencilView, context.RenderTargetView);",
        "                    else",
        "                        deviceContext.OutputMerger.SetTargets(context.RenderTargetView);",
        "",
        "                    if (context.BlendState != null) {",
        "                        deviceContext.OutputMerger.BlendState = context.BlendState;",
        "                        deviceContext.OutputMerger.BlendFactor = context.BlendFactor;",
        "                    }",
        "",
        "                    if (context.DepthStencilState != null) {",
        "                        deviceContext.OutputMerger.DepthStencilState = context.DepthStencilState;",
        "                    }",
        "",
        "                    if (context.RasterizerState != null) {",
        "                        deviceContext.Rasterizer.State = context.RasterizerState;",
        "                    }",
        "",
        "                    deviceContext.Rasterizer.SetViewports(new [] { context.Viewport });",
        "                    deviceContext.InputAssembler.InputLayout = context.InputLayout;",
        "                    deviceContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.PointList;",
        "                    deviceContext.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(null, 0, 0));",
        "",
        "                    var technique = context.Effect.GetTechniqueByIndex(0);",
        "                    for (int i = 0; i < technique.Description.PassCount; ++i) {",
        "                        technique.GetPassByIndex(i).Apply(deviceContext);",
        "                        deviceContext.Draw(_maxNumParticles, 0);",
        "                    }",
        "",
        "                    // remove target views that they are no longer bound as output and can be used also as input",
        "                    DepthStencilView dsv = null;",
        "                    RenderTargetView rtv = null;",
        "                    deviceContext.OutputMerger.SetTargets(dsv, rtv);",
        "                    deviceContext.VertexShader.SetShaderResource(0, null);",
        "                    deviceContext.PixelShader.SetShaderResource(0, null);",
        "                    context.Effect = previousEffect;",
        "                }",
        "                catch (Exception exception)",
        "                {",
        "                    Logger.Error(this,\"render error: {0}\", exception.Message);",
        "                }",
        "            }",
        "",
        "            Changed = false;",
        "            return context;",
        "        }",
        "",
        "        void InitializeBuffer(OperatorPartContext context, int newMaxNumParticles)",
        "        {",
        "            newMaxNumParticles = Math.Max(512, newMaxNumParticles); //at least we need to have 512 particles",
        "",
        "            if (_particleStateBuffer == null || _maxNumParticles != newMaxNumParticles)",
        "            {",
        "                using (var data = new DataStream(Marshal.SizeOf(typeof(ParticleStateLayout))*newMaxNumParticles, true, true))",
        "                {",
        "                    for (int i = 0; i < newMaxNumParticles; ++i)",
        "                        data.Write(new ParticleStateLayout(new Vector3(0), new Vector3(0), 0.0f, -1.0f, 0.0f));",
        "                    data.Position = 0;",
        "",
        "                    var bufferDesc = new BufferDescription",
        "                                         {",
        "                                             Usage = ResourceUsage.Default,",
        "                                             SizeInBytes = Marshal.SizeOf(typeof(ParticleStateLayout))*newMaxNumParticles,",
        "                                             StructureByteStride = Marshal.SizeOf(typeof(ParticleStateLayout)),",
        "                                             BindFlags = BindFlags.ShaderResource | BindFlags.UnorderedAccess,",
        "                                             OptionFlags = ResourceOptionFlags.BufferStructured",
        "                                         };",
        "                    _particleStateBuffer = new Buffer(context.D3DDevice, data, bufferDesc);",
        "                }",
        "                _maxNumParticles = newMaxNumParticles;",
        "            }",
        "        }",
        "",
        "        public override int NumCodes()",
        "        {",
        "            return 3;",
        "        }",
        "",
        "        public override CompilerErrorCollection Compile(int codeIdx)",
        "        {",
        "            var errors = new CompilerErrorCollection();",
        "            try",
        "            {",
        "                switch (codeIdx)",
        "                {",
        "                    case 0:",
        "                    {",
        "                        Utilities.DisposeObj(ref _csInitParticles);",
        "                        var t = GetCode(codeIdx);",
        "                        using (var bytecode = ShaderBytecode.Compile(GetCode(codeIdx), \"CSInitParticles\", \"cs_5_0\", ShaderFlags.Debug))",
        "                            _csInitParticles = new ComputeShader(D3DDevice.Device, bytecode);",
        "                        break;",
        "                    }",
        "                    case 1:",
        "                    {",
        "                        Utilities.DisposeObj(ref _csUpdateParticles);",
        "                        using (var bytecode = ShaderBytecode.Compile(GetCode(codeIdx), \"CSUpdateParticles\", \"cs_5_0\", ShaderFlags.Debug))",
        "                            _csUpdateParticles = new ComputeShader(D3DDevice.Device, bytecode);",
        "                        break;",
        "                    }",
        "                    case 2:",
        "                    {",
        "                        Utilities.DisposeObj(ref _fxRenderParticles);",
        "                        using (var bytecode = ShaderBytecode.Compile(GetCode(codeIdx), \"fx_5_0\", ShaderFlags.Debug, EffectFlags.None, null, null))",
        "                            _fxRenderParticles = new Effect(D3DDevice.Device, bytecode);",
        "                        break;",
        "                    }",
        "                }",
        "            }",
        "            catch (SharpDX.CompilationException ex)",
        "            {",
        "                errors = ErrorsFromString(ex.Message);",
        "                Logger.Error(this,\"Fx compile error: {0}\", ex.Message);",
        "            }",
        "            return errors;",
        "        }",
        "",
        "        void SetupParticleInitParametersBuffer(OperatorPartContext context, int particleIndex, int numParticlesToAdd, float time,",
        "                                               Vector3 emitPosition, Vector3 previousEmitPosition, Vector3 emitDirection, Vector3 previousEmitDirection,",
        "                                               float scatterSpeed, float scatterAngle, Vector2 textureCells, Vector2 emitSizeRange, int maxNumParticles,",
        "                                               int reset)",
        "        {",
        "            var param = new ParticleInitParametersBufferLayout(particleIndex, numParticlesToAdd, time, emitPosition, previousEmitPosition, ",
        "                                                               emitDirection, previousEmitDirection, scatterSpeed, scatterAngle, textureCells,",
        "                                                               emitSizeRange, maxNumParticles, reset);",
        "            using (var data = new DataStream(Marshal.SizeOf(typeof(ParticleInitParametersBufferLayout)), true, true))",
        "            {",
        "                data.Write(param);",
        "                data.Position = 0;",
        "",
        "                if (_particleInitParametersBuffer == null)",
        "                {",
        "                    _currentParticleIndex = 0;",
        "                    var bufferDesc = new BufferDescription { Usage = ResourceUsage.Default, SizeInBytes = Marshal.SizeOf(typeof(ParticleInitParametersBufferLayout)), BindFlags = BindFlags.ConstantBuffer };",
        "                    _particleInitParametersBuffer = new Buffer(context.D3DDevice, data, bufferDesc);",
        "                }",
        "                else",
        "                {",
        "                    context.D3DDevice.ImmediateContext.UpdateSubresource(new DataBox(data.DataPointer, 0, 0), _particleInitParametersBuffer);",
        "                }",
        "            }",
        "        }",
        "",
        "        void SetupParticleUpdateParametersBuffer(OperatorPartContext context, float deltaTime, float friction, Vector3 wind, Vector3 attractorPosition,",
        "                                                 float attractorStrength, float attractorRadius, float attractorDecay, ",
        "                                                 float noiseTime, float noiseAmount, float noiseScale, float noiseSeed, float noiseRadius)",
        "        {",
        "            var param = new ParticleUpdateParametersBufferLayout(deltaTime, friction, wind, ",
        "            attractorPosition, attractorStrength, attractorRadius, attractorDecay, ",
        "            noiseTime, noiseAmount, noiseScale, noiseSeed, noiseRadius);",
        "            using (var data = new DataStream(Marshal.SizeOf(typeof(ParticleUpdateParametersBufferLayout)), true, true))",
        "            {",
        "                data.Write(param);",
        "                data.Position = 0;",
        "",
        "                if (_particleUpdateParametersBuffer == null)",
        "                {",
        "                    var bufferDesc = new BufferDescription { Usage = ResourceUsage.Default, SizeInBytes = Marshal.SizeOf(typeof(ParticleUpdateParametersBufferLayout)), BindFlags = BindFlags.ConstantBuffer };",
        "                    _particleUpdateParametersBuffer = new Buffer(context.D3DDevice, data, bufferDesc);",
        "                }",
        "                else",
        "                {",
        "                    context.D3DDevice.ImmediateContext.UpdateSubresource(new DataBox(data.DataPointer, 0, 0), _particleUpdateParametersBuffer);",
        "                }",
        "            }",
        "        }",
        "",
        "        ComputeShader _csInitParticles;",
        "        ComputeShader _csUpdateParticles;",
        "        Effect _fxRenderParticles;",
        "        Buffer _particleStateBuffer;",
        "        int _maxNumParticles;",
        "        int _currentParticleIndex;",
        "        Vector3 _previousEmitPosition;",
        "        Vector3 _previousEmitDirection;",
        "",
        "        float _time;",
        "    }",
        "}",
        ""
      ],
      "AdditionalAssemblies": []
    }
  ],
  "Operators": [],
  "Connections": [
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "02946c7c-8ea9-4fb2-ac11-40058664a3c0"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "ed13125b-9957-42b8-9b80-90348511db15",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "6f2ff940-1864-4107-b5b7-e2e801c5e4f7",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "29b8873c-8852-41fe-afdc-e10db60d7984",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "0744dbaf-7436-4bb2-916d-0df57bd29b94",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "0ca8099e-56fa-4c7f-87b9-3773b2496a46",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "9701a750-c1c9-4696-ac89-73755df2892b",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "ca002ebd-4803-48f1-b88c-2286dddb2599",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "f9b022c7-86e5-48ee-b102-d22eb34825ab",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "1c446a47-7f43-4f9a-96a0-20fd99ab3a15",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "7215f477-d5db-4de9-b387-92d6b875dd96",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "0147d885-baf5-46fb-940f-99183cf20c75",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "c98f96b6-d073-428a-86e4-7735d7a5ce40",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "534133af-ccf5-426b-872b-1b2e6f2adf3e",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "fc4950c2-90a5-49db-8580-66abf6db2d25",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "bfe5ce5f-4558-4100-b59d-db0c946af495",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "18c1ec41-33c0-47fb-bf4a-fe42e60c8974",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "ff0e674c-90c9-4a14-a457-b8c7a751052e",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "aeadba0c-f5fa-4a8a-ad7f-0e9b3984a668",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "b0d3b4d5-2097-4aa1-9eb3-551ecb6584a4",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "52e665a5-3a8c-49d2-b248-6ae089d7b1a5",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "cdacdc39-3804-442e-b57d-02c5c22637f1",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "8cc147fd-d9ca-4ecb-8251-a57facdfcdcc",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "bda3fe4e-a1a4-4bb6-81c1-403a47ffeb3c",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "70f0e1a7-63fe-45c8-ba42-1fed2abacb17",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "5982d1c5-9d98-4528-a431-ca5d8f0b7145",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "9ed350cb-0fcf-43c7-b92a-1d18cfa9eb5b",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "1afbc129-b231-462e-8d67-f9daa9dcdd47",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "dacf87dc-289b-43bf-95a9-b67f20ccd02c",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "c0c3c6b1-065c-4b33-904d-98c728ec6287",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "9591b9a4-092b-4e67-a4ae-4739d8b5be7d",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "c5ff3ea9-a587-45c9-9f9e-f8b2c99a33ee",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "0ee60abf-1d0a-4a4c-944f-3440c69d8737",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "017e5475-91c9-4844-81d0-a35109d7e560",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "f4a2705c-1e99-41e8-bc27-d258b17ae330",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "99479879-b69a-472b-a15b-4f358bfe23d3",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "9e569fd4-f209-47ac-9a64-59dc25cac23f",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "57c466d9-1c0b-4173-8194-5060c2f44e0a",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "60243669-dd17-4e4c-af54-6e49e7518a73",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "ef63190a-6b7b-4c3c-9313-6c250ff34182",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "804b952f-f6e2-4835-8b15-6fd4f7a7fd24",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "df75ce7a-d94c-445e-9fb9-5d195fc3e2fe",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "ecb22b1a-cdeb-4a6d-9b5b-4c4a8ebd6a0a",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "9b7124d2-9f0e-40fd-8cb7-ca2c39355a58",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "8b2b2bab-d58d-4879-bdcd-728bcb6f6550",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "76cefae6-6414-4c3c-9228-f9afd770eba6",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "bdafa0c9-ca26-4d23-8d48-965751514938",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "00e2efa1-df51-4054-a798-78b08f738117",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "5fcd9042-5820-40ec-81ad-70665bee09ce",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "7fde69c7-1e1e-4590-b648-751bc041c8cd",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "200bb68a-ac79-4a32-a619-57155bac8810",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "d36076eb-a1a1-4a08-892f-d2266c46ee9e",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "48803f16-f69d-4c57-91f8-b56dc0920d09"
    }
  ]
}