Simplify orx-jumpflood api

This commit is contained in:
Edwin Jakobs
2019-08-06 17:45:30 +02:00
parent 640d3edd10
commit 988d07e3a4
4 changed files with 182 additions and 153 deletions

View File

@@ -2,8 +2,8 @@ package org.openrndr.extra.jumpfill
import org.openrndr.color.ColorRGBa import org.openrndr.color.ColorRGBa
import org.openrndr.draw.* import org.openrndr.draw.*
import org.openrndr.filter.blend.passthrough
import org.openrndr.math.Matrix44 import org.openrndr.math.Matrix44
import org.openrndr.math.Vector2
import org.openrndr.resourceUrl import org.openrndr.resourceUrl
class EncodePoints : Filter(filterShaderFromUrl(resourceUrl("/shaders/gl3/encode-points.frag"))) class EncodePoints : Filter(filterShaderFromUrl(resourceUrl("/shaders/gl3/encode-points.frag")))
@@ -12,6 +12,7 @@ class JumpFlood : Filter(filterShaderFromUrl(resourceUrl("/shaders/gl3/jumpflood
var step: Int by parameters var step: Int by parameters
} }
class PixelDirection : Filter(filterShaderFromUrl(resourceUrl("/shaders/gl3/pixel-direction.frag")))
class PixelDistance : Filter(filterShaderFromUrl(resourceUrl("/shaders/gl3/pixel-distance.frag"))) class PixelDistance : Filter(filterShaderFromUrl(resourceUrl("/shaders/gl3/pixel-distance.frag")))
class ContourPoints : Filter(filterShaderFromUrl(resourceUrl("/shaders/gl3/contour-points.frag"))) class ContourPoints : Filter(filterShaderFromUrl(resourceUrl("/shaders/gl3/contour-points.frag")))
class Threshold : Filter(filterShaderFromUrl(resourceUrl("/shaders/gl3/threshold.frag"))) { class Threshold : Filter(filterShaderFromUrl(resourceUrl("/shaders/gl3/threshold.frag"))) {
@@ -22,12 +23,12 @@ class Threshold : Filter(filterShaderFromUrl(resourceUrl("/shaders/gl3/threshold
} }
} }
val encodePoints by lazy { EncodePoints() } private val encodePoints by lazy { EncodePoints() }
val jumpFlood by lazy { JumpFlood() } private val jumpFlood by lazy { JumpFlood() }
val pixelDistance by lazy { PixelDistance() } private val pixelDistance by lazy { PixelDistance() }
val contourPoints by lazy { ContourPoints() } private val pixelDirection by lazy { PixelDistance() }
val threshold by lazy { Threshold() } private val contourPoints by lazy { ContourPoints() }
private val threshold by lazy { Threshold() }
class JumpFlooder(val width: Int, val height: Int) { class JumpFlooder(val width: Int, val height: Int) {
private val dimension = Math.max(width, height) private val dimension = Math.max(width, height)
@@ -42,29 +43,24 @@ class JumpFlooder(val width: Int, val height: Int) {
colorBuffer(type = ColorType.FLOAT32) colorBuffer(type = ColorType.FLOAT32)
} }
val result: ColorBuffer get() = final.colorBuffer(0) val encoded: ColorBuffer get() = final.colorBuffer(0)
private val square = renderTarget(squareDim, squareDim) { private val square = renderTarget(squareDim, squareDim) {
colorBuffer() colorBuffer()
} }
private var contourUsed = false // fun distanceToContour(drawer: Drawer, input: ColorBuffer, thresholdValue: Double = 0.5): ColorBuffer {
val thresholded by lazy { colorBuffer(width, height) } // threshold.threshold = thresholdValue
val edges by lazy { colorBuffer(width, height) } // threshold.apply(input, thresholded)
// contourPoints.apply(thresholded, edges)
fun distanceToContour(drawer: Drawer, input: ColorBuffer, thresholdValue: Double = 0.5): ColorBuffer { // contourUsed = true
threshold.threshold = thresholdValue // return jumpFlood(drawer, edges)
threshold.apply(input, thresholded) // }
contourPoints.apply(thresholded, edges)
contourUsed = true
return jumpFlood(drawer, edges)
}
fun directions(xRange: IntProgression = 0 until width, yRange: IntProgression = 0 until height): Array<List<Vector2>> {
result.shadow.download()
return result.shadow.mapIndexed(xRange, yRange) { _, _, r, g, _, _ -> Vector2(r, g) }
}
// fun directions(xRange: IntProgression = 0 until width, yRange: IntProgression = 0 until height): Array<List<Vector2>> {
// result.shadow.download()
// return result.shadow.mapIndexed(xRange, yRange) { _, _, r, g, _, _ -> Vector2(r, g) }
// }
fun jumpFlood(drawer: Drawer, input: ColorBuffer): ColorBuffer { fun jumpFlood(drawer: Drawer, input: ColorBuffer): ColorBuffer {
if (input.width != width || input.height != height) { if (input.width != width || input.height != height) {
@@ -85,7 +81,6 @@ class JumpFlooder(val width: Int, val height: Int) {
jumpFlood.apply(coordinates[i % 2], coordinates[(i + 1) % 2]) jumpFlood.apply(coordinates[i % 2], coordinates[(i + 1) % 2])
} }
pixelDistance.apply(arrayOf(coordinates[exp % 2], thresholded), coordinates[exp % 2])
drawer.isolatedWithTarget(final) { drawer.isolatedWithTarget(final) {
drawer.background(ColorRGBa.BLACK) drawer.background(ColorRGBa.BLACK)
drawer.ortho(final) drawer.ortho(final)
@@ -93,36 +88,56 @@ class JumpFlooder(val width: Int, val height: Int) {
drawer.model = Matrix44.IDENTITY drawer.model = Matrix44.IDENTITY
drawer.image(coordinates[exp % 2]) drawer.image(coordinates[exp % 2])
} }
return result return encoded
} }
fun destroy(destroyFinal: Boolean = true) { fun destroy() {
coordinates.forEach { it.destroy() } coordinates.forEach { it.destroy() }
square.colorBuffer(0).destroy() square.colorBuffer(0).destroy()
square.detachColorBuffers() square.detachColorBuffers()
square.destroy() square.destroy()
if (destroyFinal) { final.colorBuffer(0).destroy()
final.colorBuffer(0).destroy()
}
final.detachColorBuffers() final.detachColorBuffers()
final.destroy() final.destroy()
}
}
if (contourUsed) { private fun encodeDecodeBitmap(drawer: Drawer, preprocess: Filter, decoder: Filter, bitmap: ColorBuffer,
edges.destroy() jumpFlooder: JumpFlooder? = null,
thresholded.destroy() result: ColorBuffer? = null
} ): ColorBuffer {
val _jumpFlooder = jumpFlooder ?: JumpFlooder(bitmap.width, bitmap.height)
val _result = result ?: colorBuffer(bitmap.width, bitmap.height, type = ColorType.FLOAT16)
preprocess.apply(bitmap, _result)
val encoded = _jumpFlooder.jumpFlood(drawer, _result)
decoder.apply(arrayOf(encoded, bitmap), _result)
if (jumpFlooder == null) {
_jumpFlooder.destroy()
} }
return _result
} }
fun jumpFlood(drawer: Drawer, points: ColorBuffer): ColorBuffer { /**
val jumpFlooder = JumpFlooder(points.width, points.height) * Creates a color buffer containing the coordinates of the nearest centroids
jumpFlooder.jumpFlood(drawer, points) * @param bitmap a ColorBuffer with centroids in white
val result = jumpFlooder.result */
jumpFlooder.destroy(false) fun centroidsFromBitmap(drawer: Drawer, bitmap: ColorBuffer,
return result jumpFlooder: JumpFlooder? = null,
} result: ColorBuffer? = null
): ColorBuffer = encodeDecodeBitmap(drawer, passthrough, passthrough, bitmap, jumpFlooder, result)
fun distanceFieldFromBitmap(drawer: Drawer, bitmap: ColorBuffer,
jumpFlooder: JumpFlooder? = null,
result: ColorBuffer? = null
): ColorBuffer = encodeDecodeBitmap(drawer, contourPoints, pixelDistance, bitmap, jumpFlooder, result)
fun directionFieldFromBitmap(drawer: Drawer, bitmap: ColorBuffer,
jumpFlooder: JumpFlooder? = null,
result: ColorBuffer? = null
): ColorBuffer = encodeDecodeBitmap(drawer, contourPoints, pixelDirection, bitmap, jumpFlooder, result)

View File

@@ -8,17 +8,15 @@ out vec4 o_color;
void main() { void main() {
vec2 stepSize = 1.0 / textureSize(tex0, 0); vec2 stepSize = 1.0 / textureSize(tex0, 0);
float ref = step(0.5 , texture(tex0, v_texCoord0).r); float ref = step(0.5 , texture(tex0, v_texCoord0).r);
vec4 outc = vec4(-1.0, -1.0, 0.0, 1.0);
float contour = 0.0; float laplacian = -4 * ref;
for (int y = -1; y <= 1; ++y) {
for (int x = -1; x <= 1; ++x) { laplacian += step(0.5, texture(tex0, v_texCoord0 + vec2(stepSize.x, 0.0)).r);
float smp = step(0.5, texture(tex0, v_texCoord0 + vec2(x,y) * stepSize).r); laplacian += step(0.5, texture(tex0, v_texCoord0 - vec2(stepSize.x, 0.0)).r);
if (smp != ref && ref == 1.0) { laplacian += step(0.5, texture(tex0, v_texCoord0 + vec2(0.0, stepSize.y)).r);
contour = 1.0; laplacian += step(0.5, texture(tex0, v_texCoord0 - vec2(0.0, stepSize.y)).r);
}
} float contour = 1.0 - step(0.0, laplacian);
}
o_color = vec4(contour, contour, contour, 1.0); o_color = vec4(contour, contour, contour, 1.0);
} }

View File

@@ -0,0 +1,16 @@
#version 330 core
uniform sampler2D tex0;
uniform sampler2D tex1;
in vec2 v_texCoord0;
out vec4 o_color;
void main() {
vec2 size = textureSize(tex0, 0);
vec2 pixelPosition = v_texCoord0;
vec2 centroidPixelPosition = texture(tex0, v_texCoord0).xy;
vec2 pixelDistance = (centroidPixelPosition - pixelPosition) * size * vec2(1.0, -1.0);
float threshold = texture(tex1, v_texCoord0).r;
o_color = vec4(pixelDistance, threshold, 1.0);
}

View File

@@ -12,5 +12,5 @@ void main() {
vec2 centroidPixelPosition = texture(tex0, v_texCoord0).xy; vec2 centroidPixelPosition = texture(tex0, v_texCoord0).xy;
vec2 pixelDistance = (centroidPixelPosition - pixelPosition) * size * vec2(1.0, -1.0); vec2 pixelDistance = (centroidPixelPosition - pixelPosition) * size * vec2(1.0, -1.0);
float threshold = texture(tex1, v_texCoord0).r; float threshold = texture(tex1, v_texCoord0).r;
o_color = vec4(pixelDistance, threshold, 1.0); o_color = vec4(length(pixelDistance), threshold, 0.0, 1.0);
} }