in vec4 pos;
void main() {
gl_Position = pos;
}
#version 460
const uint MAX_ROTATIONS_LEVEL = 6;
const uint MAX_ROTATIONS = 1 << MAX_ROTATIONS_LEVEL;
layout(binding = 0) buffer SSBO0 {
ivec4 DistanceMap[MAX_ROTATIONS * 2];
int HeightMap[];
};
in GS_OUT {
vec2 TexCoord;
}
gs_out;
out vec4 Color;
layout(location = 0) uniform int ScreenWidth;
uniform sampler2D image;
void main() {
if(texture(image, gs_out.TexCoord).r > 0) {
atomicMax(HeightMap[gl_PrimitiveID * ScreenWidth + int(gl_FragCoord.x)], int(gl_FragCoord.y));
atomicMax(DistanceMap[gl_PrimitiveID].x, (int(gl_FragCoord.y) << 16) + int(gl_FragCoord.x));
atomicMin(DistanceMap[gl_PrimitiveID].z, (int(-gl_FragCoord.y) << 16) + int(gl_FragCoord.x));
}
}
#version 460
const uint MAX_ROTATIONS_LEVEL = 6;
const uint MAX_ROTATIONS = 1 << MAX_ROTATIONS_LEVEL;
const vec2 center = vec2(0.5, 0.25);
layout(points, invocations = MAX_ROTATIONS) in;
layout(triangle_strip, max_vertices = 4) out;
out GS_OUT {
vec2 TexCoord;
}
gs_out;
void main() {
float a = 6.283185307179586476925286766559 / MAX_ROTATIONS * gl_InvocationID;
mat4 RotMat = mat4(cos(a), -sin(a), 0.0, 0.0, sin(a), cos(a), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
gl_PrimitiveID = gl_InvocationID;
gl_Position = vec4(-gl_in[0].gl_Position.x, gl_in[0].gl_Position.y, 0.0, 1.0) * RotMat;
gs_out.TexCoord = vec2(-gl_in[0].gl_Position.z, gl_in[0].gl_Position.w) + center;
EmitVertex();
gl_Position = vec4(gl_in[0].gl_Position.xy, 0.0, 1.0) * RotMat;
gs_out.TexCoord = gl_in[0].gl_Position.zw + center;
EmitVertex();
gl_Position = vec4(-gl_in[0].gl_Position.xy, 0.0, 1.0) * RotMat;
gs_out.TexCoord = center - gl_in[0].gl_Position.zw;
EmitVertex();
gl_Position = vec4(gl_in[0].gl_Position.x, -gl_in[0].gl_Position.y, 0.0, 1.0) * RotMat;
gs_out.TexCoord = vec2(gl_in[0].gl_Position.z, -gl_in[0].gl_Position.w) + center;
EmitVertex();
EndPrimitive();
}
#version 460
const uint MAX_DIST = 50;
const uint MAX_ROTATIONS_LEVEL = 6;
const uint MAX_ROTATIONS = 1 << MAX_ROTATIONS_LEVEL;
const uint DIST_TOP = (MAX_ROTATIONS * 0) >> 2;
const uint DIST_RIGHT = (MAX_ROTATIONS * 1) >> 2;
const uint DIST_BOTTOM = (MAX_ROTATIONS * 2) >> 2;
const uint DIST_LEFT = (MAX_ROTATIONS * 3) >> 2;
layout(local_size_z = MAX_ROTATIONS) in;
layout(binding = 0) buffer SSBO0 {
ivec4 DistanceMap[MAX_ROTATIONS * 2];
uint HeightMap[];
};
layout(binding = 1) buffer SSBO1 {
uint PlacementMap[];
};
layout(binding = 2) buffer SSBO2 {
uint SheetWidth, HeightMapWidth, Rotations, reserved;
uint SheetHeightMap[10000 + MAX_DIST];
uvec2 NFP[];
};
void main() {
uint i, j, k;
if(gl_LocalInvocationID.z >> Rotations == 0) {
uint angle = gl_LocalInvocationID.z << (MAX_ROTATIONS_LEVEL - Rotations);
uint n = (gl_GlobalInvocationID.x << Rotations) + gl_LocalInvocationID.z;
if(PlacementMap[n] == 0) {
uvec2 curPlace = uvec2(NFP[gl_GlobalInvocationID.x].x & 0xFFFF, NFP[gl_GlobalInvocationID.x].x >> 16);
switch(NFP[gl_GlobalInvocationID.x].y) {
case 0:
curPlace = uvec2(curPlace.x, curPlace.y - (DistanceMap[angle + DIST_LEFT].z + DistanceMap[angle + DIST_BOTTOM].y));
break;
case 1:
curPlace = uvec2(curPlace.x + (DistanceMap[angle + DIST_BOTTOM].x - DistanceMap[angle + DIST_LEFT].y), curPlace.y);
break;
case 2:
curPlace = curPlace.xy - uvec2(DistanceMap[angle + DIST_RIGHT].y + DistanceMap[angle + DIST_LEFT].y, DistanceMap[angle + DIST_BOTTOM].y - DistanceMap[angle + DIST_RIGHT].x);
break;
}
uint Area = 0;
for(i = 0; i < curPlace.x; i++) Area += SheetHeightMap[i];
i = HeightMapWidth * angle;
uint len = HeightMap[i] + curPlace.x;
for(j = curPlace.x, k = i + 1; j < len; j++, k++) Area += max(SheetHeightMap[j], HeightMap[k] + curPlace.y);
for(j = len; j < SheetWidth; j++) Area += SheetHeightMap[j];
PlacementMap[n] = Area;
}
}
}
#version 460 in vec4 Pos;
void main() {
gl_Position = vec4(Pos.xy, gl_VertexID, Pos.z);
}
#version 460 in GS_OUT {
vec2 TexCoord;
}
gs_out;
layout(binding = 0) uniform sampler2D image;
layout(binding = 1) uniform sampler2DRect back;
layout(binding = 1) buffer SSBO1 {
uint PlacementMap[];
};
void main() {
if((texture(image, gs_out.TexCoord.xy).r * texture(back, gl_FragCoord.xy).r != 0)) {
PlacementMap[gl_PrimitiveID] = 0xFFFFFFFF;
}
}
#version 460
const uint MAX_ROTATIONS_LEVEL = 6;
const uint MAX_ROTATIONS = 1 << MAX_ROTATIONS_LEVEL;
const uint DIST_TOP = (MAX_ROTATIONS * 0) >> 2;
const uint DIST_RIGHT = (MAX_ROTATIONS * 1) >> 2;
const uint DIST_BOTTOM = (MAX_ROTATIONS * 2) >> 2;
const uint DIST_LEFT = (MAX_ROTATIONS * 3) >> 2;
layout(binding = 0) buffer SSBO0 {
ivec4 DistanceMap[MAX_ROTATIONS * 2];
};
layout(binding = 1) buffer SSBO1 {
uint PlacementMap[];
};
layout(binding = 2) buffer SSBO2 {
uint FrameBuffer[];
};
layout(points, invocations = MAX_ROTATIONS) in;
layout(triangle_strip, max_vertices = 4) out;
out GS_OUT {
vec2 TexCoord;
}
gs_out;
layout(location = 0) uniform vec4 Param;
layout(location = 1) uniform int Rotations;
void main() {
const vec2 Center = vec2(0.5, 0.25);
const float PI = 3.1415926535897932384626433832795;
if(gl_InvocationID >> Rotations == 0) {
uint i = gl_InvocationID << (MAX_ROTATIONS_LEVEL - Rotations);
float a = i * (PI * 2) / MAX_ROTATIONS;
ivec4 top = DistanceMap[i + DIST_TOP];
ivec4 right = DistanceMap[i + DIST_RIGHT];
ivec4 bottom = DistanceMap[i + DIST_BOTTOM];
ivec4 left = DistanceMap[i + DIST_LEFT];
ivec2 pos;
switch(int(gl_in[0].gl_Position.w)) {
case 0:
pos = ivec2(gl_in[0].gl_Position.xy) - ivec2(0, left.z + bottom.y);
break;
case 1:
pos = ivec2(gl_in[0].gl_Position.xy) + ivec2(bottom.x - left.y, 0);
break;
case 2:
pos = ivec2(gl_in[0].gl_Position.xy) + ivec2(-left.y, right.x) - ivec2(right.y, bottom.y);
break;
}
ivec2 UpperRight = ivec2(left.y, bottom.y) + ivec2(right.y, top.y) + pos;
gl_PrimitiveID = (int(gl_in[0].gl_Position.z) << Rotations) + gl_InvocationID;
if(any(lessThan(vec4(pos.xy, Param.zw), vec4(0, 0, UpperRight)))) {
PlacementMap[gl_PrimitiveID] = 0xFFFFFFFF;
return;
}
vec4 Rect = fma(vec4(pos, UpperRight), 2 / Param.zwzw, vec4(-1, -1, -1, -1));
ivec2 center = ivec2(pos + ivec2(left.y, bottom.y));
ivec3 index = (center.yyy - ivec3(-left.x, bottom.y, right.x)) * ivec3(Param.zzz) + center.xxx - ivec3(left.y + 1, bottom.x, 1 - right.y);
if(any(greaterThan(uvec3(FrameBuffer[index.x], FrameBuffer[index.y], FrameBuffer[index.z]), uvec3(0, 0, 0)))) {
PlacementMap[gl_PrimitiveID] = 0xFFFFFFFF;
return;
}
float b = atan(left.y, top.y) - a;
gl_Position = vec4(Rect.xw, 0, 1);
gs_out.TexCoord = fma(vec2(-sin(b), cos(b)) * length(vec2(left.y, top.y)), Param.xy, Center);
EmitVertex();
b = -atan(right.y, top.y) - a;
gl_Position = vec4(Rect.zw, 0, 1);
gs_out.TexCoord = fma(vec2(-sin(b), cos(b)) * length(vec2(right.y, top.y)), Param.xy, Center);
EmitVertex();
b = PI - atan(left.y, bottom.y) - a;
gl_Position = vec4(Rect.xy, 0, 1);
gs_out.TexCoord = fma(vec2(-sin(b), cos(b)) * length(vec2(left.y, bottom.y)), Param.xy, Center);
EmitVertex();
b = PI + atan(right.y, bottom.y) - a;
gl_Position = vec4(Rect.zy, 0, 1);
gs_out.TexCoord = fma(vec2(-sin(b), cos(b)) * length(vec2(right.y, bottom.y)), Param.xy, Center);
EmitVertex();
EndPrimitive();
}
}