mirror of
https://github.com/hyprwm/Hyprland.git
synced 2026-08-24 02:24:14 -05:00
127 lines
4.8 KiB
GLSL
127 lines
4.8 KiB
GLSL
#version 300 es
|
|
#define ALLOW_INCLUDES
|
|
#extension GL_ARB_shading_language_include : enable
|
|
|
|
precision highp float;
|
|
precision highp int;
|
|
precision highp usampler2D;
|
|
|
|
in vec2 v_texcoord;
|
|
uniform sampler2D fluidJarParticleTex;
|
|
uniform usampler2D fluidJarGraphTex;
|
|
uniform vec2 fluidJarResolution;
|
|
uniform vec2 fluidJarGridSize;
|
|
uniform int fluidJarParticleCount;
|
|
uniform int fluidJarFrame;
|
|
|
|
#include "fluidJar.glsl"
|
|
|
|
layout(location = 0) out uvec4 fragColor;
|
|
|
|
ivec4 nearestIds = ivec4(-1);
|
|
vec4 nearestDistances = vec4(1e6);
|
|
|
|
void insertNearest(float distanceValue, int id) {
|
|
if (nearestDistances.x > distanceValue) {
|
|
nearestDistances = vec4(distanceValue, nearestDistances.xyz);
|
|
nearestIds = ivec4(id, nearestIds.xyz);
|
|
} else if (nearestDistances.y > distanceValue) {
|
|
nearestDistances.yzw = vec3(distanceValue, nearestDistances.yz);
|
|
nearestIds.yzw = ivec3(id, nearestIds.yz);
|
|
} else if (nearestDistances.z > distanceValue) {
|
|
nearestDistances.zw = vec2(distanceValue, nearestDistances.z);
|
|
nearestIds.zw = ivec2(id, nearestIds.z);
|
|
} else if (nearestDistances.w > distanceValue) {
|
|
nearestDistances.w = distanceValue;
|
|
nearestIds.w = id;
|
|
}
|
|
}
|
|
|
|
bool alreadySorted(int id, int currentId) {
|
|
return id < 0 || id >= fluidJarParticleCount || id == currentId || any(equal(nearestIds, ivec4(id)));
|
|
}
|
|
|
|
int neighborDirection(vec2 delta, int firstId, int secondId) {
|
|
if (dot(delta, delta) < 1e-6) {
|
|
float pairHash = fluidJarHash13(vec3(float(min(firstId, secondId)), float(max(firstId, secondId)), 0.731));
|
|
int pairDirection = min(int(pairHash * 4.0), 3);
|
|
return firstId < secondId ? pairDirection : pairDirection ^ 1;
|
|
}
|
|
|
|
if (abs(delta.x) >= abs(delta.y))
|
|
return delta.x >= 0.0 ? 0 : 1;
|
|
return delta.y >= 0.0 ? 2 : 3;
|
|
}
|
|
|
|
void sortCandidate(int candidate, int direction, FluidJarParticle particle, ivec2 gridSize) {
|
|
if (alreadySorted(candidate, particle.id))
|
|
return;
|
|
|
|
vec2 neighborPosition = texelFetch(fluidJarParticleTex, fluidJarAddress(candidate, 0, gridSize), 0).xy;
|
|
vec2 delta = neighborPosition - particle.position;
|
|
if (neighborDirection(delta, particle.id, candidate) != direction)
|
|
return;
|
|
insertNearest(length(delta), candidate);
|
|
}
|
|
|
|
void sortGridCandidate(int row, int columnOffset, int direction, FluidJarParticle particle, ivec2 gridSize) {
|
|
if (row < 0 || row >= gridSize.y)
|
|
return;
|
|
|
|
int rowStart = row * gridSize.x;
|
|
int rowCount = min(gridSize.x, fluidJarParticleCount - rowStart);
|
|
if (rowCount <= 0)
|
|
return;
|
|
|
|
vec2 spacing = fluidJarResolution / vec2(gridSize);
|
|
float centering = 0.5 * float(gridSize.x - rowCount);
|
|
int column = clamp(int(particle.position.x / spacing.x - centering) + columnOffset, 0, rowCount - 1);
|
|
sortCandidate(rowStart + column, direction, particle, gridSize);
|
|
}
|
|
|
|
void main() {
|
|
ivec2 pixel = ivec2(gl_FragCoord.xy);
|
|
ivec2 gridSize = ivec2(fluidJarGridSize);
|
|
ivec2 storageSize = FLUID_JAR_GRAPH_SLOT_SIZE * gridSize;
|
|
if (any(greaterThanEqual(pixel, storageSize))) {
|
|
fragColor = uvec4(0u);
|
|
return;
|
|
}
|
|
|
|
ivec2 cell = pixel / FLUID_JAR_GRAPH_SLOT_SIZE;
|
|
int id = cell.x + cell.y * gridSize.x;
|
|
int field = pixel.x % FLUID_JAR_GRAPH_SLOT_SIZE.x;
|
|
int direction = field / 2;
|
|
int pairIndex = field % 2;
|
|
if (id >= fluidJarParticleCount) {
|
|
fragColor = uvec4(0u);
|
|
return;
|
|
}
|
|
|
|
FluidJarParticle particle = fluidJarLoadParticle(fluidJarParticleTex, id, gridSize);
|
|
int estimatedRow = min(int(particle.position.y / (fluidJarResolution.y / float(gridSize.y))), (fluidJarParticleCount - 1) / gridSize.x);
|
|
for (int offset = -4; offset <= 4; ++offset)
|
|
sortGridCandidate(estimatedRow + offset, 0, direction, particle, gridSize);
|
|
for (int offset = 1; offset <= 2; ++offset) {
|
|
sortGridCandidate(estimatedRow, -offset, direction, particle, gridSize);
|
|
sortGridCandidate(estimatedRow, offset, direction, particle, gridSize);
|
|
}
|
|
|
|
for (int index = 0; index < 8; ++index)
|
|
sortCandidate(int(float(fluidJarParticleCount) * fluidJarHash13(vec3(float(fluidJarFrame), float(id), float(index)))), direction, particle, gridSize);
|
|
|
|
ivec4 directNeighbors = fluidJarLoadNeighbors(fluidJarGraphTex, id, direction, gridSize);
|
|
for (int index = 0; index < 4; ++index) {
|
|
int neighborId = directNeighbors[index];
|
|
sortCandidate(neighborId, direction, particle, gridSize);
|
|
if (neighborId < 0 || neighborId >= fluidJarParticleCount)
|
|
continue;
|
|
|
|
ivec4 indirectNeighbors = fluidJarLoadNeighbors(fluidJarGraphTex, neighborId, (fluidJarFrame + id) % 4, gridSize);
|
|
for (int indirect = 0; indirect < 2; ++indirect)
|
|
sortCandidate(indirectNeighbors[indirect], direction, particle, gridSize);
|
|
}
|
|
|
|
fragColor = fluidJarEncodeIdPair(pairIndex == 0 ? nearestIds.xy : nearestIds.zw);
|
|
}
|