Merge branch 'compositor-mask' of https://github.com/ricardomatias/orx into ricardomatias-compositor-mask
This commit is contained in:
@@ -5,40 +5,50 @@ A simple toolkit to make composite images.
|
|||||||
##### Usage
|
##### Usage
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
import org.openrndr.Configuration
|
|
||||||
import org.openrndr.Program
|
|
||||||
import org.openrndr.application
|
import org.openrndr.application
|
||||||
import org.openrndr.color.ColorRGBa
|
import org.openrndr.draw.loadImage
|
||||||
import org.openrndr.extra.compositor.*
|
import org.openrndr.extra.compositor.*
|
||||||
import org.openrndr.filter.blend.add
|
import org.openrndr.extra.fx.blend.Add
|
||||||
import org.openrndr.filter.blur.ApproximateGaussianBlur
|
import org.openrndr.extra.fx.edges.EdgesWork
|
||||||
|
import org.openrndr.extra.gui.GUI
|
||||||
|
import org.openrndr.math.Vector2
|
||||||
|
|
||||||
class Compositor001 : Program() {
|
|
||||||
|
|
||||||
override fun setup() {
|
fun main() {
|
||||||
val drawing = compose {
|
application {
|
||||||
draw {
|
configure {
|
||||||
drawer.fill = ColorRGBa.PINK
|
width = 768
|
||||||
drawer.circle(width / 2.0, height / 2.0, 10.0)
|
height = 768
|
||||||
}
|
|
||||||
|
|
||||||
layer {
|
|
||||||
draw {
|
|
||||||
drawer.circle(width / 2.0, height / 2.0, 100.0)
|
|
||||||
}
|
|
||||||
post(ApproximateGaussianBlur()) {
|
|
||||||
window = 10
|
|
||||||
sigma = Math.cos(seconds * 10.0) * 10.0 + 10.0
|
|
||||||
}
|
|
||||||
blend(add)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
program {
|
||||||
|
val gui = GUI()
|
||||||
|
|
||||||
extend {
|
val w2 = width / 2.0
|
||||||
drawing.draw(drawer)
|
val h2 = height / 2.0
|
||||||
|
|
||||||
|
val c = compose {
|
||||||
|
draw {
|
||||||
|
drawer.fill = ColorRGBa.PINK
|
||||||
|
drawer.circle(width / 2.0, height / 2.0, 10.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
layer {
|
||||||
|
blend(Add())
|
||||||
|
|
||||||
|
draw {
|
||||||
|
drawer.circle(width / 2.0, height / 2.0, 100.0)
|
||||||
|
}
|
||||||
|
post(ApproximateGaussianBlur()) {
|
||||||
|
window = 10
|
||||||
|
sigma = Math.cos(seconds * 10.0) * 10.0 + 10.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
extend(gui)
|
||||||
|
extend {
|
||||||
|
c.draw(drawer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun main(args: Array<String>) = application(Compositor001(), Configuration())
|
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
dependencies {
|
dependencies {
|
||||||
api project(":orx-parameters")
|
api project(":orx-parameters")
|
||||||
|
api project(":orx-fx")
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,10 @@ import org.openrndr.Extension
|
|||||||
import org.openrndr.Program
|
import org.openrndr.Program
|
||||||
import org.openrndr.color.ColorRGBa
|
import org.openrndr.color.ColorRGBa
|
||||||
import org.openrndr.draw.*
|
import org.openrndr.draw.*
|
||||||
|
import org.openrndr.extra.fx.blend.DestinationIn
|
||||||
|
import org.openrndr.extra.fx.blend.DestinationOut
|
||||||
|
import org.openrndr.extra.fx.blend.SourceIn
|
||||||
|
import org.openrndr.extra.fx.blend.SourceOut
|
||||||
import org.openrndr.extra.parameters.BooleanParameter
|
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
|
||||||
@@ -27,6 +31,9 @@ fun RenderTarget.deepDestroy() {
|
|||||||
*/
|
*/
|
||||||
@Description("Layer")
|
@Description("Layer")
|
||||||
open class Layer internal constructor() {
|
open class Layer internal constructor() {
|
||||||
|
var sourceOut = SourceOut()
|
||||||
|
var destinationIn = SourceIn()
|
||||||
|
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
|
||||||
@@ -36,6 +43,8 @@ open class Layer internal constructor() {
|
|||||||
|
|
||||||
@BooleanParameter("enabled")
|
@BooleanParameter("enabled")
|
||||||
var enabled = true
|
var enabled = true
|
||||||
|
@BooleanParameter("Invert mask")
|
||||||
|
var invertMask = false
|
||||||
var clearColor: ColorRGBa? = ColorRGBa.TRANSPARENT
|
var clearColor: ColorRGBa? = ColorRGBa.TRANSPARENT
|
||||||
private var layerTarget: RenderTarget? = null
|
private var layerTarget: RenderTarget? = null
|
||||||
|
|
||||||
@@ -55,21 +64,27 @@ open class Layer internal constructor() {
|
|||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
val localLayerTarget = layerTarget
|
if (shouldCreateLayerTarget(activeRenderTarget)) {
|
||||||
if (localLayerTarget == null || (localLayerTarget.width != activeRenderTarget.width || localLayerTarget.height != activeRenderTarget.height)) {
|
createLayerTarget(activeRenderTarget, drawer)
|
||||||
layerTarget?.deepDestroy()
|
|
||||||
layerTarget = renderTarget(activeRenderTarget.width, activeRenderTarget.height) {
|
|
||||||
colorBuffer(type = colorType)
|
|
||||||
depthBuffer()
|
|
||||||
}
|
|
||||||
layerTarget?.let {
|
|
||||||
drawer.withTarget(it) {
|
|
||||||
drawer.background(ColorRGBa.TRANSPARENT)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
layerTarget?.let { target ->
|
layerTarget?.let { target ->
|
||||||
|
maskLayer?.let {
|
||||||
|
if (it.shouldCreateLayerTarget(activeRenderTarget)) {
|
||||||
|
it.createLayerTarget(activeRenderTarget, drawer)
|
||||||
|
}
|
||||||
|
|
||||||
|
it.layerTarget?.let { maskRt ->
|
||||||
|
drawer.isolatedWithTarget(maskRt) {
|
||||||
|
clearColor?.let {
|
||||||
|
drawer.background(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
it.drawFunc()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
drawer.isolatedWithTarget(target) {
|
drawer.isolatedWithTarget(target) {
|
||||||
clearColor?.let {
|
clearColor?.let {
|
||||||
drawer.background(it)
|
drawer.background(it)
|
||||||
@@ -109,6 +124,12 @@ open class Layer internal constructor() {
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maskLayer?.let {
|
||||||
|
val maskFilter = if (invertMask) sourceOut else destinationIn
|
||||||
|
|
||||||
|
maskFilter.apply(arrayOf(it.layerTarget!!.colorBuffer(0), layerPost), layerPost)
|
||||||
|
}
|
||||||
|
|
||||||
val localBlendFilter = blendFilter
|
val localBlendFilter = blendFilter
|
||||||
if (localBlendFilter == null) {
|
if (localBlendFilter == null) {
|
||||||
drawer.isolatedWithTarget(activeRenderTarget) {
|
drawer.isolatedWithTarget(activeRenderTarget) {
|
||||||
@@ -123,6 +144,23 @@ open class Layer internal constructor() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun shouldCreateLayerTarget(activeRenderTarget: RenderTarget): Boolean {
|
||||||
|
return layerTarget == null || (layerTarget?.width != activeRenderTarget.width || layerTarget?.height != activeRenderTarget.height)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createLayerTarget(activeRenderTarget: RenderTarget, drawer: Drawer) {
|
||||||
|
layerTarget?.deepDestroy()
|
||||||
|
layerTarget = renderTarget(activeRenderTarget.width, activeRenderTarget.height) {
|
||||||
|
colorBuffer(type = colorType)
|
||||||
|
depthBuffer()
|
||||||
|
}
|
||||||
|
layerTarget?.let {
|
||||||
|
drawer.withTarget(it) {
|
||||||
|
drawer.background(ColorRGBa.TRANSPARENT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -141,6 +179,15 @@ fun Layer.draw(function: () -> Unit) {
|
|||||||
drawFunc = function
|
drawFunc = function
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the drawing acts as a mask on the layer
|
||||||
|
*/
|
||||||
|
fun Layer.mask(function: () -> Unit) {
|
||||||
|
maskLayer = Layer().apply {
|
||||||
|
this.drawFunc = function
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* add a post-processing filter to the layer
|
* add a post-processing filter to the layer
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user