Files
samples/strand.comp
2026-04-06 19:25:26 -04:00

87 lines
2.6 KiB
GLSL

/*
* Copyright (c) 2026 Mykhailo Mamedov. All rights reserved.
*
* RESEARCH PREVIEW / REFERENCE ONLY:
* This source code is provided solely for the purpose of reviewing
* the author's research methods and implementation.
*
* NO LICENSE GRANTED:
* This code is NOT for distribution, modification, or use in any
* project (commercial or otherwise). Unauthorized copying or
* use of this code is strictly prohibited.
*
* For inquiries regarding use or licensing, contact: ua.modin@gmail.com
*/
#version 460
#extension GL_EXT_debug_printf : enable
#extension GL_EXT_shader_atomic_float : enable
layout(local_size_x = 64) in;
struct CurveHeader {
uint poolOffset;
uint pointCount;
uint maxPoints;
uint _padding;
vec4 color;
};
struct PointData {
vec4 pos; // xyz = worldPos, w = radius
};
layout(std430, binding = 0) readonly buffer HeaderBuffer { CurveHeader headers[]; };
layout(std430, binding = 1) readonly buffer PointPool { PointData pool[]; };
layout(std430, binding = 2) writeonly buffer RenderBuffer { vec4 smoothPoints[]; };
layout(r32f, binding = 3) uniform image3D shadowVolume;
layout(push_constant) uniform Push {
mat4 viewProj;
vec3 gridOrigin;
float gridCellSize;
float gridExtent;
uint frameCount;
float _pad[2];
} pc;
shared vec4 s_Points[100];
shared CurveHeader s_Header;
void main() {
uint strandIdx = gl_WorkGroupID.x;
uint segmentIdx = gl_LocalInvocationID.x; // 0 to 63
if (segmentIdx == 0) s_Header = headers[strandIdx];
barrier();
if (s_Header.pointCount == 0) return;
for (uint i = segmentIdx; i < 100; i += 64) {
if (i < s_Header.pointCount) {
s_Points[i] = pool[s_Header.poolOffset + i].pos;
}
}
barrier();
float t_global = float(segmentIdx) / 63.0;
float segProgress = t_global * float(s_Header.pointCount - 1);
int i = int(floor(segProgress));
float t_local = fract(segProgress);
// Fetch from shared memory
vec3 p0 = s_Points[max(i - 1, 0)].xyz;
vec3 p1 = s_Points[i].xyz;
vec3 p2 = s_Points[min(i + 1, int(s_Header.pointCount - 1))].xyz;
vec3 p3 = s_Points[min(i + 2, int(s_Header.pointCount - 1))].xyz;
vec3 finalPos = catmullRom(p0, p1, p2, p3, t_local);
float radius = mix(s_Points[i].w, s_Points[min(i + 1, int(s_Header.pointCount - 1))].w, t_local);
uint outIdx = (strandIdx * 64) + segmentIdx;
smoothPoints[outIdx] = vec4(finalPos, radius);
ivec3 voxel = ivec3(((finalPos - pc.gridOrigin) / pc.gridExtent)*pc.gridSize);
if (all(greaterThanEqual(voxel, ivec3(0))) && all(lessThan(voxel, ivec3(pc.gridSize)))) {
imageAtomicAdd(shadowVolume, voxel, 0.01);
}
}