[orx-compositor] Add BufferMultisample support (#236)

Co-authored-by: Yvee1 <stevenvdb@live.nl>
This commit is contained in:
Vechro
2022-06-09 14:20:24 +03:00
committed by GitHub
parent 621fd2bdf2
commit 34914b5a47
2 changed files with 117 additions and 26 deletions

View File

@@ -33,7 +33,7 @@ fun RenderTarget.deepDestroy() {
* A single layer representation * A single layer representation
*/ */
@Description("Layer") @Description("Layer")
open class Layer internal constructor() { open class Layer internal constructor(val bufferMultisample: BufferMultisample = BufferMultisample.Disabled) {
var copyLayers: List<Layer> = listOf() var copyLayers: List<Layer> = listOf()
var sourceOut = SourceOut() var sourceOut = SourceOut()
var sourceIn = SourceIn() var sourceIn = SourceIn()
@@ -43,7 +43,8 @@ open class Layer internal constructor() {
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<Pair<Filter, Filter.() -> Unit>> = mutableListOf()
var colorType = ColorType.UINT8 var colorType = ColorType.UINT8
var accumulation: ColorBuffer? = null private var resolvedColorBuffer: ColorBuffer? = null
private var activeRenderTargetColorBuffer: ColorBuffer? = null
@BooleanParameter("enabled") @BooleanParameter("enabled")
var enabled = true var enabled = true
@@ -68,14 +69,8 @@ open class Layer internal constructor() {
val activeRenderTarget = RenderTarget.active val activeRenderTarget = RenderTarget.active
accumulation = if (activeRenderTarget !is ProgramRenderTarget) {
activeRenderTarget.colorBuffer(0)
} else {
null
}
if (shouldCreateLayerTarget(activeRenderTarget)) { if (shouldCreateLayerTarget(activeRenderTarget)) {
createLayerTarget(activeRenderTarget, drawer) createLayerTarget(activeRenderTarget, drawer, bufferMultisample)
} }
layerTarget?.let { target -> layerTarget?.let { target ->
@@ -87,7 +82,12 @@ open class Layer internal constructor() {
} }
it.layerTarget?.let { copyTarget -> it.layerTarget?.let { copyTarget ->
if (it.bufferMultisample == BufferMultisample.Disabled) {
drawer.image(copyTarget.colorBuffer(0)) drawer.image(copyTarget.colorBuffer(0))
} else {
copyTarget.colorBuffer(0).copyTo(it.resolvedColorBuffer!!)
drawer.image(it.resolvedColorBuffer!!)
}
} }
} }
} }
@@ -95,7 +95,7 @@ open class Layer internal constructor() {
maskLayer?.let { maskLayer?.let {
if (it.shouldCreateLayerTarget(activeRenderTarget)) { if (it.shouldCreateLayerTarget(activeRenderTarget)) {
it.createLayerTarget(activeRenderTarget, drawer) it.createLayerTarget(activeRenderTarget, drawer, it.bufferMultisample)
} }
it.layerTarget?.let { maskRt -> it.layerTarget?.let { maskRt ->
@@ -125,11 +125,9 @@ open class Layer internal constructor() {
} }
if (postFilters.size > 0) { if (postFilters.size > 0) {
val sizeMismatch = if (postBufferCache.isNotEmpty()) { val sizeMismatch = postBufferCache.isNotEmpty()
postBufferCache[0].width != activeRenderTarget.width || postBufferCache[0].height != activeRenderTarget.height && (postBufferCache[0].width != activeRenderTarget.width
} else { || postBufferCache[0].height != activeRenderTarget.height)
false
}
if (sizeMismatch) { if (sizeMismatch) {
postBufferCache.forEach { it.destroy() } postBufferCache.forEach { it.destroy() }
@@ -137,8 +135,14 @@ open class Layer internal constructor() {
} }
if (postBufferCache.isEmpty()) { if (postBufferCache.isEmpty()) {
postBufferCache += persistent { colorBuffer(activeRenderTarget.width, activeRenderTarget.height, type = colorType) } postBufferCache += persistent {
postBufferCache += persistent { colorBuffer(activeRenderTarget.width, activeRenderTarget.height, type = colorType) } colorBuffer(activeRenderTarget.width, activeRenderTarget.height,
activeRenderTarget.contentScale, type = colorType)
}
postBufferCache += persistent {
colorBuffer(activeRenderTarget.width, activeRenderTarget.height,
activeRenderTarget.contentScale, type = colorType)
}
} }
} }
@@ -155,7 +159,6 @@ open class Layer internal constructor() {
maskLayer?.let { maskLayer?.let {
val maskFilter = if (invertMask) sourceOut else sourceIn val maskFilter = if (invertMask) sourceOut else sourceIn
maskFilter.apply(arrayOf(layerPost, it.layerTarget!!.colorBuffer(0)), layerPost) maskFilter.apply(arrayOf(layerPost, it.layerTarget!!.colorBuffer(0)), layerPost)
} }
@@ -165,27 +168,56 @@ open class Layer internal constructor() {
drawer.ortho() drawer.ortho()
drawer.view = Matrix44.IDENTITY drawer.view = Matrix44.IDENTITY
drawer.model = Matrix44.IDENTITY drawer.model = Matrix44.IDENTITY
if (bufferMultisample == BufferMultisample.Disabled) {
drawer.image(layerPost, layerPost.bounds, drawer.bounds) drawer.image(layerPost, layerPost.bounds, drawer.bounds)
} else {
layerPost.copyTo(resolvedColorBuffer!!)
drawer.image(resolvedColorBuffer!!, layerPost.bounds, drawer.bounds)
}
} }
} else { } else {
localBlendFilter.first.apply(localBlendFilter.second) localBlendFilter.first.apply(localBlendFilter.second)
localBlendFilter.first.apply(arrayOf(activeRenderTarget.colorBuffer(0), layerPost), activeRenderTarget.colorBuffer(0)) activeRenderTarget.colorBuffer(0).copyTo(activeRenderTargetColorBuffer!!)
if (bufferMultisample == BufferMultisample.Disabled) {
localBlendFilter.first.apply(arrayOf(activeRenderTargetColorBuffer!!, layerPost),
activeRenderTargetColorBuffer!!)
} else {
layerPost.copyTo(resolvedColorBuffer!!)
localBlendFilter.first.apply(arrayOf(activeRenderTargetColorBuffer!!, resolvedColorBuffer!!),
activeRenderTargetColorBuffer!!)
} }
accumulation?.copyTo(target.colorBuffer(0)) if (activeRenderTarget !is ProgramRenderTarget) {
activeRenderTargetColorBuffer!!.copyTo(target.colorBuffer(0))
}
activeRenderTargetColorBuffer!!.copyTo(activeRenderTarget.colorBuffer(0))
}
} }
} }
private fun shouldCreateLayerTarget(activeRenderTarget: RenderTarget): Boolean { private fun shouldCreateLayerTarget(activeRenderTarget: RenderTarget): Boolean {
return layerTarget == null || ((layerTarget?.width != activeRenderTarget.width || layerTarget?.height != activeRenderTarget.height) && activeRenderTarget.width > 0 && activeRenderTarget.height > 0) return layerTarget == null
|| ((layerTarget?.width != activeRenderTarget.width || layerTarget?.height != activeRenderTarget.height)
&& activeRenderTarget.width > 0 && activeRenderTarget.height > 0)
} }
private fun createLayerTarget(activeRenderTarget: RenderTarget, drawer: Drawer) { private fun createLayerTarget(
activeRenderTarget: RenderTarget, drawer: Drawer, bufferMultisample: BufferMultisample
) {
layerTarget?.deepDestroy() layerTarget?.deepDestroy()
layerTarget = renderTarget(activeRenderTarget.width, activeRenderTarget.height) { layerTarget = renderTarget(activeRenderTarget.width, activeRenderTarget.height,
activeRenderTarget.contentScale, bufferMultisample) {
colorBuffer(type = colorType) colorBuffer(type = colorType)
depthBuffer() depthBuffer()
} }
if (bufferMultisample != BufferMultisample.Disabled) {
resolvedColorBuffer?.destroy()
resolvedColorBuffer = colorBuffer(activeRenderTarget.width, activeRenderTarget.height,
activeRenderTarget.contentScale, type = colorType)
}
activeRenderTargetColorBuffer?.destroy()
activeRenderTargetColorBuffer = colorBuffer(activeRenderTarget.width, activeRenderTarget.height,
activeRenderTarget.contentScale, type = colorType)
layerTarget?.let { layerTarget?.let {
drawer.withTarget(it) { drawer.withTarget(it) {
drawer.clear(ColorRGBa.TRANSPARENT) drawer.clear(ColorRGBa.TRANSPARENT)
@@ -203,6 +235,15 @@ fun Layer.layer(function: Layer.() -> Unit): Layer {
return layer return layer
} }
/**
* create a layer within the composition with a custom [BufferMultisample]
*/
fun Layer.layer(bufferMultisample: BufferMultisample, function: Layer.() -> Unit): Layer {
val layer = Layer(bufferMultisample).apply { function() }
children.add(layer)
return layer
}
/** /**
* set the draw contents of the layer * set the draw contents of the layer
*/ */

View File

@@ -0,0 +1,50 @@
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.draw.BufferMultisample
import org.openrndr.extra.compositor.blend
import org.openrndr.extra.compositor.compose
import org.openrndr.extra.compositor.draw
import org.openrndr.extra.compositor.layer
import org.openrndr.extra.fx.blend.Normal
import org.openrndr.math.Vector2
import org.openrndr.shape.Rectangle
/**
* Demonstration of using [BufferMultisample] on a per layer basis.
* Try changing which layer has multisampling applied and observe the results.
*/
fun main() = application {
configure {
width = 800
height = 800
}
program {
val layers = compose {
layer(BufferMultisample.SampleCount(16)) {
draw {
drawer.translate(drawer.bounds.center)
drawer.rotate(seconds)
drawer.fill = ColorRGBa.PINK
drawer.rectangle(Rectangle.fromCenter(Vector2.ZERO, 200.0))
}
layer() {
blend(Normal()) {
clip = true
}
draw {
drawer.rotate(seconds * -2)
drawer.fill = ColorRGBa.WHITE
drawer.rectangle(Rectangle.fromCenter(Vector2.ZERO, 200.0))
}
}
}
}
extend {
drawer.clear(ColorRGBa.WHITE)
layers.draw(drawer)
}
}
}