• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#version 460 core
2#extension GL_ARB_separate_shader_objects : enable
3#extension GL_ARB_shading_language_420pack : enable
4
5
6#include "common/dotfield_common.h"
7#include "common/dotfield_struct_common.h"
8
9// sets
10
11// set 0, input buffer
12layout(set = 0, binding = 0, std430) readonly buffer inBuffer
13{
14    uvec2 inputBuffer[];
15};
16
17// set 1, output buffer
18layout(set = 1, binding = 0, std430) writeonly buffer outBuffer
19{
20    uvec2 outputBuffer[];
21};
22
23layout(push_constant, std430) uniform uPushConstant
24{
25    DotfieldSimulationPushConstantStruct inPushConstant;
26};
27
28// specialization
29layout(constant_id = 0) const uint LOAD_MODE = 0;
30
31
32///////////////////////////////////////////////////////////////////////////////
33
34// Sample input buffer with clamping
35vec3 sampleGrid(int x, int y)
36{
37    int sx = clamp(x, 0, int(inPushConstant.indices.x - 1));
38    int sy = clamp(y, 0, int(inPushConstant.indices.y - 1));
39
40    uvec2 inp = inputBuffer[sy * inPushConstant.indices.x + sx];
41    return vec3(unpackHalf2x16(inp.x), unpackHalf2x16(inp.y).x);
42}
43
44layout(local_size_x = DOTFIELD_SIMULATION_TGS, local_size_y = 1, local_size_z = 1) in;
45void main()
46{
47    // Tunable variables
48    const float displacementSpeed = 0.2f;
49    const vec3 maxDisplacement = vec3(0.2f, 0.2f, 0.7f);
50    const float tensionFactor = 0.1f;
51    const float dampenFactor = 0.9f;
52
53    const uint tid = gl_GlobalInvocationID.x;
54
55    const int grid_x = int(tid % inPushConstant.indices.x);
56    const int grid_y = int(tid / inPushConstant.indices.x);
57
58    vec3 inValue;
59    vec3 outValue;
60    if ( LOAD_MODE == 0 ) {
61        // Normal mode, read input buffer
62        uvec2 current = inputBuffer[tid];
63        outValue.xy = unpackHalf2x16(current.x);
64        outValue.z = unpackHalf2x16(current.y).x;
65
66        const float diag = 0.70710678118f; // 1/sqrt(2)
67        inValue = sampleGrid(grid_x - 1, grid_y - 1);
68        inValue += sampleGrid(grid_x + 1, grid_y - 1);
69        inValue += sampleGrid(grid_x - 1, grid_y + 1);
70        inValue += sampleGrid(grid_x + 1, grid_y + 1);
71        inValue *= diag;
72
73        inValue += sampleGrid(grid_x - 1, grid_y);
74        inValue += sampleGrid(grid_x + 1, grid_y);
75        inValue += sampleGrid(grid_x, grid_y - 1);
76        inValue += sampleGrid(grid_x, grid_y + 1);
77
78        inValue /= (diag * 4 + 4); // calculate weighted average
79    } else {
80        // First frame, initialize to zero
81        inValue = vec3(0.f);
82        outValue = vec3(0.f);
83    }
84    outValue *= dampenFactor;
85    outValue = mix(inValue, outValue, tensionFactor);
86
87    if ( inPushConstant.pos.z > 0 )
88    {
89        // Apply touch
90        vec2 delta = vec2(grid_x, grid_y) - inPushConstant.pos.xy;
91        float distance = length(delta);
92        if ( distance < inPushConstant.pos.z )
93        {
94            delta /= inPushConstant.pos.z;
95            float reconstructZ = -sqrt(1.f - dot(delta, delta));
96            vec3 delta3 = normalize(vec3(delta, reconstructZ));
97            outValue = mix(outValue, delta3 * maxDisplacement, displacementSpeed);
98        }
99    }
100    uvec2 outp;
101    outp.x = packHalf2x16(outValue.xy);
102    outp.y = packHalf2x16(outValue.zz);
103    outputBuffer[tid] = outp;
104}
105