Sweeps: Fix jugged outline and streaking.

This commit is contained in:
treeform 2021-11-29 07:51:43 -08:00
parent 44f3bcfa98
commit b9402e592d

View file

@ -2256,9 +2256,15 @@ when defined(pixieSweeps):
var cutterLine: float32 = 0 var cutterLine: float32 = 0
block doubleFor: block doubleFor:
for a in sweeps[i]: for a in sweeps[i]:
let aSeg = segment(vec2(a.atx, cutLines[i]), vec2(a.tox, cutLines[i+1])) let aSeg = segment(
vec2(a.atx, cutLines[i]),
vec2(a.tox, cutLines[i+1])
)
for b in sweeps[i]: for b in sweeps[i]:
let bSeg = segment(vec2(b.atx, cutLines[i]), vec2(b.tox, cutLines[i+1])) let bSeg = segment(
vec2(b.atx, cutLines[i]),
vec2(b.tox, cutLines[i+1])
)
var at: Vec2 var at: Vec2
if intersectsInner(aSeg, bSeg, at): if intersectsInner(aSeg, bSeg, at):
needsCut = true needsCut = true
@ -2320,7 +2326,7 @@ when defined(pixieSweeps):
# echo "L ", sw.x, " ", sw.y # echo "L ", sw.x, " ", sw.y
proc computeCoverage( proc computeCoverage(
coverages: var seq[uint8], coverages: var seq[uint16],
y: int, y: int,
startX: int, startX: int,
cutLines: seq[float32], cutLines: seq[float32],
@ -2347,53 +2353,61 @@ when defined(pixieSweeps):
minEi = min(neX, seX).int minEi = min(neX, seX).int
maxEi = max(neX, seX).ceil.int maxEi = max(neX, seX).ceil.int
# TODO: Add case when trapezoids both starts and stops on same pixle.
let let
nw = vec2(sweep[i+0].atx, cutLines[currCutLine]) nw = vec2(sweep[i+0].atx, cutLines[currCutLine])
sw = vec2(sweep[i+0].tox, cutLines[currCutLine + 1]) sw = vec2(sweep[i+0].tox, cutLines[currCutLine + 1])
f16 = (256 * 256 - 1).float32
for x in minWi ..< maxWi: for x in minWi ..< maxWi:
var area = pixelCover(nw - vec2(x.float32, y.float32), sw - vec2( var area = pixelCover(
x.float32, y.float32)) nw - vec2(x.float32, y.float32),
coverages[x - startX] += (area * 255).uint8 sw - vec2(x.float32, y.float32)
)
coverages[x - startX] += (area * f16).uint16
let x = maxWi let x = maxWi
var midArea = pixelCover(nw - vec2(x.float32, y.float32), sw - vec2( var midArea = pixelCover(
x.float32, y.float32)) nw - vec2(x.float32, y.float32),
var midArea8 = (midArea * 255).uint8 sw - vec2(x.float32, y.float32)
for x in maxWi ..< minEi: )
# TODO: Maybe try coverages of uint16 to prevent streeks in solid white fill? for x in maxWi ..< maxEi:
coverages[x - startX] += midArea8 coverages[x - startX] += (midArea * f16).uint16
let let
ne = vec2(sweep[i+1].atx, cutLines[currCutLine]) ne = vec2(sweep[i+1].atx, cutLines[currCutLine])
se = vec2(sweep[i+1].tox, cutLines[currCutLine + 1]) se = vec2(sweep[i+1].tox, cutLines[currCutLine + 1])
for x in minEi ..< maxEi: for x in minEi ..< maxEi:
var area = midArea - pixelCover(ne - vec2(x.float32, y.float32), se - var area = pixelCover(
vec2(x.float32, y.float32)) ne - vec2(x.float32, y.float32),
coverages[x - startX] += (area * 255).uint8 se - vec2(x.float32, y.float32)
)
coverages[x - startX] -= (area * f16).uint16
i += 2 i += 2
var var
currCutLine = 0 currCutLine = 0
coverages = newSeq[uint8](bounds.w.int) coverages16 = newSeq[uint16](bounds.w.int)
coverages8 = newSeq[uint8](bounds.w.int)
for scanLine in cutLines[0].int ..< cutLines[^1].ceil.int: for scanLine in cutLines[0].int ..< cutLines[^1].ceil.int:
zeroMem(coverages[0].addr, coverages.len)
coverages.computeCoverage(scanLine, startX, cutLines, currCutLine, sweeps[currCutLine]) zeroMem(coverages16[0].addr, coverages16.len * 2)
coverages16.computeCoverage(
scanLine, startX, cutLines, currCutLine, sweeps[currCutLine])
while cutLines[currCutLine + 1] < scanLine.float + 1.0: while cutLines[currCutLine + 1] < scanLine.float + 1.0:
inc currCutLine inc currCutLine
if currCutLine == sweeps.len: if currCutLine == sweeps.len:
break break
coverages.computeCoverage(scanLine, startX, cutLines, currCutLine, coverages16.computeCoverage(
sweeps[currCutLine]) scanLine, startX, cutLines, currCutLine, sweeps[currCutLine])
for i in 0 ..< coverages16.len:
coverages8[i] = (coverages16[i] shr 8).uint8
image.fillCoverage( image.fillCoverage(
rgbx, rgbx,
startX = startX, startX = startX,
y = scanLine, y = scanLine,
coverages, coverages8,
blendMode blendMode
) )