package org.openrndr.extra.jumpfill import org.openrndr.draw.* import org.openrndr.extra.parameters.BooleanParameter import org.openrndr.math.Vector4 import org.openrndr.resourceUrl import org.openrndr.shape.Shape import org.openrndr.shape.ShapeContour class ShapeSDF : Filter(filterShaderFromUrl(resourceUrl("/shaders/gl3/shape-sdf.frag"))) { 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 init { useUV = false rectify = false } fun setShapes(shapes: List) { setContours(shapes.flatMap { it.contours }) } fun setContours(contours: List) { val from = mutableListOf() val to = mutableListOf() 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, target: Array) { 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) } }