forked from LukasBanana/LLGL
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathExample.CSStretchConstraints.450core.comp
164 lines (136 loc) · 4.61 KB
/
Example.CSStretchConstraints.450core.comp
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// GLSL Compute Shader "CSStretchConstraints"
// Generated by XShaderCompiler
// 11/10/2019 20:18:28
#version 450 core
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
layout(std140, row_major, binding = 0) uniform SceneState
{
mat4 wvpMatrix;
mat4 wMatrix;
vec4 gravity;
uvec2 gridSize;
uvec2 _pad0;
float damping;
float dTime;
float dStiffness;
float _pad1;
vec4 lightVec;
};
// Sub view of a particle
struct ParticleView
{
vec4 currPos;
vec4 nextPos;
vec4 origPos;
vec4 normal;
float invMass;
};
// Particle buffers
layout(std430, binding = 1) readonly buffer parBase
{
vec4 g_parBase[];
};
layout(std430, binding = 2) buffer parCurrPos
{
vec4 g_parCurrPos[];
};
layout(std430, binding = 3) writeonly buffer parNextPos
{
vec4 g_parNextPos[];
};
layout(std430, binding = 6) buffer parNormal
{
vec4 g_parNormal[];
};
// Returns the particle index for the specified grid
uint GridPosToIndex(uvec2 gridPos)
{
return (gridPos.y * gridSize.x + gridPos.x);
}
// Converts the specified grid UV coordinates to the original vertex coordinates.
// Only distance between those coordinates are important.
vec4 UVToOrigPos(vec2 uv)
{
return vec4(uv.x * 2.0 - 1.0, 0.0, uv.y * -2.0, 1.0);
}
void AccumulateStretchConstraints(ParticleView par, ivec2 neighborGridPos, inout vec3 dCorrection)
{
if (neighborGridPos.x < 0 || uint(neighborGridPos.x) >= gridSize.x ||
neighborGridPos.y < 0 || uint(neighborGridPos.y) >= gridSize.y)
{
return;
}
// Read neighbor particle
uint idx = GridPosToIndex(uvec2(neighborGridPos));
vec4 otherCurrPos = g_parCurrPos[idx];
vec4 otherOrigPos = UVToOrigPos(g_parBase[idx].xy);
float otherInvMass = g_parBase[idx].z;
// Compute edge distance between particle and its neighbor
vec3 dPos = (par.nextPos - otherCurrPos).xyz;
float currDist = length(dPos);
float edgeDist = distance(par.origPos, otherOrigPos);
// Compute stretch constraint
dPos = normalize(dPos) * ((currDist - edgeDist) / (par.invMass + otherInvMass));
// Adjust position
dCorrection += (dPos * -par.invMass);
}
vec3 ReadParticlePos(uvec2 gridPos)
{
return g_parCurrPos[GridPosToIndex(gridPos)].xyz;
}
void AccumulateSurfaceNormal(vec4 pos, ivec2 gridPos0, ivec2 gridPos1, inout vec4 normal)
{
if (gridPos0.x < 0 || uint(gridPos0.x) >= gridSize.x ||
gridPos0.y < 0 || uint(gridPos0.y) >= gridSize.y ||
gridPos1.x < 0 || uint(gridPos1.x) >= gridSize.x ||
gridPos1.y < 0 || uint(gridPos1.y) >= gridSize.y)
{
return;
}
vec3 v0 = ReadParticlePos(uvec2(gridPos0)) - pos.xyz;
vec3 v1 = ReadParticlePos(uvec2(gridPos1)) - pos.xyz;
normal.xyz += cross(v0, v1);
}
void ApplyStretchConstraints(inout ParticleView par, ivec2 gridPos)
{
if (par.invMass == 0.0)
{
return;
}
// Apply stretch constraints
vec3 dPos = vec3(0);
AccumulateStretchConstraints(par, gridPos + ivec2( 0, -1), dPos);
AccumulateStretchConstraints(par, gridPos + ivec2( 0, +1), dPos);
AccumulateStretchConstraints(par, gridPos + ivec2(-1, 0), dPos);
AccumulateStretchConstraints(par, gridPos + ivec2(+1, 0), dPos);
AccumulateStretchConstraints(par, gridPos + ivec2(-1, -1), dPos);
AccumulateStretchConstraints(par, gridPos + ivec2(+1, -1), dPos);
AccumulateStretchConstraints(par, gridPos + ivec2(-1, +1), dPos);
AccumulateStretchConstraints(par, gridPos + ivec2(+1, +1), dPos);
dPos /= vec3(8.0);
// Compute normal
vec4 normal = vec4(0);
AccumulateSurfaceNormal(par.currPos, gridPos + ivec2( 0, +1), gridPos + ivec2(+1, 0), normal);
AccumulateSurfaceNormal(par.currPos, gridPos + ivec2(+1, 0), gridPos + ivec2( 0, -1), normal);
AccumulateSurfaceNormal(par.currPos, gridPos + ivec2( 0, -1), gridPos + ivec2(-1, 0), normal);
AccumulateSurfaceNormal(par.currPos, gridPos + ivec2(-1, 0), gridPos + ivec2( 0, +1), normal);
par.normal = normal / 4.0;
// Adjust position by correction vector
par.nextPos.xyz += dPos * dStiffness;
}
void main()
{
uint idx = GridPosToIndex(gl_GlobalInvocationID.xy);
// Read particle
ParticleView par;
par.currPos = g_parCurrPos[idx];
par.nextPos = par.currPos;
par.origPos = UVToOrigPos(g_parBase[idx].xy);
par.normal = g_parNormal[idx];
par.invMass = g_parBase[idx].z;
// Apply stretch constraints
ApplyStretchConstraints(par, ivec2(gl_GlobalInvocationID.xy));
// Write next position back to swap-buffer
g_parNextPos[idx] = par.nextPos;
g_parNormal[idx] = par.normal;
}