Add HashBloom, GaussianBloom, SetBackground, Contour and Tiles to orx-fx
This commit is contained in:
@@ -44,6 +44,7 @@ class ApproximateGaussianBlur : Filter(Shader.createFromCode(Filter.filterVertex
|
||||
private var intermediateCache = mutableMapOf<ColorBufferDescription, ColorBuffer>()
|
||||
|
||||
|
||||
|
||||
init {
|
||||
window = 5
|
||||
spread = 1.0
|
||||
|
||||
154
orx-fx/src/main/kotlin/blur/MipBloom.kt
Normal file
154
orx-fx/src/main/kotlin/blur/MipBloom.kt
Normal file
@@ -0,0 +1,154 @@
|
||||
package org.openrndr.extra.fx.blur
|
||||
|
||||
import org.openrndr.color.ColorRGBa
|
||||
import org.openrndr.draw.*
|
||||
import org.openrndr.extra.fx.filterFragmentCode
|
||||
import org.openrndr.extra.parameters.BooleanParameter
|
||||
import org.openrndr.extra.parameters.Description
|
||||
import org.openrndr.extra.parameters.DoubleParameter
|
||||
import org.openrndr.extra.parameters.IntParameter
|
||||
import org.openrndr.filter.color.delinearize
|
||||
import org.openrndr.filter.color.linearize
|
||||
|
||||
class BloomDownscale : Filter(Shader.createFromCode(filterVertexCode, filterFragmentCode("blur/bloom-downscale.frag"))) {
|
||||
|
||||
}
|
||||
|
||||
class BloomUpscale : Filter(Shader.createFromCode(filterVertexCode, filterFragmentCode("blur/bloom-upscale.frag"))) {
|
||||
var gain:Double by parameters
|
||||
var shape:Double by parameters
|
||||
var seed:Double by parameters
|
||||
|
||||
init {
|
||||
gain = 1.0
|
||||
shape = 1.0
|
||||
seed = 1.0
|
||||
}
|
||||
}
|
||||
|
||||
class BloomCombine: Filter(Shader.createFromCode(filterVertexCode, filterFragmentCode("blur/bloom-combine.frag"))) {
|
||||
var gain: Double by parameters
|
||||
var bias: ColorRGBa by parameters
|
||||
|
||||
init {
|
||||
bias = ColorRGBa.BLACK
|
||||
gain = 1.0
|
||||
}
|
||||
}
|
||||
|
||||
@Description("MipBloom")
|
||||
open class MipBloom<T:Filter>(val blur:T) : Filter(Shader.createFromCode(filterVertexCode, filterFragmentCode("blur/bloom-combine.frag"))) {
|
||||
var passes = 6
|
||||
|
||||
@DoubleParameter("shape", 0.0, 4.0)
|
||||
var shape: Double = 1.0
|
||||
|
||||
@DoubleParameter("gain", 0.0, 4.0)
|
||||
var gain: Double = 1.0
|
||||
|
||||
@BooleanParameter("sRGB")
|
||||
var sRGB = true
|
||||
|
||||
var intermediates = mutableListOf<ColorBuffer>()
|
||||
var sourceCopy: ColorBuffer? = null
|
||||
|
||||
val upscale = BloomUpscale()
|
||||
val downScale = BloomDownscale()
|
||||
val combine = BloomCombine()
|
||||
|
||||
override fun apply(source: Array<ColorBuffer>, target: Array<ColorBuffer>) {
|
||||
|
||||
sourceCopy?.let {
|
||||
if (it.width != source[0].width || it.height != source[0].height) {
|
||||
it.destroy()
|
||||
sourceCopy = null
|
||||
}
|
||||
}
|
||||
|
||||
if (sourceCopy == null) {
|
||||
sourceCopy = colorBuffer(source[0].width, source[0].height, type = ColorType.FLOAT16)
|
||||
}
|
||||
|
||||
source[0].copyTo(sourceCopy!!)
|
||||
|
||||
upscale.shape = shape
|
||||
if (intermediates.size != passes
|
||||
|| (intermediates.isNotEmpty() && (intermediates[0].width!=target[0].width || intermediates[0].height != target[0].height) )) {
|
||||
intermediates.forEach {
|
||||
it.destroy()
|
||||
}
|
||||
intermediates.clear()
|
||||
|
||||
for (pass in 0 until passes) {
|
||||
val tdiv = 1 shl (pass+1)
|
||||
val cb = colorBuffer(target[0].width / tdiv, target[0].height / tdiv, type = ColorType.FLOAT16)
|
||||
intermediates.add(cb)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (sRGB) {
|
||||
linearize.apply(sourceCopy!!, sourceCopy!!)
|
||||
}
|
||||
|
||||
downScale.apply(sourceCopy!!, intermediates[0])
|
||||
blur.apply(intermediates[0], intermediates[0])
|
||||
|
||||
for (pass in 1 until passes) {
|
||||
downScale.apply(intermediates[pass-1], intermediates[pass])
|
||||
blur.apply(intermediates[pass], intermediates[pass])
|
||||
}
|
||||
|
||||
upscale.apply(intermediates.toTypedArray(), arrayOf(target[0]))
|
||||
combine.gain = gain
|
||||
combine.apply(arrayOf(sourceCopy!!, target[0]), target)
|
||||
|
||||
if (sRGB) {
|
||||
delinearize.apply(target[0], target[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Description("Hash bloom")
|
||||
class HashBloom : MipBloom<HashBlur>(blur = HashBlur()) {
|
||||
|
||||
/**
|
||||
* Blur radius in pixels, default is 5.0
|
||||
*/
|
||||
@DoubleParameter("blur radius", 1.0, 25.0)
|
||||
var radius: Double = 5.0
|
||||
|
||||
/**
|
||||
* Number of samples, default is 30
|
||||
*/
|
||||
@IntParameter("number of samples", 1, 100)
|
||||
var samples: Int = 30
|
||||
|
||||
override fun apply(source: Array<ColorBuffer>, target: Array<ColorBuffer>) {
|
||||
blur.radius = radius
|
||||
blur.samples = samples
|
||||
super.apply(source, target)
|
||||
}
|
||||
}
|
||||
|
||||
@Description("Gaussian bloom")
|
||||
class GaussianBloom : MipBloom<GaussianBlur>(blur = GaussianBlur()) {
|
||||
|
||||
/**
|
||||
* blur sample window, default value is 5
|
||||
*/
|
||||
@IntParameter("window size", 1, 25)
|
||||
var window: Int = 5
|
||||
|
||||
/**
|
||||
* blur sigma, default value is 1.0
|
||||
*/
|
||||
@DoubleParameter("kernel sigma", 0.0, 25.0)
|
||||
var sigma: Double = 1.0
|
||||
|
||||
override fun apply(source: Array<ColorBuffer>, target: Array<ColorBuffer>) {
|
||||
blur.window = window
|
||||
blur.sigma = sigma
|
||||
super.apply(source, target)
|
||||
}
|
||||
}
|
||||
24
orx-fx/src/main/kotlin/color/SetBackground.kt
Normal file
24
orx-fx/src/main/kotlin/color/SetBackground.kt
Normal file
@@ -0,0 +1,24 @@
|
||||
package org.openrndr.extra.fx.color
|
||||
|
||||
import org.openrndr.color.ColorRGBa
|
||||
import org.openrndr.draw.Filter
|
||||
import org.openrndr.draw.Shader
|
||||
import org.openrndr.extra.fx.filterFragmentCode
|
||||
import org.openrndr.extra.parameters.ColorParameter
|
||||
import org.openrndr.extra.parameters.Description
|
||||
import org.openrndr.extra.parameters.DoubleParameter
|
||||
|
||||
@Description("Set background")
|
||||
class SetBackground : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("color/set-background.frag"))) {
|
||||
|
||||
@ColorParameter("background color")
|
||||
var background: ColorRGBa by parameters
|
||||
|
||||
@DoubleParameter("background opacity", 0.0, 1.0)
|
||||
var backgroundOpacity: Double by parameters
|
||||
|
||||
init {
|
||||
background = ColorRGBa.GRAY
|
||||
backgroundOpacity = 1.0
|
||||
}
|
||||
}
|
||||
37
orx-fx/src/main/kotlin/distort/Tiles.kt
Normal file
37
orx-fx/src/main/kotlin/distort/Tiles.kt
Normal file
@@ -0,0 +1,37 @@
|
||||
package org.openrndr.extra.fx.distort
|
||||
|
||||
import org.openrndr.draw.*
|
||||
import org.openrndr.extra.fx.filterFragmentCode
|
||||
import org.openrndr.extra.parameters.Description
|
||||
import org.openrndr.extra.parameters.DoubleParameter
|
||||
import org.openrndr.extra.parameters.IntParameter
|
||||
|
||||
@Description("Tiles")
|
||||
class Tiles : Filter(Shader.createFromCode(filterVertexCode, filterFragmentCode("distort/tiles.frag"))) {
|
||||
|
||||
@DoubleParameter("rotation", -180.0, 180.0, order = 2)
|
||||
var rotation: Double by parameters
|
||||
|
||||
@IntParameter("x segments", 0, 256, order = 0)
|
||||
var xSegments: Int by parameters
|
||||
|
||||
@IntParameter("y segments", 0, 256, order = 0)
|
||||
var ySegments: Int by parameters
|
||||
|
||||
|
||||
|
||||
init {
|
||||
rotation = 0.0
|
||||
xSegments = 32
|
||||
ySegments = 32
|
||||
}
|
||||
|
||||
var bicubicFiltering = false
|
||||
override fun apply(source: Array<ColorBuffer>, target: Array<ColorBuffer>) {
|
||||
if (bicubicFiltering && source.isNotEmpty()) {
|
||||
source[0].generateMipmaps()
|
||||
source[0].filter(MinifyingFilter.LINEAR_MIPMAP_LINEAR, MagnifyingFilter.LINEAR)
|
||||
}
|
||||
super.apply(source, target)
|
||||
}
|
||||
}
|
||||
41
orx-fx/src/main/kotlin/edges/Contour.kt
Normal file
41
orx-fx/src/main/kotlin/edges/Contour.kt
Normal file
@@ -0,0 +1,41 @@
|
||||
package org.openrndr.extra.vfx
|
||||
|
||||
import org.openrndr.color.ColorRGBa
|
||||
import org.openrndr.draw.Filter
|
||||
import org.openrndr.draw.Shader
|
||||
import org.openrndr.draw.filterShaderFromUrl
|
||||
import org.openrndr.extra.fx.filterFragmentCode
|
||||
import org.openrndr.extra.parameters.ColorParameter
|
||||
import org.openrndr.extra.parameters.Description
|
||||
import org.openrndr.extra.parameters.DoubleParameter
|
||||
import org.openrndr.extra.parameters.IntParameter
|
||||
import org.openrndr.resourceUrl
|
||||
|
||||
@Description("Contour")
|
||||
class Contour : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("edges/contour.frag"))) {
|
||||
@DoubleParameter("levels", 1.0, 16.0)
|
||||
var levels: Double by parameters
|
||||
|
||||
|
||||
@DoubleParameter("contour width", 0.0, 4.0)
|
||||
var contourWidth: Double by parameters
|
||||
|
||||
@DoubleParameter("contour opacity", 0.0, 1.0)
|
||||
var contourOpacity: Double by parameters
|
||||
|
||||
@DoubleParameter("background opacity", 0.0, 1.0)
|
||||
var backgroundOpacity: Double by parameters
|
||||
|
||||
|
||||
@ColorParameter("contour color")
|
||||
var contourColor: ColorRGBa by parameters
|
||||
|
||||
|
||||
init {
|
||||
levels = 6.0
|
||||
contourWidth = 0.4
|
||||
contourColor = ColorRGBa.BLACK
|
||||
backgroundOpacity = 1.0
|
||||
contourOpacity = 1.0
|
||||
}
|
||||
}
|
||||
@@ -11,9 +11,11 @@ uniform float sigma;
|
||||
uniform float spread;
|
||||
uniform float gain;
|
||||
|
||||
uniform int sourceLevel;
|
||||
|
||||
out vec4 o_color;
|
||||
void main() {
|
||||
vec2 s = 1.0 / textureSize(tex0, 0).xy;
|
||||
vec2 s = 1.0 / textureSize(tex0, sourceLevel).xy;
|
||||
int w = window;
|
||||
|
||||
vec4 sum = vec4(0.0);
|
||||
@@ -21,7 +23,7 @@ void main() {
|
||||
for (int x = -w; x <= w; ++x) {
|
||||
float lw = exp( -(x*x) / (2 * sigma * sigma) ) ;
|
||||
vec2 tc = v_texCoord0 + x * blurDirection * s;// * spread;
|
||||
sum += texture(tex0, tc) * lw;
|
||||
sum += textureLod(tex0, tc, sourceLevel) * lw;
|
||||
weight += lw;
|
||||
}
|
||||
o_color = (sum / weight) * gain;
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#version 330 core
|
||||
|
||||
out vec4 o_output;
|
||||
in vec2 v_texCoord0;
|
||||
|
||||
uniform sampler2D tex0;
|
||||
uniform sampler2D tex1;
|
||||
|
||||
uniform float gain;
|
||||
uniform vec4 bias;
|
||||
|
||||
void main() {
|
||||
o_output = texture(tex0, v_texCoord0) + texture(tex1, v_texCoord0)*gain;
|
||||
o_output.a = clamp(o_output.a, 0.0, 1.0);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#version 330
|
||||
|
||||
out vec4 o_output;
|
||||
in vec2 v_texCoord0;
|
||||
uniform sampler2D tex0;
|
||||
|
||||
|
||||
// -- based on https://github.com/excess-demogroup/even-laster-engine/blob/a451a89f6bd6d3c6017d5890b92d9f72823bc742/src/shaders/bloom.fra
|
||||
void main()
|
||||
{
|
||||
float centerWeight = 0.16210282163712664;
|
||||
vec2 diagonalOffsets = vec2(0.3842896354828526, 1.2048616327242379);
|
||||
vec4 offsets = vec4(-diagonalOffsets.xy, +diagonalOffsets.xy) / textureSize(tex0, 0).xyxy;
|
||||
float diagonalWeight = 0.2085034734347498;
|
||||
|
||||
o_output = textureLod(tex0, v_texCoord0, 0) * centerWeight +
|
||||
textureLod(tex0, v_texCoord0 + offsets.xy, 0) * diagonalWeight +
|
||||
textureLod(tex0, v_texCoord0 + offsets.wx, 0) * diagonalWeight +
|
||||
textureLod(tex0, v_texCoord0 + offsets.zw, 0) * diagonalWeight +
|
||||
textureLod(tex0, v_texCoord0 + offsets.yz, 0) * diagonalWeight;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
#version 330
|
||||
|
||||
float nrand(vec2 n) {
|
||||
return fract(sin(dot(n.xy, vec2(12.9898, 78.233))) * 43758.5453);
|
||||
}
|
||||
|
||||
// -- based on https://github.com/excess-demogroup/even-laster-engine/blob/a451a89f6bd6d3c6017d5890b92d9f72823bc742/src/shaders/bloom_upscale.frag
|
||||
uniform float seed;
|
||||
uniform float shape;
|
||||
uniform float gain;
|
||||
|
||||
in vec2 v_texCoord0;
|
||||
out vec4 o_output;
|
||||
|
||||
uniform sampler2D tex0;
|
||||
uniform sampler2D tex1;
|
||||
uniform sampler2D tex2;
|
||||
uniform sampler2D tex3;
|
||||
uniform sampler2D tex4;
|
||||
uniform sampler2D tex5;
|
||||
|
||||
vec4 sampleBloom(vec2 pos, float shape) {
|
||||
vec4 sum = vec4(0);
|
||||
float total = 0;
|
||||
|
||||
{
|
||||
float weight = pow(0.0, shape);
|
||||
vec2 rnd = vec2(nrand(3 + 0.0 + pos.xy + seed),
|
||||
nrand(5 + 0.0 + pos.yx - seed));
|
||||
rnd = (rnd * 2 - 1) / textureSize(tex0, 0);
|
||||
sum += textureLod(tex0, pos + rnd * 0.25, 0.0) * weight;
|
||||
total += weight;
|
||||
}
|
||||
{
|
||||
float weight = pow(1.0, shape);
|
||||
vec2 rnd = vec2(nrand(3 + 0.0 + pos.xy + seed),
|
||||
nrand(5 + 0.0 + pos.yx - seed));
|
||||
rnd = (rnd * 2 - 1) / textureSize(tex1, 0);
|
||||
sum += textureLod(tex1, pos + rnd * 0.25, 0.0) * weight;
|
||||
total += weight;
|
||||
}
|
||||
{
|
||||
float weight = pow(2.0, shape);
|
||||
vec2 rnd = vec2(nrand(3 + 0.0 + pos.xy + seed),
|
||||
nrand(5 + 0.0 + pos.yx - seed));
|
||||
rnd = (rnd * 2 - 1) / textureSize(tex2, 0);
|
||||
sum += textureLod(tex2, pos + rnd * 0.25, 0.0) * weight;
|
||||
total += weight;
|
||||
}
|
||||
|
||||
{
|
||||
float weight = pow(3.0, shape);
|
||||
vec2 rnd = vec2(nrand(3 + 0.0 + pos.xy + seed),
|
||||
nrand(5 + 0.0 + pos.yx - seed));
|
||||
rnd = (rnd * 3 - 1) / textureSize(tex3, 0);
|
||||
sum += textureLod(tex3, pos + rnd * 0.25, 0.0) * weight;
|
||||
total += weight;
|
||||
}
|
||||
{
|
||||
float weight = pow(4.0, shape);
|
||||
vec2 rnd = vec2(nrand(3 + 0.0 + pos.xy + seed),
|
||||
nrand(5 + 0.0 + pos.yx - seed));
|
||||
rnd = (rnd * 3 - 1) / textureSize(tex3, 0);
|
||||
sum += textureLod(tex4, pos + rnd * 0.25, 0.0) * weight;
|
||||
total += weight;
|
||||
}
|
||||
{
|
||||
float weight = pow(5.0, shape);
|
||||
vec2 rnd = vec2(nrand(3 + 0.0 + pos.xy + seed),
|
||||
nrand(5 + 0.0 + pos.yx - seed));
|
||||
rnd = (rnd * 3 - 1) / textureSize(tex3, 0);
|
||||
sum += textureLod(tex5, pos + rnd * 0.25, 0.0) * weight;
|
||||
total += weight;
|
||||
}
|
||||
|
||||
return sum / total;
|
||||
}
|
||||
|
||||
void main() {
|
||||
o_output = sampleBloom(v_texCoord0, shape) * gain;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#version 330 core
|
||||
|
||||
uniform vec4 background;
|
||||
uniform float backgroundOpacity;
|
||||
in vec2 v_texCoord0;
|
||||
uniform sampler2D tex0;
|
||||
|
||||
out vec4 o_color;
|
||||
void main() {
|
||||
vec4 c = texture(tex0, v_texCoord0);
|
||||
o_color = c + (1.0 - c.a) * background * backgroundOpacity;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
#version 330 core
|
||||
|
||||
in vec2 v_texCoord0;
|
||||
uniform sampler2D tex0; // input
|
||||
uniform float rotation;
|
||||
uniform int xSegments;
|
||||
uniform int ySegments;
|
||||
|
||||
out vec4 o_color;
|
||||
|
||||
uniform int segments;
|
||||
float truncate(float x, int segments) {
|
||||
if (segments == 0) {
|
||||
return x;
|
||||
} else {
|
||||
return floor(x*segments) / segments;
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 uv = v_texCoord0 - vec2(0.5);
|
||||
float cr = cos(radians(rotation));
|
||||
float sr = sin(radians(rotation));
|
||||
|
||||
mat2 rm = mat2(cr, -sr, sr, cr);
|
||||
|
||||
vec2 ruv = rm * uv;
|
||||
vec2 truv = vec2( truncate(ruv.x, xSegments), truncate(ruv.y, ySegments));
|
||||
vec2 tuv = transpose(rm) * truv + vec2(0.5);
|
||||
|
||||
vec4 c = vec4(0.0);
|
||||
tuv.x = clamp(tuv.x, 0.0, 1.0);
|
||||
tuv.y = clamp(tuv.y, 0.0, 1.0);
|
||||
c = texture(tex0, tuv);
|
||||
|
||||
o_color = c * texture(tex0, v_texCoord0).a;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#version 330 core
|
||||
uniform sampler2D tex0;
|
||||
in vec2 v_texCoord0;
|
||||
out vec4 o_output;
|
||||
uniform float levels;
|
||||
uniform float contourWidth;
|
||||
uniform float contourOpacity;
|
||||
uniform vec4 contourColor;
|
||||
uniform float backgroundOpacity;
|
||||
|
||||
void main() {
|
||||
vec2 step = 1.0 / textureSize(tex0, 0);
|
||||
vec4 box = vec4(0.0);
|
||||
for (int j = -1; j <=1; ++j) {
|
||||
for (int i = -1; i <= 1; ++i) {
|
||||
box += texture(tex0, v_texCoord0 + step * vec2(i, j));
|
||||
}
|
||||
}
|
||||
box /= 9.0;
|
||||
float v = sin(3.1415926535 * levels * dot(vec3(1.0/3.0),box.xyz));
|
||||
float level = floor(dot(vec3(1.0/3.0),box.xyz) * levels) / levels;
|
||||
//int plateauIndex = min(levels-1, int(level * levels));
|
||||
float contour = 1.0 - smoothstep(0., contourWidth, 0.5 * abs(v) / fwidth(v));
|
||||
|
||||
vec4 t = texture(tex0, v_texCoord0);
|
||||
o_output = t * backgroundOpacity * (1.0-contour) + contour * contourColor * contourOpacity * t.a;
|
||||
}
|
||||
Reference in New Issue
Block a user