float4x4 gWorldViewProj : WorldViewProjection; float4x4 gViewInverse : ViewInverse; Texture2D gParticleTexture; SamplerState samPoint { Filter = MIN_MAG_MIP_POINT; AddressU = WRAP; AddressV = WRAP; }; //STATES //****** BlendState AlphaBlending { BlendEnable[0] = TRUE; SrcBlend = SRC_ALPHA; DestBlend = INV_SRC_ALPHA; BlendOp = ADD; SrcBlendAlpha = ONE; DestBlendAlpha = ZERO; BlendOpAlpha = ADD; RenderTargetWriteMask[0] = 0x0f; }; DepthStencilState DisableDepthWriting { //Enable Depth Rendering DepthEnable = TRUE; //Disable Depth Writing DepthWriteMask = ZERO; }; RasterizerState BackCulling { CullMode = BACK; }; //SHADER STRUCTS //************** struct VS_DATA { float3 Position : POSITION; float4 Color: COLOR; float Size: TEXCOORD0; float Rotation: TEXCOORD1; }; struct GS_DATA { float4 Position : SV_POSITION; float2 TexCoord: TEXCOORD0; float4 Color : COLOR; }; //VERTEX SHADER //************* VS_DATA MainVS(VS_DATA input) { return input; } //GEOMETRY SHADER //*************** void CreateVertex(inout TriangleStream<GS_DATA> triStream, float3 pos, float2 texCoord, float4 col, float2x2 uvRotation) { //Step 1. Create a GS_DATA object GS_DATA gsData = (GS_DATA)0; //Step 2. Transform the position using the WVP Matrix and assign it to (GS_DATA object).Position (Keep in mind: float3 -> float4, Homogeneous Coordinates) gsData.Position = mul(float4(pos, 1.0f), gWorldViewProj); //Step 3. Assign texCoord to (GS_DATA object).TexCoord //This is a little formula to do texture rotation by transforming the texture coordinates (Can cause artifacts) /* texCoord -= float2(0.5f,0.5f); texCoord = mul(texCoord, uvRotation); texCoord += float2(0.5f,0.5f); */ gsData.TexCoord = texCoord; //Step 4. Assign color to (GS_DATA object).Color gsData.Color = col; //Step 5. Append (GS_DATA object) to the TriangleStream parameter (TriangleStream::Append(...)) triStream.Append(gsData); //TEMP //triStream.Append((GS_DATA)0); //Remove this line } [maxvertexcount(4)] void MainGS(point VS_DATA vertex[1], inout TriangleStream<GS_DATA> triStream) { //Use these variable names float3 topLeft, topRight, bottomLeft, bottomRight; float size = vertex[0].Size / 2; float3 origin = vertex[0].Position; //Vertices (Keep in mind that 'origin' contains the center of the quad topLeft = float3(-size, size, 0); topRight = float3(size, size, 0); bottomLeft = float3(-size, -size, 0); bottomRight = float3(size, -size, 0); //Transform the vertices using the ViewInverse (Rotational Part Only!!! (~ normal transformation)), this will force them to always point towards the camera (cfr. BillBoarding) topLeft = mul(topLeft, (float3x3) gViewInverse) + origin; topRight = mul(topRight, (float3x3) gViewInverse) + origin; bottomLeft = mul(bottomLeft, (float3x3) gViewInverse) + origin; bottomRight = mul(bottomRight, (float3x3) gViewInverse) + origin; //This is the 2x2 rotation matrix we need to transform our TextureCoordinates (Texture Rotation) float2x2 uvRotation = {cos(vertex[0].Rotation), - sin(vertex[0].Rotation), sin(vertex[0].Rotation), cos(vertex[0].Rotation)}; //Create Geometry (Trianglestrip) CreateVertex(triStream, bottomLeft, float2(0,1), vertex[0].Color, uvRotation); CreateVertex(triStream, topLeft, float2(0,0), vertex[0].Color, uvRotation); CreateVertex(triStream, bottomRight, float2(1,1), vertex[0].Color, uvRotation); CreateVertex(triStream, topRight, float2(1,0), vertex[0].Color, uvRotation); } //PIXEL SHADER //************ float4 MainPS(GS_DATA input) : SV_TARGET { //Simple Texture Sampling float4 result = gParticleTexture.Sample(samPoint, input.TexCoord); return input.Color * result; } // Default Technique technique10 Default { pass p0 { SetVertexShader(CompileShader(vs_4_0, MainVS())); SetGeometryShader(CompileShader(gs_4_0, MainGS())); SetPixelShader(CompileShader(ps_4_0, MainPS())); SetRasterizerState(BackCulling); SetDepthStencilState(DisableDepthWriting, 0); SetBlendState(AlphaBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF); } }