pathfinder/resources/shaders/gl4/d3d11/dice.cs.glsl

221 lines
6.0 KiB
Plaintext
Raw Normal View History

2020-06-23 15:35:57 -04:00
#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 mat2 uTransform;
uniform vec2 uTranslation;
uniform int uPathCount;
uniform int uLastBatchSegmentIndex;
uniform int uMaxMicrolineCount;
layout(std430, binding = 0)buffer bComputeIndirectParams {
restrict uint iComputeIndirectParams[];
};
layout(std430, binding = 1)buffer bDiceMetadata {
restrict readonly uvec4 iDiceMetadata[];
};
layout(std430, binding = 2)buffer bPoints {
restrict readonly vec2 iPoints[];
};
layout(std430, binding = 3)buffer bInputIndices {
restrict readonly uvec2 iInputIndices[];
};
layout(std430, binding = 4)buffer bMicrolines {
restrict uvec4 iMicrolines[];
};
void emitMicroline(vec4 microlineSegment, uint pathIndex, uint outputMicrolineIndex){
if(outputMicrolineIndex >= uMaxMicrolineCount)
return;
ivec4 microlineSubpixels = ivec4(round(clamp(microlineSegment, - 32768.0, 32767.0)* 256.0));
ivec4 microlinePixels = ivec4(floor(vec4(microlineSubpixels)/ 256.0));
ivec4 microlineFractPixels = microlineSubpixels - microlinePixels * 256;
iMicrolines[outputMicrolineIndex]=
uvec4((uint(microlinePixels . x)& 0xffff)|(uint(microlinePixels . y)<< 16),
(uint(microlinePixels . z)& 0xffff)|(uint(microlinePixels . w)<< 16),
uint(microlineFractPixels . x)|(uint(microlineFractPixels . y)<< 8)|
(uint(microlineFractPixels . z)<< 16)|(uint(microlineFractPixels . w)<< 24),
pathIndex);
}
bool curveIsFlat(vec4 baseline, vec4 ctrl){
vec4 uv = vec4(3.0)* ctrl - vec4(2.0)* baseline - baseline . zwxy;
uv *= uv;
uv = max(uv, uv . zwxy);
return uv . x + uv . y <= 16.0 * 0.25 * 0.25;
}
void subdivideCurve(vec4 baseline,
vec4 ctrl,
float t,
out vec4 prevBaseline,
out vec4 prevCtrl,
out vec4 nextBaseline,
out vec4 nextCtrl){
vec2 p0 = baseline . xy, p1 = ctrl . xy, p2 = ctrl . zw, p3 = baseline . zw;
vec2 p0p1 = mix(p0, p1, t), p1p2 = mix(p1, p2, t), p2p3 = mix(p2, p3, t);
vec2 p0p1p2 = mix(p0p1, p1p2, t), p1p2p3 = mix(p1p2, p2p3, t);
vec2 p0p1p2p3 = mix(p0p1p2, p1p2p3, t);
prevBaseline = vec4(p0, p0p1p2p3);
prevCtrl = vec4(p0p1, p0p1p2);
nextBaseline = vec4(p0p1p2p3, p3);
nextCtrl = vec4(p1p2p3, p2p3);
}
vec2 sampleCurve(vec4 baseline, vec4 ctrl, float t){
vec2 p0 = baseline . xy, p1 = ctrl . xy, p2 = ctrl . zw, p3 = baseline . zw;
vec2 p0p1 = mix(p0, p1, t), p1p2 = mix(p1, p2, t), p2p3 = mix(p2, p3, t);
vec2 p0p1p2 = mix(p0p1, p1p2, t), p1p2p3 = mix(p1p2, p2p3, t);
return mix(p0p1p2, p1p2p3, t);
}
vec2 sampleLine(vec4 line, float t){
return mix(line . xy, line . zw, t);
}
vec2 getPoint(uint pointIndex){
return uTransform * iPoints[pointIndex]+ uTranslation;
}
void main(){
uint batchSegmentIndex = gl_GlobalInvocationID . x;
if(batchSegmentIndex >= uLastBatchSegmentIndex)
return;
uint lowPathIndex = 0, highPathIndex = uint(uPathCount);
int iteration = 0;
while(iteration < 1024 && lowPathIndex + 1 < highPathIndex){
uint midPathIndex = lowPathIndex +(highPathIndex - lowPathIndex)/ 2;
uint midBatchSegmentIndex = iDiceMetadata[midPathIndex]. z;
if(batchSegmentIndex < midBatchSegmentIndex){
highPathIndex = midPathIndex;
} else {
lowPathIndex = midPathIndex;
if(batchSegmentIndex == midBatchSegmentIndex)
break;
}
iteration ++;
}
uint batchPathIndex = lowPathIndex;
uvec4 diceMetadata = iDiceMetadata[batchPathIndex];
uint firstGlobalSegmentIndexInPath = diceMetadata . y;
uint firstBatchSegmentIndexInPath = diceMetadata . z;
uint globalSegmentIndex = batchSegmentIndex - firstBatchSegmentIndexInPath +
firstGlobalSegmentIndexInPath;
uvec2 inputIndices = iInputIndices[globalSegmentIndex];
uint fromPointIndex = inputIndices . x, flagsPathIndex = inputIndices . y;
uint toPointIndex = fromPointIndex;
if((flagsPathIndex & 0x40000000u)!= 0u)
toPointIndex += 3;
else if((flagsPathIndex & 0x80000000u)!= 0u)
toPointIndex += 2;
else
toPointIndex += 1;
vec4 baseline = vec4(getPoint(fromPointIndex), getPoint(toPointIndex));
vec4 ctrl = vec4(0.0);
float segmentCountF;
bool isCurve =(flagsPathIndex &(0x40000000u |
0x80000000u))!= 0;
if(isCurve){
vec2 ctrl0 = getPoint(fromPointIndex + 1);
if((flagsPathIndex & 0x80000000u)!= 0){
vec2 ctrl0_2 = ctrl0 * vec2(2.0);
ctrl =(baseline +(ctrl0 * vec2(2.0)). xyxy)* vec4(1.0 / 3.0);
} else {
ctrl = vec4(ctrl0, getPoint(fromPointIndex + 2));
}
vec2 bound = vec2(6.0)* max(abs(ctrl . zw - 2.0 * ctrl . xy + baseline . xy),
abs(baseline . zw - 2.0 * ctrl . zw + ctrl . xy));
segmentCountF = sqrt(length(bound)/(8.0 * 0.25));
} else {
segmentCountF = length(baseline . zw - baseline . xy)/ 16.0;
}
int segmentCount = max(int(ceil(segmentCountF)), 1);
uint firstOutputMicrolineIndex =
atomicAdd(iComputeIndirectParams[3],
segmentCount);
float prevT = 0.0;
vec2 prevPoint = baseline . xy;
for(int segmentIndex = 0;segmentIndex < segmentCount;segmentIndex ++){
float nextT = float(segmentIndex + 1)/ float(segmentCount);
vec2 nextPoint;
if(isCurve)
nextPoint = sampleCurve(baseline, ctrl, nextT);
else
nextPoint = sampleLine(baseline, nextT);
emitMicroline(vec4(prevPoint, nextPoint),
batchPathIndex,
firstOutputMicrolineIndex + segmentIndex);
prevT = nextT;
prevPoint = nextPoint;
}
}