From 47d2c94df5db8e725628aca9b0ea3c69145e1311 Mon Sep 17 00:00:00 2001 From: Edwin Jakobs Date: Thu, 17 Jan 2019 19:39:31 +0100 Subject: [PATCH] Add FastIntegralImage --- .../src/main/kotlin/FastIntegralImage.kt | 77 +++++++++++++++++++ .../resources/shaders/gl3/integral-image.frag | 26 +++++++ 2 files changed, 103 insertions(+) create mode 100644 orx-integral-image/src/main/kotlin/FastIntegralImage.kt create mode 100644 orx-integral-image/src/main/resources/shaders/gl3/integral-image.frag diff --git a/orx-integral-image/src/main/kotlin/FastIntegralImage.kt b/orx-integral-image/src/main/kotlin/FastIntegralImage.kt new file mode 100644 index 00000000..feaad8f4 --- /dev/null +++ b/orx-integral-image/src/main/kotlin/FastIntegralImage.kt @@ -0,0 +1,77 @@ +package org.openrndr.extra.integralimage + +import org.openrndr.draw.* +import org.openrndr.filter.blend.passthrough +import org.openrndr.math.Vector2 +import org.openrndr.resourceUrl + + +class FastIntegralImageFilter : Filter(filterShaderFromUrl(resourceUrl( + "/shaders/gl3/integral-image.frag" +))) { + var passIndex: Int by parameters + var passDirection: Vector2 by parameters + var sampleCount: Int by parameters + var sampleCountBase: Int by parameters +} + +class FastIntegralImage : Filter(filterShaderFromUrl(resourceUrl( + "/shaders/gl3/integral-image.frag" +))) { + + var intermediate: ColorBuffer? = null + val filter = FastIntegralImageFilter() + + private fun sampleCounts(size:Int, sampleCountBase:Int) : List { + var remainder = size + val sampleCounts = mutableListOf() + while (remainder > 0) { + sampleCounts += if (remainder >= sampleCountBase) { + sampleCountBase + } else { + remainder + } + remainder /= sampleCountBase + } + return sampleCounts + } + + override fun apply(source: Array, target: Array) { + + val sampleCountBase = 16 + val xSampleCounts = sampleCounts(source[0].width, sampleCountBase) + val ySampleCounts = sampleCounts(source[0].height, sampleCountBase) + + val li = intermediate + if (li == null || (li.width != source[0].width || li.height != source[0].height)) { + intermediate?.destroy() + intermediate = colorBuffer(source[0].width, source[0].height, 1.0, ColorFormat.RGBa, ColorType.FLOAT32) + } + + val targets = arrayOf(target, arrayOf(intermediate!!)) + + var targetIndex = 0 + + filter.sampleCountBase = sampleCountBase + + filter.passDirection = Vector2.UNIT_X + for (pass in 0 until xSampleCounts.size) { + filter.sampleCount = xSampleCounts[pass] + filter.passIndex = pass + filter.apply( if (pass == 0) source else targets[targetIndex%2], targets[(targetIndex+1)%2]) + targetIndex++ + } + + filter.passDirection = Vector2.UNIT_Y + for (pass in 0 until ySampleCounts.size) { + filter.sampleCount = ySampleCounts[pass] + filter.passIndex = pass + filter.apply( targets[targetIndex%2], targets[(targetIndex+1)%2]) + targetIndex++ + } + + if (targetIndex%2 == 1) { + passthrough.apply(targets[1], targets[0]) + } + } +} \ No newline at end of file diff --git a/orx-integral-image/src/main/resources/shaders/gl3/integral-image.frag b/orx-integral-image/src/main/resources/shaders/gl3/integral-image.frag new file mode 100644 index 00000000..0b304920 --- /dev/null +++ b/orx-integral-image/src/main/resources/shaders/gl3/integral-image.frag @@ -0,0 +1,26 @@ +#version 330 core + +uniform sampler2D tex0; +in vec2 v_texCoord0; +out vec4 o_color; + +uniform int passIndex; +uniform int sampleCount; +uniform int sampleCountBase; +uniform vec2 passDirection; + + +void main() { + vec2 passOffset = vec2(pow(sampleCountBase, passIndex)) * (1.0/textureSize(tex0, 0)) * passDirection; + + vec2 uv0 = v_texCoord0; + vec4 result = vec4(0.0); + for (int i = 0; i < sampleCount; ++i) { + vec2 readUV = v_texCoord0 - vec2(i *passOffset); + float factor = step(0.0, readUV.x) * step(0.0, readUV.y); + result += factor * texture(tex0, readUV); + } + + o_color = result; + +} \ No newline at end of file