cbuffer MatrixBuffer
{
    matrix worldMatrix;
    matrix viewMatrix;
    matrix projectionMatrix;
};

struct VertexInputType
{
    float4 position : POSITION;
    float4 color : COLOR;
    float2 size: SIZE;
    float angle: PSIZE;
};

struct GeoOut
{
    float4 Pos : SV_POSITION;
    //float3 PosW : POSITION;
    //float3 NormalW : NORMAL;
    float2 Tex : TEXCOORD0;
    //uint PrimID : SV_PrimitiveID;
    float4 color : COLOR;
};

[maxvertexcount(4)]
void ParticleGeometryShader(point VertexInputType gin[1], inout TriangleStream<GeoOut> triStream)
{
    //
    // Compute the local coordinate system of the sprite relative to the
    // world space such that the billboard is aligned with the y-axis
    // and faces the eye.
    //
    gin[0].position.w=1.0f;
    gin[0].position = mul(gin[0].position, worldMatrix);
    
    float4x4 rotateZ = { cos(gin[0].angle), sin(gin[0].angle), 0.0, 0.0,
		-sin(gin[0].angle), cos(gin[0].angle), 0.0, 0.0,
		0.0, 0.0, 1.0, 0.0,
		0.0, 0.0, 0.0, 1.0   };

    float4x4 rotated = mul(viewMatrix,rotateZ);

    float4 up = float4(rotated._12_22_32, 0.0f);
    float4 right = float4(rotated._11_21_31, 0.0f);
    //float3 look =  - viewMatrix._13_23_33;
    //look.y = 0.0f; // y-axis aligned, so project to xz-plane
    //look.x = 0.0f;
    //look = normalize(look);
    //float3 right = cross(up, look);
    //
    // Compute triangle strip vertices (quad) in world space.
    //
    float halfWidth = gin[0].size.x;
    float halfHeight = gin[0].size.y;
    float4 v[4];
    v[0] = float4(gin[0].position - halfWidth*right - halfHeight*up);
    v[1] = float4(gin[0].position - halfWidth*right + halfHeight*up);
    v[2] = float4(gin[0].position + halfWidth*right - halfHeight*up);
    v[3] = float4(gin[0].position + halfWidth*right + halfHeight*up);

    float2 texCoord[4];
    texCoord[0] = float2(0, 1);
    texCoord[1] = float2(0, 0);
    texCoord[2] = float2(1, 1);
    texCoord[3] = float2(1, 0);

    //
    // Transform quad vertices to world space and output
    // them as a triangle strip.
    GeoOut gout;
    [unroll]
    for(int i = 0; i < 4; ++i)
    {
        //gout.Pos = mul(v[i], objectMatrix);
        //gout.Pos = mul(v[i], worldMatrix);
        gout.Pos = mul(v[i], viewMatrix);
        gout.Pos = mul(gout.Pos, projectionMatrix);
        //gout.PosH = mul(v[i], worldViewProjMatrix);
        //gout.NormalW = look;
        gout.Tex = texCoord[i];
        //gout.PrimID = primID;
        gout.color = gin[0].color;
        triStream.Append(gout);
    }
}