[orx-compositor] Remove use() add aside {}
This commit is contained in:
@@ -43,6 +43,7 @@ kotlin {
|
|||||||
val jvmDemo by getting {
|
val jvmDemo by getting {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(project(":orx-fx"))
|
implementation(project(":orx-fx"))
|
||||||
|
implementation(project(":orx-compositor"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import org.openrndr.extra.parameters.BooleanParameter
|
|||||||
import org.openrndr.extra.parameters.Description
|
import org.openrndr.extra.parameters.Description
|
||||||
import org.openrndr.math.Matrix44
|
import org.openrndr.math.Matrix44
|
||||||
|
|
||||||
private val postBufferCache = mutableListOf<ColorBuffer>()
|
|
||||||
|
|
||||||
fun RenderTarget.deepDestroy() {
|
fun RenderTarget.deepDestroy() {
|
||||||
val cbcopy = colorAttachments.map { it }
|
val cbcopy = colorAttachments.map { it }
|
||||||
@@ -30,19 +29,26 @@ fun RenderTarget.deepDestroy() {
|
|||||||
destroy()
|
destroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class LayerType {
|
||||||
|
LAYER,
|
||||||
|
ASIDE
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A single layer representation
|
* A single layer representation
|
||||||
*/
|
*/
|
||||||
@Description("Layer")
|
@Description("Layer")
|
||||||
open class Layer internal constructor(val bufferMultisample: BufferMultisample = BufferMultisample.Disabled) {
|
open class Layer internal constructor(
|
||||||
var copyLayers: List<Layer> = listOf()
|
val type: LayerType,
|
||||||
|
val bufferMultisample: BufferMultisample = BufferMultisample.Disabled
|
||||||
|
) {
|
||||||
var sourceOut = SourceOut()
|
var sourceOut = SourceOut()
|
||||||
var sourceIn = SourceIn()
|
var sourceIn = SourceIn()
|
||||||
var maskLayer: Layer? = null
|
var maskLayer: Layer? = null
|
||||||
var drawFunc: () -> Unit = {}
|
var drawFunc: () -> Unit = {}
|
||||||
val children: MutableList<Layer> = mutableListOf()
|
val children: MutableList<Layer> = mutableListOf()
|
||||||
var blendFilter: Pair<Filter, Filter.() -> Unit>? = null
|
var blendFilter: Pair<Filter, Filter.() -> Unit>? = null
|
||||||
val postFilters: MutableList<Pair<Filter, Filter.() -> Unit>> = mutableListOf()
|
val postFilters: MutableList<Triple<Filter, Array<out Layer>, Filter.() -> Unit>> = mutableListOf()
|
||||||
var colorType = ColorType.UINT8
|
var colorType = ColorType.UINT8
|
||||||
private var unresolvedAccumulation: ColorBuffer? = null
|
private var unresolvedAccumulation: ColorBuffer? = null
|
||||||
var accumulation: ColorBuffer? = null
|
var accumulation: ColorBuffer? = null
|
||||||
@@ -63,7 +69,7 @@ open class Layer internal constructor(val bufferMultisample: BufferMultisample =
|
|||||||
/**
|
/**
|
||||||
* draw the layer
|
* draw the layer
|
||||||
*/
|
*/
|
||||||
fun drawLayer(drawer: Drawer) {
|
protected fun drawLayer(drawer: Drawer, cache: ColorBufferCache) {
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -75,25 +81,6 @@ open class Layer internal constructor(val bufferMultisample: BufferMultisample =
|
|||||||
}
|
}
|
||||||
|
|
||||||
layerTarget?.let { target ->
|
layerTarget?.let { target ->
|
||||||
if (copyLayers.isNotEmpty()) {
|
|
||||||
copyLayers.forEach {
|
|
||||||
drawer.isolatedWithTarget(target) {
|
|
||||||
clearColor?.let {
|
|
||||||
drawer.clear(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
it.layerTarget?.let { copyTarget ->
|
|
||||||
if (it.bufferMultisample == BufferMultisample.Disabled) {
|
|
||||||
drawer.image(copyTarget.colorBuffer(0))
|
|
||||||
} else {
|
|
||||||
copyTarget.colorBuffer(0).copyTo(it.accumulation!!)
|
|
||||||
drawer.image(it.accumulation!!)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
maskLayer?.let {
|
maskLayer?.let {
|
||||||
if (it.shouldCreateLayerTarget(activeRenderTarget)) {
|
if (it.shouldCreateLayerTarget(activeRenderTarget)) {
|
||||||
it.createLayerTarget(activeRenderTarget, drawer, it.bufferMultisample)
|
it.createLayerTarget(activeRenderTarget, drawer, it.bufferMultisample)
|
||||||
@@ -101,11 +88,6 @@ open class Layer internal constructor(val bufferMultisample: BufferMultisample =
|
|||||||
|
|
||||||
it.layerTarget?.let { maskRt ->
|
it.layerTarget?.let { maskRt ->
|
||||||
drawer.isolatedWithTarget(maskRt) {
|
drawer.isolatedWithTarget(maskRt) {
|
||||||
if (copyLayers.isEmpty()) {
|
|
||||||
clearColor?.let { color ->
|
|
||||||
drawer.clear(color)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
drawer.fill = ColorRGBa.WHITE
|
drawer.fill = ColorRGBa.WHITE
|
||||||
drawer.stroke = ColorRGBa.WHITE
|
drawer.stroke = ColorRGBa.WHITE
|
||||||
it.drawFunc()
|
it.drawFunc()
|
||||||
@@ -114,48 +96,34 @@ open class Layer internal constructor(val bufferMultisample: BufferMultisample =
|
|||||||
}
|
}
|
||||||
|
|
||||||
drawer.isolatedWithTarget(target) {
|
drawer.isolatedWithTarget(target) {
|
||||||
if (copyLayers.isEmpty()) {
|
children.filter { it.type == LayerType.ASIDE }.forEach {
|
||||||
clearColor?.let {
|
it.drawLayer(drawer, cache)
|
||||||
drawer.clear(it)
|
}
|
||||||
}
|
|
||||||
|
clearColor?.let {
|
||||||
|
drawer.clear(it)
|
||||||
}
|
}
|
||||||
drawFunc()
|
drawFunc()
|
||||||
children.forEach {
|
children.filter { it.type == LayerType.LAYER }.forEach {
|
||||||
it.drawLayer(drawer)
|
it.drawLayer(drawer, cache)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (postFilters.size > 0) {
|
val layerPost = if (postFilters.isEmpty()) target.colorBuffer(0) else postFilters.let { filters ->
|
||||||
val sizeMismatch = postBufferCache.isNotEmpty()
|
val targets = cache[ColorBufferCacheKey(colorType, target.contentScale)]
|
||||||
&& (postBufferCache[0].width != activeRenderTarget.width
|
targets.forEach {
|
||||||
|| postBufferCache[0].height != activeRenderTarget.height)
|
it.fill(ColorRGBa.TRANSPARENT)
|
||||||
|
|
||||||
if (sizeMismatch) {
|
|
||||||
postBufferCache.forEach { it.destroy() }
|
|
||||||
postBufferCache.clear()
|
|
||||||
}
|
}
|
||||||
|
var localSource = target.colorBuffer(0)
|
||||||
if (postBufferCache.isEmpty()) {
|
for ((i, filter) in filters.withIndex()) {
|
||||||
postBufferCache += persistent {
|
filter.first.apply(filter.third)
|
||||||
colorBuffer(activeRenderTarget.width, activeRenderTarget.height,
|
val sources =
|
||||||
activeRenderTarget.contentScale, type = colorType)
|
arrayOf(localSource) + filter.second.map { it.result ?: error("no result for layer $it") }
|
||||||
}
|
.toTypedArray()
|
||||||
postBufferCache += persistent {
|
filter.first.apply(sources, arrayOf(targets[i % targets.size]))
|
||||||
colorBuffer(activeRenderTarget.width, activeRenderTarget.height,
|
localSource = targets[i % targets.size]
|
||||||
activeRenderTarget.contentScale, type = colorType)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
targets[postFilters.lastIndex % targets.size]
|
||||||
|
|
||||||
val layerPost = postFilters.let { filters ->
|
|
||||||
val targets = postBufferCache
|
|
||||||
val result = filters.foldIndexed(target.colorBuffer(0)) { i, source, filter ->
|
|
||||||
val localTarget = targets[i % targets.size]
|
|
||||||
filter.first.apply(filter.second)
|
|
||||||
filter.first.apply(source, localTarget)
|
|
||||||
localTarget
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
maskLayer?.let {
|
maskLayer?.let {
|
||||||
@@ -163,41 +131,52 @@ open class Layer internal constructor(val bufferMultisample: BufferMultisample =
|
|||||||
maskFilter.apply(arrayOf(layerPost, it.layerTarget!!.colorBuffer(0)), layerPost)
|
maskFilter.apply(arrayOf(layerPost, it.layerTarget!!.colorBuffer(0)), layerPost)
|
||||||
}
|
}
|
||||||
|
|
||||||
val localBlendFilter = blendFilter
|
if (type == LayerType.ASIDE) {
|
||||||
if (localBlendFilter == null) {
|
if (postFilters.isNotEmpty()) {
|
||||||
drawer.isolatedWithTarget(activeRenderTarget) {
|
require(layerPost != result)
|
||||||
drawer.ortho()
|
layerPost.copyTo(result ?: error("no result"))
|
||||||
drawer.view = Matrix44.IDENTITY
|
}
|
||||||
drawer.model = Matrix44.IDENTITY
|
} else if (type == LayerType.LAYER) {
|
||||||
|
val localBlendFilter = blendFilter
|
||||||
|
if (localBlendFilter == null) {
|
||||||
|
drawer.isolated {
|
||||||
|
drawer.defaults()
|
||||||
|
if (bufferMultisample == BufferMultisample.Disabled) {
|
||||||
|
drawer.image(layerPost, layerPost.bounds, drawer.bounds)
|
||||||
|
} else {
|
||||||
|
layerPost.copyTo(accumulation!!)
|
||||||
|
drawer.image(accumulation!!, layerPost.bounds, drawer.bounds)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
localBlendFilter.first.apply(localBlendFilter.second)
|
||||||
|
activeRenderTarget.colorBuffer(0).copyTo(unresolvedAccumulation!!)
|
||||||
if (bufferMultisample == BufferMultisample.Disabled) {
|
if (bufferMultisample == BufferMultisample.Disabled) {
|
||||||
drawer.image(layerPost, layerPost.bounds, drawer.bounds)
|
localBlendFilter.first.apply(
|
||||||
|
arrayOf(unresolvedAccumulation!!, layerPost),
|
||||||
|
unresolvedAccumulation!!
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
layerPost.copyTo(accumulation!!)
|
layerPost.copyTo(accumulation!!)
|
||||||
drawer.image(accumulation!!, layerPost.bounds, drawer.bounds)
|
localBlendFilter.first.apply(
|
||||||
|
arrayOf(unresolvedAccumulation!!, accumulation!!),
|
||||||
|
unresolvedAccumulation!!
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
|
||||||
localBlendFilter.first.apply(localBlendFilter.second)
|
|
||||||
activeRenderTarget.colorBuffer(0).copyTo(unresolvedAccumulation!!)
|
|
||||||
if (bufferMultisample == BufferMultisample.Disabled) {
|
|
||||||
localBlendFilter.first.apply(arrayOf(unresolvedAccumulation!!, layerPost), unresolvedAccumulation!!)
|
|
||||||
} else {
|
|
||||||
layerPost.copyTo(accumulation!!)
|
|
||||||
localBlendFilter.first.apply(arrayOf(unresolvedAccumulation!!, accumulation!!), unresolvedAccumulation!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (activeRenderTarget !is ProgramRenderTarget) {
|
if (activeRenderTarget !is ProgramRenderTarget) {
|
||||||
unresolvedAccumulation!!.copyTo(target.colorBuffer(0))
|
unresolvedAccumulation!!.copyTo(target.colorBuffer(0))
|
||||||
|
}
|
||||||
|
unresolvedAccumulation!!.copyTo(activeRenderTarget.colorBuffer(0))
|
||||||
}
|
}
|
||||||
unresolvedAccumulation!!.copyTo(activeRenderTarget.colorBuffer(0))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun shouldCreateLayerTarget(activeRenderTarget: RenderTarget): Boolean {
|
private fun shouldCreateLayerTarget(activeRenderTarget: RenderTarget): Boolean {
|
||||||
return layerTarget == null
|
return layerTarget == null
|
||||||
|| ((layerTarget?.width != activeRenderTarget.width || layerTarget?.height != activeRenderTarget.height)
|
|| ((layerTarget?.width != activeRenderTarget.width || layerTarget?.height != activeRenderTarget.height)
|
||||||
&& activeRenderTarget.width > 0 && activeRenderTarget.height > 0)
|
&& activeRenderTarget.width > 0 && activeRenderTarget.height > 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createLayerTarget(
|
private fun createLayerTarget(
|
||||||
@@ -229,26 +208,72 @@ open class Layer internal constructor(val bufferMultisample: BufferMultisample =
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Drawer.image(layer: Layer) {
|
||||||
|
val cb = layer.result
|
||||||
|
if (cb != null) {
|
||||||
|
image(cb)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* create a layer within the composition
|
* create a layer within the composition
|
||||||
*/
|
*/
|
||||||
fun Layer.layer(function: Layer.() -> Unit): Layer {
|
fun Layer.layer(
|
||||||
val layer = Layer().apply { function() }
|
colorType: ColorType = this.colorType,
|
||||||
|
multisample: BufferMultisample = BufferMultisample.Disabled,
|
||||||
|
function: Layer.() -> Unit
|
||||||
|
): Layer {
|
||||||
|
val layer = Layer(LayerType.LAYER, multisample).apply { function() }
|
||||||
|
layer.colorType = colorType
|
||||||
children.add(layer)
|
children.add(layer)
|
||||||
return layer
|
return layer
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
fun Layer.aside(
|
||||||
* create a layer within the composition with a custom [BufferMultisample]
|
colorType: ColorType = this.colorType,
|
||||||
*/
|
multisample: BufferMultisample = BufferMultisample.Disabled,
|
||||||
fun Layer.layer(bufferMultisample: BufferMultisample, function: Layer.() -> Unit): Layer {
|
function: Layer.() -> Unit
|
||||||
val layer = Layer(bufferMultisample).apply { function() }
|
): Layer {
|
||||||
|
val layer = Layer(LayerType.ASIDE, multisample).apply { function() }
|
||||||
|
layer.colorType = colorType
|
||||||
children.add(layer)
|
children.add(layer)
|
||||||
return layer
|
return layer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <T : Filter1to1> Layer.apply(drawer: Drawer,
|
||||||
|
filter: T, source: Layer, colorType: ColorType = this.colorType,
|
||||||
|
function: T.() -> Unit
|
||||||
|
): Layer {
|
||||||
|
val layer = Layer(LayerType.ASIDE)
|
||||||
|
layer.colorType = colorType
|
||||||
|
layer.draw {
|
||||||
|
drawer.image(source.result!!)
|
||||||
|
//source.result!!.copyTo(result!!)
|
||||||
|
}
|
||||||
|
layer.post(filter, function)
|
||||||
|
children.add(layer)
|
||||||
|
return layer
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : Filter2to1> Layer.apply(drawer: Drawer,
|
||||||
|
filter: T, source0: Layer, source1:Layer, colorType: ColorType = this.colorType,
|
||||||
|
function: T.() -> Unit
|
||||||
|
): Layer {
|
||||||
|
val layer = Layer(LayerType.ASIDE)
|
||||||
|
layer.colorType = colorType
|
||||||
|
layer.draw {
|
||||||
|
//source0.result!!.copyTo(result!!)
|
||||||
|
drawer.image(source0.result!!)
|
||||||
|
}
|
||||||
|
layer.post(filter, source1, function)
|
||||||
|
children.add(layer)
|
||||||
|
return layer
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set the draw contents of the layer
|
* set the draw contents of the layer
|
||||||
*/
|
*/
|
||||||
@@ -256,18 +281,12 @@ fun Layer.draw(function: () -> Unit) {
|
|||||||
drawFunc = function
|
drawFunc = function
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* use the layer as a base
|
|
||||||
*/
|
|
||||||
fun Layer.use(vararg layer: Layer) {
|
|
||||||
copyLayers = layer.toList()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the drawing acts as a mask on the layer
|
* the drawing acts as a mask on the layer
|
||||||
*/
|
*/
|
||||||
fun Layer.mask(function: () -> Unit) {
|
fun Layer.mask(function: () -> Unit) {
|
||||||
maskLayer = Layer().apply {
|
maskLayer = Layer(LayerType.LAYER).apply {
|
||||||
this.drawFunc = function
|
this.drawFunc = function
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -275,24 +294,73 @@ fun Layer.mask(function: () -> Unit) {
|
|||||||
/**
|
/**
|
||||||
* add a post-processing filter to the layer
|
* add a post-processing filter to the layer
|
||||||
*/
|
*/
|
||||||
fun <F : Filter> Layer.post(filter: F, configure: F.() -> Unit = {}): F {
|
fun <F : Filter1to1> Layer.post(filter: F, configure: F.() -> Unit = {}): F {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
postFilters.add(Pair(filter as Filter, configure as Filter.() -> Unit))
|
postFilters.add(Triple(filter as Filter, emptyArray(), configure as Filter.() -> Unit))
|
||||||
return filter
|
return filter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <F : Filter2to1> Layer.post(filter: F, input1: Layer, configure: F.() -> Unit = {}): F {
|
||||||
|
require(input1.type == LayerType.ASIDE)
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
postFilters.add(Triple(filter as Filter, arrayOf(input1), configure as Filter.() -> Unit))
|
||||||
|
return filter
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <F : Filter3to1> Layer.post(filter: F, input1: Layer, input2: Layer, configure: F.() -> Unit = {}): F {
|
||||||
|
require(input1.type == LayerType.ASIDE)
|
||||||
|
require(input2.type == LayerType.ASIDE)
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
postFilters.add(Triple(filter as Filter, arrayOf(input1, input2), configure as Filter.() -> Unit))
|
||||||
|
return filter
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* add a blend filter to the layer
|
* add a blend filter to the layer
|
||||||
*/
|
*/
|
||||||
fun <F : Filter> Layer.blend(filter: F, configure: F.() -> Unit = {}): F {
|
fun <F : Filter2to1> Layer.blend(filter: F, configure: F.() -> Unit = {}): F {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
blendFilter = Pair(filter as Filter, configure as Filter.() -> Unit)
|
blendFilter = Pair(filter as Filter, configure as Filter.() -> Unit)
|
||||||
return filter
|
return filter
|
||||||
}
|
}
|
||||||
|
|
||||||
class Composite : Layer() {
|
data class ColorBufferCacheKey(
|
||||||
|
val colorType: ColorType,
|
||||||
|
val contentScale: Double
|
||||||
|
)
|
||||||
|
|
||||||
|
class ColorBufferCache(val width: Int, val height: Int) {
|
||||||
|
val cache = mutableMapOf<ColorBufferCacheKey, List<ColorBuffer>>()
|
||||||
|
|
||||||
|
operator fun get(key: ColorBufferCacheKey): List<ColorBuffer> {
|
||||||
|
return cache.getOrPut(key) {
|
||||||
|
listOf(
|
||||||
|
colorBuffer(width, height, type = key.colorType, contentScale = key.contentScale),
|
||||||
|
colorBuffer(width, height, type = key.colorType, contentScale = key.contentScale),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun destroy() {
|
||||||
|
cache.forEach {
|
||||||
|
it.value.forEach { cb -> cb.destroy() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Composite : Layer(LayerType.LAYER) {
|
||||||
|
|
||||||
|
private var cache = ColorBufferCache(RenderTarget.active.width, RenderTarget.active.height)
|
||||||
fun draw(drawer: Drawer) {
|
fun draw(drawer: Drawer) {
|
||||||
drawLayer(drawer)
|
|
||||||
|
if (cache.width != RenderTarget.active.width || cache.height != RenderTarget.active.height) {
|
||||||
|
cache.destroy()
|
||||||
|
cache = ColorBufferCache(RenderTarget.active.width, RenderTarget.active.height)
|
||||||
|
}
|
||||||
|
|
||||||
|
drawLayer(drawer, cache)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,6 +373,9 @@ fun compose(function: Layer.() -> Unit): Composite {
|
|||||||
return root
|
return root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Compositor : Extension {
|
class Compositor : Extension {
|
||||||
override var enabled: Boolean = true
|
override var enabled: Boolean = true
|
||||||
var composite = Composite()
|
var composite = Composite()
|
||||||
@@ -312,7 +383,7 @@ class Compositor : Extension {
|
|||||||
override fun afterDraw(drawer: Drawer, program: Program) {
|
override fun afterDraw(drawer: Drawer, program: Program) {
|
||||||
drawer.isolated {
|
drawer.isolated {
|
||||||
drawer.defaults()
|
drawer.defaults()
|
||||||
composite.drawLayer(drawer)
|
composite.draw(drawer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
37
orx-compositor/src/demo/kotlin/DemoAside01.kt
Normal file
37
orx-compositor/src/demo/kotlin/DemoAside01.kt
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import org.openrndr.application
|
||||||
|
import org.openrndr.color.ColorRGBa
|
||||||
|
import org.openrndr.draw.ColorType
|
||||||
|
import org.openrndr.extra.compositor.*
|
||||||
|
import org.openrndr.extra.fx.blur.DirectionalBlur
|
||||||
|
import org.openrndr.extra.fx.blur.HashBlurDynamic
|
||||||
|
import org.openrndr.extra.fx.patterns.Checkers
|
||||||
|
import kotlin.math.cos
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
application {
|
||||||
|
program {
|
||||||
|
val c = compose {
|
||||||
|
layer {
|
||||||
|
val a = aside(colorType = ColorType.FLOAT32) {
|
||||||
|
post(Checkers()) {
|
||||||
|
this.size = cos(seconds)*0.5 + 0.5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw {
|
||||||
|
drawer.clear(ColorRGBa.GRAY.shade(0.5))
|
||||||
|
drawer.circle(width/2.0, height/2.0, 100.0)
|
||||||
|
}
|
||||||
|
post(HashBlurDynamic(), a) {
|
||||||
|
time = seconds
|
||||||
|
radius = 25.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
extend {
|
||||||
|
c.draw(drawer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -23,13 +23,6 @@ fun main() = application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
program {
|
program {
|
||||||
// -- this block is for automation purposes only
|
|
||||||
if (System.getProperty("takeScreenshot") == "true") {
|
|
||||||
extend(SingleScreenshot()) {
|
|
||||||
this.outputFile = System.getProperty("screenshotPath")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data class Item(var pos: Vector3, val color: ColorRGBa) {
|
data class Item(var pos: Vector3, val color: ColorRGBa) {
|
||||||
fun draw(drawer: Drawer) {
|
fun draw(drawer: Drawer) {
|
||||||
pos -= Vector3(pos.z * 3.0, 0.0, 0.0)
|
pos -= Vector3(pos.z * 3.0, 0.0, 0.0)
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ fun main() = application {
|
|||||||
|
|
||||||
program {
|
program {
|
||||||
val layers = compose {
|
val layers = compose {
|
||||||
layer(BufferMultisample.SampleCount(16)) {
|
layer(multisample = BufferMultisample.SampleCount(16)) {
|
||||||
draw {
|
draw {
|
||||||
drawer.translate(drawer.bounds.center)
|
drawer.translate(drawer.bounds.center)
|
||||||
drawer.rotate(seconds)
|
drawer.rotate(seconds)
|
||||||
@@ -29,7 +29,7 @@ fun main() = application {
|
|||||||
drawer.rectangle(Rectangle.fromCenter(Vector2.ZERO, 200.0))
|
drawer.rectangle(Rectangle.fromCenter(Vector2.ZERO, 200.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
layer() {
|
layer {
|
||||||
blend(Normal()) {
|
blend(Normal()) {
|
||||||
clip = true
|
clip = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,90 +0,0 @@
|
|||||||
import org.openrndr.application
|
|
||||||
import org.openrndr.color.ColorRGBa
|
|
||||||
import org.openrndr.color.rgb
|
|
||||||
import org.openrndr.extensions.SingleScreenshot
|
|
||||||
import org.openrndr.extra.compositor.*
|
|
||||||
import org.openrndr.extra.fx.blend.Add
|
|
||||||
import org.openrndr.extra.fx.blur.ApproximateGaussianBlur
|
|
||||||
import org.openrndr.extra.fx.color.ColorCorrection
|
|
||||||
import kotlin.random.Random
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compositor demo of `use`, which makes it possible to
|
|
||||||
* use the color buffer of a previous layer.
|
|
||||||
*
|
|
||||||
* This program draws a series of concentric rings, most of them gray,
|
|
||||||
* 10% are pink.
|
|
||||||
*
|
|
||||||
* In a second layer we reuse that image with rings, applying an extreme
|
|
||||||
* color correction to make everything black except the pink rings,
|
|
||||||
* then apply a strong blur and finally compose it over the original
|
|
||||||
* image using blend mode Add.
|
|
||||||
*
|
|
||||||
* The result is an sharp image of gray rings with glowing pink rings.
|
|
||||||
*
|
|
||||||
* Note: see also orx-fx Bloom()
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Toggle to see the difference between a simple blur and multilayer bloom
|
|
||||||
const val effectEnabled = true
|
|
||||||
|
|
||||||
fun main() = application {
|
|
||||||
configure {
|
|
||||||
width = 900
|
|
||||||
height = 900
|
|
||||||
}
|
|
||||||
|
|
||||||
program {
|
|
||||||
// -- this block is for automation purposes only
|
|
||||||
if (System.getProperty("takeScreenshot") == "true") {
|
|
||||||
extend(SingleScreenshot()) {
|
|
||||||
this.outputFile = System.getProperty("screenshotPath")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val composite = compose {
|
|
||||||
val circles = layer {
|
|
||||||
draw {
|
|
||||||
drawer.stroke = null
|
|
||||||
val rnd = Random(frameCount / 100 + 1)
|
|
||||||
for (i in 18 downTo 0) {
|
|
||||||
drawer.fill = if (rnd.nextDouble() < 0.1)
|
|
||||||
ColorRGBa.PINK.shade(Random.nextDouble(0.88, 1.0))
|
|
||||||
else
|
|
||||||
rgb(rnd.nextInt(6) / 15.0)
|
|
||||||
|
|
||||||
drawer.circle(drawer.bounds.center, 50.0 + i * 20)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// A. To see how the plain blur looks like
|
|
||||||
if (!effectEnabled) {
|
|
||||||
post(ApproximateGaussianBlur()) {
|
|
||||||
sigma = 25.0
|
|
||||||
window = 25
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// B. This is the bloom effect
|
|
||||||
if (effectEnabled) {
|
|
||||||
layer {
|
|
||||||
use(circles) // <-- use the previous layer as starting point
|
|
||||||
post(ColorCorrection()) {
|
|
||||||
brightness = -0.3
|
|
||||||
contrast = 0.8
|
|
||||||
}
|
|
||||||
post(ApproximateGaussianBlur()) {
|
|
||||||
sigma = 25.0
|
|
||||||
window = 25
|
|
||||||
}
|
|
||||||
blend(Add())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extend {
|
|
||||||
drawer.clear(rgb(0.2))
|
|
||||||
composite.draw(drawer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user