260 lines
7.0 KiB
GLSL
260 lines
7.0 KiB
GLSL
#version {{version}}
|
|
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#extension GL_GOOGLE_include_directive : enable
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
precision highp float;
|
|
|
|
|
|
|
|
|
|
|
|
layout(local_size_x = 64)in;
|
|
|
|
uniform int uMicrolineCount;
|
|
|
|
uniform int uMaxFillCount;
|
|
|
|
layout(std430, binding = 0)buffer bMicrolines {
|
|
restrict readonly uvec4 iMicrolines[];
|
|
};
|
|
|
|
layout(std430, binding = 1)buffer bMetadata {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
restrict readonly ivec4 iMetadata[];
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
layout(std430, binding = 2)buffer bIndirectDrawParams {
|
|
restrict uint iIndirectDrawParams[];
|
|
};
|
|
|
|
layout(std430, binding = 3)buffer bFills {
|
|
restrict writeonly uint iFills[];
|
|
};
|
|
|
|
layout(std430, binding = 4)buffer bTiles {
|
|
|
|
|
|
|
|
|
|
restrict uint iTiles[];
|
|
};
|
|
|
|
layout(std430, binding = 5)buffer bBackdrops {
|
|
|
|
|
|
|
|
restrict uint iBackdrops[];
|
|
};
|
|
|
|
uint computeTileIndexNoCheck(ivec2 tileCoords, ivec4 pathTileRect, uint pathTileOffset){
|
|
ivec2 offsetCoords = tileCoords - pathTileRect . xy;
|
|
return pathTileOffset + offsetCoords . x + offsetCoords . y *(pathTileRect . z - pathTileRect . x);
|
|
}
|
|
|
|
bvec4 computeTileOutcodes(ivec2 tileCoords, ivec4 pathTileRect){
|
|
return bvec4(lessThan(tileCoords, pathTileRect . xy),
|
|
greaterThanEqual(tileCoords, pathTileRect . zw));
|
|
}
|
|
|
|
bool computeTileIndex(ivec2 tileCoords,
|
|
ivec4 pathTileRect,
|
|
uint pathTileOffset,
|
|
out uint outTileIndex){
|
|
outTileIndex = computeTileIndexNoCheck(tileCoords, pathTileRect, pathTileOffset);
|
|
return ! any(computeTileOutcodes(tileCoords, pathTileRect));
|
|
}
|
|
|
|
void addFill(vec4 lineSegment, ivec2 tileCoords, ivec4 pathTileRect, uint pathTileOffset){
|
|
|
|
uint tileIndex;
|
|
if(! computeTileIndex(tileCoords, pathTileRect, pathTileOffset, tileIndex)){
|
|
return;
|
|
}
|
|
|
|
|
|
uvec4 scaledLocalLine = uvec4((lineSegment - vec4(tileCoords . xyxy * ivec4(16)))* vec4(256.0));
|
|
if(scaledLocalLine . x == scaledLocalLine . z)
|
|
return;
|
|
|
|
|
|
uint fillIndex = atomicAdd(iIndirectDrawParams[1], 1);
|
|
|
|
|
|
uint fillLink = atomicExchange(iTiles[tileIndex * 4 + 1],
|
|
int(fillIndex));
|
|
|
|
|
|
if(fillIndex < uMaxFillCount){
|
|
iFills[fillIndex * 3 + 0]= scaledLocalLine . x |(scaledLocalLine . y << 16);
|
|
iFills[fillIndex * 3 + 1]= scaledLocalLine . z |(scaledLocalLine . w << 16);
|
|
iFills[fillIndex * 3 + 2]= fillLink;
|
|
}
|
|
}
|
|
|
|
void adjustBackdrop(int backdropDelta,
|
|
ivec2 tileCoords,
|
|
ivec4 pathTileRect,
|
|
uint pathTileOffset,
|
|
uint pathBackdropOffset){
|
|
bvec4 outcodes = computeTileOutcodes(tileCoords, pathTileRect);
|
|
if(any(outcodes)){
|
|
if(! outcodes . x && outcodes . y && ! outcodes . z){
|
|
uint backdropIndex = pathBackdropOffset + uint(tileCoords . x - pathTileRect . x);
|
|
atomicAdd(iBackdrops[backdropIndex * 3], backdropDelta);
|
|
}
|
|
} else {
|
|
uint tileIndex = computeTileIndexNoCheck(tileCoords, pathTileRect, pathTileOffset);
|
|
atomicAdd(iTiles[tileIndex * 4 + 2],
|
|
uint(backdropDelta)<< 24);
|
|
}
|
|
}
|
|
|
|
vec4 unpackMicroline(uvec4 packedMicroline, out uint outPathIndex){
|
|
outPathIndex = packedMicroline . w;
|
|
ivec4 signedMicroline = ivec4(packedMicroline);
|
|
return vec4((signedMicroline . x << 16)>> 16, signedMicroline . x >> 16,
|
|
(signedMicroline . y << 16)>> 16, signedMicroline . y >> 16)+
|
|
vec4(signedMicroline . z & 0xff,(signedMicroline . z >> 8)& 0xff,
|
|
(signedMicroline . z >> 16)& 0xff,(signedMicroline . z >> 24)& 0xff)/ 256.0;
|
|
}
|
|
|
|
void main(){
|
|
uint segmentIndex = gl_GlobalInvocationID . x;
|
|
if(segmentIndex >= uMicrolineCount)
|
|
return;
|
|
|
|
uint pathIndex;
|
|
vec4 lineSegment = unpackMicroline(iMicrolines[segmentIndex], pathIndex);
|
|
|
|
ivec4 pathTileRect = iMetadata[pathIndex * 3 + 0];
|
|
uint pathTileOffset = uint(iMetadata[pathIndex * 3 + 1]. x);
|
|
uint pathBackdropOffset = uint(iMetadata[pathIndex * 3 + 2]. x);
|
|
|
|
|
|
|
|
ivec2 tileSize = ivec2(16);
|
|
|
|
ivec4 tileLineSegment = ivec4(floor(lineSegment / vec4(tileSize . xyxy)));
|
|
ivec2 fromTileCoords = tileLineSegment . xy, toTileCoords = tileLineSegment . zw;
|
|
|
|
vec2 vector = lineSegment . zw - lineSegment . xy;
|
|
vec2 vectorIsNegative = vec2(vector . x < 0.0 ? - 1.0 : 0.0, vector . y < 0.0 ? - 1.0 : 0.0);
|
|
ivec2 tileStep = ivec2(vector . x < 0.0 ? - 1 : 1, vector . y < 0.0 ? - 1 : 1);
|
|
|
|
vec2 firstTileCrossing = vec2((fromTileCoords + ivec2(vector . x >= 0.0 ? 1 : 0,
|
|
vector . y >= 0.0 ? 1 : 0))* tileSize);
|
|
|
|
vec2 tMax =(firstTileCrossing - lineSegment . xy)/ vector;
|
|
vec2 tDelta = abs(tileSize / vector);
|
|
|
|
vec2 currentPosition = lineSegment . xy;
|
|
ivec2 tileCoords = fromTileCoords;
|
|
int lastStepDirection = 0;
|
|
uint iteration = 0;
|
|
|
|
while(iteration < 1024u){
|
|
int nextStepDirection;
|
|
if(tMax . x < tMax . y)
|
|
nextStepDirection = 1;
|
|
else if(tMax . x > tMax . y)
|
|
nextStepDirection = 2;
|
|
else if(tileStep . x > 0.0)
|
|
nextStepDirection = 1;
|
|
else
|
|
nextStepDirection = 2;
|
|
|
|
float nextT = min(nextStepDirection == 1 ? tMax . x : tMax . y, 1.0);
|
|
|
|
|
|
if(tileCoords == toTileCoords)
|
|
nextStepDirection = 0;
|
|
|
|
vec2 nextPosition = mix(lineSegment . xy, lineSegment . zw, nextT);
|
|
vec4 clippedLineSegment = vec4(currentPosition, nextPosition);
|
|
addFill(clippedLineSegment, tileCoords, pathTileRect, pathTileOffset);
|
|
|
|
|
|
vec4 auxiliarySegment;
|
|
bool haveAuxiliarySegment = false;
|
|
if(tileStep . y < 0 && nextStepDirection == 2){
|
|
auxiliarySegment = vec4(clippedLineSegment . zw, vec2(tileCoords * tileSize));
|
|
haveAuxiliarySegment = true;
|
|
} else if(tileStep . y > 0 && lastStepDirection == 2){
|
|
auxiliarySegment = vec4(vec2(tileCoords * tileSize), clippedLineSegment . xy);
|
|
haveAuxiliarySegment = true;
|
|
}
|
|
if(haveAuxiliarySegment)
|
|
addFill(auxiliarySegment, tileCoords, pathTileRect, pathTileOffset);
|
|
|
|
|
|
|
|
|
|
|
|
if(tileStep . x < 0 && lastStepDirection == 1){
|
|
adjustBackdrop(1,
|
|
tileCoords,
|
|
pathTileRect,
|
|
pathTileOffset,
|
|
pathBackdropOffset);
|
|
} else if(tileStep . x > 0 && nextStepDirection == 1){
|
|
adjustBackdrop(- 1,
|
|
tileCoords,
|
|
pathTileRect,
|
|
pathTileOffset,
|
|
pathBackdropOffset);
|
|
}
|
|
|
|
|
|
if(nextStepDirection == 1){
|
|
tMax . x += tDelta . x;
|
|
tileCoords . x += tileStep . x;
|
|
} else if(nextStepDirection == 2){
|
|
tMax . y += tDelta . y;
|
|
tileCoords . y += tileStep . y;
|
|
} else if(nextStepDirection == 0){
|
|
break;
|
|
}
|
|
|
|
currentPosition = nextPosition;
|
|
lastStepDirection = nextStepDirection;
|
|
|
|
iteration ++;
|
|
}
|
|
}
|
|
|