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