/* * 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); } }