File size: 2,263 Bytes
0c51b93
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include "shaderCommon.h"

cbuffer constBuf : register(b0)
{
	DiffuseShaderConst gParams;
};

static const float2 corners[4] =
{
	float2(0.0, 1.0),
	float2(0.0, 0.0),
	float2(1.0, 1.0),
	float2(1.0, 0.0)
};

[maxvertexcount(4)]
void diffuseGS(point DiffuseVertexOut input[1], inout TriangleStream<DiffuseGeometryOut> triStream)
{
	float4 ndcPos = input[0].ndcPos;

	// frustrum culling
	const float ndcBound = 1.0;
	if (ndcPos.x < -ndcBound) return;
	if (ndcPos.x > ndcBound) return;
	if (ndcPos.y < -ndcBound) return;
	if (ndcPos.y > ndcBound) return;

	float pointScale = gParams.diffuseScale;
	float velocityScale = 1.0;

	float3 v = input[0].viewVel.xyz;
	float3 p = input[0].viewPos.xyz;
		
	// billboard in eye space
	float3 u = float3(0.0, pointScale, 0.0);
	float3 l = float3(pointScale, 0.0, 0.0);
	
	// increase size based on life
	float lifeTime = input[0].worldPos.w;

	float lifeFade = lerp(1.0f + gParams.diffusion, 1.0, min(1.0, lifeTime*0.25f));
	u *= lifeFade;
	l *= lifeFade;

	float fade = 1.0/(lifeFade*lifeFade);
	float vlen = length(v)*gParams.motionBlurScale;
	
	if (vlen > 0.5)
	{
		float len = max(pointScale, vlen*0.016);
		fade = min(1.0, 2.0/(len/pointScale));

		u = normalize(v)*max(pointScale, vlen*0.016);	// assume 60hz
		l = normalize(cross(u, float3(0.0, 0.0, -1.0)))*pointScale;
	}
	
	{
		DiffuseGeometryOut output;
		
		output.worldPos = input[0].worldPos;	// vertex world pos (life in w)
		output.viewPos = input[0].viewPos;		// vertex eye pos
		output.viewVel.xyz = input[0].viewVel.xyz; // vertex velocity in view space
		output.viewVel.w = fade;
		output.lightDir = mul(gParams.modelView, float4(gParams.lightDir, 0.0));
		output.color = input[0].color;

		output.uv = float2(0.0, 1.0);      
		output.clipPos = mul(gParams.projection, float4(p + u - l, 1.0));
		triStream.Append(output);
		
		output.uv = float2(0.0, 0.0);
        output.clipPos = mul(gParams.projection, float4(p - u - l, 1.0));
        triStream.Append(output);

		output.uv = float2(1.0, 1.0);
        output.clipPos = mul(gParams.projection, float4(p + u + l, 1.0));
        triStream.Append(output);

		output.uv = float2(1.0, 0.0);
        output.clipPos = mul(gParams.projection, float4(p - u + l, 1.0));
        triStream.Append(output);
    }
}