mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-02 16:06:19 +00:00
0f05231c35
Signed-off-by: Elias Naur <mail@eliasnaur.com>
77 lines
1.9 KiB
Go
77 lines
1.9 KiB
Go
// SPDX-License-Identifier: Unlicense OR MIT
|
|
|
|
package gpu
|
|
|
|
import (
|
|
"image"
|
|
)
|
|
|
|
// genAreaLUT generates the lookup table conpatible with the stencilFSrc
|
|
// fragment shaders. The table contains the area of a pixel square above
|
|
// a line. The square has area 1 and is centered in (0, 0).
|
|
// The y-axis intersection of the line in [-8;+8] is specified by the
|
|
// first coordinate.
|
|
// The slope of the line [0;16] is specified by the second coordinate.
|
|
func genAreaLUT(width, height int) *image.Gray {
|
|
lut := image.NewGray(image.Rectangle{Max: image.Point{X: width, Y: height}})
|
|
for v := 0; v < height; v++ {
|
|
a := float32(v) * 16 / float32(height)
|
|
for u := 0; u < width; u++ {
|
|
var area float32
|
|
switch u {
|
|
case 0:
|
|
area = 1.0
|
|
case width - 1:
|
|
area = 0.0
|
|
default:
|
|
b := (float32(u) - float32(width)/2) / 16
|
|
// f(x) = ax+b.
|
|
area = computeLineArea(a, b)
|
|
}
|
|
lut.Pix[v*height+u] = uint8(area*255 + 0.5)
|
|
}
|
|
}
|
|
return lut
|
|
}
|
|
|
|
func computeLineArea(a, b float32) float32 {
|
|
// Compute intersections with the square edges.
|
|
// Right and left.
|
|
ry := a*+0.5 + b
|
|
ly := a*-0.5 + b
|
|
// Top and bottom.
|
|
tx := (+0.5 - b) / a
|
|
bx := (-0.5 - b) / a
|
|
// The line will intersect zero or two edges.
|
|
if ry <= -0.5 {
|
|
// Line is below the square.
|
|
return 1.0
|
|
}
|
|
if ly >= 0.5 {
|
|
// Line is above the square.
|
|
return 0.0
|
|
}
|
|
// The slope is positive, so there are only 4 possible
|
|
// pairs of edges: (bottom, right), (left, right),
|
|
// (bottom, top), (left, top).
|
|
if ry <= 0.5 {
|
|
// Intersection with right edge.
|
|
if ly <= -0.5 {
|
|
// (bottom, right).
|
|
return 1.0 - (0.5-bx)*(ry-(-0.5))/2
|
|
} else {
|
|
// (left, right).
|
|
return 1.0*(0.5-ry) + 1.0*(ry-ly)/2
|
|
}
|
|
} else {
|
|
// Intersection with top edge.
|
|
if ly <= -0.5 {
|
|
// (bottom, top).
|
|
return (bx-(-0.5))*1.0 + (tx-bx)*1.0/2
|
|
} else {
|
|
// (left, top).
|
|
return (tx - (-0.5)) * (0.5 - ly) / 2
|
|
}
|
|
}
|
|
}
|