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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
#include "shaderCommon.h"
cbuffer constBuf : register(b0)
{
FluidShaderConst gParams;
};
// returns 1.0 for x==0.0 (unlike glsl)
float Sign(float x) { return x < 0.0 ? -1.0 : 1.0; }
bool solveQuadratic(float a, float b, float c, out float minT, out float maxT)
{
#if 0
// for debugging
minT = -0.5;
maxT = 0.5;
return true;
#else
//minT = 0.0f;
//maxT = 0.0f;
#endif
if (a == 0.0 && b == 0.0)
{
minT = maxT = 0.0;
return false;
}
float discriminant = b*b - 4.0*a*c;
if (discriminant < 0.0)
{
return false;
}
float t = -0.5*(b + Sign(b)*sqrt(discriminant));
minT = t / a;
maxT = c / t;
if (minT > maxT)
{
float tmp = minT;
minT = maxT;
maxT = tmp;
}
return true;
}
float DotInvW(float4 a, float4 b) { return a.x*b.x + a.y*b.y + a.z*b.z - a.w*b.w; }
FluidVertexOut ellipsoidDepthVS(FluidVertexIn input, uint instance : SV_VertexID)
{
const float4 q1 = input.q1;
const float4 q2 = input.q2;
const float4 q3 = input.q3;
const float4x4 modelViewProjectionMatrix = gParams.modelViewProjection;
const float4x4 modelViewMatrixInverse = gParams.inverseModelView;
float3 worldPos = input.position.xyz;
// construct quadric matrix
float4x4 q;
q._m00_m10_m20_m30 = float4(q1.xyz*q1.w, 0.0);
q._m01_m11_m21_m31 = float4(q2.xyz*q2.w, 0.0);
q._m02_m12_m22_m32 = float4(q3.xyz*q3.w, 0.0);
q._m03_m13_m23_m33 = float4(worldPos, 1.0);
// transforms a normal to parameter space (inverse transpose of (q*modelview)^-T)
float4x4 invClip = mul(modelViewProjectionMatrix, q);
// solve for the right hand bounds in homogenous clip space
float a1 = DotInvW(invClip[3], invClip[3]);
float b1 = -2.0f*DotInvW(invClip[0], invClip[3]);
float c1 = DotInvW(invClip[0], invClip[0]);
float xmin;
float xmax;
solveQuadratic(a1, b1, c1, xmin, xmax);
// solve for the right hand bounds in homogenous clip space
float a2 = DotInvW(invClip[3], invClip[3]);
float b2 = -2.0f*DotInvW(invClip[1], invClip[3]);
float c2 = DotInvW(invClip[1], invClip[1]);
float ymin;
float ymax;
solveQuadratic(a2, b2, c2, ymin, ymax);
FluidVertexOut output;
output.position = float4(worldPos.xyz, 1.0);
output.bounds = float4(xmin, xmax, ymin, ymax);
// construct inverse quadric matrix (used for ray-casting in parameter space)
float4x4 invq;
invq._m00_m10_m20_m30 = float4(q1.xyz / q1.w, 0.0);
invq._m01_m11_m21_m31 = float4(q2.xyz / q2.w, 0.0);
invq._m02_m12_m22_m32 = float4(q3.xyz / q3.w, 0.0);
invq._m03_m13_m23_m33 = float4(0.0, 0.0, 0.0, 1.0);
invq = transpose(invq);
invq._m03_m13_m23_m33 = -(mul(invq, output.position));
// transform a point from view space to parameter space
invq = mul(invq, modelViewMatrixInverse);
// pass down
output.invQ0 = invq._m00_m10_m20_m30;
output.invQ1 = invq._m01_m11_m21_m31;
output.invQ2 = invq._m02_m12_m22_m32;
output.invQ3 = invq._m03_m13_m23_m33;
// compute ndc pos for frustrum culling in GS
float4 projPos = mul(modelViewProjectionMatrix, float4(worldPos.xyz, 1.0));
output.ndcPos = projPos / projPos.w;
return output;
}
|