Files
orx/orx-jumpflood/src/jvmMain/kotlin/ShapeSDF.kt
2023-12-14 17:52:19 +01:00

91 lines
2.9 KiB
Kotlin

package org.openrndr.extra.jumpfill
import org.openrndr.draw.*
import org.openrndr.extra.jumpflood.jf_shape_sdf
import org.openrndr.extra.parameters.BooleanParameter
import org.openrndr.math.Matrix44
import org.openrndr.math.Vector4
import org.openrndr.resourceUrl
import org.openrndr.shape.Rectangle
import org.openrndr.shape.Shape
import org.openrndr.shape.ShapeContour
class ShapeSDF : Filter(filterShaderFromCode(jf_shape_sdf, "shape-sdf")) {
private val fromBuffer = bufferTexture(1024, format = ColorFormat.RGBa, type = ColorType.FLOAT32)
private val toBuffer = bufferTexture(1024, format = ColorFormat.RGBa, type = ColorType.FLOAT32)
private var segmentCount = 0
@BooleanParameter("use UV map")
var useUV: Boolean by parameters
@BooleanParameter("rectify distance")
var rectify: Boolean by parameters
private var modelViewMatrixInverse by parameters
var modelViewMatrix = Matrix44.IDENTITY
set(value) {
modelViewMatrixInverse = modelViewMatrix.inversed
field = value
}
init {
useUV = false
rectify = false
modelViewMatrix = Matrix44.IDENTITY
}
fun setShapes(shapes: List<Shape>) {
setContours(shapes.flatMap { it.contours })
}
fun setContours(contours: List<ShapeContour>) {
val from = mutableListOf<Vector4>()
val to = mutableListOf<Vector4>()
for (contour in contours) {
val lin = contour.sampleLinear()
var contourLength = 0.0
for (segment in lin.segments) {
contourLength += segment.length
}
var offset = 0.0
for (segment in lin.segments) {
from.add(Vector4(segment.start.x, segment.start.y, offset, contourLength))
offset += segment.length
to.add(Vector4(segment.end.x, segment.end.y, offset, contourLength))
}
}
val fromShadow = fromBuffer.shadow
val fromWriter = fromShadow.writer()
fromWriter.rewind()
for (v in from) {
fromWriter.write(v)
}
fromShadow.upload(0, from.size * 4 * 4)
val toShadow = toBuffer.shadow
val toWriter = toShadow.writer()
toWriter.rewind()
for (v in to) {
toWriter.write(v)
}
toShadow.upload(0, to.size * 4 * 4)
segmentCount = from.size
}
override fun apply(source: Array<ColorBuffer>, target: Array<ColorBuffer>, clip: Rectangle?) {
require(target[0].type == ColorType.FLOAT16 || target[0].type == ColorType.FLOAT32) {
"needs a floating point target"
}
parameters["fromBuffer"] = fromBuffer
parameters["toBuffer"] = toBuffer
parameters["segmentCount"] = segmentCount
// -- bit of an hack
val effectiveSource = if (source.isNotEmpty()) source else target
super.apply(effectiveSource, target, clip)
}
}